From d66b30e42317206d53c7bbb91aae48c03f2d2b28 Mon Sep 17 00:00:00 2001 From: Fawaz Oduola Date: Sat, 24 Jan 2026 20:42:31 +0100 Subject: [PATCH 1/2] feat: implement achievement service with energy management, shop, and transaction modules - Add AppModule to initialize the application with necessary modules. - Create Energy module for managing user energy regeneration, consumption, and status. - Implement Shop module for handling shop items, including creation, retrieval, and purchasing. - Develop Transaction module for processing user transactions, including purchases and refunds. - Introduce Payment module to manage payment processing with providers like Stripe and PayPal. - Add necessary entities, controllers, and services for each module. - Implement cron job for periodic energy regeneration. - Set up TypeORM for PostgreSQL database integration. - Configure global validation and CORS in the main application bootstrap. --- AGENTS.md | 270 + dist/main.js | 19122 +++++++++++++++- .../achievement-service/.env.example | 17 + microservices/achievement-service/Dockerfile | 15 + microservices/achievement-service/README.md | 147 + .../achievement-service/docker-compose.yml | 35 + .../achievement-service/nest-cli.json | 8 + .../achievement-service/package-lock.json | 10091 ++++++++ .../achievement-service/package.json | 89 + .../src/achievement/achievement.module.ts | 27 + .../controllers/achievement.controller.ts | 28 + .../entities/achievement-progress.entity.ts | 30 + .../entities/achievement.entity.ts | 45 + .../src/achievement/entities/badge.entity.ts | 27 + .../services/achievement-history.service.ts | 19 + .../achievement-notification.service.ts | 15 + .../services/achievement-progress.service.ts | 47 + .../services/achievement-unlock.service.ts | 34 + .../services/achievement.service.ts | 34 + .../src/achievement/services/badge.service.ts | 33 + .../achievement-service/src/app.module.ts | 26 + .../src/energy/energy-regeneration.service.ts | 105 + .../src/energy/energy.controller.ts | 105 + .../src/energy/energy.entity.ts | 49 + .../src/energy/energy.module.ts | 14 + .../src/energy/energy.service.ts | 90 + microservices/achievement-service/src/main.ts | 23 + .../src/payment/payment.controller.ts | 40 + .../src/payment/payment.module.ts | 10 + .../src/payment/payment.service.ts | 181 + .../src/shop/shop-item.entity.ts | 72 + .../src/shop/shop.controller.ts | 85 + .../src/shop/shop.module.ts | 13 + .../src/shop/shop.service.ts | 147 + .../src/transaction/transaction.controller.ts | 173 + .../src/transaction/transaction.entity.ts | 89 + .../src/transaction/transaction.module.ts | 13 + .../src/transaction/transaction.service.ts | 235 + .../achievement-service/tsconfig.json | 24 + package.json | 141 +- 40 files changed, 31758 insertions(+), 10 deletions(-) create mode 100644 AGENTS.md create mode 100644 microservices/achievement-service/.env.example create mode 100644 microservices/achievement-service/Dockerfile create mode 100644 microservices/achievement-service/README.md create mode 100644 microservices/achievement-service/docker-compose.yml create mode 100644 microservices/achievement-service/nest-cli.json create mode 100644 microservices/achievement-service/package-lock.json create mode 100644 microservices/achievement-service/package.json create mode 100644 microservices/achievement-service/src/achievement/achievement.module.ts create mode 100644 microservices/achievement-service/src/achievement/controllers/achievement.controller.ts create mode 100644 microservices/achievement-service/src/achievement/entities/achievement-progress.entity.ts create mode 100644 microservices/achievement-service/src/achievement/entities/achievement.entity.ts create mode 100644 microservices/achievement-service/src/achievement/entities/badge.entity.ts create mode 100644 microservices/achievement-service/src/achievement/services/achievement-history.service.ts create mode 100644 microservices/achievement-service/src/achievement/services/achievement-notification.service.ts create mode 100644 microservices/achievement-service/src/achievement/services/achievement-progress.service.ts create mode 100644 microservices/achievement-service/src/achievement/services/achievement-unlock.service.ts create mode 100644 microservices/achievement-service/src/achievement/services/achievement.service.ts create mode 100644 microservices/achievement-service/src/achievement/services/badge.service.ts create mode 100644 microservices/achievement-service/src/app.module.ts create mode 100644 microservices/achievement-service/src/energy/energy-regeneration.service.ts create mode 100644 microservices/achievement-service/src/energy/energy.controller.ts create mode 100644 microservices/achievement-service/src/energy/energy.entity.ts create mode 100644 microservices/achievement-service/src/energy/energy.module.ts create mode 100644 microservices/achievement-service/src/energy/energy.service.ts create mode 100644 microservices/achievement-service/src/main.ts create mode 100644 microservices/achievement-service/src/payment/payment.controller.ts create mode 100644 microservices/achievement-service/src/payment/payment.module.ts create mode 100644 microservices/achievement-service/src/payment/payment.service.ts create mode 100644 microservices/achievement-service/src/shop/shop-item.entity.ts create mode 100644 microservices/achievement-service/src/shop/shop.controller.ts create mode 100644 microservices/achievement-service/src/shop/shop.module.ts create mode 100644 microservices/achievement-service/src/shop/shop.service.ts create mode 100644 microservices/achievement-service/src/transaction/transaction.controller.ts create mode 100644 microservices/achievement-service/src/transaction/transaction.entity.ts create mode 100644 microservices/achievement-service/src/transaction/transaction.module.ts create mode 100644 microservices/achievement-service/src/transaction/transaction.service.ts create mode 100644 microservices/achievement-service/tsconfig.json diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6c87098 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,270 @@ +# AGENTS.md + +This file provides guidance to WARP (warp.dev) when working with code in this repository. + +## 1. Project overview & layout + +This repository contains a **NestJS monolith** for the core Quest puzzle platform plus a set of **supporting microservices** under `microservices/`. + +High-level pieces: +- **Core quest-service (monolith, root app)** + - Located in `src/` with standard NestJS structure (`app.module.ts`, feature modules, controllers, services). + - Implements puzzle management, game engine integration, puzzle editor, tournaments, and the main REST API. + - Backed by PostgreSQL via TypeORM with a rich schema documented in `DATABASE_SCHEMA.md` and `SYSTEM_OVERVIEW.md`. +- **Microservices (NestJS)** in `microservices/`: + - `quest-service/`: lightweight Nest starter for a scoped quest-related service. + - `social-service/`: friends, leaderboards, multiplayer rooms, WebSocket gateway (see `microservices/social-service/INDEX.md` and `QUICKSTART.md`). + - `notification-service/`: real-time notifications, BullMQ queues, templates (see its `IMPLEMENTATION_SUMMARY.md`). + - `game-session-service/`: game session lifecycle, state snapshots, replay hooks (see its `README.md`). + - `replay-service/`: full-featured replay recording, compression, analytics, privacy/sharing (see `microservices/replay-service/IMPLEMENTATION_SUMMARY.md` and `QUICKSTART.md`). + - `economy-service/`: energy/stamina, shop, transactions (see its `README.md`). + - `moderation-service/`: content moderation queue and review workflows. + - `api-gateway/`: Nest-based gateway fronting selected microservices. + - `shared/`: shared Nest module and utilities for events, gRPC, and service discovery; includes `proto/notification.proto` and `proto/social.proto`. +- **Infrastructure & tooling** (root): + - `docker-compose.yml`: PostgreSQL, Redis, RabbitMQ, quest-service container, selected microservices, and monitoring stack (Prometheus, Loki, Promtail, Jaeger, Grafana). + - `scripts/setup-database.sh` and `DATABASE_SCHEMA.md`: database bootstrapping and schema details. + - `MONITORING.md`: observability stack and troubleshooting runbooks. + - Domain-specific docs: `PUZZLE_ENGINE_STATUS.md`, `PUZZLE_EDITOR_IMPLEMENTATION_SUMMARY.md`, `TOURNAMENT_IMPLEMENTATION.md`, `SYSTEM_OVERVIEW.md`. + +When making non-trivial changes, prefer consulting the related domain doc first; they usually summarize entities, APIs, and acceptance criteria. + +## 2. Core commands (root quest-service app) + +All commands below assume you are at the repository root (`quest-service/`). + +### 2.1 Install & environment + +```bash +# Install dependencies +npm install + +# Copy environment template and edit for your DB +cp .env.example .env + +# (Optional) Start PostgreSQL via Docker +docker-compose up -d postgres +``` + +### 2.2 Database migrations & seeding + +TypeORM is wired via `ormconfig.ts`. + +```bash +# Run pending migrations against the main quest database +npm run migration:run + +# Revert last migration +npm run migration:revert + +# Generate a new migration (name will be appended) +npm run migration:generate src/migrations/ + +# Seed baseline and performance data (if needed) +npm run seed:run +npm run seed:perf + +# Full DB setup helper (uses migrations & scripts) +./scripts/setup-database.sh +``` + +### 2.3 Running the main API + +```bash +# Development (watch mode) +npm run start:dev + +# Production build & run +npm run build +npm run start:prod + +# Health & docs (once running) +curl http://localhost:3000/health +# Swagger/OpenAPI is typically exposed at +# http://localhost:3000/api +``` + +### 2.4 Linting, formatting, and type-checking + +```bash +# Lint and auto-fix +npm run lint + +# Lint without fixing +npm run lint:check + +# Format with Prettier +npm run format + +# TypeScript type-check only (no emit) +npm run type-check +``` + +### 2.5 Tests (root app) + +Jest is configured with multiple test configs under `test/`. + +```bash +# All unit-style tests ("*.spec.ts") +npm run test:unit + +# Integration tests ("*.integration.spec.ts") +npm run test:integration + +# End-to-end tests ("*.e2e.spec.ts" via test/jest-e2e.json) +npm run test:e2e + +# Smoke and performance suites +npm run test:smoke +npm run test:performance + +# Combined test run +npm run test:all + +# Coverage for unit tests +npm run test:cov + +# Run a single test file or pattern +npm run test:unit -- --testPathPattern= + +# Watch mode while developing +npm run test:watch +``` + +## 3. Docker & full-stack workflows + +### 3.1 Run the full stack locally (root-level compose) + +The root `docker-compose.yml` brings up PostgreSQL, Redis, RabbitMQ, quest-service, selected microservices, and monitoring. + +```bash +# Bring up the entire stack with fresh builds +cp .env.example .env # if not already done +docker-compose up --build + +# Subsequent runs without rebuilding +docker-compose up -d + +# Stop and remove containers +docker-compose down + +# View logs for all services +docker-compose logs -f +``` + +Key ports (default, see `docker-compose.yml` and related service readmes): +- Core quest-service API: `http://localhost:3000` +- Notification service: `http://localhost:3001` +- Social service: `http://localhost:3002` +- Replay service: `http://localhost:3007` +- PostgreSQL: `localhost:5432` +- Redis: `localhost:6379` +- RabbitMQ (AMQP / UI): `5672` / `15672` +- Grafana: `http://localhost:3003` +- Prometheus: `http://localhost:9090` +- Jaeger: `http://localhost:16686` +- Loki: `3100` (queried via Grafana) + +### 3.2 Microservice-specific workflows + +Each Nest-based microservice under `microservices/` follows a consistent pattern: + +```bash +cd microservices/ + +# Install dependencies +npm install + +# Run in development +npm run start:dev + +# Run tests +npm test + +# Lint / format / type-check (when scripts exist) +npm run lint +npm run format +npm run type-check +``` + +Service-specific docs to consult before non-trivial edits: +- `microservices/social-service/INDEX.md` and `QUICKSTART.md` for friends, leaderboards, rooms, WebSocket events, and DB migrations (`npm run migration:run`). +- `microservices/notification-service/IMPLEMENTATION_SUMMARY.md` for notification channels, BullMQ queues, and migration workflow (`npm run migration:run`). +- `microservices/replay-service/IMPLEMENTATION_SUMMARY.md` and `QUICKSTART.md` for replay storage, compression, analytics, and its dedicated Docker stack. +- `microservices/game-session-service/README.md` for session, snapshot, and replay-related APIs. +- `microservices/economy-service/README.md` for energy, shop, transactions, and payment providers. + +## 4. Architecture notes (core quest-service) + +### 4.1 Core domains & modules + +The monolith is organized by domain-specific Nest modules (see `SYSTEM_OVERVIEW.md`, `PUZZLE_ENGINE_STATUS.md`, `PUZZLE_EDITOR_IMPLEMENTATION_SUMMARY.md`, `TOURNAMENT_IMPLEMENTATION.md`): +- **Puzzle Management & Game Engine** + - CRUD and analytics for puzzles, including search, tagging, difficulty, and bulk operations. + - A dedicated puzzle engine supports multiple puzzle types (logic grid, sequence, spatial) with difficulty scaling, hints, scoring, and achievements. +- **Puzzle Editor & Creation Tools** + - Extensive editor module (`src/puzzle-editor/...`) for drag-and-drop puzzle composition, validation, preview/simulation, versioning, templates, batch operations, import/export, and community submissions. + - Editor endpoints produce published puzzle definitions that the game engine consumes. +- **Game Sessions & Progress** + - Entities and services for tracking per-user puzzle progress, sessions, and aggregated user stats. + - Integration with achievements and leaderboards. +- **Tournaments** + - Tournament module (`src/tournaments/...`) implements multiple bracket types (single/double elimination, round-robin, Swiss), registration, match scheduling, prize distribution, spectators, and stats. +- **Cross-cutting infrastructure** + - Auth (JWT-based), throttling, health checks, metrics exposure, structured logging, and Sentry integration. + - Database access via TypeORM with a large, well-indexed schema (`DATABASE_SCHEMA.md`). + +When modifying any of these domains, always check their dedicated `*_IMPLEMENTATION*.md` or status docs for current behavior, file layout, and acceptance criteria. + +### 4.2 Database strategy + +See `DATABASE_STRATEGY.md` and `DATABASE_SCHEMA.md` for full details; key points: +- **Database-per-service pattern**: each microservice owns its own logical database (e.g., `quest_db`, `notification_db`, `social_db`), even if they share a PostgreSQL instance in development. +- **No cross-database querying**: services communicate via HTTP/gRPC or events, not by reading each other’s tables. +- **Read/write split support** in configuration (e.g., `DB_HOST` vs `DB_READ_HOST`) for future read replicas. +- Heavy use of JSONB, composite and partial indexes, and constraints/checks to enforce invariants (e.g., achievement unlock logic, progress consistency). + +## 5. Inter-service communication & integration + +The microservice ecosystem uses both asynchronous events and synchronous RPC; see `microservices/INTER_SERVICE_COMMUNICATION.md` for details. + +Key aspects: +- **Message brokers** + - RabbitMQ: topic exchanges, durable queues, dead-letter queues, exponential backoff retries. + - Redis/BullMQ: job queues with prioritization, scheduled jobs, dead-letter queues. +- **Event-driven model** + - Domain events such as `UserRegisteredEvent`, `PuzzleCompletedEvent`, `AchievementUnlockedEvent`, `FriendRequestSentEvent`, `TournamentStartedEvent`, `NotificationCreatedEvent`. + - Shared event contracts and handler interfaces live in `microservices/shared`. +- **gRPC** + - gRPC clients generated from `microservices/shared/proto/*.proto` for synchronous calls to services like social and notification. + - A shared `GrpcClientService` abstraction handles client lookup, timeouts, and error handling. +- **Service discovery & health** + - Services register themselves in a service registry abstraction and expose health endpoints (`/health`, `/health/ready`, `/health/live`). + - Discovery helpers resolve service URLs and choose healthy instances. + +When introducing new cross-service flows, prefer modeling them as events that reuse the existing event bus and gRPC abstractions instead of hand-rolling new communication mechanisms. + +## 6. Observability & debugging + +The monitoring stack is documented in `MONITORING.md` and wired through `docker-compose.yml`. + +- **Metrics** + - Each service exposes Prometheus metrics (commonly via `/metrics`); Prometheus scrapes on a fixed interval. + - The root quest-service also exposes health endpoints under `/health` and metrics under a dedicated path used by Prometheus. +- **Logs** + - Docker containers log in JSON format; Promtail ships logs to Loki. + - Query logs via Grafana’s Explore view with the Loki datasource. +- **Tracing** + - Jaeger is available at `http://localhost:16686` for distributed tracing when OpenTelemetry/Jaeger SDKs are enabled in a service. +- **Dashboards** + - Grafana (admin/admin by default) aggregates metrics, logs, and traces into dashboards. + +For production-like debugging, prefer using metrics + traces (to locate issues) and then drill into service logs for detailed context. + +## 7. Recommended entry points for new work + +For future agents starting a new task: +- **Understand the system**: skim `SYSTEM_OVERVIEW.md`, then the specific domain doc (`PUZZLE_ENGINE_STATUS.md`, `PUZZLE_EDITOR_IMPLEMENTATION_SUMMARY.md`, `TOURNAMENT_IMPLEMENTATION.md`, `DATABASE_SCHEMA.md`) relevant to your change. +- **If the task involves microservices**: read `microservices/INTER_SERVICE_COMMUNICATION.md`, then the relevant service’s README/QUICKSTART/IMPLEMENTATION_SUMMARY. +- **When modifying APIs**: update DTOs, entities, and Swagger decorators together, and verify with the appropriate Jest suite plus e2e tests. +- **When touching persistence**: update entities and migrations in tandem, and run `npm run migration:run` (or the corresponding microservice migration scripts) against a local/dev database. \ No newline at end of file diff --git a/dist/main.js b/dist/main.js index 069cddf..aaffd5c 100644 --- a/dist/main.js +++ b/dist/main.js @@ -1,3 +1,19119 @@ -git add . -git commit -m "Fix TypeScript build errors and ignore dist folder" -git push \ No newline at end of file +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "./src/achievements/entities/achievement.entity.ts": +/*!*********************************************************!*\ + !*** ./src/achievements/entities/achievement.entity.ts ***! + \*********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Achievement = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_achievement_entity_1 = __webpack_require__(/*! ./user-achievement.entity */ "./src/achievements/entities/user-achievement.entity.ts"); +const achievement_condition_types_1 = __webpack_require__(/*! ../types/achievement-condition.types */ "./src/achievements/types/achievement-condition.types.ts"); +let Achievement = class Achievement { +}; +exports.Achievement = Achievement; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Achievement.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100 }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Achievement.prototype, "name", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text' }), + __metadata("design:type", String) +], Achievement.prototype, "description", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Achievement.prototype, "category", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'common' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Achievement.prototype, "rarity", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 10 }), + __metadata("design:type", Number) +], Achievement.prototype, "points", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 255, nullable: true }), + __metadata("design:type", String) +], Achievement.prototype, "iconUrl", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 255, nullable: true }), + __metadata("design:type", String) +], Achievement.prototype, "badgeUrl", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", Boolean) +], Achievement.prototype, "isActive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], Achievement.prototype, "isSecret", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], Achievement.prototype, "unlockedCount", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), + __metadata("design:type", Number) +], Achievement.prototype, "unlockRate", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb' }), + __metadata("design:type", typeof (_a = typeof achievement_condition_types_1.AchievementConditionGroup !== "undefined" && achievement_condition_types_1.AchievementConditionGroup) === "function" ? _a : Object) +], Achievement.prototype, "unlockConditions", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'simple-array', default: [] }), + __metadata("design:type", Array) +], Achievement.prototype, "prerequisites", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', nullable: true }), + __metadata("design:type", Object) +], Achievement.prototype, "progression", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', nullable: true }), + __metadata("design:type", Object) +], Achievement.prototype, "timeConstraints", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Achievement.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], Achievement.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], Achievement.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.DeleteDateColumn)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], Achievement.prototype, "deletedAt", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => user_achievement_entity_1.UserAchievement, (userAchievement) => userAchievement.achievement), + __metadata("design:type", Array) +], Achievement.prototype, "userAchievements", void 0); +exports.Achievement = Achievement = __decorate([ + (0, typeorm_1.Entity)('achievements'), + (0, typeorm_1.Index)(['category', 'isActive']), + (0, typeorm_1.Index)(['rarity']) +], Achievement); + + +/***/ }), + +/***/ "./src/achievements/entities/user-achievement.entity.ts": +/*!**************************************************************!*\ + !*** ./src/achievements/entities/user-achievement.entity.ts ***! + \**************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UserAchievement = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +const achievement_entity_1 = __webpack_require__(/*! ./achievement.entity */ "./src/achievements/entities/achievement.entity.ts"); +let UserAchievement = class UserAchievement { +}; +exports.UserAchievement = UserAchievement; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], UserAchievement.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], UserAchievement.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], UserAchievement.prototype, "achievementId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserAchievement.prototype, "progress", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 100 }), + __metadata("design:type", Number) +], UserAchievement.prototype, "progressTotal", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + (0, typeorm_1.Index)(), + __metadata("design:type", Boolean) +], UserAchievement.prototype, "isUnlocked", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], UserAchievement.prototype, "isNotified", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], UserAchievement.prototype, "isViewed", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], UserAchievement.prototype, "unlockedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], UserAchievement.prototype, "notifiedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], UserAchievement.prototype, "viewedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], UserAchievement.prototype, "unlockContext", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], UserAchievement.prototype, "progressDetails", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], UserAchievement.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => user_entity_1.User, (user) => user.achievements, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'userId' }), + __metadata("design:type", typeof (_e = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _e : Object) +], UserAchievement.prototype, "user", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => achievement_entity_1.Achievement, (achievement) => achievement.userAchievements, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'achievementId' }), + __metadata("design:type", typeof (_f = typeof achievement_entity_1.Achievement !== "undefined" && achievement_entity_1.Achievement) === "function" ? _f : Object) +], UserAchievement.prototype, "achievement", void 0); +exports.UserAchievement = UserAchievement = __decorate([ + (0, typeorm_1.Entity)('user_achievements'), + (0, typeorm_1.Index)(['userId', 'achievementId'], { unique: true }), + (0, typeorm_1.Index)(['userId', 'unlockedAt']), + (0, typeorm_1.Index)(['achievementId', 'unlockedAt']) +], UserAchievement); + + +/***/ }), + +/***/ "./src/achievements/types/achievement-condition.types.ts": +/*!***************************************************************!*\ + !*** ./src/achievements/types/achievement-condition.types.ts ***! + \***************************************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); + + +/***/ }), + +/***/ "./src/app.controller.ts": +/*!*******************************!*\ + !*** ./src/app.controller.ts ***! + \*******************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AppController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const app_service_1 = __webpack_require__(/*! ./app.service */ "./src/app.service.ts"); +let AppController = class AppController { + constructor(appService) { + this.appService = appService; + } + getHello() { + return this.appService.getHello(); + } + getAppInfo() { + return this.appService.getAppInfo(); + } +}; +exports.AppController = AppController; +__decorate([ + (0, common_1.Get)(), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", Object) +], AppController.prototype, "getHello", null); +__decorate([ + (0, common_1.Get)('info'), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", void 0) +], AppController.prototype, "getAppInfo", null); +exports.AppController = AppController = __decorate([ + (0, common_1.Controller)(), + __metadata("design:paramtypes", [typeof (_a = typeof app_service_1.AppService !== "undefined" && app_service_1.AppService) === "function" ? _a : Object]) +], AppController); + + +/***/ }), + +/***/ "./src/app.module.ts": +/*!***************************!*\ + !*** ./src/app.module.ts ***! + \***************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AppModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const throttler_1 = __webpack_require__(/*! @nestjs/throttler */ "@nestjs/throttler"); +const core_1 = __webpack_require__(/*! @nestjs/core */ "@nestjs/core"); +const nest_winston_1 = __webpack_require__(/*! nest-winston */ "nest-winston"); +const app_controller_1 = __webpack_require__(/*! ./app.controller */ "./src/app.controller.ts"); +const app_service_1 = __webpack_require__(/*! ./app.service */ "./src/app.service.ts"); +const env_validation_1 = __webpack_require__(/*! ./config/env.validation */ "./src/config/env.validation.ts"); +const app_config_1 = __importDefault(__webpack_require__(/*! ./config/app.config */ "./src/config/app.config.ts")); +const logger_config_1 = __webpack_require__(/*! ./config/logger.config */ "./src/config/logger.config.ts"); +const users_module_1 = __webpack_require__(/*! ./users/users.module */ "./src/users/users.module.ts"); +const puzzles_module_1 = __webpack_require__(/*! ./puzzles/puzzles.module */ "./src/puzzles/puzzles.module.ts"); +const health_module_1 = __webpack_require__(/*! ./health/health.module */ "./src/health/health.module.ts"); +const hints_module_1 = __webpack_require__(/*! ./hints/hints.module */ "./src/hints/hints.module.ts"); +const notifications_module_1 = __webpack_require__(/*! ./notifications/notifications.module */ "./src/notifications/notifications.module.ts"); +const wallet_module_1 = __webpack_require__(/*! ./wallet/wallet.module */ "./src/wallet/wallet.module.ts"); +const difficulty_scaling_module_1 = __webpack_require__(/*! ./difficulty-scaling/difficulty-scaling.module */ "./src/difficulty-scaling/difficulty-scaling.module.ts"); +const tournaments_module_1 = __webpack_require__(/*! ./tournaments/tournaments.module */ "./src/tournaments/tournaments.module.ts"); +const rabbitmq_module_1 = __webpack_require__(/*! ./rabbitmq/rabbitmq.module */ "./src/rabbitmq/rabbitmq.module.ts"); +const tutorial_module_1 = __webpack_require__(/*! ./tutorial/tutorial.module */ "./src/tutorial/tutorial.module.ts"); +const referrals_module_1 = __webpack_require__(/*! ./referrals/referrals.module */ "./src/referrals/referrals.module.ts"); +const save_game_module_1 = __webpack_require__(/*! ./save-game/save-game.module */ "./src/save-game/save-game.module.ts"); +const soroban_module_1 = __webpack_require__(/*! ./soroban/soroban.module */ "./src/soroban/soroban.module.ts"); +const nft_module_1 = __webpack_require__(/*! ./nft/nft.module */ "./src/nft/nft.module.ts"); +const rewards_module_1 = __webpack_require__(/*! ./rewards/rewards.module */ "./src/rewards/rewards.module.ts"); +const puzzle_module_1 = __webpack_require__(/*! ./puzzle/puzzle.module */ "./src/puzzle/puzzle.module.ts"); +let AppModule = class AppModule { +}; +exports.AppModule = AppModule; +exports.AppModule = AppModule = __decorate([ + (0, common_1.Module)({ + imports: [ + config_1.ConfigModule.forRoot({ + isGlobal: true, + validate: env_validation_1.validateEnvironment, + load: [app_config_1.default], + envFilePath: ['.env.local', '.env'], + }), + rabbitmq_module_1.RabbitMQModule, + nest_winston_1.WinstonModule.forRootAsync({ + useFactory: (configService) => (0, logger_config_1.createLoggerConfig)(configService), + inject: [config_1.ConfigService], + }), + throttler_1.ThrottlerModule.forRootAsync({ + useFactory: (configService) => [ + { + ttl: configService.get('app.throttle.ttl') || 60000, + limit: configService.get('app.throttle.limit') || 100, + }, + ], + inject: [config_1.ConfigService], + }), + users_module_1.UsersModule, + puzzles_module_1.PuzzlesModule, + notifications_module_1.NotificationsModule, + wallet_module_1.WalletModule, + health_module_1.HealthModule, + hints_module_1.HintsModule, + difficulty_scaling_module_1.DifficultyScalingModule, + tournaments_module_1.TournamentsModule, + tutorial_module_1.TutorialModule, + referrals_module_1.ReferralsModule, + save_game_module_1.SaveGameModule, + soroban_module_1.SorobanModule, + nft_module_1.NFTModule, + rewards_module_1.RewardsModule, + puzzle_module_1.PuzzleModule, + ], + controllers: [app_controller_1.AppController], + providers: [ + app_service_1.AppService, + { + provide: core_1.APP_GUARD, + useClass: throttler_1.ThrottlerGuard, + }, + ], + }) +], AppModule); + + +/***/ }), + +/***/ "./src/app.service.ts": +/*!****************************!*\ + !*** ./src/app.service.ts ***! + \****************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AppService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +let AppService = class AppService { + constructor(configService) { + this.configService = configService; + } + getHello() { + return { + message: 'Welcome to LogiQuest Backend API! 🧩', + timestamp: new Date().toISOString(), + }; + } + getAppInfo() { + return { + name: 'LogiQuest Backend', + version: this.configService.get('npm_package_version', '1.0.0'), + environment: this.configService.get('NODE_ENV', 'development'), + apiPrefix: this.configService.get('API_PREFIX', 'api/v1'), + description: 'A puzzle-solving game backend built with NestJS', + }; + } +}; +exports.AppService = AppService; +exports.AppService = AppService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, common_1.Inject)(config_1.ConfigService)), + __metadata("design:paramtypes", [Object]) +], AppService); + + +/***/ }), + +/***/ "./src/auth/guards/jwt-auth.guard.ts": +/*!*******************************************!*\ + !*** ./src/auth/guards/jwt-auth.guard.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.JwtAuthGuard = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const passport_1 = __webpack_require__(/*! @nestjs/passport */ "@nestjs/passport"); +let JwtAuthGuard = class JwtAuthGuard extends (0, passport_1.AuthGuard)("jwt") { +}; +exports.JwtAuthGuard = JwtAuthGuard; +exports.JwtAuthGuard = JwtAuthGuard = __decorate([ + (0, common_1.Injectable)() +], JwtAuthGuard); + + +/***/ }), + +/***/ "./src/common/exceptions/http-exception.filter.ts": +/*!********************************************************!*\ + !*** ./src/common/exceptions/http-exception.filter.ts ***! + \********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AllExceptionsFilter = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const Sentry = __importStar(__webpack_require__(/*! @sentry/node */ "@sentry/node")); +let AllExceptionsFilter = class AllExceptionsFilter { + catch(exception, host) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + let status = common_1.HttpStatus.INTERNAL_SERVER_ERROR; + let message = 'An unexpected error occurred.'; + let errorCode = 'INTERNAL_ERROR'; + let errors = undefined; + if (exception instanceof common_1.HttpException) { + const httpEx = exception; + status = httpEx.getStatus(); + const res = httpEx.getResponse(); + if (typeof res === 'string') { + message = res; + } + else if (typeof res === 'object' && res !== null) { + const r = res; + message = r.message || message; + errorCode = r.errorCode || errorCode; + errors = r.errors; + } + if (status >= 500) { + Sentry.captureException(exception); + } + } + else if (exception instanceof Error) { + message = exception.message; + Sentry.captureException(exception); + } + if (status === common_1.HttpStatus.NOT_FOUND) { + message = 'The requested resource was not found.'; + errorCode = 'NOT_FOUND'; + } + else if (status === common_1.HttpStatus.UNAUTHORIZED) { + message = 'You are not authorized to access this resource.'; + errorCode = 'UNAUTHORIZED'; + } + else if (status === common_1.HttpStatus.FORBIDDEN) { + message = 'You do not have permission to perform this action.'; + errorCode = 'FORBIDDEN'; + } + else if (status === common_1.HttpStatus.BAD_REQUEST) { + message = 'The request was invalid or cannot be served.'; + errorCode = 'BAD_REQUEST'; + } + response.status(status).json({ + statusCode: status, + timestamp: new Date().toISOString(), + path: request.url, + message, + errorCode, + errors, + }); + } +}; +exports.AllExceptionsFilter = AllExceptionsFilter; +exports.AllExceptionsFilter = AllExceptionsFilter = __decorate([ + (0, common_1.Catch)() +], AllExceptionsFilter); + + +/***/ }), + +/***/ "./src/common/interceptors/sanitize.interceptor.ts": +/*!*********************************************************!*\ + !*** ./src/common/interceptors/sanitize.interceptor.ts ***! + \*********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SanitizeInterceptor = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const operators_1 = __webpack_require__(/*! rxjs/operators */ "rxjs/operators"); +const xss_1 = __importDefault(__webpack_require__(/*! xss */ "xss")); +function sanitizeObject(obj) { + if (typeof obj === 'string') { + return (0, xss_1.default)(obj); + } + else if (Array.isArray(obj)) { + return obj.map(sanitizeObject); + } + else if (typeof obj === 'object' && obj !== null) { + const sanitized = {}; + for (const key of Object.keys(obj)) { + sanitized[key] = sanitizeObject(obj[key]); + } + return sanitized; + } + return obj; +} +let SanitizeInterceptor = class SanitizeInterceptor { + intercept(context, next) { + const request = context.switchToHttp().getRequest(); + if (request.body) { + request.body = sanitizeObject(request.body); + } + if (request.query) { + request.query = sanitizeObject(request.query); + } + if (request.params) { + request.params = sanitizeObject(request.params); + } + return next.handle().pipe((0, operators_1.map)(data => sanitizeObject(data))); + } +}; +exports.SanitizeInterceptor = SanitizeInterceptor; +exports.SanitizeInterceptor = SanitizeInterceptor = __decorate([ + (0, common_1.Injectable)() +], SanitizeInterceptor); + + +/***/ }), + +/***/ "./src/common/validators/file-upload.validator.ts": +/*!********************************************************!*\ + !*** ./src/common/validators/file-upload.validator.ts ***! + \********************************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fileFilter = fileFilter; +exports.fileSizeLimit = fileSizeLimit; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const path_1 = __webpack_require__(/*! path */ "path"); +function fileFilter(allowedTypes, allowedMimeTypes) { + return (req, file, callback) => { + const ext = (0, path_1.extname)(file.originalname).toLowerCase(); + const mime = file.mimetype; + const extAllowed = allowedTypes.includes(ext); + const mimeAllowed = allowedMimeTypes ? allowedMimeTypes.includes(mime) : true; + if (!extAllowed || !mimeAllowed) { + return callback(new common_1.BadRequestException(`File type not allowed. Allowed extensions: ${allowedTypes.join(', ')}${allowedMimeTypes ? '; allowed MIME types: ' + allowedMimeTypes.join(', ') : ''}`), false); + } + callback(null, true); + }; +} +function fileSizeLimit(maxSize) { + return (req, file, callback) => { + if (file.size > maxSize) { + return callback(new common_1.BadRequestException(`File size exceeds ${maxSize} bytes.`), false); + } + callback(null, true); + }; +} + + +/***/ }), + +/***/ "./src/config/app.config.ts": +/*!**********************************!*\ + !*** ./src/config/app.config.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +exports["default"] = (0, config_1.registerAs)('app', () => ({ + name: 'LogiQuest Backend', + version: process.env.npm_package_version || '1.0.0', + port: parseInt(process.env.PORT || '3000', 10), + apiPrefix: process.env.API_PREFIX || 'api/v1', + cors: { + origin: process.env.CORS_ORIGIN || 'http://localhost:3000', + credentials: true, + }, + throttle: { + ttl: parseInt(process.env.THROTTLE_TTL || '60000', 10), + limit: parseInt(process.env.THROTTLE_LIMIT || '100', 10), + }, +})); + + +/***/ }), + +/***/ "./src/config/database-service.ts": +/*!****************************************!*\ + !*** ./src/config/database-service.ts ***! + \****************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DatabaseService = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const database_config_1 = __webpack_require__(/*! ../config/database.config */ "./src/config/database.config.ts"); +class DatabaseService { + constructor() { + this.dataSource = null; + this.healthCheckInterval = null; + this.lastHealthCheck = null; + } + static getInstance() { + if (!DatabaseService.instance) { + DatabaseService.instance = new DatabaseService(); + } + return DatabaseService.instance; + } + getDataSourceInstance() { + if (!this.dataSource) { + const configService = database_config_1.DatabaseConfigService.getInstance(); + this.dataSource = new typeorm_1.DataSource(configService.getTypeOrmConfig()); + } + return this.dataSource; + } + async initialize() { + try { + console.log('Initializing database connection...'); + const dataSource = this.getDataSourceInstance(); + if (!dataSource.isInitialized) { + await dataSource.initialize(); + } + console.log('Database connection initialized successfully'); + this.startHealthChecks(); + if (process.env.NODE_ENV === 'production') { + await this.runMigrations(); + } + } + catch (error) { + console.error('Failed to initialize database:', error); + throw error; + } + } + async runMigrations() { + try { + console.log('Running database migrations...'); + const dataSource = this.getDataSourceInstance(); + await dataSource.runMigrations(); + console.log('Migrations completed successfully'); + } + catch (error) { + console.error('Migration failed:', error); + throw error; + } + } + async revertMigration() { + try { + console.log('Reverting last migration...'); + const dataSource = this.getDataSourceInstance(); + await dataSource.undoLastMigration(); + console.log('Migration reverted successfully'); + } + catch (error) { + console.error('Migration revert failed:', error); + throw error; + } + } + async checkHealth() { + const startTime = Date.now(); + try { + const dataSource = this.getDataSourceInstance(); + const queryRunner = dataSource.createQueryRunner(); + await queryRunner.connect(); + const result = await queryRunner.query('SELECT 1 as test'); + const stats = await this.getConnectionStats(queryRunner); + await queryRunner.release(); + const latency = Date.now() - startTime; + this.lastHealthCheck = { + status: 'healthy', + connection: true, + latency, + activeConnections: stats.activeConnections, + timestamp: new Date(), + }; + return this.lastHealthCheck; + } + catch (error) { + this.lastHealthCheck = { + status: 'unhealthy', + connection: false, + latency: Date.now() - startTime, + activeConnections: 0, + timestamp: new Date(), + error: error instanceof Error ? error.message : 'Unknown error', + }; + return this.lastHealthCheck; + } + } + async getConnectionStats(queryRunner) { + const dataSource = this.getDataSourceInstance(); + const runner = queryRunner || dataSource.createQueryRunner(); + try { + if (!queryRunner) + await runner.connect(); + const result = await runner.query(` + SELECT + count(*) as total_connections, + count(*) FILTER (WHERE state = 'active') as active_connections, + count(*) FILTER (WHERE state = 'idle') as idle_connections, + count(*) FILTER (WHERE wait_event IS NOT NULL) as waiting_connections + FROM pg_stat_activity + WHERE datname = current_database() + `); + return { + totalConnections: parseInt(result[0].total_connections), + activeConnections: parseInt(result[0].active_connections), + idleConnections: parseInt(result[0].idle_connections), + waitingConnections: parseInt(result[0].waiting_connections), + }; + } + finally { + if (!queryRunner) + await runner.release(); + } + } + getLastHealthCheck() { + return this.lastHealthCheck; + } + startHealthChecks() { + this.healthCheckInterval = setInterval(async () => { + await this.checkHealth(); + }, 30000); + } + async retryConnection(maxRetries = 5, delay = 1000) { + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + const dataSource = this.getDataSourceInstance(); + if (!dataSource.isInitialized) { + await dataSource.initialize(); + } + await this.checkHealth(); + if (this.lastHealthCheck?.status === 'healthy') { + console.log(`Connection retry successful on attempt ${attempt}`); + return; + } + } + catch (error) { + console.log(`Connection attempt ${attempt} failed:`, error); + if (attempt === maxRetries) { + throw new Error(`Failed to establish database connection after ${maxRetries} attempts`); + } + await new Promise((resolve) => setTimeout(resolve, delay * attempt)); + } + } + } + async close() { + if (this.healthCheckInterval) { + clearInterval(this.healthCheckInterval); + this.healthCheckInterval = null; + } + const dataSource = this.getDataSourceInstance(); + if (dataSource.isInitialized) { + await dataSource.destroy(); + console.log('Database connection closed'); + } + } + getDataSource() { + return this.getDataSourceInstance(); + } +} +exports.DatabaseService = DatabaseService; + + +/***/ }), + +/***/ "./src/config/database.config.ts": +/*!***************************************!*\ + !*** ./src/config/database.config.ts ***! + \***************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DatabaseConfigService = void 0; +const dotenv_1 = __webpack_require__(/*! dotenv */ "dotenv"); +const path = __importStar(__webpack_require__(/*! path */ "path")); +(0, dotenv_1.config)(); +class DatabaseConfigService { + constructor() { } + static getInstance() { + if (!DatabaseConfigService.instance) { + DatabaseConfigService.instance = new DatabaseConfigService(); + } + return DatabaseConfigService.instance; + } + getConfig() { + const isTest = process.env.NODE_ENV === 'test'; + return { + host: isTest + ? process.env.TEST_DB_HOST || 'localhost' + : process.env.DB_HOST || 'localhost', + port: isTest + ? parseInt(process.env.TEST_DB_PORT || '5433') + : parseInt(process.env.DB_PORT || '5432'), + username: isTest + ? process.env.TEST_DB_USER || 'postgres' + : process.env.DB_USER || 'postgres', + password: isTest + ? process.env.TEST_DB_PASSWORD || 'password' + : process.env.DB_PASSWORD || 'password', + database: isTest + ? process.env.TEST_DB_NAME || 'myapp_test' + : process.env.DB_NAME || 'myapp', + maxConnections: parseInt(process.env.DB_MAX_CONNECTIONS || '20'), + minConnections: parseInt(process.env.DB_MIN_CONNECTIONS || '5'), + acquireTimeout: parseInt(process.env.DB_ACQUIRE_TIMEOUT || '20000'), + timeout: parseInt(process.env.DB_CONNECTION_TIMEOUT || '20000'), + idleTimeout: parseInt(process.env.DB_IDLE_TIMEOUT || '30000'), + logging: process.env.DB_LOGGING === 'true', + logLevel: process.env.LOG_LEVEL || 'info', + }; + } + getTypeOrmConfig() { + const config = this.getConfig(); + return { + type: 'postgres', + host: config.host, + port: config.port, + username: config.username, + password: config.password, + database: config.database, + entities: [path.join(__dirname, '../entities/*.{ts,js}')], + migrations: [path.join(__dirname, '../migrations/*.{ts,js}')], + subscribers: [path.join(__dirname, '../subscribers/*.{ts,js}')], + synchronize: false, + logging: config.logging + ? ['query', 'error', 'schema', 'warn', 'info', 'log'] + : false, + logger: 'advanced-console', + maxQueryExecutionTime: 5000, + poolSize: config.maxConnections, + extra: { + connectionTimeoutMillis: config.timeout, + idleTimeoutMillis: config.idleTimeout, + max: config.maxConnections, + min: config.minConnections, + acquireTimeoutMillis: config.acquireTimeout, + createTimeoutMillis: 8000, + destroyTimeoutMillis: 5000, + reapIntervalMillis: 1000, + createRetryIntervalMillis: 200, + }, + cache: { + type: 'database', + tableName: 'query_result_cache', + duration: 30000, + }, + }; + } +} +exports.DatabaseConfigService = DatabaseConfigService; + + +/***/ }), + +/***/ "./src/config/env.validation.ts": +/*!**************************************!*\ + !*** ./src/config/env.validation.ts ***! + \**************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.EnvironmentVariables = exports.Environment = void 0; +exports.validateEnvironment = validateEnvironment; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +var Environment; +(function (Environment) { + Environment["Development"] = "development"; + Environment["Production"] = "production"; + Environment["Test"] = "test"; +})(Environment || (exports.Environment = Environment = {})); +class EnvironmentVariables { + constructor() { + this.NODE_ENV = Environment.Development; + this.PORT = 3000; + this.API_PREFIX = 'api/v1'; + this.CORS_ORIGIN = 'http://localhost:3000'; + this.THROTTLE_TTL = 60000; + this.THROTTLE_LIMIT = 100; + this.LOG_LEVEL = 'info'; + this.JWT_EXPIRES_IN = '1d'; + } +} +exports.EnvironmentVariables = EnvironmentVariables; +__decorate([ + (0, class_validator_1.IsEnum)(Environment), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], EnvironmentVariables.prototype, "NODE_ENV", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.IsOptional)(), + (0, class_transformer_1.Transform)(({ value }) => parseInt(value, 10)), + __metadata("design:type", Number) +], EnvironmentVariables.prototype, "PORT", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], EnvironmentVariables.prototype, "API_PREFIX", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], EnvironmentVariables.prototype, "CORS_ORIGIN", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.IsOptional)(), + (0, class_transformer_1.Transform)(({ value }) => parseInt(value, 10)), + __metadata("design:type", Number) +], EnvironmentVariables.prototype, "THROTTLE_TTL", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.IsOptional)(), + (0, class_transformer_1.Transform)(({ value }) => parseInt(value, 10)), + __metadata("design:type", Number) +], EnvironmentVariables.prototype, "THROTTLE_LIMIT", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], EnvironmentVariables.prototype, "LOG_LEVEL", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], EnvironmentVariables.prototype, "DATABASE_URL", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], EnvironmentVariables.prototype, "JWT_SECRET", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], EnvironmentVariables.prototype, "JWT_EXPIRES_IN", void 0); +function validateEnvironment(config) { + const validatedConfig = (0, class_transformer_1.plainToInstance)(EnvironmentVariables, config, { + enableImplicitConversion: true, + }); + const errors = (0, class_validator_1.validateSync)(validatedConfig, { + skipMissingProperties: false, + }); + if (errors.length > 0) { + throw new Error(errors.toString()); + } + return validatedConfig; +} + + +/***/ }), + +/***/ "./src/config/logger.config.ts": +/*!*************************************!*\ + !*** ./src/config/logger.config.ts ***! + \*************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createLoggerConfig = void 0; +const winston = __importStar(__webpack_require__(/*! winston */ "winston")); +const env_validation_1 = __webpack_require__(/*! ./env.validation */ "./src/config/env.validation.ts"); +const createLoggerConfig = (configService) => { + const env = configService.get('NODE_ENV', { infer: true }); + const logLevel = configService.get('LOG_LEVEL', { infer: true }); + const isDevelopment = env === env_validation_1.Environment.Development; + return { + level: logLevel, + format: winston.format.combine(winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.splat(), winston.format.json(), ...(isDevelopment + ? [ + winston.format.colorize(), + winston.format.simple(), + winston.format.printf(({ timestamp, level, message, context, stack }) => { + const contextStr = context ? `[${context}]` : ''; + const stackStr = stack ? `\n${stack}` : ''; + return `${timestamp} [${level}] ${contextStr} ${message}${stackStr}`; + }), + ] + : [])), + transports: [ + new winston.transports.Console({ + silent: env === env_validation_1.Environment.Test, + }), + ...(env === env_validation_1.Environment.Production + ? [ + new winston.transports.File({ + filename: 'logs/error.log', + level: 'error', + }), + new winston.transports.File({ + filename: 'logs/combined.log', + }), + ] + : []), + ], + }; +}; +exports.createLoggerConfig = createLoggerConfig; + + +/***/ }), + +/***/ "./src/difficulty-scaling/difficulty-scaling.module.ts": +/*!*************************************************************!*\ + !*** ./src/difficulty-scaling/difficulty-scaling.module.ts ***! + \*************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DifficultyScalingModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const difficulty_scaling_service_1 = __webpack_require__(/*! ./difficulty-scaling.service */ "./src/difficulty-scaling/difficulty-scaling.service.ts"); +const player_skill_service_1 = __webpack_require__(/*! ./player-skill.service */ "./src/difficulty-scaling/player-skill.service.ts"); +const puzzle_difficulty_service_1 = __webpack_require__(/*! ./puzzle-difficulty.service */ "./src/difficulty-scaling/puzzle-difficulty.service.ts"); +let DifficultyScalingModule = class DifficultyScalingModule { +}; +exports.DifficultyScalingModule = DifficultyScalingModule; +exports.DifficultyScalingModule = DifficultyScalingModule = __decorate([ + (0, common_1.Module)({ + providers: [difficulty_scaling_service_1.DifficultyScalingService, player_skill_service_1.PlayerSkillService, puzzle_difficulty_service_1.PuzzleDifficultyService], + exports: [difficulty_scaling_service_1.DifficultyScalingService, player_skill_service_1.PlayerSkillService, puzzle_difficulty_service_1.PuzzleDifficultyService], + }) +], DifficultyScalingModule); + + +/***/ }), + +/***/ "./src/difficulty-scaling/difficulty-scaling.service.ts": +/*!**************************************************************!*\ + !*** ./src/difficulty-scaling/difficulty-scaling.service.ts ***! + \**************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DifficultyScalingService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const player_skill_service_1 = __webpack_require__(/*! ./player-skill.service */ "./src/difficulty-scaling/player-skill.service.ts"); +const puzzle_difficulty_service_1 = __webpack_require__(/*! ./puzzle-difficulty.service */ "./src/difficulty-scaling/puzzle-difficulty.service.ts"); +let DifficultyScalingService = class DifficultyScalingService { + constructor(playerSkillService, puzzleDifficultyService) { + this.playerSkillService = playerSkillService; + this.puzzleDifficultyService = puzzleDifficultyService; + } + async getRecommendedDifficulty(playerId) { + const skill = await this.playerSkillService.getPlayerSkill(playerId); + return Math.min(Math.max(skill + 0.5, 1), 5); + } + async getRecommendedDifficultyRange(playerId) { + const recommended = await this.getRecommendedDifficulty(playerId); + return { + min: Math.max(1, recommended - 0.5), + max: Math.min(5, recommended + 0.5), + }; + } +}; +exports.DifficultyScalingService = DifficultyScalingService; +exports.DifficultyScalingService = DifficultyScalingService = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [typeof (_a = typeof player_skill_service_1.PlayerSkillService !== "undefined" && player_skill_service_1.PlayerSkillService) === "function" ? _a : Object, typeof (_b = typeof puzzle_difficulty_service_1.PuzzleDifficultyService !== "undefined" && puzzle_difficulty_service_1.PuzzleDifficultyService) === "function" ? _b : Object]) +], DifficultyScalingService); + + +/***/ }), + +/***/ "./src/difficulty-scaling/player-skill-algorithm.ts": +/*!**********************************************************!*\ + !*** ./src/difficulty-scaling/player-skill-algorithm.ts ***! + \**********************************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.calculatePlayerSkill = calculatePlayerSkill; +function calculatePlayerSkill(stats) { + if (!stats) + return 1; + const accuracy = Number(stats.overallAccuracy) || 0; + const completionRate = stats.totalPuzzlesCompleted / Math.max(1, stats.totalPuzzlesAttempted); + const avgTime = Number(stats.averageCompletionTime) || 0; + const normAccuracy = Math.min(accuracy / 100, 1); + const normCompletion = Math.min(completionRate, 1); + const normTime = 1 - Math.min(Math.max((avgTime - 60) / 540, 0), 1); + const skill = 1 + 4 * (0.5 * normAccuracy + 0.3 * normCompletion + 0.2 * normTime); + return Math.round(skill * 10) / 10; +} + + +/***/ }), + +/***/ "./src/difficulty-scaling/player-skill.service.ts": +/*!********************************************************!*\ + !*** ./src/difficulty-scaling/player-skill.service.ts ***! + \********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PlayerSkillService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_stats_entity_1 = __webpack_require__(/*! ../users/entities/user-stats.entity */ "./src/users/entities/user-stats.entity.ts"); +const player_skill_algorithm_1 = __webpack_require__(/*! ./player-skill-algorithm */ "./src/difficulty-scaling/player-skill-algorithm.ts"); +let PlayerSkillService = class PlayerSkillService { + constructor(userStatsRepository) { + this.userStatsRepository = userStatsRepository; + } + async getPlayerSkill(playerId) { + const stats = await this.userStatsRepository.findOne({ where: { userId: playerId } }); + return (0, player_skill_algorithm_1.calculatePlayerSkill)(stats); + } +}; +exports.PlayerSkillService = PlayerSkillService; +exports.PlayerSkillService = PlayerSkillService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(user_stats_entity_1.UserStats)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object]) +], PlayerSkillService); + + +/***/ }), + +/***/ "./src/difficulty-scaling/puzzle-difficulty-algorithm.ts": +/*!***************************************************************!*\ + !*** ./src/difficulty-scaling/puzzle-difficulty-algorithm.ts ***! + \***************************************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.calculatePuzzleDifficulty = calculatePuzzleDifficulty; +function calculatePuzzleDifficulty(puzzle, ratings) { + if (!puzzle) + return 1; + const completionRate = puzzle.analytics?.completionRate ?? (puzzle.completions / Math.max(1, puzzle.attempts)); + const avgTime = puzzle.averageCompletionTime || 0; + const votes = { easy: 0, medium: 0, hard: 0, expert: 0 }; + for (const r of ratings) { + if (r.difficultyVote && votes.hasOwnProperty(r.difficultyVote)) { + votes[r.difficultyVote]++; + } + } + const totalVotes = Object.values(votes).reduce((a, b) => a + b, 0) || 1; + const voteScore = (votes.easy * 1 + votes.medium * 2 + votes.hard * 3 + votes.expert * 4) / totalVotes; + const normCompletion = 1 - Math.min(completionRate, 1); + const normTime = Math.min(Math.max((avgTime - 60) / 540, 0), 1); + const difficulty = 1 + 4 * (0.4 * normCompletion + 0.3 * normTime + 0.3 * (voteScore / 4)); + return Math.round(difficulty * 10) / 10; +} + + +/***/ }), + +/***/ "./src/difficulty-scaling/puzzle-difficulty.service.ts": +/*!*************************************************************!*\ + !*** ./src/difficulty-scaling/puzzle-difficulty.service.ts ***! + \*************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PuzzleDifficultyService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const puzzle_entity_1 = __webpack_require__(/*! ../puzzles/entities/puzzle.entity */ "./src/puzzles/entities/puzzle.entity.ts"); +const puzzle_rating_entity_1 = __webpack_require__(/*! ../puzzles/entities/puzzle-rating.entity */ "./src/puzzles/entities/puzzle-rating.entity.ts"); +const puzzle_difficulty_algorithm_1 = __webpack_require__(/*! ./puzzle-difficulty-algorithm */ "./src/difficulty-scaling/puzzle-difficulty-algorithm.ts"); +let PuzzleDifficultyService = class PuzzleDifficultyService { + constructor(puzzleRepository, puzzleRatingRepository) { + this.puzzleRepository = puzzleRepository; + this.puzzleRatingRepository = puzzleRatingRepository; + } + async getPuzzleDifficulty(puzzleId) { + const puzzle = await this.puzzleRepository.findOne({ where: { id: puzzleId } }); + const ratings = await this.puzzleRatingRepository.find({ where: { puzzleId } }); + return (0, puzzle_difficulty_algorithm_1.calculatePuzzleDifficulty)(puzzle, ratings); + } +}; +exports.PuzzleDifficultyService = PuzzleDifficultyService; +exports.PuzzleDifficultyService = PuzzleDifficultyService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(puzzle_entity_1.Puzzle)), + __param(1, (0, typeorm_1.InjectRepository)(puzzle_rating_entity_1.PuzzleRating)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object]) +], PuzzleDifficultyService); + + +/***/ }), + +/***/ "./src/game-engine/entities/game-session.entity.ts": +/*!*********************************************************!*\ + !*** ./src/game-engine/entities/game-session.entity.ts ***! + \*********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GameSession = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +let GameSession = class GameSession { +}; +exports.GameSession = GameSession; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], GameSession.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 255 }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], GameSession.prototype, "sessionId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], GameSession.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + __metadata("design:type", String) +], GameSession.prototype, "playerId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", typeof (_a = typeof Record !== "undefined" && Record) === "function" ? _a : Object) +], GameSession.prototype, "sessionData", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'web' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], GameSession.prototype, "platform", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100, nullable: true }), + __metadata("design:type", String) +], GameSession.prototype, "deviceInfo", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100, nullable: true }), + __metadata("design:type", String) +], GameSession.prototype, "browserInfo", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone' }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], GameSession.prototype, "startTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], GameSession.prototype, "endTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], GameSession.prototype, "duration", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], GameSession.prototype, "puzzlesAttempted", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], GameSession.prototype, "puzzlesCompleted", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], GameSession.prototype, "puzzlesFailed", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], GameSession.prototype, "puzzlesSkipped", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], GameSession.prototype, "totalScore", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], GameSession.prototype, "totalHintsUsed", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], GameSession.prototype, "achievementsUnlocked", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), + __metadata("design:type", Number) +], GameSession.prototype, "averageAccuracy", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], GameSession.prototype, "longestStreak", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'simple-array', default: [] }), + __metadata("design:type", Array) +], GameSession.prototype, "puzzleIds", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'simple-array', default: [] }), + __metadata("design:type", Array) +], GameSession.prototype, "categoriesPlayed", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], GameSession.prototype, "analytics", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], GameSession.prototype, "sessionConfig", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], GameSession.prototype, "sessionState", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], GameSession.prototype, "contextData", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", Boolean) +], GameSession.prototype, "isActive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'ongoing' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], GameSession.prototype, "status", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], GameSession.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], GameSession.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => user_entity_1.User, (user) => user.gameSessions, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'userId' }), + __metadata("design:type", typeof (_f = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _f : Object) +], GameSession.prototype, "user", void 0); +exports.GameSession = GameSession = __decorate([ + (0, typeorm_1.Entity)('game_sessions'), + (0, typeorm_1.Index)(['userId', 'startTime']), + (0, typeorm_1.Index)(['sessionId'], { unique: true }), + (0, typeorm_1.Index)(['userId', 'isActive']), + (0, typeorm_1.Index)(['endTime']) +], GameSession); + + +/***/ }), + +/***/ "./src/game-logic/entities/puzzle-progress.entity.ts": +/*!***********************************************************!*\ + !*** ./src/game-logic/entities/puzzle-progress.entity.ts ***! + \***********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PuzzleProgress = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +let PuzzleProgress = class PuzzleProgress { +}; +exports.PuzzleProgress = PuzzleProgress; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], PuzzleProgress.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], PuzzleProgress.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], PuzzleProgress.prototype, "puzzleId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'not_started' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], PuzzleProgress.prototype, "status", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], PuzzleProgress.prototype, "attempts", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], PuzzleProgress.prototype, "score", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], PuzzleProgress.prototype, "bestScore", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], PuzzleProgress.prototype, "hintsUsed", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], PuzzleProgress.prototype, "timeSpent", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', nullable: true }), + __metadata("design:type", Number) +], PuzzleProgress.prototype, "bestTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], PuzzleProgress.prototype, "startedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], PuzzleProgress.prototype, "completedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], PuzzleProgress.prototype, "lastAttemptAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 3, scale: 2, nullable: true }), + __metadata("design:type", Number) +], PuzzleProgress.prototype, "rating", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], PuzzleProgress.prototype, "progress", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], PuzzleProgress.prototype, "metrics", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], PuzzleProgress.prototype, "sessionData", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], PuzzleProgress.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], PuzzleProgress.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)('User', 'puzzleProgress', { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'userId' }), + __metadata("design:type", Object) +], PuzzleProgress.prototype, "user", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)('Puzzle', 'progress', { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'puzzleId' }), + __metadata("design:type", Object) +], PuzzleProgress.prototype, "puzzle", void 0); +exports.PuzzleProgress = PuzzleProgress = __decorate([ + (0, typeorm_1.Entity)('puzzle_progress'), + (0, typeorm_1.Index)(['userId', 'puzzleId'], { unique: true }), + (0, typeorm_1.Index)(['userId', 'status']), + (0, typeorm_1.Index)(['puzzleId', 'status']) +], PuzzleProgress); + + +/***/ }), + +/***/ "./src/health/health.controller.ts": +/*!*****************************************!*\ + !*** ./src/health/health.controller.ts ***! + \*****************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HealthController = void 0; +const database_service_1 = __webpack_require__(/*! ../config/database-service */ "./src/config/database-service.ts"); +const performance_service_1 = __webpack_require__(/*! ../monitoring/performance.service */ "./src/monitoring/performance.service.ts"); +class HealthController { + constructor() { + this.databaseService = database_service_1.DatabaseService.getInstance(); + this.performanceService = new performance_service_1.PerformanceMonitoringService(this.databaseService.getDataSource()); + } + async checkHealth(req, res) { + try { + const health = await this.databaseService.checkHealth(); + const status = health.status === 'healthy' ? 200 : 503; + res.status(status).json({ + status: health.status, + timestamp: health.timestamp, + database: { + connection: health.connection, + latency: `${health.latency}ms`, + activeConnections: health.activeConnections, + }, + error: health.error, + }); + } + catch (error) { + res.status(503).json({ + status: 'unhealthy', + timestamp: new Date(), + error: error instanceof Error ? error.message : 'Unknown error', + }); + } + } + async getMetrics(req, res) { + try { + const metrics = await this.performanceService.getMetrics(); + res.json(metrics); + } + catch (error) { + res.status(500).json({ + error: error instanceof Error ? error.message : 'Failed to fetch metrics', + }); + } + } + async getConnectionStats(req, res) { + try { + const stats = await this.databaseService.getConnectionStats(); + res.json(stats); + } + catch (error) { + res.status(500).json({ + error: error instanceof Error + ? error.message + : 'Failed to fetch connection stats', + }); + } + } +} +exports.HealthController = HealthController; + + +/***/ }), + +/***/ "./src/health/health.module.ts": +/*!*************************************!*\ + !*** ./src/health/health.module.ts ***! + \*************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HealthModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const terminus_1 = __webpack_require__(/*! @nestjs/terminus */ "@nestjs/terminus"); +const health_controller_1 = __webpack_require__(/*! ./health.controller */ "./src/health/health.controller.ts"); +let HealthModule = class HealthModule { +}; +exports.HealthModule = HealthModule; +exports.HealthModule = HealthModule = __decorate([ + (0, common_1.Module)({ + imports: [terminus_1.TerminusModule], + controllers: [health_controller_1.HealthController], + }) +], HealthModule); + + +/***/ }), + +/***/ "./src/hints/algorithms/engine.ts": +/*!****************************************!*\ + !*** ./src/hints/algorithms/engine.ts ***! + \****************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.generateAlgorithmicHints = generateAlgorithmicHints; +function generateAlgorithmicHints(ctx) { + const { puzzleType, difficulty, puzzleState, playerState } = ctx; + const progress = puzzleState?.progress ?? 0; + const errors = puzzleState?.errors ?? []; + const generic = { + order: 1, + type: 'general', + content: baseGuidance(puzzleType, difficulty), + }; + const contextual = { + order: 2, + type: 'contextual', + content: contextualGuidance(puzzleType, progress, errors), + }; + const strategic = { + order: 3, + type: 'strategic', + content: strategicGuidance(puzzleType, difficulty), + }; + const specific = { + order: 4, + type: 'specific', + content: specificNudge(puzzleType, puzzleState), + }; + specific.content = maskPotentialSpoilers(specific.content); + return [generic, contextual, strategic, specific]; +} +function baseGuidance(type, difficulty) { + switch (type) { + case 'multiple-choice': + return 'Eliminate clearly wrong options first to narrow your choices.'; + case 'fill-blank': + return 'Break the problem into smaller parts and verify each piece.'; + case 'drag-drop': + return 'Group related items before placing them to see patterns.'; + case 'code': + return 'Recreate the failing case in a minimal example and test iteratively.'; + case 'visual': + return 'Scan for symmetry and repeated shapes; start from the edges.'; + case 'logic-grid': + return 'Use process of elimination and mark contradictions immediately.'; + } +} +function contextualGuidance(type, progress, errors) { + if (progress < 0.33) { + return 'Focus on the initial constraints before exploring alternatives.'; + } + if (errors?.length) { + return `Review recent steps; watch out for: ${errors.slice(0, 2).join(', ')}.`; + } + return 'You are on track—double-check the last step for consistency.'; +} +function strategicGuidance(type, difficulty) { + if (difficulty === 'hard' || difficulty === 'expert') { + return 'Consider tackling sub-problems first and merging insights later.'; + } + return 'Try a simpler path first; verify assumptions before proceeding.'; +} +function specificNudge(type, puzzleState) { + switch (type) { + case 'multiple-choice': + return 'Re-check the option contradicting the main clue from earlier.'; + case 'logic-grid': + return 'Look at the intersection of the two most constrained categories.'; + case 'code': + return 'Inspect boundary conditions around the input size and null handling.'; + default: + return 'Revisit the step where your approach first diverged.'; + } +} +function maskPotentialSpoilers(text) { + return text.replace(/[A-Z]\)/g, 'option').replace(/\b\d+\b/g, 'n'); +} + + +/***/ }), + +/***/ "./src/hints/dto/create-hint.dto.ts": +/*!******************************************!*\ + !*** ./src/hints/dto/create-hint.dto.ts ***! + \******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HintUsageDto = exports.RequestHintDto = exports.CreateHintDto = exports.HintType = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +var HintType; +(function (HintType) { + HintType["GENERAL"] = "general"; + HintType["CONTEXTUAL"] = "contextual"; + HintType["STRATEGIC"] = "strategic"; + HintType["SPECIFIC"] = "specific"; + HintType["TUTORIAL"] = "tutorial"; +})(HintType || (exports.HintType = HintType = {})); +class CreateHintDto { +} +exports.CreateHintDto = CreateHintDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], CreateHintDto.prototype, "puzzleId", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + __metadata("design:type", Number) +], CreateHintDto.prototype, "order", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(HintType), + __metadata("design:type", String) +], CreateHintDto.prototype, "type", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], CreateHintDto.prototype, "content", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], CreateHintDto.prototype, "contextualData", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + __metadata("design:type", Number) +], CreateHintDto.prototype, "cost", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + __metadata("design:type", Number) +], CreateHintDto.prototype, "pointsPenalty", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + __metadata("design:type", Number) +], CreateHintDto.prototype, "unlockAfterSeconds", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + __metadata("design:type", Number) +], CreateHintDto.prototype, "unlockAfterAttempts", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], CreateHintDto.prototype, "skillLevelTarget", void 0); +class RequestHintDto { +} +exports.RequestHintDto = RequestHintDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], RequestHintDto.prototype, "puzzleId", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], RequestHintDto.prototype, "userId", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + __metadata("design:type", Number) +], RequestHintDto.prototype, "attemptNumber", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + __metadata("design:type", Number) +], RequestHintDto.prototype, "timeSpent", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], RequestHintDto.prototype, "playerState", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], RequestHintDto.prototype, "puzzleState", void 0); +class HintUsageDto { +} +exports.HintUsageDto = HintUsageDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], HintUsageDto.prototype, "hintId", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], HintUsageDto.prototype, "puzzleId", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], HintUsageDto.prototype, "userId", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + __metadata("design:type", Number) +], HintUsageDto.prototype, "attemptNumber", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + __metadata("design:type", Number) +], HintUsageDto.prototype, "timeSpent", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + __metadata("design:type", Boolean) +], HintUsageDto.prototype, "ledToCompletion", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + __metadata("design:type", Number) +], HintUsageDto.prototype, "timeToCompletion", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + (0, class_validator_1.Max)(5), + __metadata("design:type", Number) +], HintUsageDto.prototype, "satisfactionRating", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], HintUsageDto.prototype, "playerState", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], HintUsageDto.prototype, "puzzleState", void 0); + + +/***/ }), + +/***/ "./src/hints/entities/hint-template.entity.ts": +/*!****************************************************!*\ + !*** ./src/hints/entities/hint-template.entity.ts ***! + \****************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HintTemplate = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +let HintTemplate = class HintTemplate { +}; +exports.HintTemplate = HintTemplate; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], HintTemplate.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + __metadata("design:type", String) +], HintTemplate.prototype, "name", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text' }), + __metadata("design:type", String) +], HintTemplate.prototype, "description", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + __metadata("design:type", String) +], HintTemplate.prototype, "puzzleType", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + __metadata("design:type", String) +], HintTemplate.prototype, "category", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20 }), + __metadata("design:type", String) +], HintTemplate.prototype, "difficulty", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], HintTemplate.prototype, "order", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + __metadata("design:type", String) +], HintTemplate.prototype, "type", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text' }), + __metadata("design:type", String) +], HintTemplate.prototype, "template", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], HintTemplate.prototype, "variables", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], HintTemplate.prototype, "conditions", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], HintTemplate.prototype, "cost", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], HintTemplate.prototype, "pointsPenalty", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: true }), + __metadata("design:type", Boolean) +], HintTemplate.prototype, "isActive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], HintTemplate.prototype, "usageCount", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), + __metadata("design:type", Number) +], HintTemplate.prototype, "effectiveness", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], HintTemplate.prototype, "analytics", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], HintTemplate.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], HintTemplate.prototype, "updatedAt", void 0); +exports.HintTemplate = HintTemplate = __decorate([ + (0, typeorm_1.Entity)('hint_templates'), + (0, typeorm_1.Index)(['puzzleType', 'difficulty']), + (0, typeorm_1.Index)(['category', 'isActive']) +], HintTemplate); + + +/***/ }), + +/***/ "./src/hints/entities/hint-usage.entity.ts": +/*!*************************************************!*\ + !*** ./src/hints/entities/hint-usage.entity.ts ***! + \*************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HintUsage = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +let HintUsage = class HintUsage { +}; +exports.HintUsage = HintUsage; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], HintUsage.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], HintUsage.prototype, "hintId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], HintUsage.prototype, "puzzleId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], HintUsage.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], HintUsage.prototype, "attemptNumber", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], HintUsage.prototype, "timeSpent", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], HintUsage.prototype, "ledToCompletion", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', nullable: true }), + __metadata("design:type", Number) +], HintUsage.prototype, "timeToCompletion", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 1 }), + __metadata("design:type", Number) +], HintUsage.prototype, "satisfactionRating", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', nullable: true }), + __metadata("design:type", Object) +], HintUsage.prototype, "playerState", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', nullable: true }), + __metadata("design:type", Object) +], HintUsage.prototype, "puzzleState", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], HintUsage.prototype, "isAbuseAttempt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text', nullable: true }), + __metadata("design:type", String) +], HintUsage.prototype, "abuseReason", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', nullable: true }), + __metadata("design:type", Object) +], HintUsage.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], HintUsage.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)('Hint', { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'hintId' }), + __metadata("design:type", Object) +], HintUsage.prototype, "hint", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)('Puzzle', { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'puzzleId' }), + __metadata("design:type", Object) +], HintUsage.prototype, "puzzle", void 0); +exports.HintUsage = HintUsage = __decorate([ + (0, typeorm_1.Entity)('hint_usages'), + (0, typeorm_1.Index)(['userId', 'puzzleId']), + (0, typeorm_1.Index)(['hintId', 'createdAt']) +], HintUsage); + + +/***/ }), + +/***/ "./src/hints/entities/hint.entity.ts": +/*!*******************************************!*\ + !*** ./src/hints/entities/hint.entity.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Hint = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const hint_usage_entity_1 = __webpack_require__(/*! ./hint-usage.entity */ "./src/hints/entities/hint-usage.entity.ts"); +let Hint = class Hint { +}; +exports.Hint = Hint; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Hint.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Hint.prototype, "puzzleId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], Hint.prototype, "order", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + __metadata("design:type", String) +], Hint.prototype, "type", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text' }), + __metadata("design:type", String) +], Hint.prototype, "content", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', nullable: true }), + __metadata("design:type", Object) +], Hint.prototype, "contextualData", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], Hint.prototype, "cost", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], Hint.prototype, "pointsPenalty", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', nullable: true }), + __metadata("design:type", Number) +], Hint.prototype, "unlockAfterSeconds", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', nullable: true }), + __metadata("design:type", Number) +], Hint.prototype, "unlockAfterAttempts", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Hint.prototype, "skillLevelTarget", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: true }), + __metadata("design:type", Boolean) +], Hint.prototype, "isActive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), + __metadata("design:type", Number) +], Hint.prototype, "effectiveness", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], Hint.prototype, "usageCount", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], Hint.prototype, "successCount", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Hint.prototype, "analytics", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], Hint.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], Hint.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)('Puzzle', { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'puzzleId' }), + __metadata("design:type", Object) +], Hint.prototype, "puzzle", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => hint_usage_entity_1.HintUsage, (usage) => usage.hint), + __metadata("design:type", Array) +], Hint.prototype, "usages", void 0); +exports.Hint = Hint = __decorate([ + (0, typeorm_1.Entity)('hints'), + (0, typeorm_1.Index)(['puzzleId', 'order']), + (0, typeorm_1.Index)(['type', 'difficulty']) +], Hint); + + +/***/ }), + +/***/ "./src/hints/hints.controller.ts": +/*!***************************************!*\ + !*** ./src/hints/hints.controller.ts ***! + \***************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HintsController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const hints_service_1 = __webpack_require__(/*! ./hints.service */ "./src/hints/hints.service.ts"); +const create_hint_dto_1 = __webpack_require__(/*! ./dto/create-hint.dto */ "./src/hints/dto/create-hint.dto.ts"); +let HintsController = class HintsController { + constructor(hintsService) { + this.hintsService = hintsService; + } + async create(dto) { + return this.hintsService.createHint(dto); + } + async request(dto) { + return this.hintsService.requestHint(dto); + } + async recordUsage(dto) { + return this.hintsService.recordUsage(dto); + } + async listTemplates(puzzleType, difficulty, activeOnly) { + return this.hintsService.listTemplates({ + puzzleType, + difficulty, + activeOnly: activeOnly ? activeOnly === 'true' : undefined, + }); + } + async updateTemplate(id, body) { + return this.hintsService.updateTemplate(id, body); + } + async toggleTemplate(id, active) { + return this.hintsService.toggleTemplate(id, active === 'true'); + } + async seedTemplates() { + return this.hintsService.seedDefaultTemplates(); + } +}; +exports.HintsController = HintsController; +__decorate([ + (0, common_1.Post)('create'), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof create_hint_dto_1.CreateHintDto !== "undefined" && create_hint_dto_1.CreateHintDto) === "function" ? _b : Object]), + __metadata("design:returntype", Promise) +], HintsController.prototype, "create", null); +__decorate([ + (0, common_1.Post)('request'), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_c = typeof create_hint_dto_1.RequestHintDto !== "undefined" && create_hint_dto_1.RequestHintDto) === "function" ? _c : Object]), + __metadata("design:returntype", Promise) +], HintsController.prototype, "request", null); +__decorate([ + (0, common_1.Post)('usage'), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_d = typeof create_hint_dto_1.HintUsageDto !== "undefined" && create_hint_dto_1.HintUsageDto) === "function" ? _d : Object]), + __metadata("design:returntype", Promise) +], HintsController.prototype, "recordUsage", null); +__decorate([ + (0, common_1.Get)('templates'), + __param(0, (0, common_1.Query)('puzzleType')), + __param(1, (0, common_1.Query)('difficulty')), + __param(2, (0, common_1.Query)('activeOnly')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String, String]), + __metadata("design:returntype", Promise) +], HintsController.prototype, "listTemplates", null); +__decorate([ + (0, common_1.Patch)('templates'), + __param(0, (0, common_1.Query)('id')), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, Object]), + __metadata("design:returntype", Promise) +], HintsController.prototype, "updateTemplate", null); +__decorate([ + (0, common_1.Post)('templates/toggle'), + __param(0, (0, common_1.Query)('id')), + __param(1, (0, common_1.Query)('active')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], HintsController.prototype, "toggleTemplate", null); +__decorate([ + (0, common_1.Post)('templates/seed'), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", Promise) +], HintsController.prototype, "seedTemplates", null); +exports.HintsController = HintsController = __decorate([ + (0, common_1.Controller)('hints'), + __metadata("design:paramtypes", [typeof (_a = typeof hints_service_1.HintsService !== "undefined" && hints_service_1.HintsService) === "function" ? _a : Object]) +], HintsController); + + +/***/ }), + +/***/ "./src/hints/hints.module.ts": +/*!***********************************!*\ + !*** ./src/hints/hints.module.ts ***! + \***********************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HintsModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const hints_service_1 = __webpack_require__(/*! ./hints.service */ "./src/hints/hints.service.ts"); +const hints_controller_1 = __webpack_require__(/*! ./hints.controller */ "./src/hints/hints.controller.ts"); +const hint_entity_1 = __webpack_require__(/*! ./entities/hint.entity */ "./src/hints/entities/hint.entity.ts"); +const hint_usage_entity_1 = __webpack_require__(/*! ./entities/hint-usage.entity */ "./src/hints/entities/hint-usage.entity.ts"); +const hint_template_entity_1 = __webpack_require__(/*! ./entities/hint-template.entity */ "./src/hints/entities/hint-template.entity.ts"); +const puzzles_module_1 = __webpack_require__(/*! ../puzzles/puzzles.module */ "./src/puzzles/puzzles.module.ts"); +let HintsModule = class HintsModule { +}; +exports.HintsModule = HintsModule; +exports.HintsModule = HintsModule = __decorate([ + (0, common_1.Module)({ + imports: [ + typeorm_1.TypeOrmModule.forFeature([hint_entity_1.Hint, hint_usage_entity_1.HintUsage, hint_template_entity_1.HintTemplate]), + puzzles_module_1.PuzzlesModule, + ], + controllers: [hints_controller_1.HintsController], + providers: [hints_service_1.HintsService], + exports: [hints_service_1.HintsService], + }) +], HintsModule); + + +/***/ }), + +/***/ "./src/hints/hints.service.ts": +/*!************************************!*\ + !*** ./src/hints/hints.service.ts ***! + \************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HintsService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const hint_entity_1 = __webpack_require__(/*! ./entities/hint.entity */ "./src/hints/entities/hint.entity.ts"); +const hint_usage_entity_1 = __webpack_require__(/*! ./entities/hint-usage.entity */ "./src/hints/entities/hint-usage.entity.ts"); +const hint_template_entity_1 = __webpack_require__(/*! ./entities/hint-template.entity */ "./src/hints/entities/hint-template.entity.ts"); +const create_hint_dto_1 = __webpack_require__(/*! ./dto/create-hint.dto */ "./src/hints/dto/create-hint.dto.ts"); +const engine_1 = __webpack_require__(/*! ./algorithms/engine */ "./src/hints/algorithms/engine.ts"); +let HintsService = class HintsService { + constructor(hintRepo, usageRepo, templateRepo) { + this.hintRepo = hintRepo; + this.usageRepo = usageRepo; + this.templateRepo = templateRepo; + } + async createHint(dto) { + const hint = this.hintRepo.create({ + ...dto, + type: dto.type, + skillLevelTarget: dto.skillLevelTarget ?? {}, + contextualData: dto.contextualData, + }); + return this.hintRepo.save(hint); + } + async requestHint(dto) { + this.assertNotAbusing(dto); + await this.enforceHintLimits(dto.userId, dto.puzzleId); + const where = { + puzzleId: dto.puzzleId, + isActive: true, + }; + const candidates = await this.hintRepo.find({ + where, + order: { order: 'ASC' }, + }); + if (candidates.length === 0) { + const generated = await this.generateFromTemplates(dto); + if (!generated) { + throw new common_1.BadRequestException('No hints available for this puzzle'); + } + return generated; + } + const priorCount = await this.usageRepo.count({ + where: { userId: dto.userId, puzzleId: dto.puzzleId }, + }); + const progressive = candidates.find((h) => h.order > priorCount) ?? candidates[candidates.length - 1]; + const filtered = this.rankByContextAndPersonalization(candidates, dto, progressive.order); + const selected = filtered[0]; + await this.recordUsageInternal({ + hintId: selected.id, + puzzleId: dto.puzzleId, + userId: dto.userId, + attemptNumber: dto.attemptNumber, + timeSpent: dto.timeSpent, + ledToCompletion: false, + satisfactionRating: 3, + playerState: dto.playerState, + puzzleState: dto.puzzleState, + }); + void this.hintRepo.update(selected.id, { + usageCount: (selected.usageCount ?? 0) + 1, + analytics: { + ...selected.analytics, + }, + }); + return selected; + } + async recordUsage(dto) { + const usage = await this.recordUsageInternal(dto); + const hint = await this.hintRepo.findOne({ where: { id: dto.hintId } }); + if (hint) { + const successCount = (hint.successCount ?? 0) + (dto.ledToCompletion ? 1 : 0); + const usageCount = (hint.usageCount ?? 0) + 1; + const completionRate = successCount > 0 ? successCount / usageCount : 0; + const effectiveness = Math.min(1, Math.max(0, 0.6 * completionRate + 0.4 * (dto.satisfactionRating / 5))); + await this.hintRepo.update(hint.id, { + successCount, + usageCount, + effectiveness, + analytics: { + ...hint.analytics, + completionRate, + }, + }); + } + return usage; + } + async listTemplates(params) { + const where = {}; + if (params?.puzzleType) + where.puzzleType = params.puzzleType; + if (params?.difficulty) + where.difficulty = params.difficulty; + if (params?.activeOnly) + where.isActive = true; + return this.templateRepo.find({ where, order: { order: 'ASC' } }); + } + async createTemplate(input) { + const template = this.templateRepo.create({ + ...input, + isActive: input.isActive ?? true, + usageCount: 0, + effectiveness: 0, + analytics: {}, + }); + return this.templateRepo.save(template); + } + async updateTemplate(id, input) { + const existing = await this.templateRepo.findOne({ where: { id } }); + if (!existing) + throw new common_1.BadRequestException('Template not found'); + const updated = { ...existing, ...input, id: existing.id }; + await this.templateRepo.save(updated); + return updated; + } + async toggleTemplate(id, isActive) { + const existing = await this.templateRepo.findOne({ where: { id } }); + if (!existing) + throw new common_1.BadRequestException('Template not found'); + existing.isActive = isActive; + return this.templateRepo.save(existing); + } + async seedDefaultTemplates() { + const defaults = [ + { + name: 'MCQ General 1', + description: 'General guidance for MCQ without spoilers', + puzzleType: 'multiple-choice', + category: 'general', + difficulty: 'medium', + order: 1, + type: 'general', + template: 'Eliminate obviously wrong options and compare remaining choices.', + variables: {}, + conditions: {}, + cost: 0, + pointsPenalty: 0, + isActive: true, + }, + { + name: 'Logic Grid Context 2', + description: 'Contextual nudge based on constraints', + puzzleType: 'logic-grid', + category: 'contextual', + difficulty: 'medium', + order: 2, + type: 'contextual', + template: 'Look again at the constraint linking {{currentStep}}; resolve contradictions first.', + variables: { currentStep: { type: 'string', description: 'Current solving focus', required: false } }, + conditions: {}, + cost: 0, + pointsPenalty: 0, + isActive: true, + }, + { + name: 'Code Strategic 3', + description: 'Strategy hint for code puzzles', + puzzleType: 'code', + category: 'strategic', + difficulty: 'hard', + order: 3, + type: 'strategic', + template: 'Create a minimal repro for the failing case and add an assertion around {{progress}}.', + variables: { progress: { type: 'number', description: 'Progress percent', required: false } }, + conditions: { minSkillLevel: 2 }, + cost: 1, + pointsPenalty: 0, + isActive: true, + }, + { + name: 'Visual Specific 4', + description: 'Specific but non-spoiling nudge', + puzzleType: 'visual', + category: 'specific', + difficulty: 'easy', + order: 4, + type: 'specific', + template: 'Focus on the outer boundary; check repeated shapes before moving inward.', + variables: {}, + conditions: {}, + cost: 2, + pointsPenalty: 1, + isActive: true, + }, + ]; + let created = 0; + for (const d of defaults) { + const exists = await this.templateRepo.findOne({ where: { name: d.name } }); + if (!exists) { + const t = this.templateRepo.create(d); + await this.templateRepo.save(t); + created += 1; + } + } + return { created }; + } + async generateFromTemplates(dto) { + const puzzleType = dto.puzzleState?.type ?? 'logic-grid'; + const difficulty = dto.puzzleState?.difficulty ?? 'medium'; + const templates = await this.listTemplates({ puzzleType, difficulty, activeOnly: true }); + if (templates.length === 0) { + const alg = (0, engine_1.generateAlgorithmicHints)({ + puzzleType: dto.puzzleState?.type ?? 'logic-grid', + difficulty: dto.puzzleState?.difficulty ?? 'medium', + puzzleState: dto.puzzleState, + playerState: dto.playerState, + }); + if (!alg.length) + return null; + const chosen = alg[0]; + const hint = this.hintRepo.create({ + puzzleId: dto.puzzleId, + order: chosen.order, + type: chosen.type, + content: chosen.content, + cost: 0, + pointsPenalty: 0, + isActive: true, + skillLevelTarget: {}, + }); + return this.hintRepo.save(hint); + } + const priorCount = await this.usageRepo.count({ where: { userId: dto.userId, puzzleId: dto.puzzleId } }); + const selectedTemplate = templates.find((t) => t.order > priorCount) ?? templates[templates.length - 1]; + const content = this.fillTemplate(selectedTemplate.template, { + progress: dto.puzzleState?.progress ?? 0, + errors: dto.puzzleState?.errors ?? [], + currentStep: dto.puzzleState?.currentStep ?? 'start', + }); + const hint = this.hintRepo.create({ + puzzleId: dto.puzzleId, + order: selectedTemplate.order, + type: selectedTemplate.type, + content, + cost: selectedTemplate.cost ?? 0, + pointsPenalty: selectedTemplate.pointsPenalty ?? 0, + isActive: true, + skillLevelTarget: selectedTemplate.conditions + ? { minLevel: selectedTemplate.conditions.minSkillLevel, maxLevel: selectedTemplate.conditions.maxSkillLevel } + : {}, + }); + return this.hintRepo.save(hint); + } + fillTemplate(template, vars) { + return template.replace(/\{\{\s*(\w+)\s*\}\}/g, (_, key) => { + const value = vars[key]; + if (Array.isArray(value)) + return value.join(', '); + if (value === undefined || value === null) + return ''; + return String(value); + }); + } + rankByContextAndPersonalization(candidates, dto, minOrder) { + const skill = dto.playerState?.skillLevel ?? 0; + const prevHints = dto.playerState?.previousHintsUsed ?? 0; + const time = dto.timeSpent ?? 0; + const attempt = dto.attemptNumber ?? 1; + const orderWeight = 3; + const typeWeight = 2; + const personalizationWeight = 2; + const effectivenessWeight = 1; + const typeBaseScore = (t) => { + switch (t) { + case create_hint_dto_1.HintType.GENERAL: + return 3; + case create_hint_dto_1.HintType.CONTEXTUAL: + return 4; + case create_hint_dto_1.HintType.STRATEGIC: + return 4; + case create_hint_dto_1.HintType.SPECIFIC: + return 1; + case create_hint_dto_1.HintType.TUTORIAL: + return attempt <= 1 ? 5 : 2; + default: + return 2; + } + }; + const scored = candidates + .filter((h) => h.order >= minOrder) + .map((h) => { + const typeScore = typeBaseScore(h.type); + const inRange = this.isSkillInRange(skill, h.skillLevelTarget); + const personalizationScore = inRange ? 1 : 0; + const effScore = Number(h.effectiveness ?? 0); + const orderScore = 1 / (1 + Math.max(0, h.order - minOrder)); + const score = orderWeight * orderScore + + typeWeight * typeScore + + personalizationWeight * personalizationScore + + effectivenessWeight * effScore + + (time > 120 ? 0.5 : 0) + + (prevHints > 0 ? -0.2 * prevHints : 0); + return { h, score }; + }) + .sort((a, b) => b.score - a.score) + .map((x) => x.h); + return scored.length > 0 ? scored : candidates; + } + isSkillInRange(skill, target) { + if (!target) + return true; + const min = target.minLevel ?? -Infinity; + const max = target.maxLevel ?? Infinity; + return skill >= min && skill <= max; + } + async enforceHintLimits(userId, puzzleId) { + const now = new Date(); + const since = new Date(now.getTime() - 15 * 1000); + const count = await this.usageRepo.count({ where: { userId, puzzleId } }); + if (count >= 3) { + throw new common_1.ForbiddenException('Hint limit reached for this puzzle'); + } + const recent = await this.usageRepo.find({ + where: { + userId, + puzzleId, + createdAt: (0, typeorm_2.MoreThanOrEqual)(since), + }, + order: { createdAt: 'DESC' }, + take: 1, + }); + if (recent.length > 0) { + throw new common_1.ForbiddenException('Please wait before requesting another hint'); + } + } + assertNotAbusing(dto) { + const rapidAttempts = dto.attemptNumber > 5 && (dto.timeSpent ?? 0) < 5; + if (rapidAttempts) { + throw new common_1.ForbiddenException('Hint abuse detected'); + } + } + async recordUsageInternal(dto) { + const usage = this.usageRepo.create({ + ...dto, + isAbuseAttempt: false, + }); + return this.usageRepo.save(usage); + } +}; +exports.HintsService = HintsService; +exports.HintsService = HintsService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(hint_entity_1.Hint)), + __param(1, (0, typeorm_1.InjectRepository)(hint_usage_entity_1.HintUsage)), + __param(2, (0, typeorm_1.InjectRepository)(hint_template_entity_1.HintTemplate)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object]) +], HintsService); + + +/***/ }), + +/***/ "./src/main.ts": +/*!*********************!*\ + !*** ./src/main.ts ***! + \*********************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const core_1 = __webpack_require__(/*! @nestjs/core */ "@nestjs/core"); +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const nest_winston_1 = __webpack_require__(/*! nest-winston */ "nest-winston"); +const helmet_1 = __importDefault(__webpack_require__(/*! helmet */ "helmet")); +const app_module_1 = __webpack_require__(/*! ./app.module */ "./src/app.module.ts"); +const http_exception_filter_1 = __webpack_require__(/*! ./common/exceptions/http-exception.filter */ "./src/common/exceptions/http-exception.filter.ts"); +const sanitize_interceptor_1 = __webpack_require__(/*! ./common/interceptors/sanitize.interceptor */ "./src/common/interceptors/sanitize.interceptor.ts"); +const Sentry = __importStar(__webpack_require__(/*! @sentry/node */ "@sentry/node")); +const throttler_1 = __webpack_require__(/*! @nestjs/throttler */ "@nestjs/throttler"); +async function bootstrap() { + Sentry.init({ + dsn: process.env.SENTRY_DSN || '', + tracesSampleRate: 1.0, + environment: process.env.NODE_ENV || 'development', + }); + const app = await core_1.NestFactory.create(app_module_1.AppModule, { + bufferLogs: true, + }); + const logger = app.get(nest_winston_1.WINSTON_MODULE_NEST_PROVIDER); + app.useLogger(logger); + const configService = app.get(config_1.ConfigService); + const port = configService.get('app.port') || 3000; + const apiPrefix = configService.get('app.apiPrefix') || 'api/v1'; + const corsOrigin = configService.get('app.cors.origin') || 'http://localhost:3000'; + app.use((0, helmet_1.default)({ + contentSecurityPolicy: process.env.NODE_ENV === 'production', + crossOriginEmbedderPolicy: false, + })); + app.enableCors({ + origin: corsOrigin, + credentials: true, + methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], + allowedHeaders: ['Content-Type', 'Authorization', 'Accept'], + }); + app.useGlobalPipes(new common_1.ValidationPipe({ + whitelist: true, + forbidNonWhitelisted: true, + transform: true, + })); + app.useGlobalGuards(new throttler_1.ThrottlerGuard()); + app.useGlobalFilters(new http_exception_filter_1.AllExceptionsFilter()); + app.useGlobalInterceptors(new sanitize_interceptor_1.SanitizeInterceptor()); + app.setGlobalPrefix(apiPrefix); + await app.listen(port); + logger.log(`🚀 LogiQuest Backend is running on: http://localhost:${port}/${apiPrefix}`, 'Bootstrap'); +} +bootstrap().catch((error) => { + common_1.Logger.error('Failed to start the application', error); + process.exit(1); +}); + + +/***/ }), + +/***/ "./src/monitoring/performance.service.ts": +/*!***********************************************!*\ + !*** ./src/monitoring/performance.service.ts ***! + \***********************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PerformanceMonitoringService = void 0; +class PerformanceMonitoringService { + constructor(dataSource) { + this.dataSource = dataSource; + } + async getSlowQueries(limit = 10) { + const queryRunner = this.dataSource.createQueryRunner(); + try { + await queryRunner.connect(); + const result = await queryRunner.query(` + SELECT + query, + calls, + total_time, + mean_time, + min_time, + max_time, + rows + FROM pg_stat_statements + WHERE calls > 5 + ORDER BY mean_time DESC + LIMIT $1 + `, [limit]); + return result; + } + finally { + await queryRunner.release(); + } + } + async getCacheHitRatio() { + const queryRunner = this.dataSource.createQueryRunner(); + try { + await queryRunner.connect(); + const result = await queryRunner.query(` + SELECT + round( + sum(blks_hit) * 100.0 / sum(blks_hit + blks_read), 2 + ) as cache_hit_ratio + FROM pg_stat_database + WHERE datname = current_database() + `); + return result[0]?.cache_hit_ratio || 0; + } + finally { + await queryRunner.release(); + } + } + async getIndexUsage() { + const queryRunner = this.dataSource.createQueryRunner(); + try { + await queryRunner.connect(); + const result = await queryRunner.query(` + SELECT + round( + sum(idx_scan) * 100.0 / sum(seq_scan + idx_scan), 2 + ) as index_usage_ratio + FROM pg_stat_user_tables + WHERE seq_scan + idx_scan > 0 + `); + return result[0]?.index_usage_ratio || 0; + } + finally { + await queryRunner.release(); + } + } + async getDatabaseSize() { + const queryRunner = this.dataSource.createQueryRunner(); + try { + await queryRunner.connect(); + const result = await queryRunner.query(` + SELECT pg_size_pretty(pg_database_size(current_database())) as size + `); + return result[0]?.size || '0 bytes'; + } + finally { + await queryRunner.release(); + } + } + async getTablesSizes() { + const queryRunner = this.dataSource.createQueryRunner(); + try { + await queryRunner.connect(); + const result = await queryRunner.query(` + SELECT + schemaname||'.'||tablename as table, + pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size + FROM pg_tables + WHERE schemaname NOT IN ('information_schema', 'pg_catalog') + ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC + `); + return result; + } + finally { + await queryRunner.release(); + } + } + async getMetrics() { + const [slowQueries, cacheHitRatio, indexUsage, databaseSize, tablesSizes] = await Promise.all([ + this.getSlowQueries(), + this.getCacheHitRatio(), + this.getIndexUsage(), + this.getDatabaseSize(), + this.getTablesSizes(), + ]); + const connectionStats = await this.getConnectionStats(); + return { + connections: connectionStats, + performance: { + slowQueries, + cacheHitRatio, + indexUsage, + }, + storage: { + databaseSize, + tablesSizes, + }, + }; + } + async getConnectionStats() { + const queryRunner = this.dataSource.createQueryRunner(); + try { + await queryRunner.connect(); + const result = await queryRunner.query(` + SELECT + count(*) as total, + count(*) FILTER (WHERE state = 'active') as active, + count(*) FILTER (WHERE state = 'idle') as idle, + count(*) FILTER (WHERE wait_event IS NOT NULL) as waiting + FROM pg_stat_activity + WHERE datname = current_database() + `); + return { + total: parseInt(result[0].total), + active: parseInt(result[0].active), + idle: parseInt(result[0].idle), + waiting: parseInt(result[0].waiting), + }; + } + finally { + await queryRunner.release(); + } + } +} +exports.PerformanceMonitoringService = PerformanceMonitoringService; + + +/***/ }), + +/***/ "./src/nft/nft.controller.ts": +/*!***********************************!*\ + !*** ./src/nft/nft.controller.ts ***! + \***********************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NFTController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const nft_service_1 = __webpack_require__(/*! ./nft.service */ "./src/nft/nft.service.ts"); +let NFTController = class NFTController { + constructor(nftService) { + this.nftService = nftService; + } + async mint(body) { + return this.nftService.mintNFT(body.userAddress, body.tokenId, body.uri); + } + async getNFT(tokenId) { + return this.nftService.getNFT(parseInt(tokenId, 10)); + } + async transfer(body) { + return this.nftService.transferNFT(body.from, body.to, body.tokenId); + } +}; +exports.NFTController = NFTController; +__decorate([ + (0, common_1.Post)('mint'), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], NFTController.prototype, "mint", null); +__decorate([ + (0, common_1.Get)(':tokenId'), + __param(0, (0, common_1.Param)('tokenId')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], NFTController.prototype, "getNFT", null); +__decorate([ + (0, common_1.Post)('transfer'), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], NFTController.prototype, "transfer", null); +exports.NFTController = NFTController = __decorate([ + (0, common_1.Controller)('nft'), + __metadata("design:paramtypes", [typeof (_a = typeof nft_service_1.NFTService !== "undefined" && nft_service_1.NFTService) === "function" ? _a : Object]) +], NFTController); + + +/***/ }), + +/***/ "./src/nft/nft.module.ts": +/*!*******************************!*\ + !*** ./src/nft/nft.module.ts ***! + \*******************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NFTModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const nft_service_1 = __webpack_require__(/*! ./nft.service */ "./src/nft/nft.service.ts"); +const nft_controller_1 = __webpack_require__(/*! ./nft.controller */ "./src/nft/nft.controller.ts"); +const soroban_module_1 = __webpack_require__(/*! ../soroban/soroban.module */ "./src/soroban/soroban.module.ts"); +let NFTModule = class NFTModule { +}; +exports.NFTModule = NFTModule; +exports.NFTModule = NFTModule = __decorate([ + (0, common_1.Module)({ + imports: [soroban_module_1.SorobanModule], + controllers: [nft_controller_1.NFTController], + providers: [nft_service_1.NFTService], + exports: [nft_service_1.NFTService], + }) +], NFTModule); + + +/***/ }), + +/***/ "./src/nft/nft.service.ts": +/*!********************************!*\ + !*** ./src/nft/nft.service.ts ***! + \********************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NFTService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const soroban_service_1 = __webpack_require__(/*! ../soroban/soroban.service */ "./src/soroban/soroban.service.ts"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const stellar_sdk_1 = __webpack_require__(/*! @stellar/stellar-sdk */ "@stellar/stellar-sdk"); +let NFTService = class NFTService { + constructor(sorobanService, configService) { + this.sorobanService = sorobanService; + this.configService = configService; + this.nftContractId = this.configService.get('NFT_CONTRACT_ID'); + } + async mintNFT(userAddress, tokenId, uri) { + const params = [ + new stellar_sdk_1.Address(userAddress).toScVal(), + (0, stellar_sdk_1.nativeToScVal)(tokenId, { type: 'u64' }), + (0, stellar_sdk_1.nativeToScVal)(uri, { type: 'string' }), + ]; + const result = await this.sorobanService.invokeContract(this.nftContractId, 'mint', params); + return { + success: result.status === 'SUCCESS', + transactionHash: result.hash, + tokenId, + owner: userAddress, + uri, + }; + } + async getNFT(tokenId) { + const params = [(0, stellar_sdk_1.nativeToScVal)(tokenId, { type: 'u64' })]; + const result = (await this.sorobanService.invokeContract(this.nftContractId, 'get_nft', params)); + return result.result; + } + async transferNFT(from, to, tokenId) { + const params = [ + new stellar_sdk_1.Address(from).toScVal(), + new stellar_sdk_1.Address(to).toScVal(), + (0, stellar_sdk_1.nativeToScVal)(tokenId, { type: 'u64' }), + ]; + const result = await this.sorobanService.invokeContract(this.nftContractId, 'transfer', params); + return { + success: result.status === 'SUCCESS', + transactionHash: result.hash, + }; + } +}; +exports.NFTService = NFTService; +exports.NFTService = NFTService = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [typeof (_a = typeof soroban_service_1.SorobanService !== "undefined" && soroban_service_1.SorobanService) === "function" ? _a : Object, typeof (_b = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _b : Object]) +], NFTService); + + +/***/ }), + +/***/ "./src/notifications/devices.controller.ts": +/*!*************************************************!*\ + !*** ./src/notifications/devices.controller.ts ***! + \*************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DevicesController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const typeorm_2 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const device_entity_1 = __webpack_require__(/*! ./entities/device.entity */ "./src/notifications/entities/device.entity.ts"); +let DevicesController = class DevicesController { + constructor(repo) { + this.repo = repo; + } + async register(userId, body) { + let device = await this.repo.findOne({ where: { token: body.token } }); + if (!device) { + device = this.repo.create({ userId, token: body.token, platform: body.platform, meta: body.meta ?? {} }); + } + else { + device.userId = userId; + device.platform = body.platform ?? device.platform; + device.meta = { ...(device.meta ?? {}), ...(body.meta ?? {}) }; + } + await this.repo.save(device); + return { ok: true, device }; + } + async deregister(userId, token) { + await this.repo.delete({ token, userId }); + return { ok: true }; + } + async list(userId) { + const devices = await this.repo.find({ where: { userId } }); + return { ok: true, devices }; + } +}; +exports.DevicesController = DevicesController; +__decorate([ + (0, common_1.Post)(':userId/register'), + __param(0, (0, common_1.Param)('userId')), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, Object]), + __metadata("design:returntype", Promise) +], DevicesController.prototype, "register", null); +__decorate([ + (0, common_1.Delete)(':userId/:token'), + __param(0, (0, common_1.Param)('userId')), + __param(1, (0, common_1.Param)('token')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], DevicesController.prototype, "deregister", null); +__decorate([ + (0, common_1.Get)(':userId'), + __param(0, (0, common_1.Param)('userId')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], DevicesController.prototype, "list", null); +exports.DevicesController = DevicesController = __decorate([ + (0, common_1.Controller)('devices'), + __param(0, (0, typeorm_2.InjectRepository)(device_entity_1.Device)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_1.Repository !== "undefined" && typeorm_1.Repository) === "function" ? _a : Object]) +], DevicesController); + + +/***/ }), + +/***/ "./src/notifications/dto/create-notification.dto.ts": +/*!**********************************************************!*\ + !*** ./src/notifications/dto/create-notification.dto.ts ***! + \**********************************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreateNotificationDto = void 0; +class CreateNotificationDto { +} +exports.CreateNotificationDto = CreateNotificationDto; + + +/***/ }), + +/***/ "./src/notifications/dto/feedback.dto.ts": +/*!***********************************************!*\ + !*** ./src/notifications/dto/feedback.dto.ts ***! + \***********************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NotificationFeedbackDto = void 0; +class NotificationFeedbackDto { +} +exports.NotificationFeedbackDto = NotificationFeedbackDto; + + +/***/ }), + +/***/ "./src/notifications/dto/preference.dto.ts": +/*!*************************************************!*\ + !*** ./src/notifications/dto/preference.dto.ts ***! + \*************************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NotificationPreferenceDto = void 0; +class NotificationPreferenceDto { +} +exports.NotificationPreferenceDto = NotificationPreferenceDto; + + +/***/ }), + +/***/ "./src/notifications/email.service.ts": +/*!********************************************!*\ + !*** ./src/notifications/email.service.ts ***! + \********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var EmailService_1; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.EmailService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const nodemailer = __importStar(__webpack_require__(/*! nodemailer */ "nodemailer")); +let EmailService = EmailService_1 = class EmailService { + constructor(config) { + this.config = config; + this.logger = new common_1.Logger(EmailService_1.name); + const host = this.config.get('EMAIL_HOST') || 'localhost'; + const port = Number(this.config.get('EMAIL_PORT') || 1025); + const user = this.config.get('EMAIL_USER') || ''; + const pass = this.config.get('EMAIL_PASS') || ''; + this.transporter = nodemailer.createTransport({ host, port, auth: user ? { user, pass } : undefined }); + } + async sendEmail(to, subject, text, html) { + const from = this.config.get('EMAIL_FROM') || 'no-reply@example.com'; + const info = await this.transporter.sendMail({ from, to, subject, text, html }); + this.logger.log(`Email sent to ${to}: ${info.messageId}`); + return info; + } +}; +exports.EmailService = EmailService; +exports.EmailService = EmailService = EmailService_1 = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [Object]) +], EmailService); + + +/***/ }), + +/***/ "./src/notifications/entities/device.entity.ts": +/*!*****************************************************!*\ + !*** ./src/notifications/entities/device.entity.ts ***! + \*****************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Device = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +let Device = class Device { +}; +exports.Device = Device; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Device.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Device.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 255 }), + __metadata("design:type", String) +], Device.prototype, "token", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50, nullable: true }), + __metadata("design:type", String) +], Device.prototype, "platform", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Device.prototype, "meta", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], Device.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], Device.prototype, "updatedAt", void 0); +exports.Device = Device = __decorate([ + (0, typeorm_1.Entity)('devices') +], Device); + + +/***/ }), + +/***/ "./src/notifications/entities/notification-delivery.entity.ts": +/*!********************************************************************!*\ + !*** ./src/notifications/entities/notification-delivery.entity.ts ***! + \********************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NotificationDelivery = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +let NotificationDelivery = class NotificationDelivery { +}; +exports.NotificationDelivery = NotificationDelivery; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], NotificationDelivery.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], NotificationDelivery.prototype, "notificationId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + __metadata("design:type", String) +], NotificationDelivery.prototype, "channel", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + __metadata("design:type", String) +], NotificationDelivery.prototype, "status", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text', nullable: true }), + __metadata("design:type", String) +], NotificationDelivery.prototype, "details", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], NotificationDelivery.prototype, "createdAt", void 0); +exports.NotificationDelivery = NotificationDelivery = __decorate([ + (0, typeorm_1.Entity)('notification_deliveries') +], NotificationDelivery); + + +/***/ }), + +/***/ "./src/notifications/entities/notification.entity.ts": +/*!***********************************************************!*\ + !*** ./src/notifications/entities/notification.entity.ts ***! + \***********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Notification = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +let Notification = class Notification { +}; +exports.Notification = Notification; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Notification.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Notification.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + __metadata("design:type", String) +], Notification.prototype, "type", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 255 }), + __metadata("design:type", String) +], Notification.prototype, "title", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text', nullable: true }), + __metadata("design:type", String) +], Notification.prototype, "body", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Notification.prototype, "meta", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50, nullable: true }), + __metadata("design:type", String) +], Notification.prototype, "variantId", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], Notification.prototype, "createdAt", void 0); +exports.Notification = Notification = __decorate([ + (0, typeorm_1.Entity)('notifications') +], Notification); + + +/***/ }), + +/***/ "./src/notifications/notification.service.ts": +/*!***************************************************!*\ + !*** ./src/notifications/notification.service.ts ***! + \***************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var NotificationService_1; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NotificationService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const typeorm_2 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const notification_entity_1 = __webpack_require__(/*! ./entities/notification.entity */ "./src/notifications/entities/notification.entity.ts"); +const notification_delivery_entity_1 = __webpack_require__(/*! ./entities/notification-delivery.entity */ "./src/notifications/entities/notification-delivery.entity.ts"); +const user_entity_1 = __webpack_require__(/*! ../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +const email_service_1 = __webpack_require__(/*! ./email.service */ "./src/notifications/email.service.ts"); +const schedule_1 = __webpack_require__(/*! @nestjs/schedule */ "@nestjs/schedule"); +const device_entity_1 = __webpack_require__(/*! ./entities/device.entity */ "./src/notifications/entities/device.entity.ts"); +const push_service_1 = __webpack_require__(/*! ./push.service */ "./src/notifications/push.service.ts"); +let NotificationService = NotificationService_1 = class NotificationService { + constructor(notificationRepo, deliveryRepo, userRepo, deviceRepo, emailService, scheduler, pushService) { + this.notificationRepo = notificationRepo; + this.deliveryRepo = deliveryRepo; + this.userRepo = userRepo; + this.deviceRepo = deviceRepo; + this.emailService = emailService; + this.scheduler = scheduler; + this.pushService = pushService; + this.logger = new common_1.Logger(NotificationService_1.name); + } + async notifyAchievementUnlocked(userId, achievement) { + this.logger.log(`User ${userId} unlocked achievement: ${achievement.name}`); + const notif = this.notificationRepo.create({ + userId, + type: 'achievement', + title: `Achievement unlocked: ${achievement.name}`, + body: achievement.description, + meta: { iconUrl: achievement.iconUrl, celebrationMessage: achievement.celebrationMessage }, + }); + await this.notificationRepo.save(notif); + const user = await this.userRepo.findOne({ where: { id: userId } }); + if (!user) + return false; + const prefs = user.preferences?.notifications ?? { email: false, push: false }; + if (prefs.email) { + try { + await this.emailService.sendEmail(user.email, `You unlocked ${achievement.name}`, achievement.description); + await this.recordDelivery(notif.id, 'email', 'sent'); + } + catch (err) { + this.logger.error('Email send failed', err); + await this.recordDelivery(notif.id, 'email', 'failed', String(err)); + } + } + if (prefs.push) { + const devices = await this.deviceRepo.find({ where: { userId } }); + if (devices?.length) { + for (const d of devices) { + const res = await this.pushService.sendToToken(d.token, { title: notif.title, body: notif.body }); + if (res?.success) { + await this.recordDelivery(notif.id, 'push', 'sent', JSON.stringify(res)); + } + else if (res?.queued) { + await this.recordDelivery(notif.id, 'push', 'queued'); + } + else { + await this.recordDelivery(notif.id, 'push', 'failed', JSON.stringify(res)); + } + } + } + else { + await this.recordDelivery(notif.id, 'push', 'no_devices'); + } + } + await this.recordDelivery(notif.id, 'in_app', 'delivered'); + return true; + } + async createNotificationForUsers(opts) { + const targets = []; + if (opts.userIds?.length) + targets.push(...opts.userIds); + if (opts.segment) { + const users = await this.userRepo.find({ where: {} }); + for (const u of users) { + const val = u.metadata?.[opts.segment.key]; + if (val === opts.segment.value) + targets.push(u.id); + } + } + for (const userId of [...new Set(targets)]) { + const notif = this.notificationRepo.create({ + userId, + type: opts.type, + title: opts.title, + body: opts.body, + meta: opts.meta ?? {}, + variantId: opts.variantId, + }); + await this.notificationRepo.save(notif); + if (opts.sendAt && opts.sendAt > new Date()) { + const jobName = `notification-send-${notif.id}`; + const timeout = setTimeout(async () => { + await this.dispatchNotification(notif.id); + this.scheduler.deleteTimeout(jobName); + }, opts.sendAt.getTime() - Date.now()); + this.scheduler.addTimeout(jobName, timeout); + await this.recordDelivery(notif.id, 'scheduler', 'scheduled'); + } + else { + await this.dispatchNotification(notif.id); + } + } + } + async dispatchNotification(notificationId) { + const notif = await this.notificationRepo.findOne({ where: { id: notificationId } }); + if (!notif) + return; + const user = await this.userRepo.findOne({ where: { id: notif.userId } }); + if (!user) + return; + const prefs = user.preferences?.notifications ?? { email: false, push: false }; + await this.recordDelivery(notif.id, 'in_app', 'delivered'); + if (prefs.email) { + try { + await this.emailService.sendEmail(user.email, notif.title, notif.body ?? ''); + await this.recordDelivery(notif.id, 'email', 'sent'); + } + catch (err) { + this.logger.error('Email send failed', err); + await this.recordDelivery(notif.id, 'email', 'failed', String(err)); + } + } + if (prefs.push) { + const devices = await this.deviceRepo.find({ where: { userId: notif.userId } }); + if (devices?.length) { + for (const d of devices) { + const res = await this.pushService.sendToToken(d.token, { title: notif.title, body: notif.body }); + if (res?.success) { + await this.recordDelivery(notif.id, 'push', 'sent', JSON.stringify(res)); + } + else if (res?.queued) { + await this.recordDelivery(notif.id, 'push', 'queued'); + } + else { + await this.recordDelivery(notif.id, 'push', 'failed', JSON.stringify(res)); + } + } + } + else { + await this.recordDelivery(notif.id, 'push', 'no_devices'); + } + } + } + async recordDelivery(notificationId, channel, status, details) { + const d = this.deliveryRepo.create({ notificationId, channel, status, details }); + await this.deliveryRepo.save(d); + } + async setPreferences(userId, preferencesPatch) { + const user = await this.userRepo.findOne({ where: { id: userId } }); + if (!user) + return null; + user.preferences = { ...(user.preferences ?? {}), ...preferencesPatch }; + return this.userRepo.save(user); + } + async getPreferences(userId) { + const user = await this.userRepo.findOne({ where: { id: userId } }); + return user?.preferences ?? null; + } + async recordFeedback(notificationId, userId, feedback) { + const notif = await this.notificationRepo.findOne({ where: { id: notificationId } }); + if (!notif) + return null; + notif.meta = notif.meta ?? {}; + notif.meta.feedback = notif.meta.feedback ?? []; + notif.meta.feedback.push({ userId, action: feedback.action, comment: feedback.comment, at: new Date() }); + await this.notificationRepo.save(notif); + await this.recordDelivery(notificationId, 'feedback', 'received', feedback.action); + return notif; + } +}; +exports.NotificationService = NotificationService; +exports.NotificationService = NotificationService = NotificationService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_2.InjectRepository)(notification_entity_1.Notification)), + __param(1, (0, typeorm_2.InjectRepository)(notification_delivery_entity_1.NotificationDelivery)), + __param(2, (0, typeorm_2.InjectRepository)(user_entity_1.User)), + __param(3, (0, typeorm_2.InjectRepository)(device_entity_1.Device)), + __param(5, (0, common_1.Inject)(schedule_1.SchedulerRegistry)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_1.Repository !== "undefined" && typeorm_1.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_1.Repository !== "undefined" && typeorm_1.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_1.Repository !== "undefined" && typeorm_1.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_1.Repository !== "undefined" && typeorm_1.Repository) === "function" ? _d : Object, typeof (_e = typeof email_service_1.EmailService !== "undefined" && email_service_1.EmailService) === "function" ? _e : Object, Object, typeof (_f = typeof push_service_1.PushService !== "undefined" && push_service_1.PushService) === "function" ? _f : Object]) +], NotificationService); + + +/***/ }), + +/***/ "./src/notifications/notifications.controller.ts": +/*!*******************************************************!*\ + !*** ./src/notifications/notifications.controller.ts ***! + \*******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NotificationsController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const notification_service_1 = __webpack_require__(/*! ./notification.service */ "./src/notifications/notification.service.ts"); +const create_notification_dto_1 = __webpack_require__(/*! ./dto/create-notification.dto */ "./src/notifications/dto/create-notification.dto.ts"); +const preference_dto_1 = __webpack_require__(/*! ./dto/preference.dto */ "./src/notifications/dto/preference.dto.ts"); +const feedback_dto_1 = __webpack_require__(/*! ./dto/feedback.dto */ "./src/notifications/dto/feedback.dto.ts"); +let NotificationsController = class NotificationsController { + constructor(service) { + this.service = service; + } + async create(body) { + await this.service.createNotificationForUsers({ + userIds: body.userIds, + segment: body.segment, + type: body.type, + title: body.title, + body: body.body, + meta: body.meta, + sendAt: body.sendAt ? new Date(body.sendAt) : undefined, + variantId: body.variantId, + }); + return { ok: true }; + } + async setPreferences(userId, prefs) { + const updated = await this.service.setPreferences(userId, { notifications: prefs }); + return { ok: true, preferences: updated?.preferences }; + } + async getPreferences(userId) { + const prefs = await this.service.getPreferences(userId); + return { ok: true, preferences: prefs }; + } + async feedback(notificationId, body) { + const res = await this.service.recordFeedback(notificationId, body.userId ?? 'unknown', { action: body.action, comment: body.comment }); + return { ok: !!res }; + } +}; +exports.NotificationsController = NotificationsController; +__decorate([ + (0, common_1.Post)('create'), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof create_notification_dto_1.CreateNotificationDto !== "undefined" && create_notification_dto_1.CreateNotificationDto) === "function" ? _b : Object]), + __metadata("design:returntype", Promise) +], NotificationsController.prototype, "create", null); +__decorate([ + (0, common_1.Post)(':userId/preferences'), + __param(0, (0, common_1.Param)('userId')), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_c = typeof preference_dto_1.NotificationPreferenceDto !== "undefined" && preference_dto_1.NotificationPreferenceDto) === "function" ? _c : Object]), + __metadata("design:returntype", Promise) +], NotificationsController.prototype, "setPreferences", null); +__decorate([ + (0, common_1.Get)(':userId/preferences'), + __param(0, (0, common_1.Param)('userId')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], NotificationsController.prototype, "getPreferences", null); +__decorate([ + (0, common_1.Post)(':notificationId/feedback'), + __param(0, (0, common_1.Param)('notificationId')), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_d = typeof feedback_dto_1.NotificationFeedbackDto !== "undefined" && feedback_dto_1.NotificationFeedbackDto) === "function" ? _d : Object]), + __metadata("design:returntype", Promise) +], NotificationsController.prototype, "feedback", null); +exports.NotificationsController = NotificationsController = __decorate([ + (0, common_1.Controller)('notifications'), + __metadata("design:paramtypes", [typeof (_a = typeof notification_service_1.NotificationService !== "undefined" && notification_service_1.NotificationService) === "function" ? _a : Object]) +], NotificationsController); + + +/***/ }), + +/***/ "./src/notifications/notifications.module.ts": +/*!***************************************************!*\ + !*** ./src/notifications/notifications.module.ts ***! + \***************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NotificationsModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const notification_entity_1 = __webpack_require__(/*! ./entities/notification.entity */ "./src/notifications/entities/notification.entity.ts"); +const notification_delivery_entity_1 = __webpack_require__(/*! ./entities/notification-delivery.entity */ "./src/notifications/entities/notification-delivery.entity.ts"); +const device_entity_1 = __webpack_require__(/*! ./entities/device.entity */ "./src/notifications/entities/device.entity.ts"); +const notification_service_1 = __webpack_require__(/*! ./notification.service */ "./src/notifications/notification.service.ts"); +const email_service_1 = __webpack_require__(/*! ./email.service */ "./src/notifications/email.service.ts"); +const notifications_controller_1 = __webpack_require__(/*! ./notifications.controller */ "./src/notifications/notifications.controller.ts"); +const push_service_1 = __webpack_require__(/*! ./push.service */ "./src/notifications/push.service.ts"); +const devices_controller_1 = __webpack_require__(/*! ./devices.controller */ "./src/notifications/devices.controller.ts"); +const user_entity_1 = __webpack_require__(/*! ../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +let NotificationsModule = class NotificationsModule { +}; +exports.NotificationsModule = NotificationsModule; +exports.NotificationsModule = NotificationsModule = __decorate([ + (0, common_1.Module)({ + imports: [typeorm_1.TypeOrmModule.forFeature([notification_entity_1.Notification, notification_delivery_entity_1.NotificationDelivery, device_entity_1.Device, user_entity_1.User]), config_1.ConfigModule], + providers: [notification_service_1.NotificationService, email_service_1.EmailService, push_service_1.PushService], + controllers: [notifications_controller_1.NotificationsController, devices_controller_1.DevicesController], + exports: [notification_service_1.NotificationService], + }) +], NotificationsModule); + + +/***/ }), + +/***/ "./src/notifications/push.service.ts": +/*!*******************************************!*\ + !*** ./src/notifications/push.service.ts ***! + \*******************************************/ +/***/ (() => { + +throw new Error("Module parse failed: 'return' outside of function (6:8)\nFile was processed with these loaders:\n * ./node_modules/ts-loader/index.js\nYou may need an additional loader to handle the result of these loaders.\n| if (!this.enabled) {\n| this.logger.debug('Push disabled - token would be:', token);\n> return { success: false, queued: true };\n| }\n| try {"); + +/***/ }), + +/***/ "./src/puzzle/puzzle.controller.ts": +/*!*****************************************!*\ + !*** ./src/puzzle/puzzle.controller.ts ***! + \*****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PuzzleController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const puzzle_service_1 = __webpack_require__(/*! ./puzzle.service */ "./src/puzzle/puzzle.service.ts"); +const rewards_service_1 = __webpack_require__(/*! ../rewards/rewards.service */ "./src/rewards/rewards.service.ts"); +const nft_service_1 = __webpack_require__(/*! ../nft/nft.service */ "./src/nft/nft.service.ts"); +let PuzzleController = class PuzzleController { + constructor(puzzleService, rewardsService, nftService) { + this.puzzleService = puzzleService; + this.rewardsService = rewardsService; + this.nftService = nftService; + } + async create(body) { + return this.puzzleService.createPuzzle(body.puzzleId, body.solution); + } + async verify(body) { + const verification = await this.puzzleService.verifySolution(body.puzzleId, body.solution); + if (verification.verified) { + await this.puzzleService.markCompleted(body.puzzleId, body.userAddress); + const rewardResult = await this.rewardsService.distributeReward(body.userAddress, 100); + const nftResult = await this.nftService.mintNFT(body.userAddress, Date.now(), `ipfs://puzzle-${body.puzzleId}-achievement`); + return { + ...verification, + rewardDistributed: rewardResult.success, + rewardTransactionHash: rewardResult.transactionHash, + nftMinted: nftResult.success, + nftTransactionHash: nftResult.transactionHash, + }; + } + return verification; + } +}; +exports.PuzzleController = PuzzleController; +__decorate([ + (0, common_1.Post)('create'), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], PuzzleController.prototype, "create", null); +__decorate([ + (0, common_1.Post)('verify'), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], PuzzleController.prototype, "verify", null); +exports.PuzzleController = PuzzleController = __decorate([ + (0, common_1.Controller)('puzzle'), + __metadata("design:paramtypes", [typeof (_a = typeof puzzle_service_1.PuzzleService !== "undefined" && puzzle_service_1.PuzzleService) === "function" ? _a : Object, typeof (_b = typeof rewards_service_1.RewardsService !== "undefined" && rewards_service_1.RewardsService) === "function" ? _b : Object, typeof (_c = typeof nft_service_1.NFTService !== "undefined" && nft_service_1.NFTService) === "function" ? _c : Object]) +], PuzzleController); + + +/***/ }), + +/***/ "./src/puzzle/puzzle.module.ts": +/*!*************************************!*\ + !*** ./src/puzzle/puzzle.module.ts ***! + \*************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PuzzleModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const puzzle_service_1 = __webpack_require__(/*! ./puzzle.service */ "./src/puzzle/puzzle.service.ts"); +const puzzle_controller_1 = __webpack_require__(/*! ./puzzle.controller */ "./src/puzzle/puzzle.controller.ts"); +const soroban_module_1 = __webpack_require__(/*! ../soroban/soroban.module */ "./src/soroban/soroban.module.ts"); +const nft_module_1 = __webpack_require__(/*! ../nft/nft.module */ "./src/nft/nft.module.ts"); +const rewards_module_1 = __webpack_require__(/*! ../rewards/rewards.module */ "./src/rewards/rewards.module.ts"); +let PuzzleModule = class PuzzleModule { +}; +exports.PuzzleModule = PuzzleModule; +exports.PuzzleModule = PuzzleModule = __decorate([ + (0, common_1.Module)({ + imports: [soroban_module_1.SorobanModule, nft_module_1.NFTModule, rewards_module_1.RewardsModule], + controllers: [puzzle_controller_1.PuzzleController], + providers: [puzzle_service_1.PuzzleService], + }) +], PuzzleModule); + + +/***/ }), + +/***/ "./src/puzzle/puzzle.service.ts": +/*!**************************************!*\ + !*** ./src/puzzle/puzzle.service.ts ***! + \**************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PuzzleService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const soroban_service_1 = __webpack_require__(/*! ../soroban/soroban.service */ "./src/soroban/soroban.service.ts"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const stellar_sdk_1 = __webpack_require__(/*! @stellar/stellar-sdk */ "@stellar/stellar-sdk"); +const crypto = __importStar(__webpack_require__(/*! crypto */ "crypto")); +let PuzzleService = class PuzzleService { + constructor(sorobanService, configService) { + this.sorobanService = sorobanService; + this.configService = configService; + this.puzzleContractId = this.configService.get('PUZZLE_CONTRACT_ID'); + } + async createPuzzle(puzzleId, solution) { + const solutionHash = crypto + .createHash('sha256') + .update(solution) + .digest('hex'); + const params = [ + (0, stellar_sdk_1.nativeToScVal)(puzzleId, { type: 'u64' }), + (0, stellar_sdk_1.nativeToScVal)(solutionHash, { type: 'string' }), + ]; + const result = await this.sorobanService.invokeContract(this.puzzleContractId, 'create_puzzle', params); + return { + success: result.status === 'SUCCESS', + puzzleId, + transactionHash: result.hash, + }; + } + async verifySolution(puzzleId, solution) { + const params = [ + (0, stellar_sdk_1.nativeToScVal)(puzzleId, { type: 'u64' }), + (0, stellar_sdk_1.nativeToScVal)(solution, { type: 'string' }), + ]; + const result = await this.sorobanService.invokeContract(this.puzzleContractId, 'verify_solution', params); + return { + verified: result.status === 'SUCCESS', + puzzleId, + transactionHash: result.hash, + }; + } + async markCompleted(puzzleId, userAddress) { + const params = [ + (0, stellar_sdk_1.nativeToScVal)(puzzleId, { type: 'u64' }), + new stellar_sdk_1.Address(userAddress).toScVal(), + ]; + const result = await this.sorobanService.invokeContract(this.puzzleContractId, 'mark_completed', params); + return { + success: result.status === 'SUCCESS', + puzzleId, + user: userAddress, + transactionHash: result.hash, + }; + } +}; +exports.PuzzleService = PuzzleService; +exports.PuzzleService = PuzzleService = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [typeof (_a = typeof soroban_service_1.SorobanService !== "undefined" && soroban_service_1.SorobanService) === "function" ? _a : Object, typeof (_b = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _b : Object]) +], PuzzleService); + + +/***/ }), + +/***/ "./src/puzzles/category.controller.ts": +/*!********************************************!*\ + !*** ./src/puzzles/category.controller.ts ***! + \********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d, _e, _f, _g, _h; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CategoriesController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const category_service_1 = __webpack_require__(/*! ./category.service */ "./src/puzzles/category.service.ts"); +const create_category_dto_1 = __webpack_require__(/*! ./dto/create-category.dto */ "./src/puzzles/dto/create-category.dto.ts"); +const update_category_dto_1 = __webpack_require__(/*! ./dto/update-category.dto */ "./src/puzzles/dto/update-category.dto.ts"); +let CategoriesController = class CategoriesController { + constructor(categoriesService) { + this.categoriesService = categoriesService; + } + create(createCategoryDto) { + return this.categoriesService.create(createCategoryDto); + } + findAll() { + return this.categoriesService.findAll(); + } + findOne(id) { + return this.categoriesService.findOne(id); + } + update(id, updateCategoryDto) { + return this.categoriesService.update(id, updateCategoryDto); + } + remove(id) { + return this.categoriesService.remove(id); + } +}; +exports.CategoriesController = CategoriesController; +__decorate([ + (0, common_1.Post)(), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof create_category_dto_1.CreateCategoryDto !== "undefined" && create_category_dto_1.CreateCategoryDto) === "function" ? _b : Object]), + __metadata("design:returntype", typeof (_c = typeof Promise !== "undefined" && Promise) === "function" ? _c : Object) +], CategoriesController.prototype, "create", null); +__decorate([ + (0, common_1.Get)(), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", typeof (_d = typeof Promise !== "undefined" && Promise) === "function" ? _d : Object) +], CategoriesController.prototype, "findAll", null); +__decorate([ + (0, common_1.Get)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_e = typeof Promise !== "undefined" && Promise) === "function" ? _e : Object) +], CategoriesController.prototype, "findOne", null); +__decorate([ + (0, common_1.Patch)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_f = typeof update_category_dto_1.UpdateCategoryDto !== "undefined" && update_category_dto_1.UpdateCategoryDto) === "function" ? _f : Object]), + __metadata("design:returntype", typeof (_g = typeof Promise !== "undefined" && Promise) === "function" ? _g : Object) +], CategoriesController.prototype, "update", null); +__decorate([ + (0, common_1.Delete)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_h = typeof Promise !== "undefined" && Promise) === "function" ? _h : Object) +], CategoriesController.prototype, "remove", null); +exports.CategoriesController = CategoriesController = __decorate([ + (0, common_1.Controller)('categories'), + __metadata("design:paramtypes", [typeof (_a = typeof category_service_1.CategoriesService !== "undefined" && category_service_1.CategoriesService) === "function" ? _a : Object]) +], CategoriesController); + + +/***/ }), + +/***/ "./src/puzzles/category.service.ts": +/*!*****************************************!*\ + !*** ./src/puzzles/category.service.ts ***! + \*****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CategoriesService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const category_entity_1 = __webpack_require__(/*! ./entities/category.entity */ "./src/puzzles/entities/category.entity.ts"); +const puzzle_entity_1 = __webpack_require__(/*! ./entities/puzzle.entity */ "./src/puzzles/entities/puzzle.entity.ts"); +let CategoriesService = class CategoriesService { + constructor(categoriesRepository, puzzlesRepository) { + this.categoriesRepository = categoriesRepository; + this.puzzlesRepository = puzzlesRepository; + } + async create(createCategoryDto) { + const category = this.categoriesRepository.create(createCategoryDto); + return this.categoriesRepository.save(category); + } + async findAll() { + return this.categoriesRepository.find({}); + } + async findOne(id) { + const category = await this.categoriesRepository.findOne({ + where: { id }, + }); + if (!category) { + throw new common_1.NotFoundException(`Category with ID "${id}" not found`); + } + return category; + } + async update(id, updateCategoryDto) { + const category = await this.findOne(id); + Object.assign(category, updateCategoryDto); + return this.categoriesRepository.save(category); + } + async remove(id) { + const category = await this.findOne(id); + const result = await this.categoriesRepository.delete(id); + if (result.affected === 0) { + throw new common_1.NotFoundException(`Category with ID "${id}" not found`); + } + } + getCategoryRepository() { + return this.categoriesRepository; + } +}; +exports.CategoriesService = CategoriesService; +exports.CategoriesService = CategoriesService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(category_entity_1.Category)), + __param(1, (0, typeorm_1.InjectRepository)(puzzle_entity_1.Puzzle)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object]) +], CategoriesService); + + +/***/ }), + +/***/ "./src/puzzles/collection.controller.ts": +/*!**********************************************!*\ + !*** ./src/puzzles/collection.controller.ts ***! + \**********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d, _e, _f, _g, _h; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CollectionsController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const collection_service_1 = __webpack_require__(/*! ./collection.service */ "./src/puzzles/collection.service.ts"); +const create_collection_dto_1 = __webpack_require__(/*! ./dto/create-collection.dto */ "./src/puzzles/dto/create-collection.dto.ts"); +const update_collection_dto_1 = __webpack_require__(/*! ./dto/update-collection.dto */ "./src/puzzles/dto/update-collection.dto.ts"); +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class CollectionQueryDto { +} +__decorate([ + (0, class_validator_1.IsOptional)(), + IsUUID({}, { each: true }), + __metadata("design:type", Array) +], CollectionQueryDto.prototype, "categoryIds", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + IsUUID({}, { each: true }), + __metadata("design:type", Array) +], CollectionQueryDto.prototype, "themeIds", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + IsString(), + __metadata("design:type", String) +], CollectionQueryDto.prototype, "search", void 0); +let CollectionsController = class CollectionsController { + constructor(collectionsService) { + this.collectionsService = collectionsService; + } + create(createCollectionDto) { + return this.collectionsService.create(createCollectionDto); + } + findAll(query) { + return this.collectionsService.findAll(query); + } + findOne(id) { + return this.collectionsService.findOne(id); + } + update(id, updateCollectionDto) { + return this.collectionsService.update(id, updateCollectionDto); + } + remove(id) { + return this.collectionsService.remove(id); + } +}; +exports.CollectionsController = CollectionsController; +__decorate([ + (0, common_1.Post)(), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof create_collection_dto_1.CreateCollectionDto !== "undefined" && create_collection_dto_1.CreateCollectionDto) === "function" ? _b : Object]), + __metadata("design:returntype", typeof (_c = typeof Promise !== "undefined" && Promise) === "function" ? _c : Object) +], CollectionsController.prototype, "create", null); +__decorate([ + (0, common_1.Get)(), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [CollectionQueryDto]), + __metadata("design:returntype", typeof (_d = typeof Promise !== "undefined" && Promise) === "function" ? _d : Object) +], CollectionsController.prototype, "findAll", null); +__decorate([ + (0, common_1.Get)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_e = typeof Promise !== "undefined" && Promise) === "function" ? _e : Object) +], CollectionsController.prototype, "findOne", null); +__decorate([ + (0, common_1.Patch)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_f = typeof update_collection_dto_1.UpdateCollectionDto !== "undefined" && update_collection_dto_1.UpdateCollectionDto) === "function" ? _f : Object]), + __metadata("design:returntype", typeof (_g = typeof Promise !== "undefined" && Promise) === "function" ? _g : Object) +], CollectionsController.prototype, "update", null); +__decorate([ + (0, common_1.Delete)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_h = typeof Promise !== "undefined" && Promise) === "function" ? _h : Object) +], CollectionsController.prototype, "remove", null); +exports.CollectionsController = CollectionsController = __decorate([ + (0, common_1.Controller)('collections'), + __metadata("design:paramtypes", [typeof (_a = typeof collection_service_1.CollectionsService !== "undefined" && collection_service_1.CollectionsService) === "function" ? _a : Object]) +], CollectionsController); + + +/***/ }), + +/***/ "./src/puzzles/collection.service.ts": +/*!*******************************************!*\ + !*** ./src/puzzles/collection.service.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CollectionsService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const collection_entity_1 = __webpack_require__(/*! ./entities/collection.entity */ "./src/puzzles/entities/collection.entity.ts"); +const puzzle_entity_1 = __webpack_require__(/*! ./entities/puzzle.entity */ "./src/puzzles/entities/puzzle.entity.ts"); +const category_entity_1 = __webpack_require__(/*! ./entities/category.entity */ "./src/puzzles/entities/category.entity.ts"); +const user_collection_progress_entity_1 = __webpack_require__(/*! ../user-progress/entities/user-collection-progress.entity */ "./src/user-progress/entities/user-collection-progress.entity.ts"); +let CollectionsService = class CollectionsService { + constructor(collectionsRepository, puzzlesRepository, categoriesRepository, userCollectionProgressRepository) { + this.collectionsRepository = collectionsRepository; + this.puzzlesRepository = puzzlesRepository; + this.categoriesRepository = categoriesRepository; + this.userCollectionProgressRepository = userCollectionProgressRepository; + } + async create(createCollectionDto) { + const { puzzleIds, categoryIds, rewards, ...collectionData } = createCollectionDto; + const collection = this.collectionsRepository.create({ + ...collectionData, + rewards: rewards || [], + }); + if (puzzleIds && puzzleIds.length > 0) { + const puzzles = await this.puzzlesRepository.findBy({ id: (0, typeorm_2.In)(puzzleIds) }); + if (puzzles.length !== puzzleIds.length) { + throw new common_1.BadRequestException('One or more puzzle IDs not found.'); + } + collection.puzzles = puzzles; + } + if (categoryIds && categoryIds.length > 0) { + const categories = await this.categoriesRepository.findBy({ id: (0, typeorm_2.In)(categoryIds) }); + if (categories.length !== categoryIds.length) { + throw new common_1.BadRequestException('One or more category IDs not found.'); + } + collection.categories = categories; + } + return this.collectionsRepository.save(collection); + } + async findAll() { + return this.collectionsRepository.find({ + relations: ['puzzles', 'categories', 'userProgress'], + }); + } + async findOne(id) { + const collection = await this.collectionsRepository.findOne({ + where: { id }, + relations: ['puzzles', 'categories', 'userProgress'], + }); + if (!collection) { + throw new common_1.NotFoundException(`Collection with ID "${id}" not found`); + } + return collection; + } + async update(id, updateCollectionDto) { + const collection = await this.findOne(id); + const { puzzleIds, categoryIds, rewards, ...collectionData } = updateCollectionDto; + Object.assign(collection, collectionData); + if (rewards !== undefined) { + collection.rewards = rewards; + } + if (puzzleIds !== undefined) { + if (puzzleIds.length > 0) { + const puzzles = await this.puzzlesRepository.findBy({ id: (0, typeorm_2.In)(puzzleIds) }); + if (puzzles.length !== puzzleIds.length) { + throw new common_1.BadRequestException('One or more puzzle IDs not found.'); + } + collection.puzzles = puzzles; + } + else { + collection.puzzles = []; + } + } + if (categoryIds !== undefined) { + if (categoryIds.length > 0) { + const categories = await this.categoriesRepository.findBy({ id: (0, typeorm_2.In)(categoryIds) }); + if (categories.length !== categoryIds.length) { + throw new common_1.BadRequestException('One or more category IDs not found.'); + } + collection.categories = categories; + } + else { + collection.categories = []; + } + } + return this.collectionsRepository.save(collection); + } + async remove(id) { + await this.findOne(id); + const result = await this.collectionsRepository.delete(id); + if (result.affected === 0) { + throw new common_1.NotFoundException(`Collection with ID "${id}" not found`); + } + } + async grantRewards(collectionId, userId) { + const collection = await this.findOne(collectionId); + if (!collection.rewards || collection.rewards.length === 0) { + return; + } + console.log(`Granting ${collection.rewards.length} rewards to user ${userId} for completing collection ${collectionId}.`); + } + getCollectionRepository() { + return this.collectionsRepository; + } +}; +exports.CollectionsService = CollectionsService; +exports.CollectionsService = CollectionsService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(collection_entity_1.Collection)), + __param(1, (0, typeorm_1.InjectRepository)(puzzle_entity_1.Puzzle)), + __param(2, (0, typeorm_1.InjectRepository)(category_entity_1.Category)), + __param(3, (0, typeorm_1.InjectRepository)(user_collection_progress_entity_1.UserCollectionProgress)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object]) +], CollectionsService); + + +/***/ }), + +/***/ "./src/puzzles/dto/bulk-operations.dto.ts": +/*!************************************************!*\ + !*** ./src/puzzles/dto/bulk-operations.dto.ts ***! + \************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ImportPuzzleDto = exports.ExportPuzzleDto = exports.BulkUpdateDto = exports.BulkAction = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +var BulkAction; +(function (BulkAction) { + BulkAction["PUBLISH"] = "publish"; + BulkAction["UNPUBLISH"] = "unpublish"; + BulkAction["ARCHIVE"] = "archive"; + BulkAction["DELETE"] = "delete"; + BulkAction["UPDATE_CATEGORY"] = "update_category"; + BulkAction["ADD_TAGS"] = "add_tags"; + BulkAction["REMOVE_TAGS"] = "remove_tags"; +})(BulkAction || (exports.BulkAction = BulkAction = {})); +class BulkUpdateDto { +} +exports.BulkUpdateDto = BulkUpdateDto; +__decorate([ + (0, class_validator_1.IsEnum)(BulkAction), + __metadata("design:type", String) +], BulkUpdateDto.prototype, "action", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], BulkUpdateDto.prototype, "value", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], BulkUpdateDto.prototype, "reason", void 0); +class ExportPuzzleDto { + constructor() { + this.format = 'json'; + this.limit = 1000; + } +} +exports.ExportPuzzleDto = ExportPuzzleDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ExportPuzzleDto.prototype, "format", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ExportPuzzleDto.prototype, "category", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + (0, class_transformer_1.Type)(() => Number), + __metadata("design:type", Number) +], ExportPuzzleDto.prototype, "limit", void 0); +class ImportPuzzleDto { + constructor() { + this.importMode = 'create'; + this.validateOnly = false; + } +} +exports.ImportPuzzleDto = ImportPuzzleDto; +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ImportPuzzleDto.prototype, "format", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ImportPuzzleDto.prototype, "importMode", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], ImportPuzzleDto.prototype, "validateOnly", void 0); + + +/***/ }), + +/***/ "./src/puzzles/dto/create-category.dto.ts": +/*!************************************************!*\ + !*** ./src/puzzles/dto/create-category.dto.ts ***! + \************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreateCategoryDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class CreateCategoryDto { +} +exports.CreateCategoryDto = CreateCategoryDto; +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], CreateCategoryDto.prototype, "name", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], CreateCategoryDto.prototype, "description", void 0); + + +/***/ }), + +/***/ "./src/puzzles/dto/create-collection.dto.ts": +/*!**************************************************!*\ + !*** ./src/puzzles/dto/create-collection.dto.ts ***! + \**************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreateCollectionDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +class RewardDto { +} +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], RewardDto.prototype, "type", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], RewardDto.prototype, "value", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + IsNumber(), + __metadata("design:type", Number) +], RewardDto.prototype, "quantity", void 0); +class CreateCollectionDto { +} +exports.CreateCollectionDto = CreateCollectionDto; +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], CreateCollectionDto.prototype, "name", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], CreateCollectionDto.prototype, "description", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsUUID)({}, { each: true }), + __metadata("design:type", Array) +], CreateCollectionDto.prototype, "puzzleIds", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsUUID)({}, { each: true }), + __metadata("design:type", Array) +], CreateCollectionDto.prototype, "categoryIds", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.ValidateNested)({ each: true }), + (0, class_transformer_1.Type)(() => RewardDto), + __metadata("design:type", Array) +], CreateCollectionDto.prototype, "rewards", void 0); + + +/***/ }), + +/***/ "./src/puzzles/dto/create-puzzle.dto.ts": +/*!**********************************************!*\ + !*** ./src/puzzles/dto/create-puzzle.dto.ts ***! + \**********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreatePuzzleDto = exports.PuzzleScoringDto = exports.PuzzleHintDto = exports.PuzzleContentDto = exports.PuzzleContentType = exports.PuzzleDifficulty = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +var PuzzleDifficulty; +(function (PuzzleDifficulty) { + PuzzleDifficulty["EASY"] = "easy"; + PuzzleDifficulty["MEDIUM"] = "medium"; + PuzzleDifficulty["HARD"] = "hard"; + PuzzleDifficulty["EXPERT"] = "expert"; +})(PuzzleDifficulty || (exports.PuzzleDifficulty = PuzzleDifficulty = {})); +var PuzzleContentType; +(function (PuzzleContentType) { + PuzzleContentType["MULTIPLE_CHOICE"] = "multiple-choice"; + PuzzleContentType["FILL_BLANK"] = "fill-blank"; + PuzzleContentType["DRAG_DROP"] = "drag-drop"; + PuzzleContentType["CODE"] = "code"; + PuzzleContentType["VISUAL"] = "visual"; + PuzzleContentType["LOGIC_GRID"] = "logic-grid"; +})(PuzzleContentType || (exports.PuzzleContentType = PuzzleContentType = {})); +class PuzzleContentDto { +} +exports.PuzzleContentDto = PuzzleContentDto; +__decorate([ + (0, class_validator_1.IsEnum)(PuzzleContentType), + __metadata("design:type", String) +], PuzzleContentDto.prototype, "type", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(10), + __metadata("design:type", String) +], PuzzleContentDto.prototype, "question", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + __metadata("design:type", Array) +], PuzzleContentDto.prototype, "options", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], PuzzleContentDto.prototype, "explanation", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], PuzzleContentDto.prototype, "media", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], PuzzleContentDto.prototype, "interactive", void 0); +class PuzzleHintDto { +} +exports.PuzzleHintDto = PuzzleHintDto; +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + __metadata("design:type", Number) +], PuzzleHintDto.prototype, "order", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(5), + __metadata("design:type", String) +], PuzzleHintDto.prototype, "text", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + __metadata("design:type", Number) +], PuzzleHintDto.prototype, "pointsPenalty", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + __metadata("design:type", Number) +], PuzzleHintDto.prototype, "unlockAfter", void 0); +class PuzzleScoringDto { +} +exports.PuzzleScoringDto = PuzzleScoringDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], PuzzleScoringDto.prototype, "timeBonus", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], PuzzleScoringDto.prototype, "accuracyBonus", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], PuzzleScoringDto.prototype, "streakBonus", void 0); +class CreatePuzzleDto { +} +exports.CreatePuzzleDto = CreatePuzzleDto; +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(5), + (0, class_validator_1.MaxLength)(200), + __metadata("design:type", String) +], CreatePuzzleDto.prototype, "title", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(20), + (0, class_validator_1.MaxLength)(1000), + __metadata("design:type", String) +], CreatePuzzleDto.prototype, "description", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(3), + (0, class_validator_1.MaxLength)(50), + __metadata("design:type", String) +], CreatePuzzleDto.prototype, "category", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(PuzzleDifficulty), + __metadata("design:type", String) +], CreatePuzzleDto.prototype, "difficulty", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + (0, class_validator_1.Max)(10), + __metadata("design:type", Number) +], CreatePuzzleDto.prototype, "difficultyRating", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(10), + (0, class_validator_1.Max)(1000), + __metadata("design:type", Number) +], CreatePuzzleDto.prototype, "basePoints", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(30), + (0, class_validator_1.Max)(3600), + __metadata("design:type", Number) +], CreatePuzzleDto.prototype, "timeLimit", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.Max)(10), + __metadata("design:type", Number) +], CreatePuzzleDto.prototype, "maxHints", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => PuzzleContentDto), + __metadata("design:type", PuzzleContentDto) +], CreatePuzzleDto.prototype, "content", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.ValidateNested)({ each: true }), + (0, class_transformer_1.Type)(() => PuzzleHintDto), + __metadata("design:type", Array) +], CreatePuzzleDto.prototype, "hints", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + __metadata("design:type", Array) +], CreatePuzzleDto.prototype, "tags", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsUUID)(4, { each: true }), + __metadata("design:type", Array) +], CreatePuzzleDto.prototype, "prerequisites", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => PuzzleScoringDto), + __metadata("design:type", PuzzleScoringDto) +], CreatePuzzleDto.prototype, "scoring", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsBoolean)(), + __metadata("design:type", Boolean) +], CreatePuzzleDto.prototype, "isFeatured", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], CreatePuzzleDto.prototype, "parentPuzzleId", void 0); + + +/***/ }), + +/***/ "./src/puzzles/dto/create-theme.dto.ts": +/*!*********************************************!*\ + !*** ./src/puzzles/dto/create-theme.dto.ts ***! + \*********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreateThemeDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class CreateThemeDto { +} +exports.CreateThemeDto = CreateThemeDto; +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], CreateThemeDto.prototype, "name", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], CreateThemeDto.prototype, "description", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsUUID)({}, { each: true }), + __metadata("design:type", Array) +], CreateThemeDto.prototype, "collectionIds", void 0); + + +/***/ }), + +/***/ "./src/puzzles/dto/index.ts": +/*!**********************************!*\ + !*** ./src/puzzles/dto/index.ts ***! + \**********************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__webpack_require__(/*! ./create-puzzle.dto */ "./src/puzzles/dto/create-puzzle.dto.ts"), exports); +__exportStar(__webpack_require__(/*! ./update-puzzle.dto */ "./src/puzzles/dto/update-puzzle.dto.ts"), exports); +__exportStar(__webpack_require__(/*! ./search-puzzle.dto */ "./src/puzzles/dto/search-puzzle.dto.ts"), exports); +__exportStar(__webpack_require__(/*! ./bulk-operations.dto */ "./src/puzzles/dto/bulk-operations.dto.ts"), exports); + + +/***/ }), + +/***/ "./src/puzzles/dto/search-puzzle.dto.ts": +/*!**********************************************!*\ + !*** ./src/puzzles/dto/search-puzzle.dto.ts ***! + \**********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PuzzleStatsDto = exports.SearchPuzzleDto = exports.SortOrder = exports.SortBy = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +const create_puzzle_dto_1 = __webpack_require__(/*! ./create-puzzle.dto */ "./src/puzzles/dto/create-puzzle.dto.ts"); +var SortBy; +(function (SortBy) { + SortBy["CREATED_AT"] = "createdAt"; + SortBy["TITLE"] = "title"; + SortBy["DIFFICULTY"] = "difficulty"; + SortBy["RATING"] = "rating"; + SortBy["PLAYS"] = "totalPlays"; + SortBy["COMPLETION_RATE"] = "completionRate"; +})(SortBy || (exports.SortBy = SortBy = {})); +var SortOrder; +(function (SortOrder) { + SortOrder["ASC"] = "ASC"; + SortOrder["DESC"] = "DESC"; +})(SortOrder || (exports.SortOrder = SortOrder = {})); +class SearchPuzzleDto { + constructor() { + this.page = 1; + this.limit = 20; + this.sortBy = SortBy.CREATED_AT; + this.sortOrder = SortOrder.DESC; + } +} +exports.SearchPuzzleDto = SearchPuzzleDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], SearchPuzzleDto.prototype, "search", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], SearchPuzzleDto.prototype, "category", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)(create_puzzle_dto_1.PuzzleDifficulty), + __metadata("design:type", typeof (_a = typeof create_puzzle_dto_1.PuzzleDifficulty !== "undefined" && create_puzzle_dto_1.PuzzleDifficulty) === "function" ? _a : Object) +], SearchPuzzleDto.prototype, "difficulty", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + (0, class_validator_1.Max)(10), + (0, class_transformer_1.Type)(() => Number), + __metadata("design:type", Number) +], SearchPuzzleDto.prototype, "minRating", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + (0, class_validator_1.Max)(10), + (0, class_transformer_1.Type)(() => Number), + __metadata("design:type", Number) +], SearchPuzzleDto.prototype, "maxRating", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + (0, class_transformer_1.Transform)(({ value }) => typeof value === 'string' ? value.split(',') : value), + __metadata("design:type", Array) +], SearchPuzzleDto.prototype, "tags", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsBoolean)(), + (0, class_transformer_1.Transform)(({ value }) => value === 'true'), + __metadata("design:type", Boolean) +], SearchPuzzleDto.prototype, "isFeatured", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsBoolean)(), + (0, class_transformer_1.Transform)(({ value }) => value === 'true'), + __metadata("design:type", Boolean) +], SearchPuzzleDto.prototype, "isPublished", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], SearchPuzzleDto.prototype, "createdBy", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + (0, class_transformer_1.Type)(() => Number), + __metadata("design:type", Number) +], SearchPuzzleDto.prototype, "page", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + (0, class_validator_1.Max)(100), + (0, class_transformer_1.Type)(() => Number), + __metadata("design:type", Number) +], SearchPuzzleDto.prototype, "limit", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)(SortBy), + __metadata("design:type", String) +], SearchPuzzleDto.prototype, "sortBy", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)(SortOrder), + __metadata("design:type", String) +], SearchPuzzleDto.prototype, "sortOrder", void 0); +class PuzzleStatsDto { + constructor() { + this.includeStats = false; + this.period = 'all'; + } +} +exports.PuzzleStatsDto = PuzzleStatsDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsBoolean)(), + (0, class_transformer_1.Transform)(({ value }) => value === 'true'), + __metadata("design:type", Boolean) +], PuzzleStatsDto.prototype, "includeStats", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], PuzzleStatsDto.prototype, "period", void 0); + + +/***/ }), + +/***/ "./src/puzzles/dto/update-category.dto.ts": +/*!************************************************!*\ + !*** ./src/puzzles/dto/update-category.dto.ts ***! + \************************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UpdateCategoryDto = void 0; +const mapped_types_1 = __webpack_require__(/*! @nestjs/mapped-types */ "@nestjs/mapped-types"); +const create_category_dto_1 = __webpack_require__(/*! ./create-category.dto */ "./src/puzzles/dto/create-category.dto.ts"); +class UpdateCategoryDto extends (0, mapped_types_1.PartialType)(create_category_dto_1.CreateCategoryDto) { +} +exports.UpdateCategoryDto = UpdateCategoryDto; + + +/***/ }), + +/***/ "./src/puzzles/dto/update-collection.dto.ts": +/*!**************************************************!*\ + !*** ./src/puzzles/dto/update-collection.dto.ts ***! + \**************************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UpdateCollectionDto = void 0; +const mapped_types_1 = __webpack_require__(/*! @nestjs/mapped-types */ "@nestjs/mapped-types"); +const create_collection_dto_1 = __webpack_require__(/*! ./create-collection.dto */ "./src/puzzles/dto/create-collection.dto.ts"); +class UpdateCollectionDto extends (0, mapped_types_1.PartialType)(create_collection_dto_1.CreateCollectionDto) { +} +exports.UpdateCollectionDto = UpdateCollectionDto; + + +/***/ }), + +/***/ "./src/puzzles/dto/update-puzzle.dto.ts": +/*!**********************************************!*\ + !*** ./src/puzzles/dto/update-puzzle.dto.ts ***! + \**********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UpdatePuzzleDto = void 0; +const mapped_types_1 = __webpack_require__(/*! @nestjs/mapped-types */ "@nestjs/mapped-types"); +const create_puzzle_dto_1 = __webpack_require__(/*! ./create-puzzle.dto */ "./src/puzzles/dto/create-puzzle.dto.ts"); +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class UpdatePuzzleDto extends (0, mapped_types_1.PartialType)((0, mapped_types_1.OmitType)(create_puzzle_dto_1.CreatePuzzleDto, ['parentPuzzleId'])) { +} +exports.UpdatePuzzleDto = UpdatePuzzleDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsBoolean)(), + __metadata("design:type", Boolean) +], UpdatePuzzleDto.prototype, "isPublished", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsBoolean)(), + __metadata("design:type", Boolean) +], UpdatePuzzleDto.prototype, "isArchived", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + (0, class_validator_1.MaxLength)(500), + __metadata("design:type", String) +], UpdatePuzzleDto.prototype, "updateReason", void 0); + + +/***/ }), + +/***/ "./src/puzzles/dto/update-theme.dto.ts": +/*!*********************************************!*\ + !*** ./src/puzzles/dto/update-theme.dto.ts ***! + \*********************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UpdateThemeDto = void 0; +const mapped_types_1 = __webpack_require__(/*! @nestjs/mapped-types */ "@nestjs/mapped-types"); +const create_theme_dto_1 = __webpack_require__(/*! ./create-theme.dto */ "./src/puzzles/dto/create-theme.dto.ts"); +class UpdateThemeDto extends (0, mapped_types_1.PartialType)(create_theme_dto_1.CreateThemeDto) { +} +exports.UpdateThemeDto = UpdateThemeDto; + + +/***/ }), + +/***/ "./src/puzzles/entities/category.entity.ts": +/*!*************************************************!*\ + !*** ./src/puzzles/entities/category.entity.ts ***! + \*************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Category = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const puzzle_entity_1 = __webpack_require__(/*! ./puzzle.entity */ "./src/puzzles/entities/puzzle.entity.ts"); +let Category = class Category { +}; +exports.Category = Category; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Category.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ unique: true }), + __metadata("design:type", String) +], Category.prototype, "name", void 0); +__decorate([ + (0, typeorm_1.Column)({ nullable: true }), + __metadata("design:type", String) +], Category.prototype, "description", void 0); +__decorate([ + (0, typeorm_1.ManyToMany)(() => puzzle_entity_1.Puzzle, (puzzle) => puzzle.categories), + (0, typeorm_1.JoinTable)(), + __metadata("design:type", Array) +], Category.prototype, "puzzles", void 0); +exports.Category = Category = __decorate([ + (0, typeorm_1.Entity)() +], Category); + + +/***/ }), + +/***/ "./src/puzzles/entities/collection.entity.ts": +/*!***************************************************!*\ + !*** ./src/puzzles/entities/collection.entity.ts ***! + \***************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Collection = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const puzzle_entity_1 = __webpack_require__(/*! ./puzzle.entity */ "./src/puzzles/entities/puzzle.entity.ts"); +const category_entity_1 = __webpack_require__(/*! ./category.entity */ "./src/puzzles/entities/category.entity.ts"); +const user_collection_progress_entity_1 = __webpack_require__(/*! ../../user-progress/entities/user-collection-progress.entity */ "./src/user-progress/entities/user-collection-progress.entity.ts"); +let Collection = class Collection { +}; +exports.Collection = Collection; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Collection.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)(), + __metadata("design:type", String) +], Collection.prototype, "name", void 0); +__decorate([ + (0, typeorm_1.Column)({ nullable: true }), + __metadata("design:type", String) +], Collection.prototype, "description", void 0); +__decorate([ + (0, typeorm_1.ManyToMany)(() => puzzle_entity_1.Puzzle, (puzzle) => puzzle.collections), + (0, typeorm_1.JoinTable)(), + __metadata("design:type", Array) +], Collection.prototype, "puzzles", void 0); +__decorate([ + (0, typeorm_1.ManyToMany)(() => category_entity_1.Category, (category) => category.collections), + (0, typeorm_1.JoinTable)(), + __metadata("design:type", Array) +], Collection.prototype, "categories", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => user_collection_progress_entity_1.UserCollectionProgress, (userCollectionProgress) => userCollectionProgress.collection), + __metadata("design:type", Array) +], Collection.prototype, "userProgress", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: [] }), + __metadata("design:type", typeof (_a = typeof Array !== "undefined" && Array) === "function" ? _a : Object) +], Collection.prototype, "rewards", void 0); +exports.Collection = Collection = __decorate([ + (0, typeorm_1.Entity)() +], Collection); + + +/***/ }), + +/***/ "./src/puzzles/entities/puzzle-rating.entity.ts": +/*!******************************************************!*\ + !*** ./src/puzzles/entities/puzzle-rating.entity.ts ***! + \******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PuzzleRating = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +const puzzle_entity_1 = __webpack_require__(/*! ./puzzle.entity */ "./src/puzzles/entities/puzzle.entity.ts"); +let PuzzleRating = class PuzzleRating { +}; +exports.PuzzleRating = PuzzleRating; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], PuzzleRating.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], PuzzleRating.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], PuzzleRating.prototype, "submissionId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], PuzzleRating.prototype, "puzzleId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 3, scale: 2 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], PuzzleRating.prototype, "rating", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, nullable: true }), + __metadata("design:type", String) +], PuzzleRating.prototype, "difficultyVote", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text', nullable: true }), + __metadata("design:type", String) +], PuzzleRating.prototype, "review", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'simple-array', default: [] }), + __metadata("design:type", Array) +], PuzzleRating.prototype, "tags", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + (0, typeorm_1.Index)(), + __metadata("design:type", Boolean) +], PuzzleRating.prototype, "isReported", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", Boolean) +], PuzzleRating.prototype, "isPublic", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], PuzzleRating.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], PuzzleRating.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], PuzzleRating.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], PuzzleRating.prototype, "lastEditedAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => user_entity_1.User, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'userId' }), + __metadata("design:type", typeof (_d = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _d : Object) +], PuzzleRating.prototype, "user", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => puzzle_entity_1.Puzzle, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'puzzleId' }), + __metadata("design:type", typeof (_e = typeof puzzle_entity_1.Puzzle !== "undefined" && puzzle_entity_1.Puzzle) === "function" ? _e : Object) +], PuzzleRating.prototype, "puzzle", void 0); +exports.PuzzleRating = PuzzleRating = __decorate([ + (0, typeorm_1.Entity)('puzzle_ratings'), + (0, typeorm_1.Index)(['userId', 'puzzleId'], { unique: true }), + (0, typeorm_1.Index)(['puzzleId', 'rating']) +], PuzzleRating); + + +/***/ }), + +/***/ "./src/puzzles/entities/puzzle.entity.ts": +/*!***********************************************!*\ + !*** ./src/puzzles/entities/puzzle.entity.ts ***! + \***********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Puzzle = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +let Puzzle = class Puzzle { +}; +exports.Puzzle = Puzzle; +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], Puzzle.prototype, "archivedAt", void 0); +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Puzzle.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 200 }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Puzzle.prototype, "title", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text' }), + __metadata("design:type", String) +], Puzzle.prototype, "description", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Puzzle.prototype, "category", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'medium' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Puzzle.prototype, "difficulty", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 1 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], Puzzle.prototype, "difficultyRating", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 100 }), + __metadata("design:type", Number) +], Puzzle.prototype, "basePoints", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 300 }), + __metadata("design:type", Number) +], Puzzle.prototype, "timeLimit", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 3 }), + __metadata("design:type", Number) +], Puzzle.prototype, "maxHints", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], Puzzle.prototype, "attempts", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], Puzzle.prototype, "completions", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], Puzzle.prototype, "averageRating", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], Puzzle.prototype, "ratingCount", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], Puzzle.prototype, "averageCompletionTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", Boolean) +], Puzzle.prototype, "isActive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + (0, typeorm_1.Index)(), + __metadata("design:type", Boolean) +], Puzzle.prototype, "isFeatured", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], Puzzle.prototype, "publishedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Puzzle.prototype, "createdBy", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb' }), + __metadata("design:type", Object) +], Puzzle.prototype, "content", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: [] }), + __metadata("design:type", typeof (_c = typeof Array !== "undefined" && Array) === "function" ? _c : Object) +], Puzzle.prototype, "hints", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'simple-array', default: [] }), + (0, typeorm_1.Index)(), + __metadata("design:type", Array) +], Puzzle.prototype, "tags", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: [] }), + __metadata("design:type", Array) +], Puzzle.prototype, "prerequisites", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Puzzle.prototype, "scoring", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Puzzle.prototype, "analytics", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Puzzle.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], Puzzle.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], Puzzle.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.DeleteDateColumn)(), + __metadata("design:type", typeof (_f = typeof Date !== "undefined" && Date) === "function" ? _f : Object) +], Puzzle.prototype, "deletedAt", void 0); +__decorate([ + (0, typeorm_1.OneToMany)('PuzzleProgress', 'puzzle'), + __metadata("design:type", Array) +], Puzzle.prototype, "progress", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => Puzzle, { nullable: true }), + (0, typeorm_1.JoinColumn)({ name: 'parentPuzzleId' }), + __metadata("design:type", Puzzle) +], Puzzle.prototype, "parentPuzzle", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => Puzzle, (puzzle) => puzzle.parentPuzzle), + __metadata("design:type", Array) +], Puzzle.prototype, "childPuzzles", void 0); +exports.Puzzle = Puzzle = __decorate([ + (0, typeorm_1.Entity)('puzzles'), + (0, typeorm_1.Index)(['category', 'difficulty']), + (0, typeorm_1.Index)(['isActive', 'publishedAt']), + (0, typeorm_1.Index)(['createdBy']) +], Puzzle); + + +/***/ }), + +/***/ "./src/puzzles/entities/theme.entity.ts": +/*!**********************************************!*\ + !*** ./src/puzzles/entities/theme.entity.ts ***! + \**********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Theme = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const collection_entity_1 = __webpack_require__(/*! ./collection.entity */ "./src/puzzles/entities/collection.entity.ts"); +let Theme = class Theme { +}; +exports.Theme = Theme; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Theme.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ unique: true }), + __metadata("design:type", String) +], Theme.prototype, "name", void 0); +__decorate([ + (0, typeorm_1.Column)({ nullable: true }), + __metadata("design:type", String) +], Theme.prototype, "description", void 0); +__decorate([ + (0, typeorm_1.ManyToMany)(() => collection_entity_1.Collection, (collection) => collection.themes), + (0, typeorm_1.JoinTable)(), + __metadata("design:type", Array) +], Theme.prototype, "collections", void 0); +exports.Theme = Theme = __decorate([ + (0, typeorm_1.Entity)('themes') +], Theme); + + +/***/ }), + +/***/ "./src/puzzles/puzzles.controller.ts": +/*!*******************************************!*\ + !*** ./src/puzzles/puzzles.controller.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var PuzzlesController_1; +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PuzzlesController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const puzzles_service_1 = __webpack_require__(/*! ./puzzles.service */ "./src/puzzles/puzzles.service.ts"); +const dto_1 = __webpack_require__(/*! ./dto */ "./src/puzzles/dto/index.ts"); +let PuzzlesController = PuzzlesController_1 = class PuzzlesController { + constructor(puzzlesService) { + this.puzzlesService = puzzlesService; + this.logger = new common_1.Logger(PuzzlesController_1.name); + } + async create(createPuzzleDto) { + const userId = 'temp-user-id'; + this.logger.log(`Creating puzzle: ${createPuzzleDto.title} by user: ${userId}`); + return await this.puzzlesService.create(createPuzzleDto, userId); + } + async findAll(searchDto) { + this.logger.log(`Searching puzzles with filters: ${JSON.stringify(searchDto)}`); + return await this.puzzlesService.findAll(searchDto); + } + async getAnalytics(period) { + return await this.puzzlesService.getAnalytics(period); + } + async bulkUpdate(puzzleIds, bulkUpdateDto) { + const userId = 'temp-user-id'; + this.logger.log(`Bulk updating ${puzzleIds.length} puzzles with action: ${bulkUpdateDto.action}`); + return await this.puzzlesService.bulkUpdate(puzzleIds, bulkUpdateDto, userId); + } + async findOne(id) { + return await this.puzzlesService.findOne(id); + } + async getPuzzleStats(id, statsDto) { + const puzzle = await this.puzzlesService.findOne(id); + return { + puzzle, + stats: { + period: statsDto.period, + includeStats: statsDto.includeStats, + }, + }; + } + async update(id, updatePuzzleDto) { + const userId = 'temp-user-id'; + this.logger.log(`Updating puzzle: ${id} by user: ${userId}`); + return await this.puzzlesService.update(id, updatePuzzleDto, userId); + } + async remove(id) { + const userId = 'temp-user-id'; + this.logger.log(`Deleting puzzle: ${id} by user: ${userId}`); + await this.puzzlesService.remove(id, userId); + } + async publish(id) { + const userId = 'temp-user-id'; + this.logger.log(`Publishing puzzle: ${id} by user: ${userId}`); + return await this.puzzlesService.update(id, { isPublished: true }, userId); + } + async unpublish(id) { + const userId = 'temp-user-id'; + this.logger.log(`Unpublishing puzzle: ${id} by user: ${userId}`); + return await this.puzzlesService.update(id, { isPublished: false }, userId); + } + async duplicate(id) { + const userId = 'temp-user-id'; + this.logger.log(`Duplicating puzzle: ${id} by user: ${userId}`); + const originalPuzzle = await this.puzzlesService.findOne(id); + const duplicateDto = { + title: `${originalPuzzle.title} (Copy)`, + description: originalPuzzle.description, + category: originalPuzzle.category, + difficulty: originalPuzzle.difficulty, + difficultyRating: originalPuzzle.difficultyRating, + basePoints: originalPuzzle.basePoints, + timeLimit: originalPuzzle.timeLimit, + maxHints: originalPuzzle.maxHints, + content: originalPuzzle.content, + hints: originalPuzzle.hints, + tags: originalPuzzle.tags, + scoring: originalPuzzle.scoring, + isFeatured: false, + }; + return await this.puzzlesService.create(duplicateDto, userId); + } +}; +exports.PuzzlesController = PuzzlesController; +__decorate([ + (0, common_1.Post)(), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof dto_1.CreatePuzzleDto !== "undefined" && dto_1.CreatePuzzleDto) === "function" ? _b : Object]), + __metadata("design:returntype", typeof (_c = typeof Promise !== "undefined" && Promise) === "function" ? _c : Object) +], PuzzlesController.prototype, "create", null); +__decorate([ + (0, common_1.Get)(), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_d = typeof dto_1.SearchPuzzleDto !== "undefined" && dto_1.SearchPuzzleDto) === "function" ? _d : Object]), + __metadata("design:returntype", typeof (_e = typeof Promise !== "undefined" && Promise) === "function" ? _e : Object) +], PuzzlesController.prototype, "findAll", null); +__decorate([ + (0, common_1.Get)('analytics'), + __param(0, (0, common_1.Query)('period')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_f = typeof Promise !== "undefined" && Promise) === "function" ? _f : Object) +], PuzzlesController.prototype, "getAnalytics", null); +__decorate([ + (0, common_1.Patch)('bulk'), + __param(0, (0, common_1.Body)('puzzleIds', new common_1.ParseArrayPipe({ items: String }))), + __param(1, (0, common_1.Body)('bulkUpdate')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Array, typeof (_g = typeof dto_1.BulkUpdateDto !== "undefined" && dto_1.BulkUpdateDto) === "function" ? _g : Object]), + __metadata("design:returntype", Promise) +], PuzzlesController.prototype, "bulkUpdate", null); +__decorate([ + (0, common_1.Get)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_h = typeof Promise !== "undefined" && Promise) === "function" ? _h : Object) +], PuzzlesController.prototype, "findOne", null); +__decorate([ + (0, common_1.Get)(':id/stats'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_j = typeof dto_1.PuzzleStatsDto !== "undefined" && dto_1.PuzzleStatsDto) === "function" ? _j : Object]), + __metadata("design:returntype", Promise) +], PuzzlesController.prototype, "getPuzzleStats", null); +__decorate([ + (0, common_1.Patch)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_k = typeof dto_1.UpdatePuzzleDto !== "undefined" && dto_1.UpdatePuzzleDto) === "function" ? _k : Object]), + __metadata("design:returntype", typeof (_l = typeof Promise !== "undefined" && Promise) === "function" ? _l : Object) +], PuzzlesController.prototype, "update", null); +__decorate([ + (0, common_1.Delete)(':id'), + (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_m = typeof Promise !== "undefined" && Promise) === "function" ? _m : Object) +], PuzzlesController.prototype, "remove", null); +__decorate([ + (0, common_1.Post)(':id/publish'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_o = typeof Promise !== "undefined" && Promise) === "function" ? _o : Object) +], PuzzlesController.prototype, "publish", null); +__decorate([ + (0, common_1.Post)(':id/unpublish'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_p = typeof Promise !== "undefined" && Promise) === "function" ? _p : Object) +], PuzzlesController.prototype, "unpublish", null); +__decorate([ + (0, common_1.Post)(':id/duplicate'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_q = typeof Promise !== "undefined" && Promise) === "function" ? _q : Object) +], PuzzlesController.prototype, "duplicate", null); +exports.PuzzlesController = PuzzlesController = PuzzlesController_1 = __decorate([ + (0, common_1.Controller)('puzzles'), + (0, common_1.UseInterceptors)(common_1.ClassSerializerInterceptor), + __metadata("design:paramtypes", [typeof (_a = typeof puzzles_service_1.PuzzlesService !== "undefined" && puzzles_service_1.PuzzlesService) === "function" ? _a : Object]) +], PuzzlesController); + + +/***/ }), + +/***/ "./src/puzzles/puzzles.module.ts": +/*!***************************************!*\ + !*** ./src/puzzles/puzzles.module.ts ***! + \***************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PuzzlesModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const puzzles_service_1 = __webpack_require__(/*! ./puzzles.service */ "./src/puzzles/puzzles.service.ts"); +const puzzles_controller_1 = __webpack_require__(/*! ./puzzles.controller */ "./src/puzzles/puzzles.controller.ts"); +const puzzle_entity_1 = __webpack_require__(/*! ./entities/puzzle.entity */ "./src/puzzles/entities/puzzle.entity.ts"); +const puzzle_progress_entity_1 = __webpack_require__(/*! ../game-logic/entities/puzzle-progress.entity */ "./src/game-logic/entities/puzzle-progress.entity.ts"); +const puzzle_rating_entity_1 = __webpack_require__(/*! ./entities/puzzle-rating.entity */ "./src/puzzles/entities/puzzle-rating.entity.ts"); +const category_entity_1 = __webpack_require__(/*! ./entities/category.entity */ "./src/puzzles/entities/category.entity.ts"); +const category_service_1 = __webpack_require__(/*! ./category.service */ "./src/puzzles/category.service.ts"); +const category_controller_1 = __webpack_require__(/*! ./category.controller */ "./src/puzzles/category.controller.ts"); +const collection_entity_1 = __webpack_require__(/*! ./entities/collection.entity */ "./src/puzzles/entities/collection.entity.ts"); +const collection_service_1 = __webpack_require__(/*! ./collection.service */ "./src/puzzles/collection.service.ts"); +const collection_controller_1 = __webpack_require__(/*! ./collection.controller */ "./src/puzzles/collection.controller.ts"); +const theme_entity_1 = __webpack_require__(/*! ./entities/theme.entity */ "./src/puzzles/entities/theme.entity.ts"); +const theme_service_1 = __webpack_require__(/*! ./theme.service */ "./src/puzzles/theme.service.ts"); +const theme_controller_1 = __webpack_require__(/*! ./theme.controller */ "./src/puzzles/theme.controller.ts"); +let PuzzlesModule = class PuzzlesModule { +}; +exports.PuzzlesModule = PuzzlesModule; +exports.PuzzlesModule = PuzzlesModule = __decorate([ + (0, common_1.Module)({ + imports: [ + typeorm_1.TypeOrmModule.forFeature([ + puzzle_entity_1.Puzzle, + puzzle_progress_entity_1.PuzzleProgress, + puzzle_rating_entity_1.PuzzleRating, + category_entity_1.Category, + collection_entity_1.Collection, + theme_entity_1.Theme + ]) + ], + controllers: [ + puzzles_controller_1.PuzzlesController, + category_controller_1.CategoriesController, + collection_controller_1.CollectionsController, + theme_controller_1.ThemesController + ], + providers: [ + puzzles_service_1.PuzzlesService, + category_service_1.CategoriesService, + collection_service_1.CollectionsService, + theme_service_1.ThemesService + ], + exports: [puzzles_service_1.PuzzlesService] + }) +], PuzzlesModule); + + +/***/ }), + +/***/ "./src/puzzles/puzzles.service.ts": +/*!****************************************!*\ + !*** ./src/puzzles/puzzles.service.ts ***! + \****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var PuzzlesService_1; +var _a, _b, _c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PuzzlesService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const puzzle_entity_1 = __webpack_require__(/*! ./entities/puzzle.entity */ "./src/puzzles/entities/puzzle.entity.ts"); +const puzzle_progress_entity_1 = __webpack_require__(/*! ../game-logic/entities/puzzle-progress.entity */ "./src/game-logic/entities/puzzle-progress.entity.ts"); +const puzzle_rating_entity_1 = __webpack_require__(/*! ./entities/puzzle-rating.entity */ "./src/puzzles/entities/puzzle-rating.entity.ts"); +const dto_1 = __webpack_require__(/*! ./dto */ "./src/puzzles/dto/index.ts"); +let PuzzlesService = PuzzlesService_1 = class PuzzlesService { + constructor(puzzleRepository, progressRepository, ratingRepository) { + this.puzzleRepository = puzzleRepository; + this.progressRepository = progressRepository; + this.ratingRepository = ratingRepository; + this.logger = new common_1.Logger(PuzzlesService_1.name); + } + async create(createPuzzleDto, createdBy) { + try { + const puzzleData = { + title: createPuzzleDto.title, + description: createPuzzleDto.description, + category: createPuzzleDto.category, + difficulty: createPuzzleDto.difficulty, + difficultyRating: createPuzzleDto.difficultyRating, + basePoints: createPuzzleDto.basePoints, + timeLimit: createPuzzleDto.timeLimit, + maxHints: createPuzzleDto.maxHints, + content: createPuzzleDto.content, + hints: createPuzzleDto.hints || [], + tags: createPuzzleDto.tags || [], + prerequisites: createPuzzleDto.prerequisites || [], + scoring: createPuzzleDto.scoring || {}, + isFeatured: createPuzzleDto.isFeatured || false, + createdBy, + publishedAt: undefined, + analytics: { + completionRate: 0, + averageAttempts: 0, + commonErrors: [], + timeDistribution: { + min: 0, + max: 0, + median: 0, + q1: 0, + q3: 0 + } + }, + metadata: { + version: '1.0', + lastModifiedBy: createdBy, + reviewStatus: 'pending' + } + }; + const puzzle = this.puzzleRepository.create(puzzleData); + const savedPuzzle = await this.puzzleRepository.save(puzzle); + this.logger.log(`Created puzzle: ${savedPuzzle.id} by user: ${createdBy}`); + return savedPuzzle; + } + catch (error) { + this.logger.error(`Failed to create puzzle: ${error.message}`, error.stack); + throw error; + } + } + async findAll(searchDto) { + try { + const { search, category, difficulty, minRating, maxRating, tags, isFeatured, isPublished, createdBy, page = 1, limit = 20, sortBy = dto_1.SortBy.CREATED_AT, sortOrder = dto_1.SortOrder.DESC } = searchDto; + const queryBuilder = this.puzzleRepository + .createQueryBuilder('puzzle') + .where('puzzle.deletedAt IS NULL'); + if (search) { + queryBuilder.andWhere('(puzzle.title ILIKE :search OR puzzle.description ILIKE :search)', { search: `%${search}%` }); + } + if (category) { + queryBuilder.andWhere('puzzle.category = :category', { category }); + } + if (difficulty) { + queryBuilder.andWhere('puzzle.difficulty = :difficulty', { difficulty }); + } + if (minRating !== undefined) { + queryBuilder.andWhere('puzzle.difficultyRating >= :minRating', { minRating }); + } + if (maxRating !== undefined) { + queryBuilder.andWhere('puzzle.difficultyRating <= :maxRating', { maxRating }); + } + if (isFeatured !== undefined) { + queryBuilder.andWhere('puzzle.isFeatured = :isFeatured', { isFeatured }); + } + if (isPublished !== undefined) { + if (isPublished) { + queryBuilder.andWhere('puzzle.publishedAt IS NOT NULL'); + } + else { + queryBuilder.andWhere('puzzle.publishedAt IS NULL'); + } + } + if (createdBy) { + queryBuilder.andWhere('puzzle.createdBy = :createdBy', { createdBy }); + } + this.applySorting(queryBuilder, sortBy, sortOrder); + const [puzzles, total] = await queryBuilder + .skip((page - 1) * limit) + .take(limit) + .getManyAndCount(); + const puzzlesWithStats = await this.enhanceWithStats(puzzles); + return { + puzzles: puzzlesWithStats, + total, + page, + limit, + totalPages: Math.ceil(total / limit) + }; + } + catch (error) { + this.logger.error(`Failed to search puzzles: ${error.message}`, error.stack); + throw error; + } + } + async findOne(id, userId) { + try { + const puzzle = await this.puzzleRepository + .createQueryBuilder('puzzle') + .where('puzzle.id = :id', { id }) + .andWhere('puzzle.deletedAt IS NULL') + .getOne(); + if (!puzzle) { + throw new common_1.NotFoundException(`Puzzle with ID ${id} not found`); + } + if (!puzzle.publishedAt && userId !== puzzle.createdBy) { + throw new common_1.NotFoundException(`Puzzle with ID ${id} not found`); + } + const [enhancedPuzzle] = await this.enhanceWithStats([puzzle]); + return enhancedPuzzle; + } + catch (error) { + this.logger.error(`Failed to find puzzle ${id}: ${error.message}`, error.stack); + throw error; + } + } + async update(id, updatePuzzleDto, userId) { + try { + const puzzle = await this.findOne(id, userId); + if (puzzle.createdBy !== userId) { + throw new common_1.BadRequestException('You can only update puzzles you created'); + } + const updateData = { ...updatePuzzleDto }; + if (updateData.isPublished !== undefined) { + updateData.publishedAt = updateData.isPublished ? new Date() : null; + delete updateData.isPublished; + } + await this.puzzleRepository.update(id, updateData); + const updatedPuzzle = await this.findOne(id, userId); + this.logger.log(`Updated puzzle: ${id}`); + return updatedPuzzle; + } + catch (error) { + this.logger.error(`Failed to update puzzle ${id}: ${error.message}`, error.stack); + throw error; + } + } + async remove(id, userId) { + try { + const puzzle = await this.findOne(id, userId); + if (puzzle.createdBy !== userId) { + throw new common_1.BadRequestException('You can only delete puzzles you created'); + } + await this.puzzleRepository.softDelete(id); + this.logger.log(`Deleted puzzle: ${id}`); + } + catch (error) { + this.logger.error(`Failed to remove puzzle ${id}: ${error.message}`, error.stack); + throw error; + } + } + async bulkUpdate(puzzleIds, bulkUpdateDto, userId) { + const errors = []; + let updated = 0; + try { + for (const puzzleId of puzzleIds) { + try { + await this.executeBulkAction(puzzleId, bulkUpdateDto, userId); + updated++; + } + catch (error) { + errors.push(`${puzzleId}: ${error.message}`); + } + } + this.logger.log(`Bulk update completed: ${updated} updated, ${errors.length} errors`); + return { updated, errors }; + } + catch (error) { + this.logger.error(`Bulk update failed: ${error.message}`, error.stack); + throw error; + } + } + async getAnalytics(period = 'all') { + try { + const baseQuery = this.puzzleRepository.createQueryBuilder('puzzle') + .where('puzzle.deletedAt IS NULL'); + const [totalPuzzles, publishedPuzzles, topPuzzles] = await Promise.all([ + baseQuery.getCount(), + baseQuery.clone().andWhere('puzzle.publishedAt IS NOT NULL').getCount(), + this.puzzleRepository.find({ + where: { deletedAt: (0, typeorm_2.IsNull)(), publishedAt: (0, typeorm_2.Not)((0, typeorm_2.IsNull)()) }, + order: { completions: 'DESC' }, + take: 10 + }) + ]); + return { + totalPuzzles, + publishedPuzzles, + categoryCounts: {}, + difficultyDistribution: {}, + averageRating: 0, + topPerformingPuzzles: topPuzzles, + recentActivity: { + created: 0, + published: 0, + played: 0 + } + }; + } + catch (error) { + this.logger.error(`Failed to get analytics: ${error.message}`, error.stack); + throw error; + } + } + applySorting(queryBuilder, sortBy, sortOrder) { + switch (sortBy) { + case dto_1.SortBy.TITLE: + queryBuilder.orderBy('puzzle.title', sortOrder); + break; + case dto_1.SortBy.DIFFICULTY: + queryBuilder.orderBy('puzzle.difficultyRating', sortOrder); + break; + case dto_1.SortBy.RATING: + queryBuilder.orderBy('puzzle.averageRating', sortOrder); + break; + case dto_1.SortBy.PLAYS: + queryBuilder.orderBy('puzzle.attempts', sortOrder); + break; + case dto_1.SortBy.COMPLETION_RATE: + queryBuilder.orderBy('puzzle.completions', sortOrder); + break; + default: + queryBuilder.orderBy('puzzle.createdAt', sortOrder); + } + } + async enhanceWithStats(puzzles) { + return puzzles.map(puzzle => ({ + ...puzzle, + totalPlays: puzzle.attempts, + uniquePlayers: 0, + completionRate: puzzle.attempts > 0 ? (puzzle.completions / puzzle.attempts) * 100 : 0, + averageRating: puzzle.averageRating, + averageCompletionTime: puzzle.averageCompletionTime + })); + } + async executeBulkAction(puzzleId, bulkUpdateDto, userId) { + const { action, value } = bulkUpdateDto; + switch (action) { + case dto_1.BulkAction.PUBLISH: + await this.puzzleRepository.update(puzzleId, { publishedAt: new Date() }); + break; + case dto_1.BulkAction.UNPUBLISH: + await this.puzzleRepository.update(puzzleId, { publishedAt: undefined }); + break; + case dto_1.BulkAction.ARCHIVE: + await this.puzzleRepository.softDelete(puzzleId); + break; + default: + throw new common_1.BadRequestException(`Unsupported bulk action: ${action}`); + } + } +}; +exports.PuzzlesService = PuzzlesService; +exports.PuzzlesService = PuzzlesService = PuzzlesService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(puzzle_entity_1.Puzzle)), + __param(1, (0, typeorm_1.InjectRepository)(puzzle_progress_entity_1.PuzzleProgress)), + __param(2, (0, typeorm_1.InjectRepository)(puzzle_rating_entity_1.PuzzleRating)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object]) +], PuzzlesService); + + +/***/ }), + +/***/ "./src/puzzles/theme.controller.ts": +/*!*****************************************!*\ + !*** ./src/puzzles/theme.controller.ts ***! + \*****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d, _e, _f, _g, _h; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ThemesController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const theme_service_1 = __webpack_require__(/*! ./theme.service */ "./src/puzzles/theme.service.ts"); +const create_theme_dto_1 = __webpack_require__(/*! ./dto/create-theme.dto */ "./src/puzzles/dto/create-theme.dto.ts"); +const update_theme_dto_1 = __webpack_require__(/*! ./dto/update-theme.dto */ "./src/puzzles/dto/update-theme.dto.ts"); +let ThemesController = class ThemesController { + constructor(themesService) { + this.themesService = themesService; + } + create(createThemeDto) { + return this.themesService.create(createThemeDto); + } + findAll() { + return this.themesService.findAll(); + } + findOne(id) { + return this.themesService.findOne(id); + } + update(id, updateThemeDto) { + return this.themesService.update(id, updateThemeDto); + } + remove(id) { + return this.themesService.remove(id); + } +}; +exports.ThemesController = ThemesController; +__decorate([ + (0, common_1.Post)(), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof create_theme_dto_1.CreateThemeDto !== "undefined" && create_theme_dto_1.CreateThemeDto) === "function" ? _b : Object]), + __metadata("design:returntype", typeof (_c = typeof Promise !== "undefined" && Promise) === "function" ? _c : Object) +], ThemesController.prototype, "create", null); +__decorate([ + (0, common_1.Get)(), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", typeof (_d = typeof Promise !== "undefined" && Promise) === "function" ? _d : Object) +], ThemesController.prototype, "findAll", null); +__decorate([ + (0, common_1.Get)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_e = typeof Promise !== "undefined" && Promise) === "function" ? _e : Object) +], ThemesController.prototype, "findOne", null); +__decorate([ + (0, common_1.Patch)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_f = typeof update_theme_dto_1.UpdateThemeDto !== "undefined" && update_theme_dto_1.UpdateThemeDto) === "function" ? _f : Object]), + __metadata("design:returntype", typeof (_g = typeof Promise !== "undefined" && Promise) === "function" ? _g : Object) +], ThemesController.prototype, "update", null); +__decorate([ + (0, common_1.Delete)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", typeof (_h = typeof Promise !== "undefined" && Promise) === "function" ? _h : Object) +], ThemesController.prototype, "remove", null); +exports.ThemesController = ThemesController = __decorate([ + (0, common_1.Controller)('themes'), + __metadata("design:paramtypes", [typeof (_a = typeof theme_service_1.ThemesService !== "undefined" && theme_service_1.ThemesService) === "function" ? _a : Object]) +], ThemesController); + + +/***/ }), + +/***/ "./src/puzzles/theme.service.ts": +/*!**************************************!*\ + !*** ./src/puzzles/theme.service.ts ***! + \**************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ThemesService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const theme_entity_1 = __webpack_require__(/*! ./entities/theme.entity */ "./src/puzzles/entities/theme.entity.ts"); +const collection_entity_1 = __webpack_require__(/*! ./entities/collection.entity */ "./src/puzzles/entities/collection.entity.ts"); +let ThemesService = class ThemesService { + constructor(themesRepository, collectionsRepository) { + this.themesRepository = themesRepository; + this.collectionsRepository = collectionsRepository; + } + async create(createThemeDto) { + const { collectionIds, ...themeData } = createThemeDto; + const theme = this.themesRepository.create(themeData); + if (collectionIds && collectionIds.length > 0) { + const collections = await this.collectionsRepository.findBy({ id: (0, typeorm_2.In)(collectionIds) }); + if (collections.length !== collectionIds.length) { + throw new common_1.BadRequestException('One or more collection IDs not found.'); + } + theme.collections = collections; + } + return this.themesRepository.save(theme); + } + async findAll() { + return this.themesRepository.find({ + relations: ['collections'], + }); + } + async findOne(id) { + const theme = await this.themesRepository.findOne({ + where: { id }, + relations: ['collections'], + }); + if (!theme) { + throw new common_1.NotFoundException(`Theme with ID "${id}" not found`); + } + return theme; + } + async update(id, updateThemeDto) { + const theme = await this.findOne(id); + const { collectionIds, ...themeData } = updateThemeDto; + Object.assign(theme, themeData); + if (collectionIds !== undefined) { + if (collectionIds.length > 0) { + const collections = await this.collectionsRepository.findBy({ id: (0, typeorm_2.In)(collectionIds) }); + if (collections.length !== collectionIds.length) { + throw new common_1.BadRequestException('One or more collection IDs not found.'); + } + theme.collections = collections; + } + else { + theme.collections = []; + } + } + return this.themesRepository.save(theme); + } + async remove(id) { + await this.findOne(id); + const result = await this.themesRepository.delete(id); + if (result.affected === 0) { + throw new common_1.NotFoundException(`Theme with ID "${id}" not found`); + } + } +}; +exports.ThemesService = ThemesService; +exports.ThemesService = ThemesService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(theme_entity_1.Theme)), + __param(1, (0, typeorm_1.InjectRepository)(collection_entity_1.Collection)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object]) +], ThemesService); + + +/***/ }), + +/***/ "./src/rabbitmq/rabbitmq.module.ts": +/*!*****************************************!*\ + !*** ./src/rabbitmq/rabbitmq.module.ts ***! + \*****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.RabbitMQModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const microservices_1 = __webpack_require__(/*! @nestjs/microservices */ "@nestjs/microservices"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +let RabbitMQModule = class RabbitMQModule { +}; +exports.RabbitMQModule = RabbitMQModule; +exports.RabbitMQModule = RabbitMQModule = __decorate([ + (0, common_1.Global)(), + (0, common_1.Module)({ + imports: [ + microservices_1.ClientsModule.registerAsync([ + { + name: 'REPLAY_SERVICE', + useFactory: (configService) => ({ + transport: microservices_1.Transport.RMQ, + options: { + urls: [configService.get('RABBITMQ_URL') || 'amqp://admin:rabbitmq123@rabbitmq:5672'], + queue: 'replay_queue', + queueOptions: { + durable: true, + }, + }, + }), + inject: [config_1.ConfigService], + }, + ]), + ], + exports: [microservices_1.ClientsModule], + }) +], RabbitMQModule); + + +/***/ }), + +/***/ "./src/referrals/dto/create-referral-code.dto.ts": +/*!*******************************************************!*\ + !*** ./src/referrals/dto/create-referral-code.dto.ts ***! + \*******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreateReferralCodeDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class CreateReferralCodeDto { +} +exports.CreateReferralCodeDto = CreateReferralCodeDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsDateString)(), + __metadata("design:type", String) +], CreateReferralCodeDto.prototype, "expiresAt", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsBoolean)(), + __metadata("design:type", Boolean) +], CreateReferralCodeDto.prototype, "isActive", void 0); + + +/***/ }), + +/***/ "./src/referrals/dto/referral-analytics.dto.ts": +/*!*****************************************************!*\ + !*** ./src/referrals/dto/referral-analytics.dto.ts ***! + \*****************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ReferralAnalyticsDto = exports.ReferralAnalyticsPeriod = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +var ReferralAnalyticsPeriod; +(function (ReferralAnalyticsPeriod) { + ReferralAnalyticsPeriod["DAY"] = "day"; + ReferralAnalyticsPeriod["WEEK"] = "week"; + ReferralAnalyticsPeriod["MONTH"] = "month"; + ReferralAnalyticsPeriod["YEAR"] = "year"; + ReferralAnalyticsPeriod["ALL_TIME"] = "all_time"; +})(ReferralAnalyticsPeriod || (exports.ReferralAnalyticsPeriod = ReferralAnalyticsPeriod = {})); +class ReferralAnalyticsDto { +} +exports.ReferralAnalyticsDto = ReferralAnalyticsDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsDateString)(), + __metadata("design:type", String) +], ReferralAnalyticsDto.prototype, "startDate", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsDateString)(), + __metadata("design:type", String) +], ReferralAnalyticsDto.prototype, "endDate", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)(ReferralAnalyticsPeriod), + __metadata("design:type", String) +], ReferralAnalyticsDto.prototype, "period", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ReferralAnalyticsDto.prototype, "userId", void 0); + + +/***/ }), + +/***/ "./src/referrals/dto/referral-leaderboard.dto.ts": +/*!*******************************************************!*\ + !*** ./src/referrals/dto/referral-leaderboard.dto.ts ***! + \*******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ReferralLeaderboardDto = exports.ReferralLeaderboardType = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +var ReferralLeaderboardType; +(function (ReferralLeaderboardType) { + ReferralLeaderboardType["TOTAL_REFERRALS"] = "total_referrals"; + ReferralLeaderboardType["ACTIVE_REFERRALS"] = "active_referrals"; + ReferralLeaderboardType["REWARDS_EARNED"] = "rewards_earned"; +})(ReferralLeaderboardType || (exports.ReferralLeaderboardType = ReferralLeaderboardType = {})); +class ReferralLeaderboardDto { + constructor() { + this.type = ReferralLeaderboardType.TOTAL_REFERRALS; + this.limit = 100; + this.offset = 0; + } +} +exports.ReferralLeaderboardDto = ReferralLeaderboardDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)(ReferralLeaderboardType), + __metadata("design:type", String) +], ReferralLeaderboardDto.prototype, "type", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_transformer_1.Type)(() => Number), + (0, class_validator_1.IsInt)(), + (0, class_validator_1.Min)(1), + __metadata("design:type", Number) +], ReferralLeaderboardDto.prototype, "limit", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_transformer_1.Type)(() => Number), + (0, class_validator_1.IsInt)(), + (0, class_validator_1.Min)(0), + __metadata("design:type", Number) +], ReferralLeaderboardDto.prototype, "offset", void 0); + + +/***/ }), + +/***/ "./src/referrals/dto/use-referral-code.dto.ts": +/*!****************************************************!*\ + !*** ./src/referrals/dto/use-referral-code.dto.ts ***! + \****************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UseReferralCodeDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class UseReferralCodeDto { +} +exports.UseReferralCodeDto = UseReferralCodeDto; +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsNotEmpty)(), + __metadata("design:type", String) +], UseReferralCodeDto.prototype, "code", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], UseReferralCodeDto.prototype, "source", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], UseReferralCodeDto.prototype, "campaign", void 0); + + +/***/ }), + +/***/ "./src/referrals/entities/referral-code.entity.ts": +/*!********************************************************!*\ + !*** ./src/referrals/entities/referral-code.entity.ts ***! + \********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ReferralCode = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +let ReferralCode = class ReferralCode { +}; +exports.ReferralCode = ReferralCode; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], ReferralCode.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, unique: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], ReferralCode.prototype, "code", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], ReferralCode.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.OneToOne)(() => user_entity_1.User), + (0, typeorm_1.JoinColumn)({ name: 'userId' }), + __metadata("design:type", typeof (_a = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _a : Object) +], ReferralCode.prototype, "user", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], ReferralCode.prototype, "totalReferrals", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], ReferralCode.prototype, "activeReferrals", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], ReferralCode.prototype, "totalRewardsEarned", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: true }), + __metadata("design:type", Boolean) +], ReferralCode.prototype, "isActive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], ReferralCode.prototype, "expiresAt", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], ReferralCode.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], ReferralCode.prototype, "updatedAt", void 0); +exports.ReferralCode = ReferralCode = __decorate([ + (0, typeorm_1.Entity)('referral_codes'), + (0, typeorm_1.Index)(['code'], { unique: true }), + (0, typeorm_1.Index)(['userId'], { unique: true }) +], ReferralCode); + + +/***/ }), + +/***/ "./src/referrals/entities/referral.entity.ts": +/*!***************************************************!*\ + !*** ./src/referrals/entities/referral.entity.ts ***! + \***************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f, _g, _h; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Referral = exports.ReferralStatus = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +const referral_code_entity_1 = __webpack_require__(/*! ./referral-code.entity */ "./src/referrals/entities/referral-code.entity.ts"); +var ReferralStatus; +(function (ReferralStatus) { + ReferralStatus["PENDING"] = "pending"; + ReferralStatus["COMPLETED"] = "completed"; + ReferralStatus["REWARDED"] = "rewarded"; + ReferralStatus["CANCELLED"] = "cancelled"; +})(ReferralStatus || (exports.ReferralStatus = ReferralStatus = {})); +let Referral = class Referral { +}; +exports.Referral = Referral; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Referral.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Referral.prototype, "referrerId", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => user_entity_1.User), + (0, typeorm_1.JoinColumn)({ name: 'referrerId' }), + __metadata("design:type", typeof (_a = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _a : Object) +], Referral.prototype, "referrer", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Referral.prototype, "refereeId", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => user_entity_1.User), + (0, typeorm_1.JoinColumn)({ name: 'refereeId' }), + __metadata("design:type", typeof (_b = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _b : Object) +], Referral.prototype, "referee", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + __metadata("design:type", String) +], Referral.prototype, "referralCodeId", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => referral_code_entity_1.ReferralCode), + (0, typeorm_1.JoinColumn)({ name: 'referralCodeId' }), + __metadata("design:type", typeof (_c = typeof referral_code_entity_1.ReferralCode !== "undefined" && referral_code_entity_1.ReferralCode) === "function" ? _c : Object) +], Referral.prototype, "referralCode", void 0); +__decorate([ + (0, typeorm_1.Column)({ + type: 'varchar', + length: 20, + default: ReferralStatus.PENDING, + }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Referral.prototype, "status", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], Referral.prototype, "referrerReward", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], Referral.prototype, "refereeReward", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], Referral.prototype, "referrerRewarded", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], Referral.prototype, "refereeRewarded", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], Referral.prototype, "referrerRewardedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], Referral.prototype, "refereeRewardedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_f = typeof Date !== "undefined" && Date) === "function" ? _f : Object) +], Referral.prototype, "completedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Referral.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + __metadata("design:type", typeof (_g = typeof Date !== "undefined" && Date) === "function" ? _g : Object) +], Referral.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + __metadata("design:type", typeof (_h = typeof Date !== "undefined" && Date) === "function" ? _h : Object) +], Referral.prototype, "updatedAt", void 0); +exports.Referral = Referral = __decorate([ + (0, typeorm_1.Entity)('referrals'), + (0, typeorm_1.Index)(['referrerId', 'refereeId'], { unique: true }), + (0, typeorm_1.Index)(['referralCodeId']), + (0, typeorm_1.Index)(['refereeId']), + (0, typeorm_1.Index)(['status']) +], Referral); + + +/***/ }), + +/***/ "./src/referrals/referral-analytics.service.ts": +/*!*****************************************************!*\ + !*** ./src/referrals/referral-analytics.service.ts ***! + \*****************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var ReferralAnalyticsService_1; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ReferralAnalyticsService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const referral_entity_1 = __webpack_require__(/*! ./entities/referral.entity */ "./src/referrals/entities/referral.entity.ts"); +const referral_code_entity_1 = __webpack_require__(/*! ./entities/referral-code.entity */ "./src/referrals/entities/referral-code.entity.ts"); +const referral_analytics_dto_1 = __webpack_require__(/*! ./dto/referral-analytics.dto */ "./src/referrals/dto/referral-analytics.dto.ts"); +const referral_entity_2 = __webpack_require__(/*! ./entities/referral.entity */ "./src/referrals/entities/referral.entity.ts"); +let ReferralAnalyticsService = ReferralAnalyticsService_1 = class ReferralAnalyticsService { + constructor(referralRepository, referralCodeRepository) { + this.referralRepository = referralRepository; + this.referralCodeRepository = referralCodeRepository; + this.logger = new common_1.Logger(ReferralAnalyticsService_1.name); + } + async getAnalytics(dto) { + const { startDate, endDate, period, userId } = dto; + let dateRange = null; + if (startDate && endDate) { + dateRange = { + start: new Date(startDate), + end: new Date(endDate), + }; + } + else if (period && period !== referral_analytics_dto_1.ReferralAnalyticsPeriod.ALL_TIME) { + dateRange = this.getPeriodDateRange(period); + } + const whereClause = {}; + if (userId) { + whereClause.referrerId = userId; + } + if (dateRange) { + whereClause.createdAt = (0, typeorm_2.Between)(dateRange.start, dateRange.end); + } + const referrals = await this.referralRepository.find({ + where: whereClause, + relations: ['referrer', 'referee'], + }); + const totalReferrals = referrals.length; + const completedReferrals = referrals.filter((r) => r.status === referral_entity_2.ReferralStatus.COMPLETED).length; + const pendingReferrals = referrals.filter((r) => r.status === referral_entity_2.ReferralStatus.PENDING).length; + const totalRewardsDistributed = referrals + .filter((r) => r.referrerRewarded) + .reduce((sum, r) => sum + r.referrerReward, 0) + + referrals + .filter((r) => r.refereeRewarded) + .reduce((sum, r) => sum + r.refereeReward, 0); + const referrerRewards = referrals + .filter((r) => r.referrerRewarded) + .reduce((sum, r) => sum + r.referrerReward, 0); + const refereeRewards = referrals + .filter((r) => r.refereeRewarded) + .reduce((sum, r) => sum + r.refereeReward, 0); + const conversionRate = totalReferrals > 0 ? (completedReferrals / totalReferrals) * 100 : 0; + const averageRewardsPerReferral = completedReferrals > 0 + ? totalRewardsDistributed / completedReferrals + : 0; + const referralsByStatus = referrals.reduce((acc, r) => { + acc[r.status] = (acc[r.status] || 0) + 1; + return acc; + }, {}); + const referralsByPeriod = this.groupReferralsByPeriod(referrals, period || referral_analytics_dto_1.ReferralAnalyticsPeriod.DAY); + const topReferrers = await this.getTopReferrers(userId, dateRange, 10); + return { + totalReferrals, + completedReferrals, + pendingReferrals, + totalRewardsDistributed, + referrerRewards, + refereeRewards, + conversionRate: Math.round(conversionRate * 100) / 100, + averageRewardsPerReferral: Math.round(averageRewardsPerReferral * 100) / 100, + referralsByStatus, + referralsByPeriod, + topReferrers, + }; + } + getPeriodDateRange(period) { + const end = new Date(); + let start = new Date(); + switch (period) { + case referral_analytics_dto_1.ReferralAnalyticsPeriod.DAY: + start.setDate(start.getDate() - 1); + break; + case referral_analytics_dto_1.ReferralAnalyticsPeriod.WEEK: + start.setDate(start.getDate() - 7); + break; + case referral_analytics_dto_1.ReferralAnalyticsPeriod.MONTH: + start.setMonth(start.getMonth() - 1); + break; + case referral_analytics_dto_1.ReferralAnalyticsPeriod.YEAR: + start.setFullYear(start.getFullYear() - 1); + break; + } + return { start, end }; + } + groupReferralsByPeriod(referrals, period) { + const groups = new Map(); + referrals.forEach((referral) => { + let key; + const date = new Date(referral.createdAt); + switch (period) { + case referral_analytics_dto_1.ReferralAnalyticsPeriod.DAY: + key = date.toISOString().split('T')[0]; + break; + case referral_analytics_dto_1.ReferralAnalyticsPeriod.WEEK: + const weekStart = new Date(date); + weekStart.setDate(date.getDate() - date.getDay()); + key = weekStart.toISOString().split('T')[0]; + break; + case referral_analytics_dto_1.ReferralAnalyticsPeriod.MONTH: + const month = date.getMonth() + 1; + key = `${date.getFullYear()}-${month < 10 ? '0' : ''}${month}`; + break; + case referral_analytics_dto_1.ReferralAnalyticsPeriod.YEAR: + key = String(date.getFullYear()); + break; + default: + key = date.toISOString().split('T')[0]; + } + if (!groups.has(key)) { + groups.set(key, { count: 0, completed: 0 }); + } + const group = groups.get(key); + group.count++; + if (referral.status === referral_entity_2.ReferralStatus.COMPLETED) { + group.completed++; + } + }); + return Array.from(groups.entries()) + .map(([period, data]) => ({ period, ...data })) + .sort((a, b) => a.period.localeCompare(b.period)); + } + async getTopReferrers(userId, dateRange, limit = 10) { + const queryBuilder = this.referralCodeRepository + .createQueryBuilder('rc') + .leftJoin('rc.user', 'user') + .select([ + 'rc.userId', + 'user.username', + 'rc.totalReferrals', + 'rc.totalRewardsEarned', + ]) + .where('rc.isActive = :isActive', { isActive: true }) + .andWhere('user.status = :status', { status: 'active' }); + if (userId) { + queryBuilder.andWhere('rc.userId = :userId', { userId }); + } + if (dateRange) { + queryBuilder.andWhere('rc.createdAt BETWEEN :start AND :end', { + start: dateRange.start, + end: dateRange.end, + }); + } + queryBuilder + .orderBy('rc.totalReferrals', 'DESC') + .addOrderBy('rc.totalRewardsEarned', 'DESC') + .limit(limit); + const results = await queryBuilder.getRawMany(); + return results.map((result) => ({ + userId: result.rc_userId, + username: result.user_username || 'Unknown', + count: result.rc_totalReferrals || 0, + rewards: result.rc_totalRewardsEarned || 0, + })); + } + async getDashboardSummary(userId) { + const whereClause = {}; + if (userId) { + whereClause.referrerId = userId; + } + const [referrals, recentReferrals] = await Promise.all([ + this.referralRepository.find({ where: whereClause }), + this.referralRepository.find({ + where: whereClause, + relations: ['referee'], + order: { createdAt: 'DESC' }, + take: 10, + }), + ]); + const totalReferrals = referrals.length; + const activeReferrals = referrals.filter((r) => r.status === referral_entity_2.ReferralStatus.PENDING).length; + const completedReferrals = referrals.filter((r) => r.status === referral_entity_2.ReferralStatus.COMPLETED).length; + const totalRewards = referrals + .filter((r) => r.referrerRewarded) + .reduce((sum, r) => sum + r.referrerReward, 0); + return { + totalReferrals, + activeReferrals, + completedReferrals, + totalRewards, + recentReferrals: recentReferrals.map((r) => ({ + id: r.id, + refereeId: r.refereeId, + refereeUsername: r.referee?.username || 'Unknown', + status: r.status, + createdAt: r.createdAt, + })), + }; + } +}; +exports.ReferralAnalyticsService = ReferralAnalyticsService; +exports.ReferralAnalyticsService = ReferralAnalyticsService = ReferralAnalyticsService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(referral_entity_1.Referral)), + __param(1, (0, typeorm_1.InjectRepository)(referral_code_entity_1.ReferralCode)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object]) +], ReferralAnalyticsService); + + +/***/ }), + +/***/ "./src/referrals/referral-leaderboard.service.ts": +/*!*******************************************************!*\ + !*** ./src/referrals/referral-leaderboard.service.ts ***! + \*******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var ReferralLeaderboardService_1; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ReferralLeaderboardService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const referral_code_entity_1 = __webpack_require__(/*! ./entities/referral-code.entity */ "./src/referrals/entities/referral-code.entity.ts"); +const referral_leaderboard_dto_1 = __webpack_require__(/*! ./dto/referral-leaderboard.dto */ "./src/referrals/dto/referral-leaderboard.dto.ts"); +let ReferralLeaderboardService = ReferralLeaderboardService_1 = class ReferralLeaderboardService { + constructor(referralCodeRepository) { + this.referralCodeRepository = referralCodeRepository; + this.logger = new common_1.Logger(ReferralLeaderboardService_1.name); + } + async getLeaderboard(type = referral_leaderboard_dto_1.ReferralLeaderboardType.TOTAL_REFERRALS, limit = 100, offset = 0) { + const queryBuilder = this.referralCodeRepository + .createQueryBuilder('rc') + .leftJoin('rc.user', 'user') + .select([ + 'rc.userId', + 'user.username', + 'rc.code', + 'rc.totalReferrals', + 'rc.activeReferrals', + 'rc.totalRewardsEarned', + ]) + .where('rc.isActive = :isActive', { isActive: true }) + .andWhere('user.status = :status', { status: 'active' }); + queryBuilder + .leftJoin('referrals', 'r', 'r.referralCodeId = rc.id AND r.status = :completedStatus', { completedStatus: 'completed' }) + .addSelect('COUNT(r.id)', 'completedReferrals') + .groupBy('rc.id') + .addGroupBy('user.id') + .addGroupBy('user.username') + .addGroupBy('rc.code') + .addGroupBy('rc.totalReferrals') + .addGroupBy('rc.activeReferrals') + .addGroupBy('rc.totalRewardsEarned') + .addGroupBy('rc.createdAt'); + switch (type) { + case referral_leaderboard_dto_1.ReferralLeaderboardType.TOTAL_REFERRALS: + queryBuilder.orderBy('rc.totalReferrals', 'DESC'); + break; + case referral_leaderboard_dto_1.ReferralLeaderboardType.ACTIVE_REFERRALS: + queryBuilder.orderBy('rc.activeReferrals', 'DESC'); + break; + case referral_leaderboard_dto_1.ReferralLeaderboardType.REWARDS_EARNED: + queryBuilder.orderBy('rc.totalRewardsEarned', 'DESC'); + break; + } + queryBuilder.addOrderBy('rc.totalReferrals', 'DESC'); + queryBuilder.addOrderBy('rc.createdAt', 'ASC'); + const countQuery = this.referralCodeRepository + .createQueryBuilder('rc') + .leftJoin('rc.user', 'user') + .where('rc.isActive = :isActive', { isActive: true }) + .andWhere('user.status = :status', { status: 'active' }); + const total = await countQuery.getCount(); + queryBuilder.skip(offset).take(limit); + const results = await queryBuilder.getRawMany(); + const entries = results.map((result, index) => ({ + userId: result.rc_userId, + username: result.user_username || 'Unknown', + code: result.rc_code, + totalReferrals: result.rc_totalReferrals || 0, + activeReferrals: result.rc_activeReferrals || 0, + completedReferrals: parseInt(result.completedReferrals || '0', 10), + totalRewardsEarned: result.rc_totalRewardsEarned || 0, + rank: offset + index + 1, + })); + return { + entries, + total, + type, + }; + } + async getUserRank(userId, type = referral_leaderboard_dto_1.ReferralLeaderboardType.TOTAL_REFERRALS) { + const referralCode = await this.referralCodeRepository.findOne({ + where: { userId }, + }); + if (!referralCode || !referralCode.isActive) { + return null; + } + const queryBuilder = this.referralCodeRepository + .createQueryBuilder('rc') + .where('rc.isActive = :isActive', { isActive: true }); + switch (type) { + case referral_leaderboard_dto_1.ReferralLeaderboardType.TOTAL_REFERRALS: + queryBuilder + .andWhere('(rc.totalReferrals > :value OR (rc.totalReferrals = :value AND rc.createdAt < :createdAt))', { + value: referralCode.totalReferrals, + createdAt: referralCode.createdAt, + }) + .orderBy('rc.totalReferrals', 'DESC'); + break; + case referral_leaderboard_dto_1.ReferralLeaderboardType.ACTIVE_REFERRALS: + queryBuilder + .andWhere('(rc.activeReferrals > :value OR (rc.activeReferrals = :value AND rc.createdAt < :createdAt))', { + value: referralCode.activeReferrals, + createdAt: referralCode.createdAt, + }) + .orderBy('rc.activeReferrals', 'DESC'); + break; + case referral_leaderboard_dto_1.ReferralLeaderboardType.REWARDS_EARNED: + queryBuilder + .andWhere('(rc.totalRewardsEarned > :value OR (rc.totalRewardsEarned = :value AND rc.createdAt < :createdAt))', { + value: referralCode.totalRewardsEarned, + createdAt: referralCode.createdAt, + }) + .orderBy('rc.totalRewardsEarned', 'DESC'); + break; + } + const count = await queryBuilder.getCount(); + return count + 1; + } +}; +exports.ReferralLeaderboardService = ReferralLeaderboardService; +exports.ReferralLeaderboardService = ReferralLeaderboardService = ReferralLeaderboardService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(referral_code_entity_1.ReferralCode)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object]) +], ReferralLeaderboardService); + + +/***/ }), + +/***/ "./src/referrals/referrals.controller.ts": +/*!***********************************************!*\ + !*** ./src/referrals/referrals.controller.ts ***! + \***********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d, _e, _f, _g; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ReferralsController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const referrals_service_1 = __webpack_require__(/*! ./referrals.service */ "./src/referrals/referrals.service.ts"); +const referral_leaderboard_service_1 = __webpack_require__(/*! ./referral-leaderboard.service */ "./src/referrals/referral-leaderboard.service.ts"); +const referral_analytics_service_1 = __webpack_require__(/*! ./referral-analytics.service */ "./src/referrals/referral-analytics.service.ts"); +const create_referral_code_dto_1 = __webpack_require__(/*! ./dto/create-referral-code.dto */ "./src/referrals/dto/create-referral-code.dto.ts"); +const use_referral_code_dto_1 = __webpack_require__(/*! ./dto/use-referral-code.dto */ "./src/referrals/dto/use-referral-code.dto.ts"); +const referral_analytics_dto_1 = __webpack_require__(/*! ./dto/referral-analytics.dto */ "./src/referrals/dto/referral-analytics.dto.ts"); +const referral_leaderboard_dto_1 = __webpack_require__(/*! ./dto/referral-leaderboard.dto */ "./src/referrals/dto/referral-leaderboard.dto.ts"); +const jwt_auth_guard_1 = __webpack_require__(/*! ../auth/guards/jwt-auth.guard */ "./src/auth/guards/jwt-auth.guard.ts"); +let ReferralsController = class ReferralsController { + constructor(referralsService, leaderboardService, analyticsService) { + this.referralsService = referralsService; + this.leaderboardService = leaderboardService; + this.analyticsService = analyticsService; + } + async createReferralCode(req, createDto) { + const userId = req.user?.id || req.user?.sub || req.user?.userId; + return this.referralsService.generateReferralCode(userId, createDto); + } + async getReferralCode(req) { + const userId = req.user?.id || req.user?.sub || req.user?.userId; + return this.referralsService.getReferralCode(userId); + } + async getInviteLink(req) { + const userId = req.user?.id || req.user?.sub || req.user?.userId; + const link = await this.referralsService.generateInviteLink(userId); + return { inviteLink: link }; + } + async useReferralCode(useDto, req) { + const refereeId = req.user?.id || req.user?.sub; + const metadata = { + registrationIp: req.ip, + userAgent: req.headers['user-agent'], + }; + return this.referralsService.useReferralCode(refereeId, useDto, metadata); + } + async getReferralStats(req) { + const userId = req.user?.id || req.user?.sub || req.user?.userId; + return this.referralsService.getReferralStats(userId); + } + async getMyReferrals(req, status) { + const userId = req.user?.id || req.user?.sub || req.user?.userId; + return this.referralsService.getReferralsByReferrer(userId, status); + } + async getReferral(id) { + return this.referralsService.getReferralById(id); + } + async completeReferral(id) { + return this.referralsService.completeReferral(id); + } + async getLeaderboard(query) { + return this.leaderboardService.getLeaderboard(query.type, query.limit, query.offset); + } + async getUserRank(req, type) { + const userId = req.user?.id || req.user?.sub || req.user?.userId; + return this.leaderboardService.getUserRank(userId, type); + } + async getDashboard(req) { + const userId = req.user?.id || req.user?.sub || req.user?.userId; + return this.analyticsService.getDashboardSummary(userId); + } + async getAnalytics(query) { + return this.analyticsService.getAnalytics(query); + } +}; +exports.ReferralsController = ReferralsController; +__decorate([ + (0, common_1.Post)('code'), + (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), + (0, common_1.HttpCode)(common_1.HttpStatus.CREATED), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, typeof (_d = typeof create_referral_code_dto_1.CreateReferralCodeDto !== "undefined" && create_referral_code_dto_1.CreateReferralCodeDto) === "function" ? _d : Object]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "createReferralCode", null); +__decorate([ + (0, common_1.Get)('code'), + (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), + __param(0, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "getReferralCode", null); +__decorate([ + (0, common_1.Get)('invite-link'), + (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), + __param(0, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "getInviteLink", null); +__decorate([ + (0, common_1.Post)('use'), + (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), + (0, common_1.HttpCode)(common_1.HttpStatus.CREATED), + __param(0, (0, common_1.Body)()), + __param(1, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_e = typeof use_referral_code_dto_1.UseReferralCodeDto !== "undefined" && use_referral_code_dto_1.UseReferralCodeDto) === "function" ? _e : Object, Object]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "useReferralCode", null); +__decorate([ + (0, common_1.Get)('stats'), + (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), + __param(0, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "getReferralStats", null); +__decorate([ + (0, common_1.Get)('my-referrals'), + (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Query)('status')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, String]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "getMyReferrals", null); +__decorate([ + (0, common_1.Get)(':id'), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "getReferral", null); +__decorate([ + (0, common_1.Post)(':id/complete'), + (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "completeReferral", null); +__decorate([ + (0, common_1.Get)('leaderboard/all'), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_f = typeof referral_leaderboard_dto_1.ReferralLeaderboardDto !== "undefined" && referral_leaderboard_dto_1.ReferralLeaderboardDto) === "function" ? _f : Object]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "getLeaderboard", null); +__decorate([ + (0, common_1.Get)('leaderboard/rank'), + (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Query)('type')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, String]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "getUserRank", null); +__decorate([ + (0, common_1.Get)('analytics/dashboard'), + (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), + __param(0, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "getDashboard", null); +__decorate([ + (0, common_1.Get)('analytics/overview'), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_g = typeof referral_analytics_dto_1.ReferralAnalyticsDto !== "undefined" && referral_analytics_dto_1.ReferralAnalyticsDto) === "function" ? _g : Object]), + __metadata("design:returntype", Promise) +], ReferralsController.prototype, "getAnalytics", null); +exports.ReferralsController = ReferralsController = __decorate([ + (0, common_1.Controller)('referrals'), + __metadata("design:paramtypes", [typeof (_a = typeof referrals_service_1.ReferralsService !== "undefined" && referrals_service_1.ReferralsService) === "function" ? _a : Object, typeof (_b = typeof referral_leaderboard_service_1.ReferralLeaderboardService !== "undefined" && referral_leaderboard_service_1.ReferralLeaderboardService) === "function" ? _b : Object, typeof (_c = typeof referral_analytics_service_1.ReferralAnalyticsService !== "undefined" && referral_analytics_service_1.ReferralAnalyticsService) === "function" ? _c : Object]) +], ReferralsController); + + +/***/ }), + +/***/ "./src/referrals/referrals.module.ts": +/*!*******************************************!*\ + !*** ./src/referrals/referrals.module.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ReferralsModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const referrals_controller_1 = __webpack_require__(/*! ./referrals.controller */ "./src/referrals/referrals.controller.ts"); +const referrals_service_1 = __webpack_require__(/*! ./referrals.service */ "./src/referrals/referrals.service.ts"); +const referral_leaderboard_service_1 = __webpack_require__(/*! ./referral-leaderboard.service */ "./src/referrals/referral-leaderboard.service.ts"); +const referral_analytics_service_1 = __webpack_require__(/*! ./referral-analytics.service */ "./src/referrals/referral-analytics.service.ts"); +const referral_code_entity_1 = __webpack_require__(/*! ./entities/referral-code.entity */ "./src/referrals/entities/referral-code.entity.ts"); +const referral_entity_1 = __webpack_require__(/*! ./entities/referral.entity */ "./src/referrals/entities/referral.entity.ts"); +const user_entity_1 = __webpack_require__(/*! ../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +let ReferralsModule = class ReferralsModule { +}; +exports.ReferralsModule = ReferralsModule; +exports.ReferralsModule = ReferralsModule = __decorate([ + (0, common_1.Module)({ + imports: [ + typeorm_1.TypeOrmModule.forFeature([referral_code_entity_1.ReferralCode, referral_entity_1.Referral, user_entity_1.User]), + config_1.ConfigModule, + ], + controllers: [referrals_controller_1.ReferralsController], + providers: [ + referrals_service_1.ReferralsService, + referral_leaderboard_service_1.ReferralLeaderboardService, + referral_analytics_service_1.ReferralAnalyticsService, + ], + exports: [referrals_service_1.ReferralsService, referral_leaderboard_service_1.ReferralLeaderboardService, referral_analytics_service_1.ReferralAnalyticsService], + }) +], ReferralsModule); + + +/***/ }), + +/***/ "./src/referrals/referrals.service.ts": +/*!********************************************!*\ + !*** ./src/referrals/referrals.service.ts ***! + \********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var ReferralsService_1; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ReferralsService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const referral_code_entity_1 = __webpack_require__(/*! ./entities/referral-code.entity */ "./src/referrals/entities/referral-code.entity.ts"); +const referral_entity_1 = __webpack_require__(/*! ./entities/referral.entity */ "./src/referrals/entities/referral.entity.ts"); +const user_entity_1 = __webpack_require__(/*! ../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +let ReferralsService = ReferralsService_1 = class ReferralsService { + constructor(referralCodeRepository, referralRepository, userRepository, configService) { + this.referralCodeRepository = referralCodeRepository; + this.referralRepository = referralRepository; + this.userRepository = userRepository; + this.configService = configService; + this.logger = new common_1.Logger(ReferralsService_1.name); + this.REFERRER_REWARD = 100; + this.REFEREE_REWARD = 50; + this.baseUrl = + this.configService.get('APP_BASE_URL') || + this.configService.get('app.cors.origin') || + 'http://localhost:3000'; + } + async generateReferralCode(userId, createDto) { + const user = await this.userRepository.findOne({ where: { id: userId } }); + if (!user) { + throw new common_1.NotFoundException(`User with ID ${userId} not found`); + } + const existingCode = await this.referralCodeRepository.findOne({ + where: { userId }, + }); + if (existingCode) { + return existingCode; + } + const code = await this.generateUniqueCode(); + const referralCode = this.referralCodeRepository.create({ + code, + userId, + isActive: createDto?.isActive ?? true, + expiresAt: createDto?.expiresAt + ? new Date(createDto.expiresAt) + : undefined, + }); + const saved = await this.referralCodeRepository.save(referralCode); + if (!user.metadata) { + user.metadata = {}; + } + user.metadata.referralCode = code; + await this.userRepository.save(user); + this.logger.log(`Generated referral code ${code} for user ${userId}`); + return saved; + } + async generateUniqueCode() { + const maxAttempts = 10; + let attempts = 0; + while (attempts < maxAttempts) { + const code = this.generateRandomCode(); + const exists = await this.referralCodeRepository.findOne({ + where: { code }, + }); + if (!exists) { + return code; + } + attempts++; + } + throw new Error('Failed to generate unique referral code'); + } + generateRandomCode(length = 8) { + const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; + let result = ''; + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; + } + async getReferralCode(userId) { + const code = await this.referralCodeRepository.findOne({ + where: { userId }, + relations: ['user'], + }); + if (!code) { + return this.generateReferralCode(userId); + } + return code; + } + async generateInviteLink(userId) { + const referralCode = await this.getReferralCode(userId); + if (!referralCode.isActive) { + throw new common_1.BadRequestException('Referral code is not active'); + } + if (referralCode.expiresAt && referralCode.expiresAt < new Date()) { + throw new common_1.BadRequestException('Referral code has expired'); + } + const inviteLink = `${this.baseUrl}/signup?ref=${referralCode.code}`; + return inviteLink; + } + async useReferralCode(refereeId, useDto, metadata) { + const referee = await this.userRepository.findOne({ + where: { id: refereeId }, + }); + if (!referee) { + throw new common_1.NotFoundException(`User with ID ${refereeId} not found`); + } + const referralCode = await this.referralCodeRepository.findOne({ + where: { code: useDto.code }, + relations: ['user'], + }); + if (!referralCode) { + throw new common_1.NotFoundException(`Referral code ${useDto.code} not found`); + } + if (!referralCode.isActive) { + throw new common_1.BadRequestException('Referral code is not active'); + } + if (referralCode.expiresAt && referralCode.expiresAt < new Date()) { + throw new common_1.BadRequestException('Referral code has expired'); + } + if (referralCode.userId === refereeId) { + throw new common_1.BadRequestException('Cannot use your own referral code'); + } + const existingReferral = await this.referralRepository.findOne({ + where: { + referrerId: referralCode.userId, + refereeId, + }, + }); + if (existingReferral) { + throw new common_1.BadRequestException('Referral already exists'); + } + const referral = this.referralRepository.create({ + referrerId: referralCode.userId, + refereeId, + referralCodeId: referralCode.id, + status: referral_entity_1.ReferralStatus.PENDING, + referrerReward: this.REFERRER_REWARD, + refereeReward: this.REFEREE_REWARD, + metadata: { + registrationIp: metadata?.registrationIp, + userAgent: metadata?.userAgent, + source: useDto.source, + campaign: useDto.campaign, + }, + }); + const saved = await this.referralRepository.save(referral); + referralCode.totalReferrals += 1; + referralCode.activeReferrals += 1; + await this.referralCodeRepository.save(referralCode); + if (!referee.metadata) { + referee.metadata = {}; + } + referee.metadata.referredBy = referralCode.userId; + await this.userRepository.save(referee); + this.logger.log(`Referral created: ${referralCode.userId} -> ${refereeId} (code: ${useDto.code})`); + return saved; + } + async completeReferral(referralId) { + const referral = await this.referralRepository.findOne({ + where: { id: referralId }, + relations: ['referrer', 'referee', 'referralCode'], + }); + if (!referral) { + throw new common_1.NotFoundException(`Referral with ID ${referralId} not found`); + } + if (referral.status === referral_entity_1.ReferralStatus.COMPLETED) { + return referral; + } + referral.status = referral_entity_1.ReferralStatus.COMPLETED; + referral.completedAt = new Date(); + await this.referralRepository.save(referral); + await this.distributeRewards(referral); + this.logger.log(`Referral ${referralId} completed and rewards distributed`); + return referral; + } + async distributeRewards(referral) { + try { + if (!referral.referrerRewarded && referral.referrerReward > 0) { + await this.grantReward(referral.referrerId, referral.referrerReward, 'referral_referrer', referral.id); + referral.referrerRewarded = true; + referral.referrerRewardedAt = new Date(); + const referralCode = await this.referralCodeRepository.findOne({ + where: { id: referral.referralCodeId }, + }); + if (referralCode) { + referralCode.totalRewardsEarned += referral.referrerReward; + await this.referralCodeRepository.save(referralCode); + } + } + if (!referral.refereeRewarded && referral.refereeReward > 0) { + await this.grantReward(referral.refereeId, referral.refereeReward, 'referral_referee', referral.id); + referral.refereeRewarded = true; + referral.refereeRewardedAt = new Date(); + } + await this.referralRepository.save(referral); + } + catch (error) { + this.logger.error(`Failed to distribute rewards for referral ${referral.id}: ${error.message}`, error.stack); + throw error; + } + } + async grantReward(userId, amount, type, referralId) { + const user = await this.userRepository.findOne({ where: { id: userId } }); + if (user) { + user.experience += amount; + user.totalScore += amount; + await this.userRepository.save(user); + } + this.logger.log(`Granted ${amount} points to user ${userId} (type: ${type}, referral: ${referralId})`); + } + async getReferralsByReferrer(userId, status) { + const where = { referrerId: userId }; + if (status) { + where.status = status; + } + return this.referralRepository.find({ + where, + relations: ['referee', 'referralCode'], + order: { createdAt: 'DESC' }, + }); + } + async getReferralStats(userId) { + const referralCode = await this.referralCodeRepository.findOne({ + where: { userId }, + }); + if (!referralCode) { + return { + totalReferrals: 0, + activeReferrals: 0, + completedReferrals: 0, + totalRewardsEarned: 0, + hasCode: false, + }; + } + const [total, completed] = await Promise.all([ + this.referralRepository.count({ + where: { referrerId: userId }, + }), + this.referralRepository.count({ + where: { + referrerId: userId, + status: referral_entity_1.ReferralStatus.COMPLETED, + }, + }), + ]); + return { + totalReferrals: total, + activeReferrals: referralCode.activeReferrals, + completedReferrals: completed, + totalRewardsEarned: referralCode.totalRewardsEarned, + hasCode: true, + code: referralCode.code, + inviteLink: await this.generateInviteLink(userId), + }; + } + async getReferralById(referralId) { + const referral = await this.referralRepository.findOne({ + where: { id: referralId }, + relations: ['referrer', 'referee', 'referralCode'], + }); + if (!referral) { + throw new common_1.NotFoundException(`Referral with ID ${referralId} not found`); + } + return referral; + } +}; +exports.ReferralsService = ReferralsService; +exports.ReferralsService = ReferralsService = ReferralsService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(referral_code_entity_1.ReferralCode)), + __param(1, (0, typeorm_1.InjectRepository)(referral_entity_1.Referral)), + __param(2, (0, typeorm_1.InjectRepository)(user_entity_1.User)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _d : Object]) +], ReferralsService); + + +/***/ }), + +/***/ "./src/rewards/rewards.controller.ts": +/*!*******************************************!*\ + !*** ./src/rewards/rewards.controller.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.RewardsController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const rewards_service_1 = __webpack_require__(/*! ./rewards.service */ "./src/rewards/rewards.service.ts"); +let RewardsController = class RewardsController { + constructor(rewardsService) { + this.rewardsService = rewardsService; + } + async distribute(body) { + return this.rewardsService.distributeReward(body.userAddress, body.amount); + } + async getUserRewards(address) { + return this.rewardsService.getUserRewards(address); + } +}; +exports.RewardsController = RewardsController; +__decorate([ + (0, common_1.Post)('distribute'), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], RewardsController.prototype, "distribute", null); +__decorate([ + (0, common_1.Get)('user/:address'), + __param(0, (0, common_1.Param)('address')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], RewardsController.prototype, "getUserRewards", null); +exports.RewardsController = RewardsController = __decorate([ + (0, common_1.Controller)('rewards'), + __metadata("design:paramtypes", [typeof (_a = typeof rewards_service_1.RewardsService !== "undefined" && rewards_service_1.RewardsService) === "function" ? _a : Object]) +], RewardsController); + + +/***/ }), + +/***/ "./src/rewards/rewards.module.ts": +/*!***************************************!*\ + !*** ./src/rewards/rewards.module.ts ***! + \***************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.RewardsModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const rewards_service_1 = __webpack_require__(/*! ./rewards.service */ "./src/rewards/rewards.service.ts"); +const rewards_controller_1 = __webpack_require__(/*! ./rewards.controller */ "./src/rewards/rewards.controller.ts"); +const soroban_module_1 = __webpack_require__(/*! ../soroban/soroban.module */ "./src/soroban/soroban.module.ts"); +let RewardsModule = class RewardsModule { +}; +exports.RewardsModule = RewardsModule; +exports.RewardsModule = RewardsModule = __decorate([ + (0, common_1.Module)({ + imports: [soroban_module_1.SorobanModule], + controllers: [rewards_controller_1.RewardsController], + providers: [rewards_service_1.RewardsService], + exports: [rewards_service_1.RewardsService], + }) +], RewardsModule); + + +/***/ }), + +/***/ "./src/rewards/rewards.service.ts": +/*!****************************************!*\ + !*** ./src/rewards/rewards.service.ts ***! + \****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.RewardsService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const soroban_service_1 = __webpack_require__(/*! ../soroban/soroban.service */ "./src/soroban/soroban.service.ts"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const stellar_sdk_1 = __webpack_require__(/*! @stellar/stellar-sdk */ "@stellar/stellar-sdk"); +let RewardsService = class RewardsService { + constructor(sorobanService, configService) { + this.sorobanService = sorobanService; + this.configService = configService; + this.rewardContractId = this.configService.get('REWARD_CONTRACT_ID'); + } + async distributeReward(userAddress, amount) { + const params = [ + new stellar_sdk_1.Address(userAddress).toScVal(), + (0, stellar_sdk_1.nativeToScVal)(BigInt(amount) * 10000000n, { type: 'i128' }), + ]; + const result = await this.sorobanService.invokeContract(this.rewardContractId, 'distribute_reward', params); + return { + success: result.status === 'SUCCESS', + transactionHash: result.hash, + recipient: userAddress, + amount, + }; + } + async getUserRewards(userAddress) { + const params = [new stellar_sdk_1.Address(userAddress).toScVal()]; + const result = (await this.sorobanService.invokeContract(this.rewardContractId, 'get_user_rewards', params)); + return result.result; + } +}; +exports.RewardsService = RewardsService; +exports.RewardsService = RewardsService = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [typeof (_a = typeof soroban_service_1.SorobanService !== "undefined" && soroban_service_1.SorobanService) === "function" ? _a : Object, typeof (_b = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _b : Object]) +], RewardsService); + + +/***/ }), + +/***/ "./src/save-game/controllers/save-game.controller.ts": +/*!***********************************************************!*\ + !*** ./src/save-game/controllers/save-game.controller.ts ***! + \***********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveGameController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const jwt_auth_guard_1 = __webpack_require__(/*! ../../auth/guards/jwt-auth.guard */ "./src/auth/guards/jwt-auth.guard.ts"); +const save_game_service_1 = __webpack_require__(/*! ../services/save-game.service */ "./src/save-game/services/save-game.service.ts"); +const cloud_sync_service_1 = __webpack_require__(/*! ../services/cloud-sync.service */ "./src/save-game/services/cloud-sync.service.ts"); +const auto_save_service_1 = __webpack_require__(/*! ../services/auto-save.service */ "./src/save-game/services/auto-save.service.ts"); +const save_backup_service_1 = __webpack_require__(/*! ../services/save-backup.service */ "./src/save-game/services/save-backup.service.ts"); +const save_analytics_service_1 = __webpack_require__(/*! ../services/save-analytics.service */ "./src/save-game/services/save-analytics.service.ts"); +const create_save_game_dto_1 = __webpack_require__(/*! ../dto/create-save-game.dto */ "./src/save-game/dto/create-save-game.dto.ts"); +const update_save_game_dto_1 = __webpack_require__(/*! ../dto/update-save-game.dto */ "./src/save-game/dto/update-save-game.dto.ts"); +const sync_save_game_dto_1 = __webpack_require__(/*! ../dto/sync-save-game.dto */ "./src/save-game/dto/sync-save-game.dto.ts"); +const create_save_game_dto_2 = __webpack_require__(/*! ../dto/create-save-game.dto */ "./src/save-game/dto/create-save-game.dto.ts"); +let SaveGameController = class SaveGameController { + constructor(saveGameService, cloudSyncService, autoSaveService, backupService, analyticsService) { + this.saveGameService = saveGameService; + this.cloudSyncService = cloudSyncService; + this.autoSaveService = autoSaveService; + this.backupService = backupService; + this.analyticsService = analyticsService; + } + async create(req, dto) { + return this.saveGameService.create(req.user.id, dto); + } + async findAll(req) { + return this.saveGameService.findAll(req.user.id); + } + async getEmptySlots(req, count) { + return this.saveGameService.getEmptySlots(req.user.id, count || 10); + } + async findOne(req, slotId) { + return this.saveGameService.findOne(req.user.id, slotId); + } + async load(req, slotId) { + return this.saveGameService.load(req.user.id, slotId); + } + async update(req, slotId, dto) { + return this.saveGameService.update(req.user.id, slotId, dto); + } + async delete(req, slotId) { + await this.saveGameService.delete(req.user.id, slotId); + } + async sync(req, dto) { + return this.cloudSyncService.syncSave(req.user.id, dto); + } + async batchSync(req, dto) { + return this.cloudSyncService.batchSync(req.user.id, dto); + } + async resolveConflict(req, dto) { + return this.cloudSyncService.resolveConflict(req.user.id, dto); + } + async uploadToCloud(req, slotId, data, deviceId, platform) { + return this.cloudSyncService.uploadToCloud(req.user.id, slotId, data, deviceId, platform); + } + async downloadFromCloud(req, slotId) { + return this.cloudSyncService.downloadFromCloud(req.user.id, slotId); + } + async getCloudSaves(req) { + return this.cloudSyncService.getCloudSaves(req.user.id); + } + async enableAutoSave(req, slotId, intervalMs) { + await this.autoSaveService.enableAutoSave(req.user.id, slotId, intervalMs); + return { enabled: true, slotId, intervalMs }; + } + async disableAutoSave(req, slotId) { + await this.autoSaveService.disableAutoSave(req.user.id, slotId); + return { enabled: false }; + } + async triggerAutoSave(req, data) { + return this.autoSaveService.triggerAutoSave(req.user.id, data); + } + async getAutoSaveConfig(req, slotId) { + return this.autoSaveService.getAutoSaveConfig(req.user.id, slotId); + } + async quickSave(req, data) { + return this.autoSaveService.quickSave(req.user.id, data); + } + async quickLoad(req) { + return this.autoSaveService.quickLoad(req.user.id); + } + async getBackups(req, slotId) { + return this.backupService.getBackups(req.user.id, slotId); + } + async restoreFromBackup(req, backupId) { + return this.backupService.restoreFromBackup(backupId, req.user.id); + } + async deleteBackup(req, backupId) { + await this.backupService.deleteBackup(backupId, req.user.id); + } + async getAnalytics(req) { + return this.analyticsService.getAnalytics(req.user.id); + } +}; +exports.SaveGameController = SaveGameController; +__decorate([ + (0, common_1.Post)(), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, typeof (_f = typeof create_save_game_dto_1.CreateSaveGameDto !== "undefined" && create_save_game_dto_1.CreateSaveGameDto) === "function" ? _f : Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "create", null); +__decorate([ + (0, common_1.Get)(), + __param(0, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "findAll", null); +__decorate([ + (0, common_1.Get)('slots/empty'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Query)('count', new common_1.ParseIntPipe({ optional: true }))), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "getEmptySlots", null); +__decorate([ + (0, common_1.Get)(':slotId'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Param)('slotId', common_1.ParseIntPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "findOne", null); +__decorate([ + (0, common_1.Get)(':slotId/load'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Param)('slotId', common_1.ParseIntPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "load", null); +__decorate([ + (0, common_1.Put)(':slotId'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Param)('slotId', common_1.ParseIntPipe)), + __param(2, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number, typeof (_g = typeof update_save_game_dto_1.UpdateSaveGameDto !== "undefined" && update_save_game_dto_1.UpdateSaveGameDto) === "function" ? _g : Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "update", null); +__decorate([ + (0, common_1.Delete)(':slotId'), + (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Param)('slotId', common_1.ParseIntPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "delete", null); +__decorate([ + (0, common_1.Post)('sync'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, typeof (_h = typeof sync_save_game_dto_1.SyncSaveGameDto !== "undefined" && sync_save_game_dto_1.SyncSaveGameDto) === "function" ? _h : Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "sync", null); +__decorate([ + (0, common_1.Post)('sync/batch'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, typeof (_j = typeof sync_save_game_dto_1.BatchSyncDto !== "undefined" && sync_save_game_dto_1.BatchSyncDto) === "function" ? _j : Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "batchSync", null); +__decorate([ + (0, common_1.Post)('sync/resolve-conflict'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, typeof (_k = typeof sync_save_game_dto_1.ResolveConflictDto !== "undefined" && sync_save_game_dto_1.ResolveConflictDto) === "function" ? _k : Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "resolveConflict", null); +__decorate([ + (0, common_1.Post)('sync/upload/:slotId'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Param)('slotId', common_1.ParseIntPipe)), + __param(2, (0, common_1.Body)()), + __param(3, (0, common_1.Query)('deviceId')), + __param(4, (0, common_1.Query)('platform')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number, typeof (_l = typeof create_save_game_dto_2.SaveGameDataDto !== "undefined" && create_save_game_dto_2.SaveGameDataDto) === "function" ? _l : Object, String, String]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "uploadToCloud", null); +__decorate([ + (0, common_1.Get)('sync/download/:slotId'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Param)('slotId', common_1.ParseIntPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "downloadFromCloud", null); +__decorate([ + (0, common_1.Get)('cloud'), + __param(0, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "getCloudSaves", null); +__decorate([ + (0, common_1.Post)('auto-save/enable'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Query)('slotId', new common_1.ParseIntPipe({ optional: true }))), + __param(2, (0, common_1.Query)('intervalMs', new common_1.ParseIntPipe({ optional: true }))), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number, Number]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "enableAutoSave", null); +__decorate([ + (0, common_1.Post)('auto-save/disable'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Query)('slotId', new common_1.ParseIntPipe({ optional: true }))), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "disableAutoSave", null); +__decorate([ + (0, common_1.Post)('auto-save/trigger'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, typeof (_m = typeof create_save_game_dto_2.SaveGameDataDto !== "undefined" && create_save_game_dto_2.SaveGameDataDto) === "function" ? _m : Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "triggerAutoSave", null); +__decorate([ + (0, common_1.Get)('auto-save/config'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Query)('slotId', new common_1.ParseIntPipe({ optional: true }))), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "getAutoSaveConfig", null); +__decorate([ + (0, common_1.Post)('quick-save'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, typeof (_o = typeof create_save_game_dto_2.SaveGameDataDto !== "undefined" && create_save_game_dto_2.SaveGameDataDto) === "function" ? _o : Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "quickSave", null); +__decorate([ + (0, common_1.Get)('quick-load'), + __param(0, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "quickLoad", null); +__decorate([ + (0, common_1.Get)('backups'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Query)('slotId', new common_1.ParseIntPipe({ optional: true }))), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "getBackups", null); +__decorate([ + (0, common_1.Post)('backups/:backupId/restore'), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Param)('backupId')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, String]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "restoreFromBackup", null); +__decorate([ + (0, common_1.Delete)('backups/:backupId'), + (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT), + __param(0, (0, common_1.Request)()), + __param(1, (0, common_1.Param)('backupId')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, String]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "deleteBackup", null); +__decorate([ + (0, common_1.Get)('analytics'), + __param(0, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], SaveGameController.prototype, "getAnalytics", null); +exports.SaveGameController = SaveGameController = __decorate([ + (0, common_1.Controller)('save-games'), + (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), + __metadata("design:paramtypes", [typeof (_a = typeof save_game_service_1.SaveGameService !== "undefined" && save_game_service_1.SaveGameService) === "function" ? _a : Object, typeof (_b = typeof cloud_sync_service_1.CloudSyncService !== "undefined" && cloud_sync_service_1.CloudSyncService) === "function" ? _b : Object, typeof (_c = typeof auto_save_service_1.AutoSaveService !== "undefined" && auto_save_service_1.AutoSaveService) === "function" ? _c : Object, typeof (_d = typeof save_backup_service_1.SaveBackupService !== "undefined" && save_backup_service_1.SaveBackupService) === "function" ? _d : Object, typeof (_e = typeof save_analytics_service_1.SaveAnalyticsService !== "undefined" && save_analytics_service_1.SaveAnalyticsService) === "function" ? _e : Object]) +], SaveGameController); + + +/***/ }), + +/***/ "./src/save-game/dto/create-save-game.dto.ts": +/*!***************************************************!*\ + !*** ./src/save-game/dto/create-save-game.dto.ts ***! + \***************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreateSaveGameDto = exports.SaveGameDataDto = exports.ProgressStateDto = exports.PlayerStateDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +const save_game_interfaces_1 = __webpack_require__(/*! ../interfaces/save-game.interfaces */ "./src/save-game/interfaces/save-game.interfaces.ts"); +class PlayerStateDto { +} +exports.PlayerStateDto = PlayerStateDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], PlayerStateDto.prototype, "position", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + __metadata("design:type", Number) +], PlayerStateDto.prototype, "health", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Array) +], PlayerStateDto.prototype, "inventory", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", typeof (_a = typeof Record !== "undefined" && Record) === "function" ? _a : Object) +], PlayerStateDto.prototype, "stats", void 0); +class ProgressStateDto { +} +exports.ProgressStateDto = ProgressStateDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)({ each: true }), + __metadata("design:type", Array) +], ProgressStateDto.prototype, "completedLevels", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)({ each: true }), + __metadata("design:type", Array) +], ProgressStateDto.prototype, "unlockedAchievements", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)({ each: true }), + __metadata("design:type", Array) +], ProgressStateDto.prototype, "collectibles", void 0); +class SaveGameDataDto { +} +exports.SaveGameDataDto = SaveGameDataDto; +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + __metadata("design:type", Number) +], SaveGameDataDto.prototype, "version", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + __metadata("design:type", typeof (_b = typeof Record !== "undefined" && Record) === "function" ? _b : Object) +], SaveGameDataDto.prototype, "gameState", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => PlayerStateDto), + __metadata("design:type", PlayerStateDto) +], SaveGameDataDto.prototype, "playerState", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => ProgressStateDto), + __metadata("design:type", ProgressStateDto) +], SaveGameDataDto.prototype, "progressState", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", typeof (_c = typeof Record !== "undefined" && Record) === "function" ? _c : Object) +], SaveGameDataDto.prototype, "settings", void 0); +class CreateSaveGameDto { +} +exports.CreateSaveGameDto = CreateSaveGameDto; +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.Max)(99), + __metadata("design:type", Number) +], CreateSaveGameDto.prototype, "slotId", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + (0, class_validator_1.MaxLength)(100), + __metadata("design:type", String) +], CreateSaveGameDto.prototype, "slotName", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)(save_game_interfaces_1.SaveType), + __metadata("design:type", typeof (_d = typeof save_game_interfaces_1.SaveType !== "undefined" && save_game_interfaces_1.SaveType) === "function" ? _d : Object) +], CreateSaveGameDto.prototype, "saveType", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => SaveGameDataDto), + __metadata("design:type", SaveGameDataDto) +], CreateSaveGameDto.prototype, "data", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + __metadata("design:type", Number) +], CreateSaveGameDto.prototype, "playtime", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + (0, class_validator_1.MaxLength)(64), + __metadata("design:type", String) +], CreateSaveGameDto.prototype, "deviceId", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + (0, class_validator_1.MaxLength)(50), + __metadata("design:type", String) +], CreateSaveGameDto.prototype, "platform", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", typeof (_e = typeof Record !== "undefined" && Record) === "function" ? _e : Object) +], CreateSaveGameDto.prototype, "customMetadata", void 0); + + +/***/ }), + +/***/ "./src/save-game/dto/sync-save-game.dto.ts": +/*!*************************************************!*\ + !*** ./src/save-game/dto/sync-save-game.dto.ts ***! + \*************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.BatchSyncDto = exports.ResolveConflictDto = exports.SyncSaveGameDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +const save_game_interfaces_1 = __webpack_require__(/*! ../interfaces/save-game.interfaces */ "./src/save-game/interfaces/save-game.interfaces.ts"); +const create_save_game_dto_1 = __webpack_require__(/*! ./create-save-game.dto */ "./src/save-game/dto/create-save-game.dto.ts"); +class SyncSaveGameDto { +} +exports.SyncSaveGameDto = SyncSaveGameDto; +__decorate([ + (0, class_validator_1.IsNumber)(), + __metadata("design:type", Number) +], SyncSaveGameDto.prototype, "slotId", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], SyncSaveGameDto.prototype, "localChecksum", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], SyncSaveGameDto.prototype, "lastModifiedAt", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + __metadata("design:type", Number) +], SyncSaveGameDto.prototype, "saveVersion", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => create_save_game_dto_1.SaveGameDataDto), + __metadata("design:type", typeof (_b = typeof create_save_game_dto_1.SaveGameDataDto !== "undefined" && create_save_game_dto_1.SaveGameDataDto) === "function" ? _b : Object) +], SyncSaveGameDto.prototype, "localData", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], SyncSaveGameDto.prototype, "deviceId", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], SyncSaveGameDto.prototype, "platform", void 0); +class ResolveConflictDto { +} +exports.ResolveConflictDto = ResolveConflictDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], ResolveConflictDto.prototype, "saveId", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(save_game_interfaces_1.ConflictResolution), + __metadata("design:type", typeof (_c = typeof save_game_interfaces_1.ConflictResolution !== "undefined" && save_game_interfaces_1.ConflictResolution) === "function" ? _c : Object) +], ResolveConflictDto.prototype, "resolution", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => create_save_game_dto_1.SaveGameDataDto), + __metadata("design:type", typeof (_d = typeof create_save_game_dto_1.SaveGameDataDto !== "undefined" && create_save_game_dto_1.SaveGameDataDto) === "function" ? _d : Object) +], ResolveConflictDto.prototype, "mergedData", void 0); +class BatchSyncDto { +} +exports.BatchSyncDto = BatchSyncDto; +__decorate([ + (0, class_validator_1.ValidateNested)({ each: true }), + (0, class_transformer_1.Type)(() => SyncSaveGameDto), + __metadata("design:type", Array) +], BatchSyncDto.prototype, "saves", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsBoolean)(), + __metadata("design:type", Boolean) +], BatchSyncDto.prototype, "forceCloud", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], BatchSyncDto.prototype, "deviceId", void 0); + + +/***/ }), + +/***/ "./src/save-game/dto/update-save-game.dto.ts": +/*!***************************************************!*\ + !*** ./src/save-game/dto/update-save-game.dto.ts ***! + \***************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UpdateSaveGameDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +const create_save_game_dto_1 = __webpack_require__(/*! ./create-save-game.dto */ "./src/save-game/dto/create-save-game.dto.ts"); +class UpdateSaveGameDto { +} +exports.UpdateSaveGameDto = UpdateSaveGameDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + (0, class_validator_1.MaxLength)(100), + __metadata("design:type", String) +], UpdateSaveGameDto.prototype, "slotName", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => create_save_game_dto_1.SaveGameDataDto), + __metadata("design:type", typeof (_a = typeof create_save_game_dto_1.SaveGameDataDto !== "undefined" && create_save_game_dto_1.SaveGameDataDto) === "function" ? _a : Object) +], UpdateSaveGameDto.prototype, "data", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + __metadata("design:type", Number) +], UpdateSaveGameDto.prototype, "playtime", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + (0, class_validator_1.MaxLength)(64), + __metadata("design:type", String) +], UpdateSaveGameDto.prototype, "deviceId", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + (0, class_validator_1.MaxLength)(50), + __metadata("design:type", String) +], UpdateSaveGameDto.prototype, "platform", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", typeof (_b = typeof Record !== "undefined" && Record) === "function" ? _b : Object) +], UpdateSaveGameDto.prototype, "customMetadata", void 0); + + +/***/ }), + +/***/ "./src/save-game/entities/save-game-analytics.entity.ts": +/*!**************************************************************!*\ + !*** ./src/save-game/entities/save-game-analytics.entity.ts ***! + \**************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveGameAnalytics = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +let SaveGameAnalytics = class SaveGameAnalytics { +}; +exports.SaveGameAnalytics = SaveGameAnalytics; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], SaveGameAnalytics.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + __metadata("design:type", String) +], SaveGameAnalytics.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.OneToOne)(() => user_entity_1.User, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'userId' }), + __metadata("design:type", typeof (_a = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _a : Object) +], SaveGameAnalytics.prototype, "user", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "totalSaves", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "totalLoads", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "autoSaves", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "manualSaves", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "quickSaves", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "cloudSyncs", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "syncConflicts", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "conflictsResolved", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "corruptionEvents", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "recoveryAttempts", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "successfulRecoveries", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'bigint', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "totalDataSaved", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'float', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "averageSaveSize", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp', nullable: true }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], SaveGameAnalytics.prototype, "lastSaveAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp', nullable: true }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], SaveGameAnalytics.prototype, "lastLoadAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp', nullable: true }), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], SaveGameAnalytics.prototype, "lastSyncAt", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], SaveGameAnalytics.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + __metadata("design:type", typeof (_f = typeof Date !== "undefined" && Date) === "function" ? _f : Object) +], SaveGameAnalytics.prototype, "updatedAt", void 0); +exports.SaveGameAnalytics = SaveGameAnalytics = __decorate([ + (0, typeorm_1.Entity)('save_game_analytics'), + (0, typeorm_1.Index)(['userId'], { unique: true }) +], SaveGameAnalytics); + + +/***/ }), + +/***/ "./src/save-game/entities/save-game-backup.entity.ts": +/*!***********************************************************!*\ + !*** ./src/save-game/entities/save-game-backup.entity.ts ***! + \***********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveGameBackup = exports.BackupReason = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const save_game_entity_1 = __webpack_require__(/*! ./save-game.entity */ "./src/save-game/entities/save-game.entity.ts"); +var BackupReason; +(function (BackupReason) { + BackupReason["SCHEDULED"] = "SCHEDULED"; + BackupReason["PRE_UPDATE"] = "PRE_UPDATE"; + BackupReason["MANUAL"] = "MANUAL"; + BackupReason["CONFLICT"] = "CONFLICT"; + BackupReason["CORRUPTION_DETECTED"] = "CORRUPTION_DETECTED"; +})(BackupReason || (exports.BackupReason = BackupReason = {})); +let SaveGameBackup = class SaveGameBackup { +}; +exports.SaveGameBackup = SaveGameBackup; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], SaveGameBackup.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + __metadata("design:type", String) +], SaveGameBackup.prototype, "saveGameId", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => save_game_entity_1.SaveGame, { onDelete: 'SET NULL' }), + (0, typeorm_1.JoinColumn)({ name: 'saveGameId' }), + __metadata("design:type", typeof (_a = typeof save_game_entity_1.SaveGame !== "undefined" && save_game_entity_1.SaveGame) === "function" ? _a : Object) +], SaveGameBackup.prototype, "saveGame", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + __metadata("design:type", String) +], SaveGameBackup.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], SaveGameBackup.prototype, "slotId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], SaveGameBackup.prototype, "saveVersion", void 0); +__decorate([ + (0, typeorm_1.Column)({ + type: 'enum', + enum: BackupReason, + default: BackupReason.SCHEDULED, + }), + __metadata("design:type", String) +], SaveGameBackup.prototype, "reason", void 0); +__decorate([ + (0, typeorm_1.Column)('bytea'), + __metadata("design:type", typeof (_b = typeof Buffer !== "undefined" && Buffer) === "function" ? _b : Object) +], SaveGameBackup.prototype, "compressedData", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 64 }), + __metadata("design:type", String) +], SaveGameBackup.prototype, "checksum", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], SaveGameBackup.prototype, "dataSize", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp' }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], SaveGameBackup.prototype, "expiresAt", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], SaveGameBackup.prototype, "createdAt", void 0); +exports.SaveGameBackup = SaveGameBackup = __decorate([ + (0, typeorm_1.Entity)('save_game_backups'), + (0, typeorm_1.Index)(['saveGameId', 'createdAt']), + (0, typeorm_1.Index)(['userId', 'createdAt']), + (0, typeorm_1.Index)(['expiresAt']) +], SaveGameBackup); + + +/***/ }), + +/***/ "./src/save-game/entities/save-game.entity.ts": +/*!****************************************************!*\ + !*** ./src/save-game/entities/save-game.entity.ts ***! + \****************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveGame = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +const save_game_interfaces_1 = __webpack_require__(/*! ../interfaces/save-game.interfaces */ "./src/save-game/interfaces/save-game.interfaces.ts"); +let SaveGame = class SaveGame { +}; +exports.SaveGame = SaveGame; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], SaveGame.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + __metadata("design:type", String) +], SaveGame.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => user_entity_1.User, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'userId' }), + __metadata("design:type", typeof (_a = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _a : Object) +], SaveGame.prototype, "user", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], SaveGame.prototype, "slotId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100, default: 'Save Slot' }), + __metadata("design:type", String) +], SaveGame.prototype, "slotName", void 0); +__decorate([ + (0, typeorm_1.Column)({ + type: 'enum', + enum: save_game_interfaces_1.SaveType, + default: save_game_interfaces_1.SaveType.MANUAL, + }), + __metadata("design:type", typeof (_b = typeof save_game_interfaces_1.SaveType !== "undefined" && save_game_interfaces_1.SaveType) === "function" ? _b : Object) +], SaveGame.prototype, "saveType", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 1 }), + __metadata("design:type", Number) +], SaveGame.prototype, "version", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 1 }), + __metadata("design:type", Number) +], SaveGame.prototype, "saveVersion", void 0); +__decorate([ + (0, typeorm_1.Column)('jsonb'), + __metadata("design:type", typeof (_c = typeof save_game_interfaces_1.SaveGameMetadata !== "undefined" && save_game_interfaces_1.SaveGameMetadata) === "function" ? _c : Object) +], SaveGame.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.Column)('bytea', { nullable: true }), + __metadata("design:type", typeof (_d = typeof Buffer !== "undefined" && Buffer) === "function" ? _d : Object) +], SaveGame.prototype, "compressedData", void 0); +__decorate([ + (0, typeorm_1.Column)('jsonb', { nullable: true }), + __metadata("design:type", typeof (_e = typeof save_game_interfaces_1.SaveGameData !== "undefined" && save_game_interfaces_1.SaveGameData) === "function" ? _e : Object) +], SaveGame.prototype, "rawData", void 0); +__decorate([ + (0, typeorm_1.Column)('jsonb', { nullable: true }), + __metadata("design:type", typeof (_f = typeof save_game_interfaces_1.SaveGameChecksum !== "undefined" && save_game_interfaces_1.SaveGameChecksum) === "function" ? _f : Object) +], SaveGame.prototype, "checksum", void 0); +__decorate([ + (0, typeorm_1.Column)('jsonb', { nullable: true }), + __metadata("design:type", typeof (_g = typeof save_game_interfaces_1.CompressionInfo !== "undefined" && save_game_interfaces_1.CompressionInfo) === "function" ? _g : Object) +], SaveGame.prototype, "compressionInfo", void 0); +__decorate([ + (0, typeorm_1.Column)('jsonb', { nullable: true }), + __metadata("design:type", typeof (_h = typeof save_game_interfaces_1.EncryptionInfo !== "undefined" && save_game_interfaces_1.EncryptionInfo) === "function" ? _h : Object) +], SaveGame.prototype, "encryptionInfo", void 0); +__decorate([ + (0, typeorm_1.Column)({ + type: 'enum', + enum: save_game_interfaces_1.SyncStatus, + default: save_game_interfaces_1.SyncStatus.LOCAL_ONLY, + }), + __metadata("design:type", typeof (_j = typeof save_game_interfaces_1.SyncStatus !== "undefined" && save_game_interfaces_1.SyncStatus) === "function" ? _j : Object) +], SaveGame.prototype, "syncStatus", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp', nullable: true }), + __metadata("design:type", typeof (_k = typeof Date !== "undefined" && Date) === "function" ? _k : Object) +], SaveGame.prototype, "lastSyncedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp' }), + __metadata("design:type", typeof (_l = typeof Date !== "undefined" && Date) === "function" ? _l : Object) +], SaveGame.prototype, "lastModifiedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 64, nullable: true }), + __metadata("design:type", String) +], SaveGame.prototype, "deviceId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50, nullable: true }), + __metadata("design:type", String) +], SaveGame.prototype, "platform", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], SaveGame.prototype, "isCorrupted", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', nullable: true }), + __metadata("design:type", String) +], SaveGame.prototype, "corruptionReason", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGame.prototype, "loadCount", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGame.prototype, "saveCount", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + __metadata("design:type", typeof (_m = typeof Date !== "undefined" && Date) === "function" ? _m : Object) +], SaveGame.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + __metadata("design:type", typeof (_o = typeof Date !== "undefined" && Date) === "function" ? _o : Object) +], SaveGame.prototype, "updatedAt", void 0); +exports.SaveGame = SaveGame = __decorate([ + (0, typeorm_1.Entity)('save_games'), + (0, typeorm_1.Index)(['userId', 'slotId'], { unique: true }), + (0, typeorm_1.Index)(['userId', 'syncStatus']), + (0, typeorm_1.Index)(['lastModifiedAt']) +], SaveGame); + + +/***/ }), + +/***/ "./src/save-game/interfaces/save-game.interfaces.ts": +/*!**********************************************************!*\ + !*** ./src/save-game/interfaces/save-game.interfaces.ts ***! + \**********************************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ConflictResolution = exports.SaveType = exports.SyncStatus = void 0; +var SyncStatus; +(function (SyncStatus) { + SyncStatus["LOCAL_ONLY"] = "LOCAL_ONLY"; + SyncStatus["CLOUD_ONLY"] = "CLOUD_ONLY"; + SyncStatus["SYNCED"] = "SYNCED"; + SyncStatus["LOCAL_NEWER"] = "LOCAL_NEWER"; + SyncStatus["CLOUD_NEWER"] = "CLOUD_NEWER"; + SyncStatus["CONFLICT"] = "CONFLICT"; +})(SyncStatus || (exports.SyncStatus = SyncStatus = {})); +var SaveType; +(function (SaveType) { + SaveType["AUTO"] = "AUTO"; + SaveType["MANUAL"] = "MANUAL"; + SaveType["QUICKSAVE"] = "QUICKSAVE"; +})(SaveType || (exports.SaveType = SaveType = {})); +var ConflictResolution; +(function (ConflictResolution) { + ConflictResolution["USE_LOCAL"] = "USE_LOCAL"; + ConflictResolution["USE_CLOUD"] = "USE_CLOUD"; + ConflictResolution["USE_NEWEST"] = "USE_NEWEST"; + ConflictResolution["MERGE"] = "MERGE"; + ConflictResolution["KEEP_BOTH"] = "KEEP_BOTH"; +})(ConflictResolution || (exports.ConflictResolution = ConflictResolution = {})); + + +/***/ }), + +/***/ "./src/save-game/save-game.module.ts": +/*!*******************************************!*\ + !*** ./src/save-game/save-game.module.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveGameModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const schedule_1 = __webpack_require__(/*! @nestjs/schedule */ "@nestjs/schedule"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const save_game_entity_1 = __webpack_require__(/*! ./entities/save-game.entity */ "./src/save-game/entities/save-game.entity.ts"); +const save_game_backup_entity_1 = __webpack_require__(/*! ./entities/save-game-backup.entity */ "./src/save-game/entities/save-game-backup.entity.ts"); +const save_game_analytics_entity_1 = __webpack_require__(/*! ./entities/save-game-analytics.entity */ "./src/save-game/entities/save-game-analytics.entity.ts"); +const save_game_service_1 = __webpack_require__(/*! ./services/save-game.service */ "./src/save-game/services/save-game.service.ts"); +const cloud_sync_service_1 = __webpack_require__(/*! ./services/cloud-sync.service */ "./src/save-game/services/cloud-sync.service.ts"); +const save_compression_service_1 = __webpack_require__(/*! ./services/save-compression.service */ "./src/save-game/services/save-compression.service.ts"); +const save_encryption_service_1 = __webpack_require__(/*! ./services/save-encryption.service */ "./src/save-game/services/save-encryption.service.ts"); +const save_versioning_service_1 = __webpack_require__(/*! ./services/save-versioning.service */ "./src/save-game/services/save-versioning.service.ts"); +const save_backup_service_1 = __webpack_require__(/*! ./services/save-backup.service */ "./src/save-game/services/save-backup.service.ts"); +const save_analytics_service_1 = __webpack_require__(/*! ./services/save-analytics.service */ "./src/save-game/services/save-analytics.service.ts"); +const auto_save_service_1 = __webpack_require__(/*! ./services/auto-save.service */ "./src/save-game/services/auto-save.service.ts"); +const save_game_controller_1 = __webpack_require__(/*! ./controllers/save-game.controller */ "./src/save-game/controllers/save-game.controller.ts"); +let SaveGameModule = class SaveGameModule { +}; +exports.SaveGameModule = SaveGameModule; +exports.SaveGameModule = SaveGameModule = __decorate([ + (0, common_1.Module)({ + imports: [ + typeorm_1.TypeOrmModule.forFeature([save_game_entity_1.SaveGame, save_game_backup_entity_1.SaveGameBackup, save_game_analytics_entity_1.SaveGameAnalytics]), + schedule_1.ScheduleModule.forRoot(), + config_1.ConfigModule, + ], + controllers: [save_game_controller_1.SaveGameController], + providers: [ + save_compression_service_1.SaveCompressionService, + save_encryption_service_1.SaveEncryptionService, + save_versioning_service_1.SaveVersioningService, + save_analytics_service_1.SaveAnalyticsService, + save_backup_service_1.SaveBackupService, + save_game_service_1.SaveGameService, + cloud_sync_service_1.CloudSyncService, + auto_save_service_1.AutoSaveService, + ], + exports: [ + save_game_service_1.SaveGameService, + cloud_sync_service_1.CloudSyncService, + auto_save_service_1.AutoSaveService, + save_backup_service_1.SaveBackupService, + save_analytics_service_1.SaveAnalyticsService, + ], + }) +], SaveGameModule); + + +/***/ }), + +/***/ "./src/save-game/services/auto-save.service.ts": +/*!*****************************************************!*\ + !*** ./src/save-game/services/auto-save.service.ts ***! + \*****************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var AutoSaveService_1; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AutoSaveService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const schedule_1 = __webpack_require__(/*! @nestjs/schedule */ "@nestjs/schedule"); +const save_game_entity_1 = __webpack_require__(/*! ../entities/save-game.entity */ "./src/save-game/entities/save-game.entity.ts"); +const save_game_interfaces_1 = __webpack_require__(/*! ../interfaces/save-game.interfaces */ "./src/save-game/interfaces/save-game.interfaces.ts"); +const save_game_service_1 = __webpack_require__(/*! ./save-game.service */ "./src/save-game/services/save-game.service.ts"); +const cloud_sync_service_1 = __webpack_require__(/*! ./cloud-sync.service */ "./src/save-game/services/cloud-sync.service.ts"); +let AutoSaveService = AutoSaveService_1 = class AutoSaveService { + constructor(saveGameRepo, saveGameService, cloudSyncService) { + this.saveGameRepo = saveGameRepo; + this.saveGameService = saveGameService; + this.cloudSyncService = cloudSyncService; + this.logger = new common_1.Logger(AutoSaveService_1.name); + this.autoSaveConfigs = new Map(); + this.pendingAutoSaves = []; + this.DEFAULT_INTERVAL_MS = 5 * 60 * 1000; + this.AUTO_SAVE_SLOT = 99; + this.QUICK_SAVE_SLOT = 98; + } + async enableAutoSave(userId, slotId = this.AUTO_SAVE_SLOT, intervalMs = this.DEFAULT_INTERVAL_MS) { + const configKey = this.getConfigKey(userId, slotId); + this.autoSaveConfigs.set(configKey, { + userId, + slotId, + intervalMs, + enabled: true, + }); + this.logger.log(`Auto-save enabled for user ${userId}, slot ${slotId}, interval ${intervalMs}ms`); + } + async disableAutoSave(userId, slotId = this.AUTO_SAVE_SLOT) { + const configKey = this.getConfigKey(userId, slotId); + const config = this.autoSaveConfigs.get(configKey); + if (config) { + config.enabled = false; + this.autoSaveConfigs.set(configKey, config); + } + this.logger.log(`Auto-save disabled for user ${userId}, slot ${slotId}`); + } + async queueAutoSave(userId, data, slotId) { + const targetSlot = slotId ?? this.AUTO_SAVE_SLOT; + const configKey = this.getConfigKey(userId, targetSlot); + const config = this.autoSaveConfigs.get(configKey); + if (config && !config.enabled) { + return; + } + if (config?.lastAutoSave) { + const elapsed = Date.now() - config.lastAutoSave.getTime(); + if (elapsed < (config.intervalMs || this.DEFAULT_INTERVAL_MS)) { + return; + } + } + this.pendingAutoSaves.push({ + userId, + slotId: targetSlot, + data, + timestamp: new Date(), + }); + this.logger.debug(`Queued auto-save for user ${userId}, slot ${targetSlot}`); + } + async triggerAutoSave(userId, data) { + const slotId = this.AUTO_SAVE_SLOT; + try { + const existingSave = await this.saveGameRepo.findOne({ + where: { userId, slotId }, + }); + if (existingSave) { + return await this.saveGameService.update(userId, slotId, { + data: { + version: data.version, + gameState: data.gameState, + playerState: data.playerState, + progressState: data.progressState, + settings: data.settings, + }, + }); + } + else { + return await this.saveGameService.create(userId, { + slotId, + slotName: 'Auto Save', + saveType: save_game_interfaces_1.SaveType.AUTO, + data: { + version: data.version, + gameState: data.gameState, + playerState: data.playerState, + progressState: data.progressState, + settings: data.settings, + }, + }); + } + } + catch (error) { + this.logger.error(`Auto-save failed for user ${userId}: ${error.message}`); + return null; + } + } + async quickSave(userId, data) { + const slotId = this.QUICK_SAVE_SLOT; + const existingSave = await this.saveGameRepo.findOne({ + where: { userId, slotId }, + }); + if (existingSave) { + return await this.saveGameService.update(userId, slotId, { + slotName: 'Quick Save', + data: { + version: data.version, + gameState: data.gameState, + playerState: data.playerState, + progressState: data.progressState, + settings: data.settings, + }, + }); + } + return await this.saveGameService.create(userId, { + slotId, + slotName: 'Quick Save', + saveType: save_game_interfaces_1.SaveType.QUICKSAVE, + data: { + version: data.version, + gameState: data.gameState, + playerState: data.playerState, + progressState: data.progressState, + settings: data.settings, + }, + }); + } + async quickLoad(userId) { + return await this.saveGameService.load(userId, this.QUICK_SAVE_SLOT); + } + async processPendingAutoSaves() { + if (this.pendingAutoSaves.length === 0) { + return; + } + this.logger.debug(`Processing ${this.pendingAutoSaves.length} pending auto-saves`); + const latestSaves = new Map(); + for (const pending of this.pendingAutoSaves) { + const key = this.getConfigKey(pending.userId, pending.slotId); + const existing = latestSaves.get(key); + if (!existing || pending.timestamp > existing.timestamp) { + latestSaves.set(key, pending); + } + } + this.pendingAutoSaves = []; + for (const [key, pending] of latestSaves) { + try { + await this.triggerAutoSave(pending.userId, pending.data); + const config = this.autoSaveConfigs.get(key); + if (config) { + config.lastAutoSave = new Date(); + this.autoSaveConfigs.set(key, config); + } + } + catch (error) { + this.logger.error(`Failed to process auto-save for ${key}: ${error.message}`); + } + } + } + getAutoSaveConfig(userId, slotId = this.AUTO_SAVE_SLOT) { + const configKey = this.getConfigKey(userId, slotId); + return this.autoSaveConfigs.get(configKey) || null; + } + getConfigKey(userId, slotId) { + return `${userId}:${slotId}`; + } +}; +exports.AutoSaveService = AutoSaveService; +__decorate([ + (0, schedule_1.Cron)(schedule_1.CronExpression.EVERY_MINUTE), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", typeof (_d = typeof Promise !== "undefined" && Promise) === "function" ? _d : Object) +], AutoSaveService.prototype, "processPendingAutoSaves", null); +exports.AutoSaveService = AutoSaveService = AutoSaveService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(save_game_entity_1.SaveGame)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof save_game_service_1.SaveGameService !== "undefined" && save_game_service_1.SaveGameService) === "function" ? _b : Object, typeof (_c = typeof cloud_sync_service_1.CloudSyncService !== "undefined" && cloud_sync_service_1.CloudSyncService) === "function" ? _c : Object]) +], AutoSaveService); + + +/***/ }), + +/***/ "./src/save-game/services/cloud-sync.service.ts": +/*!******************************************************!*\ + !*** ./src/save-game/services/cloud-sync.service.ts ***! + \******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var CloudSyncService_1; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CloudSyncService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const save_game_entity_1 = __webpack_require__(/*! ../entities/save-game.entity */ "./src/save-game/entities/save-game.entity.ts"); +const save_game_backup_entity_1 = __webpack_require__(/*! ../entities/save-game-backup.entity */ "./src/save-game/entities/save-game-backup.entity.ts"); +const save_game_interfaces_1 = __webpack_require__(/*! ../interfaces/save-game.interfaces */ "./src/save-game/interfaces/save-game.interfaces.ts"); +const save_compression_service_1 = __webpack_require__(/*! ./save-compression.service */ "./src/save-game/services/save-compression.service.ts"); +const save_encryption_service_1 = __webpack_require__(/*! ./save-encryption.service */ "./src/save-game/services/save-encryption.service.ts"); +const save_versioning_service_1 = __webpack_require__(/*! ./save-versioning.service */ "./src/save-game/services/save-versioning.service.ts"); +const save_backup_service_1 = __webpack_require__(/*! ./save-backup.service */ "./src/save-game/services/save-backup.service.ts"); +const save_analytics_service_1 = __webpack_require__(/*! ./save-analytics.service */ "./src/save-game/services/save-analytics.service.ts"); +let CloudSyncService = CloudSyncService_1 = class CloudSyncService { + constructor(saveGameRepo, compressionService, encryptionService, versioningService, backupService, analyticsService) { + this.saveGameRepo = saveGameRepo; + this.compressionService = compressionService; + this.encryptionService = encryptionService; + this.versioningService = versioningService; + this.backupService = backupService; + this.analyticsService = analyticsService; + this.logger = new common_1.Logger(CloudSyncService_1.name); + this.CONFLICT_THRESHOLD_MS = 60000; + } + async syncSave(userId, dto) { + const cloudSave = await this.saveGameRepo.findOne({ + where: { userId, slotId: dto.slotId }, + }); + if (!cloudSave) { + return { + success: true, + syncStatus: save_game_interfaces_1.SyncStatus.LOCAL_ONLY, + }; + } + const syncResult = this.determineSyncStatus(cloudSave, dto); + await this.analyticsService.recordSync(userId, syncResult.syncStatus === save_game_interfaces_1.SyncStatus.CONFLICT); + return syncResult; + } + determineSyncStatus(cloudSave, localInfo) { + const cloudSummary = this.toSummary(cloudSave); + if (!localInfo.localChecksum && !localInfo.lastModifiedAt) { + return { + success: true, + syncStatus: save_game_interfaces_1.SyncStatus.CLOUD_ONLY, + cloudSave: cloudSummary, + }; + } + if (localInfo.localChecksum === cloudSave.checksum?.value) { + return { + success: true, + syncStatus: save_game_interfaces_1.SyncStatus.SYNCED, + cloudSave: cloudSummary, + }; + } + const localModified = localInfo.lastModifiedAt + ? new Date(localInfo.lastModifiedAt) + : null; + const cloudModified = cloudSave.lastModifiedAt; + if (!localModified) { + return { + success: true, + syncStatus: save_game_interfaces_1.SyncStatus.CLOUD_NEWER, + cloudSave: cloudSummary, + }; + } + const timeDiff = Math.abs(localModified.getTime() - cloudModified.getTime()); + if (timeDiff < this.CONFLICT_THRESHOLD_MS) { + return { + success: false, + syncStatus: save_game_interfaces_1.SyncStatus.CONFLICT, + cloudSave: cloudSummary, + conflictDetails: { + localLastModified: localModified, + cloudLastModified: cloudModified, + localChecksum: localInfo.localChecksum || '', + cloudChecksum: cloudSave.checksum?.value || '', + suggestedResolution: this.suggestResolution(localModified, cloudModified), + }, + }; + } + if (localModified > cloudModified) { + return { + success: true, + syncStatus: save_game_interfaces_1.SyncStatus.LOCAL_NEWER, + cloudSave: cloudSummary, + }; + } + return { + success: true, + syncStatus: save_game_interfaces_1.SyncStatus.CLOUD_NEWER, + cloudSave: cloudSummary, + }; + } + suggestResolution(localModified, cloudModified) { + if (localModified > cloudModified) { + return save_game_interfaces_1.ConflictResolution.USE_LOCAL; + } + return save_game_interfaces_1.ConflictResolution.USE_CLOUD; + } + async resolveConflict(userId, dto) { + const cloudSave = await this.saveGameRepo.findOne({ + where: { id: dto.saveId, userId }, + }); + if (!cloudSave) { + throw new common_1.BadRequestException('Save not found'); + } + await this.backupService.createBackup(cloudSave, save_game_backup_entity_1.BackupReason.CONFLICT); + switch (dto.resolution) { + case save_game_interfaces_1.ConflictResolution.USE_CLOUD: + cloudSave.syncStatus = save_game_interfaces_1.SyncStatus.SYNCED; + break; + case save_game_interfaces_1.ConflictResolution.USE_LOCAL: + cloudSave.syncStatus = save_game_interfaces_1.SyncStatus.LOCAL_NEWER; + break; + case save_game_interfaces_1.ConflictResolution.USE_NEWEST: + cloudSave.syncStatus = save_game_interfaces_1.SyncStatus.SYNCED; + break; + case save_game_interfaces_1.ConflictResolution.MERGE: + if (!dto.mergedData) { + throw new common_1.BadRequestException('Merged data required for MERGE resolution'); + } + await this.updateSaveData(cloudSave, dto.mergedData); + cloudSave.syncStatus = save_game_interfaces_1.SyncStatus.SYNCED; + break; + case save_game_interfaces_1.ConflictResolution.KEEP_BOTH: + const newSlotId = await this.findNextEmptySlot(userId); + const backupSave = this.saveGameRepo.create({ + ...cloudSave, + id: undefined, + slotId: newSlotId, + slotName: `${cloudSave.slotName} (Cloud Backup)`, + syncStatus: save_game_interfaces_1.SyncStatus.SYNCED, + }); + await this.saveGameRepo.save(backupSave); + cloudSave.syncStatus = save_game_interfaces_1.SyncStatus.LOCAL_NEWER; + break; + } + cloudSave.lastSyncedAt = new Date(); + const saved = await this.saveGameRepo.save(cloudSave); + await this.analyticsService.recordConflictResolved(userId); + this.logger.log(`Resolved conflict for save ${dto.saveId} with resolution: ${dto.resolution}`); + return saved; + } + async uploadToCloud(userId, slotId, data, deviceId, platform) { + let cloudSave = await this.saveGameRepo.findOne({ + where: { userId, slotId }, + }); + const validation = this.versioningService.validateDataStructure(data); + if (!validation.valid) { + throw new common_1.BadRequestException(`Invalid save data: ${validation.errors.join(', ')}`); + } + const saveData = this.versioningService.mergeWithDefaults(data); + const { compressedData, compressionInfo } = await this.compressionService.compress(saveData); + const { encryptedData, encryptionInfo } = await this.encryptionService.encrypt(compressedData); + const checksum = { + algorithm: 'sha256', + value: this.encryptionService.generateChecksum(compressedData), + }; + if (cloudSave) { + cloudSave.compressedData = encryptedData; + cloudSave.compressionInfo = compressionInfo; + cloudSave.encryptionInfo = encryptionInfo; + cloudSave.checksum = checksum; + cloudSave.saveVersion++; + cloudSave.lastModifiedAt = new Date(); + cloudSave.lastSyncedAt = new Date(); + cloudSave.syncStatus = save_game_interfaces_1.SyncStatus.SYNCED; + cloudSave.deviceId = deviceId || cloudSave.deviceId; + cloudSave.platform = platform || cloudSave.platform; + if (process.env.NODE_ENV === 'development') { + cloudSave.rawData = saveData; + } + } + else { + cloudSave = this.saveGameRepo.create({ + userId, + slotId, + slotName: `Save Slot ${slotId}`, + version: this.versioningService.CURRENT_VERSION, + saveVersion: 1, + metadata: { + slotId, + slotName: `Save Slot ${slotId}`, + saveType: save_game_interfaces_1.SaveType.MANUAL, + playtime: 0, + }, + compressedData: encryptedData, + rawData: process.env.NODE_ENV === 'development' ? saveData : null, + checksum, + compressionInfo, + encryptionInfo, + syncStatus: save_game_interfaces_1.SyncStatus.SYNCED, + lastModifiedAt: new Date(), + lastSyncedAt: new Date(), + deviceId, + platform, + }); + } + return this.saveGameRepo.save(cloudSave); + } + async downloadFromCloud(userId, slotId) { + const cloudSave = await this.saveGameRepo.findOne({ + where: { userId, slotId }, + }); + if (!cloudSave) { + throw new common_1.BadRequestException(`No cloud save found for slot ${slotId}`); + } + if (cloudSave.isCorrupted) { + throw new common_1.BadRequestException('Cloud save is corrupted'); + } + const decryptedData = await this.encryptionService.decrypt(cloudSave.compressedData, cloudSave.encryptionInfo); + if (!this.encryptionService.verifyChecksum(decryptedData, cloudSave.checksum.value)) { + throw new common_1.BadRequestException('Cloud save data corrupted - checksum mismatch'); + } + const saveData = await this.compressionService.decompress(decryptedData, cloudSave.compressionInfo); + const migratedData = this.versioningService.migrateToCurrentVersion(saveData); + cloudSave.syncStatus = save_game_interfaces_1.SyncStatus.SYNCED; + cloudSave.lastSyncedAt = new Date(); + await this.saveGameRepo.save(cloudSave); + return { + data: migratedData, + metadata: this.toSummary(cloudSave), + }; + } + async batchSync(userId, dto) { + const results = []; + for (const save of dto.saves) { + const result = await this.syncSave(userId, { + ...save, + deviceId: dto.deviceId || save.deviceId, + }); + results.push(result); + } + return results; + } + async getCloudSaves(userId) { + const saves = await this.saveGameRepo.find({ + where: { userId }, + order: { slotId: 'ASC' }, + }); + return saves.map((save) => this.toSummary(save)); + } + async updateSaveData(save, data) { + const saveData = this.versioningService.mergeWithDefaults(data); + const { compressedData, compressionInfo } = await this.compressionService.compress(saveData); + const { encryptedData, encryptionInfo } = await this.encryptionService.encrypt(compressedData); + save.compressedData = encryptedData; + save.compressionInfo = compressionInfo; + save.encryptionInfo = encryptionInfo; + save.checksum = { + algorithm: 'sha256', + value: this.encryptionService.generateChecksum(compressedData), + }; + save.saveVersion++; + save.lastModifiedAt = new Date(); + if (process.env.NODE_ENV === 'development') { + save.rawData = saveData; + } + } + async findNextEmptySlot(userId) { + const usedSlots = await this.saveGameRepo + .createQueryBuilder('save') + .select('save.slotId') + .where('save.userId = :userId', { userId }) + .getMany(); + const usedSlotIds = new Set(usedSlots.map((s) => s.slotId)); + for (let i = 0; i < 100; i++) { + if (!usedSlotIds.has(i)) { + return i; + } + } + throw new common_1.BadRequestException('No empty save slots available'); + } + toSummary(save) { + return { + id: save.id, + slotId: save.slotId, + slotName: save.slotName, + version: save.saveVersion, + checksum: save.checksum?.value || '', + lastModifiedAt: save.lastModifiedAt, + playtime: save.metadata?.playtime || 0, + isCompressed: save.compressionInfo?.algorithm !== 'none', + isEncrypted: !!save.encryptionInfo, + }; + } +}; +exports.CloudSyncService = CloudSyncService; +exports.CloudSyncService = CloudSyncService = CloudSyncService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(save_game_entity_1.SaveGame)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof save_compression_service_1.SaveCompressionService !== "undefined" && save_compression_service_1.SaveCompressionService) === "function" ? _b : Object, typeof (_c = typeof save_encryption_service_1.SaveEncryptionService !== "undefined" && save_encryption_service_1.SaveEncryptionService) === "function" ? _c : Object, typeof (_d = typeof save_versioning_service_1.SaveVersioningService !== "undefined" && save_versioning_service_1.SaveVersioningService) === "function" ? _d : Object, typeof (_e = typeof save_backup_service_1.SaveBackupService !== "undefined" && save_backup_service_1.SaveBackupService) === "function" ? _e : Object, typeof (_f = typeof save_analytics_service_1.SaveAnalyticsService !== "undefined" && save_analytics_service_1.SaveAnalyticsService) === "function" ? _f : Object]) +], CloudSyncService); + + +/***/ }), + +/***/ "./src/save-game/services/save-analytics.service.ts": +/*!**********************************************************!*\ + !*** ./src/save-game/services/save-analytics.service.ts ***! + \**********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var SaveAnalyticsService_1; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveAnalyticsService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const save_game_analytics_entity_1 = __webpack_require__(/*! ../entities/save-game-analytics.entity */ "./src/save-game/entities/save-game-analytics.entity.ts"); +const save_game_interfaces_1 = __webpack_require__(/*! ../interfaces/save-game.interfaces */ "./src/save-game/interfaces/save-game.interfaces.ts"); +let SaveAnalyticsService = SaveAnalyticsService_1 = class SaveAnalyticsService { + constructor(analyticsRepo) { + this.analyticsRepo = analyticsRepo; + this.logger = new common_1.Logger(SaveAnalyticsService_1.name); + } + async getOrCreateAnalytics(userId) { + let analytics = await this.analyticsRepo.findOne({ where: { userId } }); + if (!analytics) { + analytics = this.analyticsRepo.create({ userId }); + analytics = await this.analyticsRepo.save(analytics); + } + return analytics; + } + async recordSave(userId, saveType, dataSize) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.totalSaves++; + analytics.lastSaveAt = new Date(); + analytics.totalDataSaved = Number(analytics.totalDataSaved) + dataSize; + analytics.averageSaveSize = + Number(analytics.totalDataSaved) / analytics.totalSaves; + switch (saveType) { + case save_game_interfaces_1.SaveType.AUTO: + analytics.autoSaves++; + break; + case save_game_interfaces_1.SaveType.MANUAL: + analytics.manualSaves++; + break; + case save_game_interfaces_1.SaveType.QUICKSAVE: + analytics.quickSaves++; + break; + } + await this.analyticsRepo.save(analytics); + } + async recordLoad(userId) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.totalLoads++; + analytics.lastLoadAt = new Date(); + await this.analyticsRepo.save(analytics); + } + async recordSync(userId, hadConflict) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.cloudSyncs++; + analytics.lastSyncAt = new Date(); + if (hadConflict) { + analytics.syncConflicts++; + } + await this.analyticsRepo.save(analytics); + } + async recordConflictResolved(userId) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.conflictsResolved++; + await this.analyticsRepo.save(analytics); + } + async recordCorruption(userId) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.corruptionEvents++; + await this.analyticsRepo.save(analytics); + } + async recordRecoveryAttempt(userId, success) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.recoveryAttempts++; + if (success) { + analytics.successfulRecoveries++; + } + await this.analyticsRepo.save(analytics); + } + async getAnalytics(userId) { + const analytics = await this.getOrCreateAnalytics(userId); + return { + totalSaves: analytics.totalSaves, + totalLoads: analytics.totalLoads, + autoSaves: analytics.autoSaves, + manualSaves: analytics.manualSaves, + cloudSyncs: analytics.cloudSyncs, + syncConflicts: analytics.syncConflicts, + corruptionEvents: analytics.corruptionEvents, + lastSaveAt: analytics.lastSaveAt, + lastLoadAt: analytics.lastLoadAt, + averageSaveSize: analytics.averageSaveSize, + }; + } + async getGlobalStats() { + const result = await this.analyticsRepo + .createQueryBuilder('analytics') + .select('COUNT(DISTINCT analytics.userId)', 'totalUsers') + .addSelect('SUM(analytics.totalSaves)', 'totalSaves') + .addSelect('SUM(analytics.cloudSyncs)', 'totalSyncs') + .addSelect('AVG(CASE WHEN analytics.cloudSyncs > 0 THEN analytics.syncConflicts::float / analytics.cloudSyncs ELSE 0 END)', 'avgConflictRate') + .addSelect('AVG(CASE WHEN analytics.totalSaves > 0 THEN analytics.corruptionEvents::float / analytics.totalSaves ELSE 0 END)', 'avgCorruptionRate') + .getRawOne(); + return { + totalUsers: parseInt(result.totalUsers) || 0, + totalSaves: parseInt(result.totalSaves) || 0, + totalSyncs: parseInt(result.totalSyncs) || 0, + averageConflictRate: parseFloat(result.avgConflictRate) || 0, + averageCorruptionRate: parseFloat(result.avgCorruptionRate) || 0, + }; + } +}; +exports.SaveAnalyticsService = SaveAnalyticsService; +exports.SaveAnalyticsService = SaveAnalyticsService = SaveAnalyticsService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(save_game_analytics_entity_1.SaveGameAnalytics)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object]) +], SaveAnalyticsService); + + +/***/ }), + +/***/ "./src/save-game/services/save-backup.service.ts": +/*!*******************************************************!*\ + !*** ./src/save-game/services/save-backup.service.ts ***! + \*******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var SaveBackupService_1; +var _a, _b, _c, _d, _e; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveBackupService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const schedule_1 = __webpack_require__(/*! @nestjs/schedule */ "@nestjs/schedule"); +const save_game_entity_1 = __webpack_require__(/*! ../entities/save-game.entity */ "./src/save-game/entities/save-game.entity.ts"); +const save_game_backup_entity_1 = __webpack_require__(/*! ../entities/save-game-backup.entity */ "./src/save-game/entities/save-game-backup.entity.ts"); +const save_compression_service_1 = __webpack_require__(/*! ./save-compression.service */ "./src/save-game/services/save-compression.service.ts"); +const save_encryption_service_1 = __webpack_require__(/*! ./save-encryption.service */ "./src/save-game/services/save-encryption.service.ts"); +const save_game_interfaces_1 = __webpack_require__(/*! ../interfaces/save-game.interfaces */ "./src/save-game/interfaces/save-game.interfaces.ts"); +let SaveBackupService = SaveBackupService_1 = class SaveBackupService { + constructor(backupRepo, saveGameRepo, compressionService, encryptionService) { + this.backupRepo = backupRepo; + this.saveGameRepo = saveGameRepo; + this.compressionService = compressionService; + this.encryptionService = encryptionService; + this.logger = new common_1.Logger(SaveBackupService_1.name); + this.SCHEDULED_BACKUP_RETENTION = 7; + this.CONFLICT_BACKUP_RETENTION = 30; + this.MANUAL_BACKUP_RETENTION = 90; + this.MAX_BACKUPS_PER_SLOT = 10; + } + async createBackup(saveGame, reason) { + this.logger.debug(`Creating ${reason} backup for save ${saveGame.id} (slot ${saveGame.slotId})`); + const retentionDays = this.getRetentionDays(reason); + const expiresAt = new Date(); + expiresAt.setDate(expiresAt.getDate() + retentionDays); + const checksum = this.encryptionService.generateChecksum(saveGame.compressedData); + const backup = this.backupRepo.create({ + saveGameId: saveGame.id, + userId: saveGame.userId, + slotId: saveGame.slotId, + saveVersion: saveGame.saveVersion, + reason, + compressedData: saveGame.compressedData, + checksum, + dataSize: saveGame.compressedData?.length || 0, + expiresAt, + }); + const savedBackup = await this.backupRepo.save(backup); + await this.cleanupOldBackups(saveGame.userId, saveGame.slotId); + return savedBackup; + } + getRetentionDays(reason) { + switch (reason) { + case save_game_backup_entity_1.BackupReason.MANUAL: + return this.MANUAL_BACKUP_RETENTION; + case save_game_backup_entity_1.BackupReason.CONFLICT: + case save_game_backup_entity_1.BackupReason.CORRUPTION_DETECTED: + return this.CONFLICT_BACKUP_RETENTION; + default: + return this.SCHEDULED_BACKUP_RETENTION; + } + } + async getBackups(userId, slotId) { + const where = { userId }; + if (slotId !== undefined) { + where.slotId = slotId; + } + return this.backupRepo.find({ + where, + order: { createdAt: 'DESC' }, + take: 50, + }); + } + async restoreFromBackup(backupId, userId) { + const backup = await this.backupRepo.findOne({ + where: { id: backupId, userId }, + }); + if (!backup) { + throw new Error('Backup not found'); + } + const currentChecksum = this.encryptionService.generateChecksum(backup.compressedData); + if (currentChecksum !== backup.checksum) { + throw new Error('Backup data corrupted - checksum mismatch'); + } + let saveGame = await this.saveGameRepo.findOne({ + where: { userId, slotId: backup.slotId }, + }); + if (saveGame) { + await this.createBackup(saveGame, save_game_backup_entity_1.BackupReason.PRE_UPDATE); + saveGame.compressedData = backup.compressedData; + saveGame.saveVersion = backup.saveVersion; + saveGame.lastModifiedAt = new Date(); + saveGame.isCorrupted = false; + saveGame.corruptionReason = null; + } + else { + saveGame = this.saveGameRepo.create({ + userId, + slotId: backup.slotId, + compressedData: backup.compressedData, + saveVersion: backup.saveVersion, + lastModifiedAt: new Date(), + metadata: { + slotId: backup.slotId, + slotName: `Restored Save (Slot ${backup.slotId})`, + saveType: save_game_interfaces_1.SaveType.MANUAL, + playtime: 0, + }, + }); + } + return this.saveGameRepo.save(saveGame); + } + async deleteBackup(backupId, userId) { + const result = await this.backupRepo.delete({ id: backupId, userId }); + if (result.affected === 0) { + throw new Error('Backup not found'); + } + } + async cleanupOldBackups(userId, slotId) { + const backups = await this.backupRepo.find({ + where: { userId, slotId }, + order: { createdAt: 'DESC' }, + }); + if (backups.length > this.MAX_BACKUPS_PER_SLOT) { + const toDelete = backups.slice(this.MAX_BACKUPS_PER_SLOT); + const idsToDelete = toDelete.map((b) => b.id); + await this.backupRepo.delete(idsToDelete); + this.logger.debug(`Cleaned up ${idsToDelete.length} old backups for user ${userId}, slot ${slotId}`); + } + } + async cleanupExpiredBackups() { + this.logger.log('Running scheduled backup cleanup'); + const result = await this.backupRepo.delete({ + expiresAt: (0, typeorm_2.LessThan)(new Date()), + }); + this.logger.log(`Cleaned up ${result.affected} expired backups`); + } +}; +exports.SaveBackupService = SaveBackupService; +__decorate([ + (0, schedule_1.Cron)(schedule_1.CronExpression.EVERY_DAY_AT_3AM), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", typeof (_e = typeof Promise !== "undefined" && Promise) === "function" ? _e : Object) +], SaveBackupService.prototype, "cleanupExpiredBackups", null); +exports.SaveBackupService = SaveBackupService = SaveBackupService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(save_game_backup_entity_1.SaveGameBackup)), + __param(1, (0, typeorm_1.InjectRepository)(save_game_entity_1.SaveGame)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof save_compression_service_1.SaveCompressionService !== "undefined" && save_compression_service_1.SaveCompressionService) === "function" ? _c : Object, typeof (_d = typeof save_encryption_service_1.SaveEncryptionService !== "undefined" && save_encryption_service_1.SaveEncryptionService) === "function" ? _d : Object]) +], SaveBackupService); + + +/***/ }), + +/***/ "./src/save-game/services/save-compression.service.ts": +/*!************************************************************!*\ + !*** ./src/save-game/services/save-compression.service.ts ***! + \************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var SaveCompressionService_1; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveCompressionService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const zlib = __importStar(__webpack_require__(/*! zlib */ "zlib")); +const util_1 = __webpack_require__(/*! util */ "util"); +const { Buffer: NodeBuffer } = __webpack_require__(/*! buffer */ "buffer"); +const gzip = (0, util_1.promisify)(zlib.gzip); +const gunzip = (0, util_1.promisify)(zlib.gunzip); +let SaveCompressionService = SaveCompressionService_1 = class SaveCompressionService { + constructor() { + this.logger = new common_1.Logger(SaveCompressionService_1.name); + } + async compress(data) { + const jsonString = JSON.stringify(data); + const originalSize = NodeBuffer.byteLength(jsonString, 'utf8'); + try { + const compressedData = await gzip(jsonString, { level: 6 }); + const compressedSize = compressedData.length; + if (compressedSize >= originalSize) { + this.logger.debug('Compression not beneficial, using raw data'); + return { + compressedData: NodeBuffer.from(jsonString, 'utf8'), + compressionInfo: { + algorithm: 'none', + originalSize, + compressedSize: originalSize, + }, + }; + } + const compressionRatio = ((1 - compressedSize / originalSize) * 100).toFixed(2); + this.logger.debug(`Compressed save data: ${originalSize} -> ${compressedSize} bytes (${compressionRatio}% reduction)`); + return { + compressedData, + compressionInfo: { + algorithm: 'gzip', + originalSize, + compressedSize, + }, + }; + } + catch (error) { + this.logger.error('Compression failed, using raw data', error); + return { + compressedData: NodeBuffer.from(jsonString, 'utf8'), + compressionInfo: { + algorithm: 'none', + originalSize, + compressedSize: originalSize, + }, + }; + } + } + async decompress(compressedData, compressionInfo) { + try { + let jsonString; + if (compressionInfo.algorithm === 'none') { + jsonString = compressedData.toString('utf8'); + } + else if (compressionInfo.algorithm === 'gzip') { + const decompressed = await gunzip(compressedData); + jsonString = decompressed.toString('utf8'); + } + else { + throw new Error(`Unsupported compression algorithm: ${compressionInfo.algorithm}`); + } + return JSON.parse(jsonString); + } + catch (error) { + this.logger.error('Decompression failed', error); + throw new Error(`Failed to decompress save data: ${error.message}`); + } + } + estimateCompressedSize(data) { + const jsonSize = JSON.stringify(data).length; + return Math.ceil(jsonSize * 0.35); + } +}; +exports.SaveCompressionService = SaveCompressionService; +exports.SaveCompressionService = SaveCompressionService = SaveCompressionService_1 = __decorate([ + (0, common_1.Injectable)() +], SaveCompressionService); + + +/***/ }), + +/***/ "./src/save-game/services/save-encryption.service.ts": +/*!***********************************************************!*\ + !*** ./src/save-game/services/save-encryption.service.ts ***! + \***********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var SaveEncryptionService_1; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveEncryptionService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const crypto = __importStar(__webpack_require__(/*! crypto */ "crypto")); +const { Buffer: NodeBuffer } = __webpack_require__(/*! buffer */ "buffer"); +let SaveEncryptionService = SaveEncryptionService_1 = class SaveEncryptionService { + constructor(configService) { + this.configService = configService; + this.logger = new common_1.Logger(SaveEncryptionService_1.name); + this.algorithm = 'aes-256-gcm'; + this.keyLength = 32; + this.ivLength = 16; + this.tagLength = 16; + this.initializeKey(); + } + initializeKey() { + const keyString = this.configService.get('SAVE_ENCRYPTION_KEY'); + if (keyString) { + this.encryptionKey = NodeBuffer.from(keyString, 'hex'); + if (this.encryptionKey.length !== this.keyLength) { + throw new Error(`Invalid encryption key length. Expected ${this.keyLength * 2} hex characters.`); + } + } + else { + this.logger.warn('SAVE_ENCRYPTION_KEY not configured. Using random key. Save data will not persist across restarts.'); + this.encryptionKey = crypto.randomBytes(this.keyLength); + } + } + async encrypt(data) { + const iv = crypto.randomBytes(this.ivLength); + const cipher = crypto.createCipheriv(this.algorithm, this.encryptionKey, iv, { + authTagLength: this.tagLength, + }); + const encrypted = NodeBuffer.concat([cipher.update(data), cipher.final()]); + const authTag = cipher.getAuthTag(); + return { + encryptedData: encrypted, + encryptionInfo: { + algorithm: 'aes-256-gcm', + iv: iv.toString('base64'), + tag: authTag.toString('base64'), + }, + }; + } + async decrypt(encryptedData, encryptionInfo) { + if (encryptionInfo.algorithm !== 'aes-256-gcm') { + throw new Error(`Unsupported encryption algorithm: ${encryptionInfo.algorithm}`); + } + const iv = NodeBuffer.from(encryptionInfo.iv, 'base64'); + const authTag = NodeBuffer.from(encryptionInfo.tag, 'base64'); + const decipher = crypto.createDecipheriv(this.algorithm, this.encryptionKey, iv, { + authTagLength: this.tagLength, + }); + decipher.setAuthTag(authTag); + try { + const decrypted = NodeBuffer.concat([decipher.update(encryptedData), decipher.final()]); + return decrypted; + } + catch (error) { + this.logger.error('Decryption failed - data may be corrupted or tampered with'); + throw new Error('Failed to decrypt save data: integrity check failed'); + } + } + generateChecksum(data) { + return crypto.createHash('sha256').update(data).digest('hex'); + } + verifyChecksum(data, expectedChecksum) { + const actualChecksum = this.generateChecksum(data); + return crypto.timingSafeEqual(NodeBuffer.from(actualChecksum, 'hex'), NodeBuffer.from(expectedChecksum, 'hex')); + } + generateDeviceKey(userId, deviceId) { + return crypto + .createHmac('sha256', this.encryptionKey) + .update(`${userId}:${deviceId}`) + .digest('hex'); + } +}; +exports.SaveEncryptionService = SaveEncryptionService; +exports.SaveEncryptionService = SaveEncryptionService = SaveEncryptionService_1 = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object]) +], SaveEncryptionService); + + +/***/ }), + +/***/ "./src/save-game/services/save-game.service.ts": +/*!*****************************************************!*\ + !*** ./src/save-game/services/save-game.service.ts ***! + \*****************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var SaveGameService_1; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveGameService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const save_game_entity_1 = __webpack_require__(/*! ../entities/save-game.entity */ "./src/save-game/entities/save-game.entity.ts"); +const save_game_backup_entity_1 = __webpack_require__(/*! ../entities/save-game-backup.entity */ "./src/save-game/entities/save-game-backup.entity.ts"); +const save_game_interfaces_1 = __webpack_require__(/*! ../interfaces/save-game.interfaces */ "./src/save-game/interfaces/save-game.interfaces.ts"); +const save_compression_service_1 = __webpack_require__(/*! ./save-compression.service */ "./src/save-game/services/save-compression.service.ts"); +const save_encryption_service_1 = __webpack_require__(/*! ./save-encryption.service */ "./src/save-game/services/save-encryption.service.ts"); +const save_versioning_service_1 = __webpack_require__(/*! ./save-versioning.service */ "./src/save-game/services/save-versioning.service.ts"); +const save_backup_service_1 = __webpack_require__(/*! ./save-backup.service */ "./src/save-game/services/save-backup.service.ts"); +const save_analytics_service_1 = __webpack_require__(/*! ./save-analytics.service */ "./src/save-game/services/save-analytics.service.ts"); +let SaveGameService = SaveGameService_1 = class SaveGameService { + constructor(saveGameRepo, compressionService, encryptionService, versioningService, backupService, analyticsService) { + this.saveGameRepo = saveGameRepo; + this.compressionService = compressionService; + this.encryptionService = encryptionService; + this.versioningService = versioningService; + this.backupService = backupService; + this.analyticsService = analyticsService; + this.logger = new common_1.Logger(SaveGameService_1.name); + this.MAX_SLOTS = 100; + } + async create(userId, dto) { + if (dto.slotId < 0 || dto.slotId >= this.MAX_SLOTS) { + throw new common_1.BadRequestException(`Slot ID must be between 0 and ${this.MAX_SLOTS - 1}`); + } + const existingSave = await this.saveGameRepo.findOne({ + where: { userId, slotId: dto.slotId }, + }); + if (existingSave) { + throw new common_1.BadRequestException(`Save slot ${dto.slotId} already exists. Use update instead.`); + } + const validation = this.versioningService.validateDataStructure(dto.data); + if (!validation.valid) { + throw new common_1.BadRequestException(`Invalid save data: ${validation.errors.join(', ')}`); + } + const saveData = this.versioningService.mergeWithDefaults(dto.data); + const { compressedData, compressionInfo } = await this.compressionService.compress(saveData); + const { encryptedData, encryptionInfo } = await this.encryptionService.encrypt(compressedData); + const checksum = { + algorithm: 'sha256', + value: this.encryptionService.generateChecksum(compressedData), + }; + const metadata = { + slotId: dto.slotId, + slotName: dto.slotName || `Save Slot ${dto.slotId}`, + saveType: dto.saveType || save_game_interfaces_1.SaveType.MANUAL, + playtime: dto.playtime || 0, + customData: dto.customMetadata, + }; + const saveGame = this.saveGameRepo.create({ + userId, + slotId: dto.slotId, + slotName: dto.slotName || `Save Slot ${dto.slotId}`, + saveType: dto.saveType || save_game_interfaces_1.SaveType.MANUAL, + version: this.versioningService.CURRENT_VERSION, + saveVersion: 1, + metadata, + compressedData: encryptedData, + rawData: process.env.NODE_ENV === 'development' ? saveData : null, + checksum, + compressionInfo, + encryptionInfo, + syncStatus: save_game_interfaces_1.SyncStatus.LOCAL_ONLY, + lastModifiedAt: new Date(), + deviceId: dto.deviceId, + platform: dto.platform, + saveCount: 1, + }); + const saved = await this.saveGameRepo.save(saveGame); + await this.analyticsService.recordSave(userId, dto.saveType || save_game_interfaces_1.SaveType.MANUAL, encryptedData.length); + this.logger.log(`Created save game ${saved.id} for user ${userId} in slot ${dto.slotId}`); + return saved; + } + async update(userId, slotId, dto) { + const saveGame = await this.saveGameRepo.findOne({ + where: { userId, slotId }, + }); + if (!saveGame) { + throw new common_1.NotFoundException(`Save slot ${slotId} not found`); + } + await this.backupService.createBackup(saveGame, save_game_backup_entity_1.BackupReason.PRE_UPDATE); + if (dto.slotName) { + saveGame.slotName = dto.slotName; + saveGame.metadata.slotName = dto.slotName; + } + if (dto.playtime !== undefined) { + saveGame.metadata.playtime = dto.playtime; + } + if (dto.customMetadata) { + saveGame.metadata.customData = { + ...saveGame.metadata.customData, + ...dto.customMetadata, + }; + } + if (dto.data) { + const validation = this.versioningService.validateDataStructure(dto.data); + if (!validation.valid) { + throw new common_1.BadRequestException(`Invalid save data: ${validation.errors.join(', ')}`); + } + const saveData = this.versioningService.mergeWithDefaults(dto.data); + const { compressedData, compressionInfo } = await this.compressionService.compress(saveData); + const { encryptedData, encryptionInfo } = await this.encryptionService.encrypt(compressedData); + saveGame.compressedData = encryptedData; + saveGame.compressionInfo = compressionInfo; + saveGame.encryptionInfo = encryptionInfo; + saveGame.checksum = { + algorithm: 'sha256', + value: this.encryptionService.generateChecksum(compressedData), + }; + if (process.env.NODE_ENV === 'development') { + saveGame.rawData = saveData; + } + } + saveGame.saveVersion++; + saveGame.saveCount++; + saveGame.lastModifiedAt = new Date(); + saveGame.deviceId = dto.deviceId || saveGame.deviceId; + saveGame.platform = dto.platform || saveGame.platform; + saveGame.syncStatus = save_game_interfaces_1.SyncStatus.LOCAL_NEWER; + const updated = await this.saveGameRepo.save(saveGame); + await this.analyticsService.recordSave(userId, saveGame.saveType, saveGame.compressedData?.length || 0); + return updated; + } + async findOne(userId, slotId) { + const saveGame = await this.saveGameRepo.findOne({ + where: { userId, slotId }, + }); + if (!saveGame) { + throw new common_1.NotFoundException(`Save slot ${slotId} not found`); + } + return saveGame; + } + async findAll(userId) { + const saves = await this.saveGameRepo.find({ + where: { userId }, + order: { slotId: 'ASC' }, + }); + return saves.map((save) => this.toSummary(save)); + } + async load(userId, slotId) { + const saveGame = await this.findOne(userId, slotId); + if (saveGame.isCorrupted) { + throw new common_1.BadRequestException(`Save is corrupted: ${saveGame.corruptionReason}. Try restoring from backup.`); + } + try { + const decryptedData = await this.encryptionService.decrypt(saveGame.compressedData, saveGame.encryptionInfo); + if (!this.encryptionService.verifyChecksum(decryptedData, saveGame.checksum.value)) { + await this.markCorrupted(saveGame, 'Checksum verification failed'); + throw new common_1.BadRequestException('Save data corrupted - checksum mismatch'); + } + const saveData = await this.compressionService.decompress(decryptedData, saveGame.compressionInfo); + const migratedData = this.versioningService.migrateToCurrentVersion(saveData); + saveGame.loadCount++; + await this.saveGameRepo.save(saveGame); + await this.analyticsService.recordLoad(userId); + return migratedData; + } + catch (error) { + this.logger.error(`Failed to load save ${saveGame.id}: ${error.message}`); + if (!saveGame.isCorrupted) { + await this.markCorrupted(saveGame, error.message); + await this.analyticsService.recordCorruption(userId); + } + throw error; + } + } + async delete(userId, slotId) { + const saveGame = await this.findOne(userId, slotId); + await this.backupService.createBackup(saveGame, save_game_backup_entity_1.BackupReason.MANUAL); + await this.saveGameRepo.remove(saveGame); + this.logger.log(`Deleted save game slot ${slotId} for user ${userId}`); + } + async getEmptySlots(userId, count = 10) { + const usedSlots = await this.saveGameRepo + .createQueryBuilder('save') + .select('save.slotId') + .where('save.userId = :userId', { userId }) + .getMany(); + const usedSlotIds = new Set(usedSlots.map((s) => s.slotId)); + const emptySlots = []; + for (let i = 0; i < this.MAX_SLOTS && emptySlots.length < count; i++) { + if (!usedSlotIds.has(i)) { + emptySlots.push(i); + } + } + return emptySlots; + } + async markCorrupted(saveGame, reason) { + saveGame.isCorrupted = true; + saveGame.corruptionReason = reason; + await this.saveGameRepo.save(saveGame); + try { + await this.backupService.createBackup(saveGame, save_game_backup_entity_1.BackupReason.CORRUPTION_DETECTED); + } + catch { + this.logger.warn(`Failed to create corruption backup for save ${saveGame.id}`); + } + } + toSummary(save) { + return { + id: save.id, + slotId: save.slotId, + slotName: save.slotName, + version: save.saveVersion, + checksum: save.checksum?.value || '', + lastModifiedAt: save.lastModifiedAt, + playtime: save.metadata?.playtime || 0, + isCompressed: save.compressionInfo?.algorithm !== 'none', + isEncrypted: !!save.encryptionInfo, + }; + } +}; +exports.SaveGameService = SaveGameService; +exports.SaveGameService = SaveGameService = SaveGameService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(save_game_entity_1.SaveGame)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof save_compression_service_1.SaveCompressionService !== "undefined" && save_compression_service_1.SaveCompressionService) === "function" ? _b : Object, typeof (_c = typeof save_encryption_service_1.SaveEncryptionService !== "undefined" && save_encryption_service_1.SaveEncryptionService) === "function" ? _c : Object, typeof (_d = typeof save_versioning_service_1.SaveVersioningService !== "undefined" && save_versioning_service_1.SaveVersioningService) === "function" ? _d : Object, typeof (_e = typeof save_backup_service_1.SaveBackupService !== "undefined" && save_backup_service_1.SaveBackupService) === "function" ? _e : Object, typeof (_f = typeof save_analytics_service_1.SaveAnalyticsService !== "undefined" && save_analytics_service_1.SaveAnalyticsService) === "function" ? _f : Object]) +], SaveGameService); + + +/***/ }), + +/***/ "./src/save-game/services/save-versioning.service.ts": +/*!***********************************************************!*\ + !*** ./src/save-game/services/save-versioning.service.ts ***! + \***********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var SaveVersioningService_1; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SaveVersioningService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +let SaveVersioningService = SaveVersioningService_1 = class SaveVersioningService { + constructor() { + this.logger = new common_1.Logger(SaveVersioningService_1.name); + this.CURRENT_VERSION = 1; + this.migrations = []; + } + isCompatible(version) { + if (version === this.CURRENT_VERSION) { + return true; + } + return this.canMigrate(version, this.CURRENT_VERSION); + } + canMigrate(fromVersion, toVersion) { + if (fromVersion >= toVersion) { + return fromVersion === toVersion; + } + let currentVersion = fromVersion; + while (currentVersion < toVersion) { + const migration = this.migrations.find((m) => m.fromVersion === currentVersion); + if (!migration) { + return false; + } + currentVersion = migration.toVersion; + } + return currentVersion === toVersion; + } + migrateToCurrentVersion(data) { + if (data.version === this.CURRENT_VERSION) { + return data; + } + if (data.version > this.CURRENT_VERSION) { + this.logger.warn(`Save data version ${data.version} is newer than supported version ${this.CURRENT_VERSION}. ` + + 'Data may not load correctly.'); + return data; + } + this.logger.log(`Migrating save data from v${data.version} to v${this.CURRENT_VERSION}`); + let migratedData = { ...data }; + let currentVersion = data.version; + while (currentVersion < this.CURRENT_VERSION) { + const migration = this.migrations.find((m) => m.fromVersion === currentVersion); + if (!migration) { + throw new Error(`No migration path from version ${currentVersion} to ${this.CURRENT_VERSION}`); + } + this.logger.debug(`Applying migration v${migration.fromVersion} -> v${migration.toVersion}`); + migratedData = migration.migrate(migratedData); + currentVersion = migration.toVersion; + } + return migratedData; + } + validateDataStructure(data) { + const errors = []; + if (!data || typeof data !== 'object') { + return { valid: false, errors: ['Data must be an object'] }; + } + const saveData = data; + if (typeof saveData.version !== 'number') { + errors.push('Missing or invalid version field'); + } + if (!saveData.gameState || typeof saveData.gameState !== 'object') { + errors.push('Missing or invalid gameState field'); + } + if (!saveData.playerState || typeof saveData.playerState !== 'object') { + errors.push('Missing or invalid playerState field'); + } + if (!saveData.progressState || typeof saveData.progressState !== 'object') { + errors.push('Missing or invalid progressState field'); + } + return { + valid: errors.length === 0, + errors, + }; + } + createDefaultSaveData() { + return { + version: this.CURRENT_VERSION, + gameState: {}, + playerState: { + position: { x: 0, y: 0 }, + health: 100, + inventory: [], + stats: {}, + }, + progressState: { + completedLevels: [], + unlockedAchievements: [], + collectibles: [], + }, + settings: {}, + }; + } + mergeWithDefaults(partialData) { + const defaults = this.createDefaultSaveData(); + return { + ...defaults, + ...partialData, + version: this.CURRENT_VERSION, + playerState: { + ...defaults.playerState, + ...partialData.playerState, + }, + progressState: { + ...defaults.progressState, + ...partialData.progressState, + }, + }; + } +}; +exports.SaveVersioningService = SaveVersioningService; +exports.SaveVersioningService = SaveVersioningService = SaveVersioningService_1 = __decorate([ + (0, common_1.Injectable)() +], SaveVersioningService); + + +/***/ }), + +/***/ "./src/soroban/soroban.module.ts": +/*!***************************************!*\ + !*** ./src/soroban/soroban.module.ts ***! + \***************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SorobanModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const soroban_service_1 = __webpack_require__(/*! ./soroban.service */ "./src/soroban/soroban.service.ts"); +let SorobanModule = class SorobanModule { +}; +exports.SorobanModule = SorobanModule; +exports.SorobanModule = SorobanModule = __decorate([ + (0, common_1.Module)({ + providers: [soroban_service_1.SorobanService], + exports: [soroban_service_1.SorobanService], + }) +], SorobanModule); + + +/***/ }), + +/***/ "./src/soroban/soroban.service.ts": +/*!****************************************!*\ + !*** ./src/soroban/soroban.service.ts ***! + \****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var SorobanService_1; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SorobanService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const stellar_sdk_1 = __webpack_require__(/*! @stellar/stellar-sdk */ "@stellar/stellar-sdk"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +let SorobanService = SorobanService_1 = class SorobanService { + constructor(configService) { + this.configService = configService; + this.logger = new common_1.Logger(SorobanService_1.name); + const rpcUrl = this.configService.get('SOROBAN_RPC_URL') || 'https://soroban-testnet.stellar.org'; + this.server = new stellar_sdk_1.rpc.Server(rpcUrl); + this.networkPassphrase = this.configService.get('STELLAR_NETWORK_PASSPHRASE') || stellar_sdk_1.Networks.TESTNET; + const secretKey = this.configService.get('STELLAR_SECRET_KEY'); + if (secretKey) { + this.sourceKeypair = stellar_sdk_1.Keypair.fromSecret(secretKey); + } + else { + this.logger.warn('STELLAR_SECRET_KEY not provided. SorobanService will be unable to sign transactions.'); + } + } + async invokeContract(contractId, method, params) { + if (!this.sourceKeypair) { + throw new Error('Source keypair not initialized. Cannot invoke contract.'); + } + try { + const contract = new stellar_sdk_1.Contract(contractId); + const sourceAccount = await this.server.getAccount(this.sourceKeypair.publicKey()); + const transaction = new stellar_sdk_1.TransactionBuilder(sourceAccount, { + fee: '1000000', + networkPassphrase: this.networkPassphrase, + }) + .addOperation(contract.call(method, ...params)) + .setTimeout(30) + .build(); + const preparedTransaction = await this.server.prepareTransaction(transaction); + preparedTransaction.sign(this.sourceKeypair); + const response = await this.server.sendTransaction(preparedTransaction); + if (response.status === 'ERROR') { + throw new Error(`Transaction failed: ${JSON.stringify(response.errorResult)}`); + } + this.logger.log(`Transaction sent: ${response.hash}. Waiting for confirmation...`); + let status = await this.server.getTransaction(response.hash); + let attempts = 0; + const maxAttempts = 15; + while (status.status === 'NOT_FOUND' && attempts < maxAttempts) { + await new Promise((resolve) => setTimeout(resolve, 1000)); + status = await this.server.getTransaction(response.hash); + attempts++; + } + const isSuccess = status.status === 'SUCCESS'; + if (!isSuccess) { + this.logger.error(`Transaction ${response.hash} failed or timed out with status: ${status.status}`); + } + else { + this.logger.log(`Transaction ${response.hash} confirmed successfully.`); + } + return { + hash: response.hash, + status: status.status, + result: status, + }; + } + catch (error) { + this.logger.error(`Error invoking contract ${contractId} method ${method}:`, error); + throw error; + } + } + async getContractData(contractId, key) { + try { + const contract = new stellar_sdk_1.Contract(contractId); + const ledgerKey = stellar_sdk_1.xdr.LedgerKey.contractData(new stellar_sdk_1.xdr.LedgerKeyContractData({ + contract: contract.address().toScAddress(), + key: key, + durability: stellar_sdk_1.xdr.ContractDataDurability.persistent(), + })); + const response = await this.server.getLedgerEntries(ledgerKey); + return response.entries[0]; + } + catch (error) { + this.logger.error(`Error fetching contract data for ${contractId}:`, error); + throw error; + } + } +}; +exports.SorobanService = SorobanService; +exports.SorobanService = SorobanService = SorobanService_1 = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object]) +], SorobanService); + + +/***/ }), + +/***/ "./src/tournaments/dto/create-tournament.dto.ts": +/*!******************************************************!*\ + !*** ./src/tournaments/dto/create-tournament.dto.ts ***! + \******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreateTournamentDto = exports.PrizeDistributionDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class PrizeDistributionDto { +} +exports.PrizeDistributionDto = PrizeDistributionDto; +__decorate([ + (0, class_validator_1.IsInt)(), + (0, class_validator_1.Min)(1), + __metadata("design:type", Number) +], PrizeDistributionDto.prototype, "position", void 0); +__decorate([ + (0, class_validator_1.IsInt)(), + (0, class_validator_1.Min)(0), + __metadata("design:type", Number) +], PrizeDistributionDto.prototype, "amount", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsInt)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.Max)(100), + __metadata("design:type", Number) +], PrizeDistributionDto.prototype, "percentage", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + __metadata("design:type", Array) +], PrizeDistributionDto.prototype, "badges", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + __metadata("design:type", Array) +], PrizeDistributionDto.prototype, "achievements", void 0); +class CreateTournamentDto { +} +exports.CreateTournamentDto = CreateTournamentDto; +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsNotEmpty)(), + __metadata("design:type", String) +], CreateTournamentDto.prototype, "name", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsNotEmpty)(), + __metadata("design:type", String) +], CreateTournamentDto.prototype, "description", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(['single-elimination', 'double-elimination', 'round-robin', 'swiss']), + __metadata("design:type", String) +], CreateTournamentDto.prototype, "bracketType", void 0); +__decorate([ + (0, class_validator_1.IsInt)(), + (0, class_validator_1.Min)(2), + (0, class_validator_1.Max)(256), + __metadata("design:type", Number) +], CreateTournamentDto.prototype, "maxParticipants", void 0); +__decorate([ + (0, class_validator_1.IsDateString)(), + __metadata("design:type", String) +], CreateTournamentDto.prototype, "registrationStartTime", void 0); +__decorate([ + (0, class_validator_1.IsDateString)(), + __metadata("design:type", String) +], CreateTournamentDto.prototype, "registrationEndTime", void 0); +__decorate([ + (0, class_validator_1.IsDateString)(), + __metadata("design:type", String) +], CreateTournamentDto.prototype, "startTime", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], CreateTournamentDto.prototype, "entryRequirements", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], CreateTournamentDto.prototype, "prizePool", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], CreateTournamentDto.prototype, "config", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], CreateTournamentDto.prototype, "rules", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + __metadata("design:type", Array) +], CreateTournamentDto.prototype, "tags", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], CreateTournamentDto.prototype, "metadata", void 0); + + +/***/ }), + +/***/ "./src/tournaments/dto/query-tournaments.dto.ts": +/*!******************************************************!*\ + !*** ./src/tournaments/dto/query-tournaments.dto.ts ***! + \******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.QueryTournamentsDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class QueryTournamentsDto { + constructor() { + this.page = 1; + this.limit = 10; + this.sortOrder = 'DESC'; + } +} +exports.QueryTournamentsDto = QueryTournamentsDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)([ + 'scheduled', + 'registration', + 'in-progress', + 'completed', + 'cancelled', + ]), + __metadata("design:type", String) +], QueryTournamentsDto.prototype, "status", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)(['single-elimination', 'double-elimination', 'round-robin', 'swiss']), + __metadata("design:type", String) +], QueryTournamentsDto.prototype, "bracketType", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsDateString)(), + __metadata("design:type", String) +], QueryTournamentsDto.prototype, "startDate", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsDateString)(), + __metadata("design:type", String) +], QueryTournamentsDto.prototype, "endDate", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsInt)(), + (0, class_validator_1.Min)(1), + __metadata("design:type", Number) +], QueryTournamentsDto.prototype, "page", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsInt)(), + (0, class_validator_1.Min)(1), + (0, class_validator_1.Max)(100), + __metadata("design:type", Number) +], QueryTournamentsDto.prototype, "limit", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)(['startTime', 'createdAt', 'prizePool', 'participants']), + __metadata("design:type", String) +], QueryTournamentsDto.prototype, "sortBy", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)(['ASC', 'DESC']), + __metadata("design:type", String) +], QueryTournamentsDto.prototype, "sortOrder", void 0); + + +/***/ }), + +/***/ "./src/tournaments/dto/submit-match-result.dto.ts": +/*!********************************************************!*\ + !*** ./src/tournaments/dto/submit-match-result.dto.ts ***! + \********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SubmitMatchResultDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class SubmitMatchResultDto { +} +exports.SubmitMatchResultDto = SubmitMatchResultDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], SubmitMatchResultDto.prototype, "matchId", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], SubmitMatchResultDto.prototype, "winnerId", void 0); +__decorate([ + (0, class_validator_1.IsInt)(), + __metadata("design:type", Number) +], SubmitMatchResultDto.prototype, "player1Score", void 0); +__decorate([ + (0, class_validator_1.IsInt)(), + __metadata("design:type", Number) +], SubmitMatchResultDto.prototype, "player2Score", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + __metadata("design:type", Array) +], SubmitMatchResultDto.prototype, "puzzleIds", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_a = typeof Array !== "undefined" && Array) === "function" ? _a : Object) +], SubmitMatchResultDto.prototype, "puzzleResults", void 0); + + +/***/ }), + +/***/ "./src/tournaments/dto/update-tournament.dto.ts": +/*!******************************************************!*\ + !*** ./src/tournaments/dto/update-tournament.dto.ts ***! + \******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UpdateTournamentDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class UpdateTournamentDto { +} +exports.UpdateTournamentDto = UpdateTournamentDto; +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], UpdateTournamentDto.prototype, "name", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], UpdateTournamentDto.prototype, "description", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsEnum)([ + 'scheduled', + 'registration', + 'in-progress', + 'completed', + 'cancelled', + ]), + __metadata("design:type", String) +], UpdateTournamentDto.prototype, "status", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], UpdateTournamentDto.prototype, "config", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + __metadata("design:type", Array) +], UpdateTournamentDto.prototype, "tags", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], UpdateTournamentDto.prototype, "metadata", void 0); + + +/***/ }), + +/***/ "./src/tournaments/entities/tournament-match.entity.ts": +/*!*************************************************************!*\ + !*** ./src/tournaments/entities/tournament-match.entity.ts ***! + \*************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TournamentMatch = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const tournament_entity_1 = __webpack_require__(/*! ./tournament.entity */ "./src/tournaments/entities/tournament.entity.ts"); +let TournamentMatch = class TournamentMatch { +}; +exports.TournamentMatch = TournamentMatch; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], TournamentMatch.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentMatch.prototype, "tournamentId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], TournamentMatch.prototype, "roundNumber", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50, nullable: true }), + __metadata("design:type", String) +], TournamentMatch.prototype, "roundName", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], TournamentMatch.prototype, "matchNumber", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'scheduled' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentMatch.prototype, "status", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentMatch.prototype, "player1Id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100, nullable: true }), + __metadata("design:type", String) +], TournamentMatch.prototype, "player1Name", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], TournamentMatch.prototype, "player1Score", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentMatch.prototype, "player2Id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100, nullable: true }), + __metadata("design:type", String) +], TournamentMatch.prototype, "player2Name", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], TournamentMatch.prototype, "player2Score", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentMatch.prototype, "winnerId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100, nullable: true }), + __metadata("design:type", String) +], TournamentMatch.prototype, "winnerName", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentMatch.prototype, "loserId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], TournamentMatch.prototype, "scheduledTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], TournamentMatch.prototype, "startTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], TournamentMatch.prototype, "endTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', nullable: true }), + __metadata("design:type", Number) +], TournamentMatch.prototype, "duration", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + __metadata("design:type", String) +], TournamentMatch.prototype, "nextMatchId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + __metadata("design:type", String) +], TournamentMatch.prototype, "loserNextMatchId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'simple-array', default: [] }), + __metadata("design:type", Array) +], TournamentMatch.prototype, "puzzleIds", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TournamentMatch.prototype, "config", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TournamentMatch.prototype, "results", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TournamentMatch.prototype, "statistics", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TournamentMatch.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], TournamentMatch.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], TournamentMatch.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => tournament_entity_1.Tournament, (tournament) => tournament.matches), + (0, typeorm_1.JoinColumn)({ name: 'tournamentId' }), + __metadata("design:type", typeof (_f = typeof tournament_entity_1.Tournament !== "undefined" && tournament_entity_1.Tournament) === "function" ? _f : Object) +], TournamentMatch.prototype, "tournament", void 0); +exports.TournamentMatch = TournamentMatch = __decorate([ + (0, typeorm_1.Entity)('tournament_matches'), + (0, typeorm_1.Index)(['tournamentId', 'roundNumber']), + (0, typeorm_1.Index)(['tournamentId', 'status']), + (0, typeorm_1.Index)(['player1Id', 'player2Id']) +], TournamentMatch); + + +/***/ }), + +/***/ "./src/tournaments/entities/tournament-participant.entity.ts": +/*!*******************************************************************!*\ + !*** ./src/tournaments/entities/tournament-participant.entity.ts ***! + \*******************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f, _g, _h; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TournamentParticipant = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const tournament_entity_1 = __webpack_require__(/*! ./tournament.entity */ "./src/tournaments/entities/tournament.entity.ts"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +let TournamentParticipant = class TournamentParticipant { +}; +exports.TournamentParticipant = TournamentParticipant; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], TournamentParticipant.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentParticipant.prototype, "tournamentId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentParticipant.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100 }), + __metadata("design:type", String) +], TournamentParticipant.prototype, "username", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'registered' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentParticipant.prototype, "status", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "seedNumber", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "currentRound", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "wins", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "losses", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "draws", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "totalScore", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "finalPosition", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "puzzlesSolved", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "totalPuzzlesAttempted", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "averageAccuracy", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "averageCompletionTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], TournamentParticipant.prototype, "longestWinStreak", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], TournamentParticipant.prototype, "registeredAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], TournamentParticipant.prototype, "checkedInAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], TournamentParticipant.prototype, "eliminatedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], TournamentParticipant.prototype, "withdrawnAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', nullable: true }), + __metadata("design:type", Object) +], TournamentParticipant.prototype, "prizeAwarded", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TournamentParticipant.prototype, "statistics", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TournamentParticipant.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], TournamentParticipant.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_f = typeof Date !== "undefined" && Date) === "function" ? _f : Object) +], TournamentParticipant.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => tournament_entity_1.Tournament, (tournament) => tournament.participants), + (0, typeorm_1.JoinColumn)({ name: 'tournamentId' }), + __metadata("design:type", typeof (_g = typeof tournament_entity_1.Tournament !== "undefined" && tournament_entity_1.Tournament) === "function" ? _g : Object) +], TournamentParticipant.prototype, "tournament", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => user_entity_1.User), + (0, typeorm_1.JoinColumn)({ name: 'userId' }), + __metadata("design:type", typeof (_h = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _h : Object) +], TournamentParticipant.prototype, "user", void 0); +exports.TournamentParticipant = TournamentParticipant = __decorate([ + (0, typeorm_1.Entity)('tournament_participants'), + (0, typeorm_1.Index)(['tournamentId', 'userId'], { unique: true }), + (0, typeorm_1.Index)(['tournamentId', 'status']), + (0, typeorm_1.Index)(['userId', 'registeredAt']) +], TournamentParticipant); + + +/***/ }), + +/***/ "./src/tournaments/entities/tournament-spectator.entity.ts": +/*!*****************************************************************!*\ + !*** ./src/tournaments/entities/tournament-spectator.entity.ts ***! + \*****************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TournamentSpectator = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +let TournamentSpectator = class TournamentSpectator { +}; +exports.TournamentSpectator = TournamentSpectator; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], TournamentSpectator.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentSpectator.prototype, "tournamentId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentSpectator.prototype, "matchId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TournamentSpectator.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100 }), + __metadata("design:type", String) +], TournamentSpectator.prototype, "username", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], TournamentSpectator.prototype, "joinedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], TournamentSpectator.prototype, "leftAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], TournamentSpectator.prototype, "totalWatchTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], TournamentSpectator.prototype, "isActive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TournamentSpectator.prototype, "engagement", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TournamentSpectator.prototype, "preferences", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], TournamentSpectator.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], TournamentSpectator.prototype, "updatedAt", void 0); +exports.TournamentSpectator = TournamentSpectator = __decorate([ + (0, typeorm_1.Entity)('tournament_spectators'), + (0, typeorm_1.Index)(['tournamentId', 'userId']), + (0, typeorm_1.Index)(['matchId', 'userId']), + (0, typeorm_1.Index)(['joinedAt']) +], TournamentSpectator); + + +/***/ }), + +/***/ "./src/tournaments/entities/tournament.entity.ts": +/*!*******************************************************!*\ + !*** ./src/tournaments/entities/tournament.entity.ts ***! + \*******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Tournament = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const tournament_participant_entity_1 = __webpack_require__(/*! ./tournament-participant.entity */ "./src/tournaments/entities/tournament-participant.entity.ts"); +const tournament_match_entity_1 = __webpack_require__(/*! ./tournament-match.entity */ "./src/tournaments/entities/tournament-match.entity.ts"); +let Tournament = class Tournament { +}; +exports.Tournament = Tournament; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Tournament.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 200 }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Tournament.prototype, "name", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text' }), + __metadata("design:type", String) +], Tournament.prototype, "description", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50, default: 'single-elimination' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Tournament.prototype, "bracketType", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'scheduled' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Tournament.prototype, "status", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 16 }), + __metadata("design:type", Number) +], Tournament.prototype, "maxParticipants", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], Tournament.prototype, "currentParticipants", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone' }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], Tournament.prototype, "registrationStartTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone' }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], Tournament.prototype, "registrationEndTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone' }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], Tournament.prototype, "startTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], Tournament.prototype, "endTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', nullable: true }), + __metadata("design:type", Number) +], Tournament.prototype, "duration", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Tournament.prototype, "createdBy", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + __metadata("design:type", String) +], Tournament.prototype, "winnerId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Tournament.prototype, "entryRequirements", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Tournament.prototype, "prizePool", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Tournament.prototype, "config", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Tournament.prototype, "bracket", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Tournament.prototype, "rules", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'simple-array', default: [] }), + (0, typeorm_1.Index)(), + __metadata("design:type", Array) +], Tournament.prototype, "tags", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Tournament.prototype, "statistics", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Tournament.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], Tournament.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_f = typeof Date !== "undefined" && Date) === "function" ? _f : Object) +], Tournament.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => tournament_participant_entity_1.TournamentParticipant, (participant) => participant.tournament), + __metadata("design:type", Array) +], Tournament.prototype, "participants", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => tournament_match_entity_1.TournamentMatch, (match) => match.tournament), + __metadata("design:type", Array) +], Tournament.prototype, "matches", void 0); +exports.Tournament = Tournament = __decorate([ + (0, typeorm_1.Entity)('tournaments'), + (0, typeorm_1.Index)(['status', 'startTime']), + (0, typeorm_1.Index)(['createdBy']) +], Tournament); + + +/***/ }), + +/***/ "./src/tournaments/tournaments.controller.ts": +/*!***************************************************!*\ + !*** ./src/tournaments/tournaments.controller.ts ***! + \***************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d, _e; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TournamentsController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const tournaments_service_1 = __webpack_require__(/*! ./tournaments.service */ "./src/tournaments/tournaments.service.ts"); +const create_tournament_dto_1 = __webpack_require__(/*! ./dto/create-tournament.dto */ "./src/tournaments/dto/create-tournament.dto.ts"); +const update_tournament_dto_1 = __webpack_require__(/*! ./dto/update-tournament.dto */ "./src/tournaments/dto/update-tournament.dto.ts"); +const query_tournaments_dto_1 = __webpack_require__(/*! ./dto/query-tournaments.dto */ "./src/tournaments/dto/query-tournaments.dto.ts"); +const submit_match_result_dto_1 = __webpack_require__(/*! ./dto/submit-match-result.dto */ "./src/tournaments/dto/submit-match-result.dto.ts"); +let TournamentsController = class TournamentsController { + constructor(tournamentsService) { + this.tournamentsService = tournamentsService; + } + async create(createTournamentDto, req) { + try { + const createdBy = req?.user?.id; + const tournament = await this.tournamentsService.create(createTournamentDto, createdBy); + return { + success: true, + message: 'Tournament created successfully', + data: tournament, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async findAll(query) { + try { + const result = await this.tournamentsService.findAll(query); + return { + success: true, + data: result.tournaments, + pagination: { + total: result.total, + page: result.page, + limit: result.limit, + totalPages: Math.ceil(result.total / result.limit), + }, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async getCompletedTournaments(limit) { + try { + const tournaments = await this.tournamentsService.getCompletedTournaments(limit || 10); + return { + success: true, + data: tournaments, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async findOne(id) { + try { + const tournament = await this.tournamentsService.findOne(id); + if (!tournament) { + throw new common_1.NotFoundException('Tournament not found'); + } + return { + success: true, + data: tournament, + }; + } + catch (error) { + if (error instanceof common_1.NotFoundException) { + throw error; + } + throw new common_1.BadRequestException(error.message); + } + } + async getBracket(id) { + try { + const bracket = await this.tournamentsService.getBracket(id); + return { + success: true, + data: bracket, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async getStandings(id) { + try { + const standings = await this.tournamentsService.getStandings(id); + return { + success: true, + data: standings, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async getTournamentHistory(id) { + try { + const history = await this.tournamentsService.getTournamentHistory(id); + return { + success: true, + data: history, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async getSpectators(id) { + try { + const spectators = await this.tournamentsService.getTournamentSpectators(id); + return { + success: true, + data: spectators, + count: spectators.length, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async update(id, updateTournamentDto) { + try { + const tournament = await this.tournamentsService.update(id, updateTournamentDto); + return { + success: true, + message: 'Tournament updated successfully', + data: tournament, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async remove(id) { + try { + await this.tournamentsService.remove(id); + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async register(id, req) { + try { + const userId = req?.user?.id || 'test-user-id'; + const username = req?.user?.username || 'TestUser'; + const participant = await this.tournamentsService.registerParticipant(id, userId, username); + return { + success: true, + message: 'Successfully registered for tournament', + data: participant, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async withdraw(id, req) { + try { + const userId = req?.user?.id || 'test-user-id'; + await this.tournamentsService.withdrawParticipant(id, userId); + return { + success: true, + message: 'Successfully withdrawn from tournament', + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async generateBracket(id) { + try { + const bracket = await this.tournamentsService.generateBracket(id); + return { + success: true, + message: 'Tournament bracket generated successfully', + data: bracket, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async submitMatchResult(matchId, submitMatchResultDto) { + try { + await this.tournamentsService.submitMatchResult(matchId, submitMatchResultDto.winnerId, submitMatchResultDto.player1Score, submitMatchResultDto.player2Score, submitMatchResultDto.puzzleResults); + return { + success: true, + message: 'Match result submitted successfully', + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async joinAsSpectator(id, req, matchId) { + try { + const userId = req?.user?.id || 'spectator-' + Date.now(); + const username = req?.user?.username || 'Spectator'; + const spectator = await this.tournamentsService.joinAsSpectator(id, userId, username, matchId); + return { + success: true, + message: 'Joined as spectator', + data: spectator, + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + async leaveAsSpectator(spectatorId) { + try { + await this.tournamentsService.leaveAsSpectator(spectatorId); + return { + success: true, + message: 'Left spectator mode', + }; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } +}; +exports.TournamentsController = TournamentsController; +__decorate([ + (0, common_1.Post)(), + (0, common_1.HttpCode)(common_1.HttpStatus.CREATED), + __param(0, (0, common_1.Body)()), + __param(1, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof create_tournament_dto_1.CreateTournamentDto !== "undefined" && create_tournament_dto_1.CreateTournamentDto) === "function" ? _b : Object, Object]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "create", null); +__decorate([ + (0, common_1.Get)(), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_c = typeof query_tournaments_dto_1.QueryTournamentsDto !== "undefined" && query_tournaments_dto_1.QueryTournamentsDto) === "function" ? _c : Object]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "findAll", null); +__decorate([ + (0, common_1.Get)('completed'), + __param(0, (0, common_1.Query)('limit')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Number]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "getCompletedTournaments", null); +__decorate([ + (0, common_1.Get)(':id'), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "findOne", null); +__decorate([ + (0, common_1.Get)(':id/bracket'), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "getBracket", null); +__decorate([ + (0, common_1.Get)(':id/standings'), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "getStandings", null); +__decorate([ + (0, common_1.Get)(':id/history'), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "getTournamentHistory", null); +__decorate([ + (0, common_1.Get)(':id/spectators'), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "getSpectators", null); +__decorate([ + (0, common_1.Patch)(':id'), + __param(0, (0, common_1.Param)('id')), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_d = typeof update_tournament_dto_1.UpdateTournamentDto !== "undefined" && update_tournament_dto_1.UpdateTournamentDto) === "function" ? _d : Object]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "update", null); +__decorate([ + (0, common_1.Delete)(':id'), + (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "remove", null); +__decorate([ + (0, common_1.Post)(':id/register'), + (0, common_1.HttpCode)(common_1.HttpStatus.CREATED), + __param(0, (0, common_1.Param)('id')), + __param(1, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, Object]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "register", null); +__decorate([ + (0, common_1.Post)(':id/withdraw'), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Param)('id')), + __param(1, (0, common_1.Request)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, Object]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "withdraw", null); +__decorate([ + (0, common_1.Post)(':id/generate-bracket'), + (0, common_1.HttpCode)(common_1.HttpStatus.CREATED), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "generateBracket", null); +__decorate([ + (0, common_1.Post)('matches/:matchId/result'), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Param)('matchId')), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_e = typeof submit_match_result_dto_1.SubmitMatchResultDto !== "undefined" && submit_match_result_dto_1.SubmitMatchResultDto) === "function" ? _e : Object]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "submitMatchResult", null); +__decorate([ + (0, common_1.Post)(':id/spectate'), + (0, common_1.HttpCode)(common_1.HttpStatus.CREATED), + __param(0, (0, common_1.Param)('id')), + __param(1, (0, common_1.Request)()), + __param(2, (0, common_1.Query)('matchId')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, Object, String]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "joinAsSpectator", null); +__decorate([ + (0, common_1.Post)('spectators/:spectatorId/leave'), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Param)('spectatorId')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TournamentsController.prototype, "leaveAsSpectator", null); +exports.TournamentsController = TournamentsController = __decorate([ + (0, common_1.Controller)('tournaments'), + __metadata("design:paramtypes", [typeof (_a = typeof tournaments_service_1.TournamentsService !== "undefined" && tournaments_service_1.TournamentsService) === "function" ? _a : Object]) +], TournamentsController); + + +/***/ }), + +/***/ "./src/tournaments/tournaments.module.ts": +/*!***********************************************!*\ + !*** ./src/tournaments/tournaments.module.ts ***! + \***********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TournamentsModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const tournaments_service_1 = __webpack_require__(/*! ./tournaments.service */ "./src/tournaments/tournaments.service.ts"); +const tournaments_controller_1 = __webpack_require__(/*! ./tournaments.controller */ "./src/tournaments/tournaments.controller.ts"); +const tournament_entity_1 = __webpack_require__(/*! ./entities/tournament.entity */ "./src/tournaments/entities/tournament.entity.ts"); +const tournament_participant_entity_1 = __webpack_require__(/*! ./entities/tournament-participant.entity */ "./src/tournaments/entities/tournament-participant.entity.ts"); +const tournament_match_entity_1 = __webpack_require__(/*! ./entities/tournament-match.entity */ "./src/tournaments/entities/tournament-match.entity.ts"); +const tournament_spectator_entity_1 = __webpack_require__(/*! ./entities/tournament-spectator.entity */ "./src/tournaments/entities/tournament-spectator.entity.ts"); +let TournamentsModule = class TournamentsModule { +}; +exports.TournamentsModule = TournamentsModule; +exports.TournamentsModule = TournamentsModule = __decorate([ + (0, common_1.Module)({ + imports: [ + typeorm_1.TypeOrmModule.forFeature([ + tournament_entity_1.Tournament, + tournament_participant_entity_1.TournamentParticipant, + tournament_match_entity_1.TournamentMatch, + tournament_spectator_entity_1.TournamentSpectator, + ]), + ], + controllers: [tournaments_controller_1.TournamentsController], + providers: [tournaments_service_1.TournamentsService], + exports: [tournaments_service_1.TournamentsService], + }) +], TournamentsModule); + + +/***/ }), + +/***/ "./src/tournaments/tournaments.service.ts": +/*!************************************************!*\ + !*** ./src/tournaments/tournaments.service.ts ***! + \************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var TournamentsService_1; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TournamentsService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const tournament_entity_1 = __webpack_require__(/*! ./entities/tournament.entity */ "./src/tournaments/entities/tournament.entity.ts"); +const tournament_participant_entity_1 = __webpack_require__(/*! ./entities/tournament-participant.entity */ "./src/tournaments/entities/tournament-participant.entity.ts"); +const tournament_match_entity_1 = __webpack_require__(/*! ./entities/tournament-match.entity */ "./src/tournaments/entities/tournament-match.entity.ts"); +const tournament_spectator_entity_1 = __webpack_require__(/*! ./entities/tournament-spectator.entity */ "./src/tournaments/entities/tournament-spectator.entity.ts"); +let TournamentsService = TournamentsService_1 = class TournamentsService { + constructor(tournamentRepository, participantRepository, matchRepository, spectatorRepository) { + this.tournamentRepository = tournamentRepository; + this.participantRepository = participantRepository; + this.matchRepository = matchRepository; + this.spectatorRepository = spectatorRepository; + this.logger = new common_1.Logger(TournamentsService_1.name); + } + async create(createTournamentDto, createdBy) { + this.logger.log(`Creating tournament: ${createTournamentDto.name}`); + const tournament = this.tournamentRepository.create({ + ...createTournamentDto, + createdBy, + status: 'scheduled', + currentParticipants: 0, + bracket: { + rounds: [], + totalRounds: 0, + currentRound: 0, + }, + statistics: { + totalMatches: 0, + completedMatches: 0, + topPerformers: [], + }, + }); + return await this.tournamentRepository.save(tournament); + } + async findAll(query) { + const { status, bracketType, startDate, endDate, page = 1, limit = 10, sortBy = 'startTime', sortOrder = 'DESC', } = query; + const queryBuilder = this.tournamentRepository.createQueryBuilder('tournament'); + if (status) { + queryBuilder.andWhere('tournament.status = :status', { status }); + } + if (bracketType) { + queryBuilder.andWhere('tournament.bracketType = :bracketType', { + bracketType, + }); + } + if (startDate && endDate) { + queryBuilder.andWhere('tournament.startTime BETWEEN :startDate AND :endDate', { + startDate, + endDate, + }); + } + else if (startDate) { + queryBuilder.andWhere('tournament.startTime >= :startDate', { + startDate, + }); + } + else if (endDate) { + queryBuilder.andWhere('tournament.startTime <= :endDate', { endDate }); + } + queryBuilder + .orderBy(`tournament.${sortBy}`, sortOrder) + .skip((page - 1) * limit) + .take(limit); + const [tournaments, total] = await queryBuilder.getManyAndCount(); + return { + tournaments, + total, + page, + limit, + }; + } + async findOne(id) { + const tournament = await this.tournamentRepository.findOne({ + where: { id }, + relations: ['participants', 'matches'], + }); + if (!tournament) { + throw new common_1.NotFoundException(`Tournament with ID ${id} not found`); + } + return tournament; + } + async update(id, updateTournamentDto) { + await this.tournamentRepository.update(id, updateTournamentDto); + return await this.findOne(id); + } + async remove(id) { + await this.tournamentRepository.delete(id); + } + async registerParticipant(tournamentId, userId, username, metadata) { + this.logger.log(`Registering participant ${username} for tournament ${tournamentId}`); + const tournament = await this.findOne(tournamentId); + if (!tournament) { + throw new Error('Tournament not found'); + } + if (tournament.status !== 'registration' && + tournament.status !== 'scheduled') { + throw new Error('Tournament registration is closed'); + } + if (tournament.currentParticipants >= tournament.maxParticipants) { + throw new Error('Tournament is full'); + } + const now = new Date(); + if (now < new Date(tournament.registrationStartTime)) { + throw new Error('Registration has not started yet'); + } + if (now > new Date(tournament.registrationEndTime)) { + throw new Error('Registration has ended'); + } + const existingParticipant = await this.participantRepository.findOne({ + where: { tournamentId, userId }, + }); + if (existingParticipant) { + throw new Error('Already registered for this tournament'); + } + const participant = this.participantRepository.create({ + tournamentId, + userId, + username, + status: 'registered', + registeredAt: new Date(), + metadata, + statistics: {}, + }); + await this.participantRepository.save(participant); + await this.tournamentRepository.update(tournamentId, { + currentParticipants: tournament.currentParticipants + 1, + }); + return participant; + } + async withdrawParticipant(tournamentId, userId) { + const participant = await this.participantRepository.findOne({ + where: { tournamentId, userId }, + }); + if (!participant) { + throw new Error('Participant not found'); + } + if (participant.status === 'active' || + participant.status === 'eliminated') { + throw new Error('Cannot withdraw after tournament has started'); + } + await this.participantRepository.update(participant.id, { + status: 'withdrawn', + withdrawnAt: new Date(), + }); + const tournament = await this.findOne(tournamentId); + await this.tournamentRepository.update(tournamentId, { + currentParticipants: Math.max(0, tournament.currentParticipants - 1), + }); + } + async generateBracket(tournamentId) { + this.logger.log(`Generating bracket for tournament ${tournamentId}`); + const tournament = await this.findOne(tournamentId); + const participants = await this.participantRepository.find({ + where: { tournamentId, status: 'registered' }, + }); + if (participants.length < 2) { + throw new Error('Not enough participants to generate bracket'); + } + const bracketType = tournament.bracketType; + let bracket; + switch (bracketType) { + case 'single-elimination': + bracket = await this.generateSingleEliminationBracket(tournament, participants); + break; + case 'double-elimination': + bracket = await this.generateDoubleEliminationBracket(tournament, participants); + break; + case 'round-robin': + bracket = await this.generateRoundRobinBracket(tournament, participants); + break; + case 'swiss': + bracket = await this.generateSwissBracket(tournament, participants); + break; + default: + throw new Error(`Unsupported bracket type: ${bracketType}`); + } + await this.tournamentRepository.update(tournamentId, { + bracket: { + rounds: bracket.rounds.map((r) => ({ + roundNumber: r.roundNumber, + roundName: r.roundName, + matches: r.matches.map((m) => m.matchId), + startTime: r.startTime, + endTime: r.endTime, + })), + totalRounds: bracket.totalRounds, + currentRound: 1, + }, + status: 'in-progress', + }); + return bracket; + } + async generateSingleEliminationBracket(tournament, participants) { + const seededParticipants = await this.seedParticipants(participants, tournament); + const nextPowerOf2 = Math.pow(2, Math.ceil(Math.log2(seededParticipants.length))); + const totalRounds = Math.log2(nextPowerOf2); + const rounds = []; + let currentMatches = []; + const firstRoundMatches = Math.ceil(seededParticipants.length / 2); + const roundNames = this.getRoundNames(totalRounds); + for (let i = 0; i < firstRoundMatches; i++) { + const player1 = seededParticipants[i * 2]; + const player2 = seededParticipants[i * 2 + 1]; + const match = await this.createMatch(tournament.id, 1, i + 1, player1, player2); + currentMatches.push({ + matchId: match.id, + roundNumber: 1, + matchNumber: i + 1, + player1: player1 + ? { id: player1.id, name: player1.username, seed: player1.seedNumber } + : undefined, + player2: player2 + ? { id: player2.id, name: player2.username, seed: player2.seedNumber } + : undefined, + status: 'scheduled', + }); + } + rounds.push({ + roundNumber: 1, + roundName: roundNames[0], + matches: currentMatches, + isComplete: false, + }); + for (let round = 2; round <= totalRounds; round++) { + const prevMatches = currentMatches; + currentMatches = []; + const matchesInRound = Math.ceil(prevMatches.length / 2); + for (let i = 0; i < matchesInRound; i++) { + const match = await this.createMatch(tournament.id, round, i + 1); + if (prevMatches[i * 2]) { + await this.matchRepository.update(prevMatches[i * 2].matchId, { + nextMatchId: match.id, + }); + } + if (prevMatches[i * 2 + 1]) { + await this.matchRepository.update(prevMatches[i * 2 + 1].matchId, { + nextMatchId: match.id, + }); + } + currentMatches.push({ + matchId: match.id, + roundNumber: round, + matchNumber: i + 1, + status: 'scheduled', + }); + } + rounds.push({ + roundNumber: round, + roundName: roundNames[round - 1], + matches: currentMatches, + isComplete: false, + }); + } + return { + tournamentId: tournament.id, + bracketType: 'single-elimination', + rounds, + totalRounds, + currentRound: 1, + }; + } + async generateDoubleEliminationBracket(tournament, participants) { + return await this.generateSingleEliminationBracket(tournament, participants); + } + async generateRoundRobinBracket(tournament, participants) { + const n = participants.length; + const totalRounds = n % 2 === 0 ? n - 1 : n; + const rounds = []; + for (let round = 1; round <= totalRounds; round++) { + const matches = []; + for (let i = 0; i < Math.floor(n / 2); i++) { + const player1Idx = i; + const player2Idx = n - 1 - i; + if (player1Idx !== player2Idx) { + const player1 = participants[player1Idx]; + const player2 = participants[player2Idx]; + const match = await this.createMatch(tournament.id, round, i + 1, player1, player2); + matches.push({ + matchId: match.id, + roundNumber: round, + matchNumber: i + 1, + player1: { id: player1.id, name: player1.username }, + player2: { id: player2.id, name: player2.username }, + status: 'scheduled', + }); + } + } + rounds.push({ + roundNumber: round, + roundName: `Round ${round}`, + matches, + isComplete: false, + }); + const temp = participants.splice(1, 1)[0]; + participants.push(temp); + } + return { + tournamentId: tournament.id, + bracketType: 'round-robin', + rounds, + totalRounds, + currentRound: 1, + }; + } + async generateSwissBracket(tournament, participants) { + const rounds = []; + const matches = []; + const shuffled = [...participants].sort(() => Math.random() - 0.5); + for (let i = 0; i < Math.floor(shuffled.length / 2); i++) { + const player1 = shuffled[i * 2]; + const player2 = shuffled[i * 2 + 1]; + const match = await this.createMatch(tournament.id, 1, i + 1, player1, player2); + matches.push({ + matchId: match.id, + roundNumber: 1, + matchNumber: i + 1, + player1: { id: player1.id, name: player1.username }, + player2: { id: player2.id, name: player2.username }, + status: 'scheduled', + }); + } + rounds.push({ + roundNumber: 1, + roundName: 'Round 1', + matches, + isComplete: false, + }); + return { + tournamentId: tournament.id, + bracketType: 'swiss', + rounds, + totalRounds: Math.ceil(Math.log2(participants.length)), + currentRound: 1, + }; + } + async seedParticipants(participants, tournament) { + const seedingMethod = tournament.rules?.matchmaking?.seedingMethod || 'random'; + let seeded; + switch (seedingMethod) { + case 'ranked': + seeded = [...participants].sort((a, b) => b.totalScore - a.totalScore); + break; + case 'seeded': + seeded = [...participants].sort((a, b) => (a.seedNumber || 999) - (b.seedNumber || 999)); + break; + case 'random': + default: + seeded = [...participants].sort(() => Math.random() - 0.5); + break; + } + for (let i = 0; i < seeded.length; i++) { + seeded[i].seedNumber = i + 1; + await this.participantRepository.update(seeded[i].id, { + seedNumber: i + 1, + status: 'active', + }); + } + return seeded; + } + getRoundNames(totalRounds) { + const names = []; + for (let i = totalRounds; i >= 1; i--) { + if (i === 1) { + names.push('Finals'); + } + else if (i === 2) { + names.push('Semi-Finals'); + } + else if (i === 3) { + names.push('Quarter-Finals'); + } + else { + names.push(`Round of ${Math.pow(2, i)}`); + } + } + return names.reverse(); + } + async createMatch(tournamentId, roundNumber, matchNumber, player1, player2) { + const match = this.matchRepository.create({ + tournamentId, + roundNumber, + matchNumber, + player1Id: player1?.id, + player1Name: player1?.username, + player2Id: player2?.id, + player2Name: player2?.username, + status: 'scheduled', + player1Score: 0, + player2Score: 0, + config: {}, + results: {}, + statistics: {}, + metadata: {}, + }); + return await this.matchRepository.save(match); + } + async submitMatchResult(matchId, winnerId, player1Score, player2Score, puzzleResults) { + this.logger.log(`Submitting match result for match ${matchId}`); + const match = await this.matchRepository.findOne({ + where: { id: matchId }, + }); + if (!match) { + throw new Error('Match not found'); + } + if (match.status === 'completed') { + throw new Error('Match already completed'); + } + const loserId = winnerId === match.player1Id ? match.player2Id : match.player1Id; + await this.matchRepository.update(matchId, { + winnerId, + winnerName: winnerId === match.player1Id ? match.player1Name : match.player2Name, + loserId, + player1Score, + player2Score, + status: 'completed', + endTime: new Date(), + duration: match.startTime + ? Math.floor((new Date().getTime() - new Date(match.startTime).getTime()) / 1000) + : 0, + results: { + puzzleResults, + }, + }); + if (winnerId) { + await this.updateParticipantStats(match.tournamentId, winnerId, true, player1Score || player2Score); + } + if (loserId) { + await this.updateParticipantStats(match.tournamentId, loserId, false, winnerId === match.player1Id ? player2Score : player1Score); + } + if (match.nextMatchId) { + await this.advanceToNextMatch(match.nextMatchId, winnerId, (winnerId === match.player1Id ? match.player1Name : match.player2Name)); + } + await this.checkTournamentCompletion(match.tournamentId); + } + async updateParticipantStats(tournamentId, participantId, isWin, score) { + const participant = await this.participantRepository.findOne({ + where: { id: participantId, tournamentId }, + }); + if (!participant) + return; + await this.participantRepository.update(participantId, { + wins: isWin ? participant.wins + 1 : participant.wins, + losses: !isWin ? participant.losses + 1 : participant.losses, + totalScore: participant.totalScore + score, + }); + if (!isWin) { + await this.participantRepository.update(participantId, { + status: 'eliminated', + eliminatedAt: new Date(), + }); + } + } + async advanceToNextMatch(nextMatchId, winnerId, winnerName) { + const nextMatch = await this.matchRepository.findOne({ + where: { id: nextMatchId }, + }); + if (!nextMatch) + return; + if (!nextMatch.player1Id) { + await this.matchRepository.update(nextMatchId, { + player1Id: winnerId, + player1Name: winnerName, + }); + } + else if (!nextMatch.player2Id) { + await this.matchRepository.update(nextMatchId, { + player2Id: winnerId, + player2Name: winnerName, + status: 'ready', + }); + } + } + async checkTournamentCompletion(tournamentId) { + const tournament = await this.findOne(tournamentId); + const matches = await this.matchRepository.find({ + where: { tournamentId }, + }); + const allMatchesCompleted = matches.every((m) => m.status === 'completed'); + if (allMatchesCompleted) { + const finalMatch = matches.reduce((prev, current) => current.roundNumber > prev.roundNumber ? current : prev); + await this.tournamentRepository.update(tournamentId, { + status: 'completed', + endTime: new Date(), + winnerId: finalMatch.winnerId, + }); + await this.distributePrizes(tournamentId); + } + } + async distributePrizes(tournamentId) { + this.logger.log(`Distributing prizes for tournament ${tournamentId}`); + const tournament = await this.findOne(tournamentId); + const participants = await this.participantRepository.find({ + where: { tournamentId }, + order: { wins: 'DESC', totalScore: 'DESC' }, + }); + const prizeDistribution = tournament.prizePool?.distribution || []; + for (let i = 0; i < Math.min(participants.length, prizeDistribution.length); i++) { + const participant = participants[i]; + const prize = prizeDistribution[i]; + await this.participantRepository.update(participant.id, { + finalPosition: i + 1, + prizeAwarded: { + amount: prize.amount, + currency: tournament.prizePool.currency, + badges: prize.badges, + achievements: prize.achievements, + awardedAt: new Date(), + }, + }); + } + } + async joinAsSpectator(tournamentId, userId, username, matchId) { + const spectator = this.spectatorRepository.create({ + tournamentId, + matchId, + userId, + username, + joinedAt: new Date(), + isActive: true, + engagement: {}, + preferences: {}, + }); + return await this.spectatorRepository.save(spectator); + } + async leaveAsSpectator(spectatorId) { + const spectator = await this.spectatorRepository.findOne({ + where: { id: spectatorId }, + }); + if (!spectator) + return; + const watchTime = Math.floor((new Date().getTime() - new Date(spectator.joinedAt).getTime()) / 1000); + await this.spectatorRepository.update(spectatorId, { + leftAt: new Date(), + isActive: false, + totalWatchTime: spectator.totalWatchTime + watchTime, + }); + } + async getTournamentSpectators(tournamentId) { + return await this.spectatorRepository.find({ + where: { tournamentId, isActive: true }, + }); + } + async getBracket(tournamentId) { + const tournament = await this.findOne(tournamentId); + const matches = await this.matchRepository.find({ + where: { tournamentId }, + order: { roundNumber: 'ASC', matchNumber: 'ASC' }, + }); + const rounds = []; + const roundMap = new Map(); + matches.forEach((match) => { + if (!roundMap.has(match.roundNumber)) { + roundMap.set(match.roundNumber, []); + } + roundMap.get(match.roundNumber).push({ + matchId: match.id, + roundNumber: match.roundNumber, + matchNumber: match.matchNumber, + player1: match.player1Id + ? { id: match.player1Id, name: match.player1Name } + : undefined, + player2: match.player2Id + ? { id: match.player2Id, name: match.player2Name } + : undefined, + winner: match.winnerId + ? { id: match.winnerId, name: match.winnerName } + : undefined, + status: match.status, + nextMatchId: match.nextMatchId, + loserNextMatchId: match.loserNextMatchId, + }); + }); + roundMap.forEach((matches, roundNumber) => { + rounds.push({ + roundNumber, + roundName: tournament.bracket.rounds?.find((r) => r.roundNumber === roundNumber) + ?.roundName || `Round ${roundNumber}`, + matches, + isComplete: matches.every((m) => m.status === 'completed'), + }); + }); + return { + tournamentId, + bracketType: tournament.bracketType, + rounds, + totalRounds: tournament.bracket.totalRounds || rounds.length, + currentRound: tournament.bracket.currentRound || 1, + }; + } + async getStandings(tournamentId) { + const participants = await this.participantRepository.find({ + where: { tournamentId }, + order: { wins: 'DESC', totalScore: 'DESC' }, + }); + return participants.map((p, index) => ({ + position: index + 1, + participantId: p.id, + userId: p.userId, + username: p.username, + wins: p.wins, + losses: p.losses, + draws: p.draws, + totalScore: p.totalScore, + averageAccuracy: p.averageAccuracy, + status: p.status, + })); + } + async getCompletedTournaments(limit = 10) { + return await this.tournamentRepository.find({ + where: { status: 'completed' }, + order: { endTime: 'DESC' }, + take: limit, + }); + } + async getTournamentHistory(tournamentId) { + const tournament = await this.findOne(tournamentId); + const participants = await this.participantRepository.find({ + where: { tournamentId }, + }); + const matches = await this.matchRepository.find({ + where: { tournamentId }, + order: { roundNumber: 'ASC', matchNumber: 'ASC' }, + }); + return { + tournament, + participants, + matches, + winner: participants.find((p) => p.finalPosition === 1), + topPerformers: participants + .sort((a, b) => b.totalScore - a.totalScore) + .slice(0, 10), + }; + } +}; +exports.TournamentsService = TournamentsService; +exports.TournamentsService = TournamentsService = TournamentsService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(tournament_entity_1.Tournament)), + __param(1, (0, typeorm_1.InjectRepository)(tournament_participant_entity_1.TournamentParticipant)), + __param(2, (0, typeorm_1.InjectRepository)(tournament_match_entity_1.TournamentMatch)), + __param(3, (0, typeorm_1.InjectRepository)(tournament_spectator_entity_1.TournamentSpectator)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object]) +], TournamentsService); + + +/***/ }), + +/***/ "./src/tutorial/controllers/contextual-help.controller.ts": +/*!****************************************************************!*\ + !*** ./src/tutorial/controllers/contextual-help.controller.ts ***! + \****************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var ContextualHelpController_1; +var _a, _b, _c, _d, _e, _f, _g; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ContextualHelpController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const contextual_help_service_1 = __webpack_require__(/*! ../services/contextual-help.service */ "./src/tutorial/services/contextual-help.service.ts"); +const localization_service_1 = __webpack_require__(/*! ../services/localization.service */ "./src/tutorial/services/localization.service.ts"); +const dto_1 = __webpack_require__(/*! ../dto */ "./src/tutorial/dto/index.ts"); +let ContextualHelpController = ContextualHelpController_1 = class ContextualHelpController { + constructor(helpService, localizationService) { + this.helpService = helpService; + this.localizationService = localizationService; + this.logger = new common_1.Logger(ContextualHelpController_1.name); + } + async create(dto) { + this.logger.log(`Creating contextual help: ${dto.name}`); + return this.helpService.create(dto); + } + async findAll(filters) { + this.logger.log(`Fetching contextual help with filters: ${JSON.stringify(filters)}`); + return this.helpService.findAll(filters); + } + async findOne(id, locale) { + this.logger.log(`Fetching contextual help: ${id}`); + const help = await this.helpService.findById(id); + if (locale) { + return this.localizationService.localizeHelp(help, locale); + } + return help; + } + async update(id, dto) { + this.logger.log(`Updating contextual help: ${id}`); + return this.helpService.update(id, dto); + } + async delete(id) { + this.logger.log(`Deleting contextual help: ${id}`); + await this.helpService.delete(id); + } + async triggerHelp(userId, dto, locale) { + this.logger.log(`Triggering help for user ${userId} in context: ${dto.context}`); + const help = await this.helpService.triggerHelp(userId, dto); + if (help && locale) { + return this.localizationService.localizeHelp(help, locale); + } + return help; + } + async recordInteraction(userId, dto) { + this.logger.log(`Recording interaction for user ${userId} on help ${dto.helpId}`); + await this.helpService.recordInteraction(userId, dto); + return { message: 'Interaction recorded successfully' }; + } + async getUserHistory(userId, helpId) { + this.logger.log(`Fetching help history for user ${userId}`); + return this.helpService.getUserHelpHistory(userId, helpId); + } + async getHelpForPuzzleStart(userId, puzzleType, locale) { + this.logger.log(`Getting puzzle start help for user ${userId}, type: ${puzzleType}`); + const help = await this.helpService.getHelpForPuzzleStart(userId, puzzleType); + if (help && locale) { + return this.localizationService.localizeHelp(help, locale); + } + return help; + } + async getHelpForRepeatedFailure(userId, puzzleId, attempts, locale) { + this.logger.log(`Getting failure help for user ${userId}, puzzle: ${puzzleId}`); + const help = await this.helpService.getHelpForRepeatedFailure(userId, puzzleId, attempts); + if (help && locale) { + return this.localizationService.localizeHelp(help, locale); + } + return help; + } + async getHelpForFeature(userId, feature, locale) { + this.logger.log(`Getting feature help for user ${userId}, feature: ${feature}`); + const help = await this.helpService.getHelpForFeature(userId, feature); + if (help && locale) { + return this.localizationService.localizeHelp(help, locale); + } + return help; + } + async getHelpAnalytics(helpId) { + this.logger.log('Fetching contextual help analytics'); + return this.helpService.getHelpAnalytics(helpId); + } +}; +exports.ContextualHelpController = ContextualHelpController; +__decorate([ + (0, common_1.Post)(), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_c = typeof dto_1.CreateContextualHelpDto !== "undefined" && dto_1.CreateContextualHelpDto) === "function" ? _c : Object]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "create", null); +__decorate([ + (0, common_1.Get)(), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_d = typeof dto_1.ContextualHelpFilterDto !== "undefined" && dto_1.ContextualHelpFilterDto) === "function" ? _d : Object]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "findAll", null); +__decorate([ + (0, common_1.Get)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Query)('locale')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "findOne", null); +__decorate([ + (0, common_1.Patch)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_e = typeof dto_1.UpdateContextualHelpDto !== "undefined" && dto_1.UpdateContextualHelpDto) === "function" ? _e : Object]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "update", null); +__decorate([ + (0, common_1.Delete)(':id'), + (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "delete", null); +__decorate([ + (0, common_1.Post)('user/:userId/trigger'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __param(2, (0, common_1.Query)('locale')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_f = typeof dto_1.TriggerContextualHelpDto !== "undefined" && dto_1.TriggerContextualHelpDto) === "function" ? _f : Object, String]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "triggerHelp", null); +__decorate([ + (0, common_1.Post)('user/:userId/interaction'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_g = typeof dto_1.RecordHelpInteractionDto !== "undefined" && dto_1.RecordHelpInteractionDto) === "function" ? _g : Object]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "recordInteraction", null); +__decorate([ + (0, common_1.Get)('user/:userId/history'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Query)('helpId')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "getUserHistory", null); +__decorate([ + (0, common_1.Get)('puzzle-start/:userId/:puzzleType'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Param)('puzzleType')), + __param(2, (0, common_1.Query)('locale')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String, String]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "getHelpForPuzzleStart", null); +__decorate([ + (0, common_1.Get)('repeated-failure/:userId/:puzzleId'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Param)('puzzleId', common_1.ParseUUIDPipe)), + __param(2, (0, common_1.Query)('attempts')), + __param(3, (0, common_1.Query)('locale')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String, Number, String]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "getHelpForRepeatedFailure", null); +__decorate([ + (0, common_1.Get)('feature/:userId/:feature'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Param)('feature')), + __param(2, (0, common_1.Query)('locale')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String, String]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "getHelpForFeature", null); +__decorate([ + (0, common_1.Get)('analytics'), + __param(0, (0, common_1.Query)('helpId')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], ContextualHelpController.prototype, "getHelpAnalytics", null); +exports.ContextualHelpController = ContextualHelpController = ContextualHelpController_1 = __decorate([ + (0, common_1.Controller)('contextual-help'), + __metadata("design:paramtypes", [typeof (_a = typeof contextual_help_service_1.ContextualHelpService !== "undefined" && contextual_help_service_1.ContextualHelpService) === "function" ? _a : Object, typeof (_b = typeof localization_service_1.LocalizationService !== "undefined" && localization_service_1.LocalizationService) === "function" ? _b : Object]) +], ContextualHelpController); + + +/***/ }), + +/***/ "./src/tutorial/controllers/index.ts": +/*!*******************************************!*\ + !*** ./src/tutorial/controllers/index.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__webpack_require__(/*! ./tutorial.controller */ "./src/tutorial/controllers/tutorial.controller.ts"), exports); +__exportStar(__webpack_require__(/*! ./tutorial-progress.controller */ "./src/tutorial/controllers/tutorial-progress.controller.ts"), exports); +__exportStar(__webpack_require__(/*! ./contextual-help.controller */ "./src/tutorial/controllers/contextual-help.controller.ts"), exports); +__exportStar(__webpack_require__(/*! ./tutorial-analytics.controller */ "./src/tutorial/controllers/tutorial-analytics.controller.ts"), exports); + + +/***/ }), + +/***/ "./src/tutorial/controllers/tutorial-analytics.controller.ts": +/*!*******************************************************************!*\ + !*** ./src/tutorial/controllers/tutorial-analytics.controller.ts ***! + \*******************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var TutorialAnalyticsController_1; +var _a, _b, _c, _d, _e, _f, _g; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TutorialAnalyticsController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const tutorial_analytics_service_1 = __webpack_require__(/*! ../services/tutorial-analytics.service */ "./src/tutorial/services/tutorial-analytics.service.ts"); +const dto_1 = __webpack_require__(/*! ../dto */ "./src/tutorial/dto/index.ts"); +let TutorialAnalyticsController = TutorialAnalyticsController_1 = class TutorialAnalyticsController { + constructor(analyticsService) { + this.analyticsService = analyticsService; + this.logger = new common_1.Logger(TutorialAnalyticsController_1.name); + } + async getCompletionRate(tutorialId, dateRange) { + this.logger.log(`Getting completion rate for tutorial: ${tutorialId}`); + const rate = await this.analyticsService.getCompletionRate(tutorialId, dateRange); + return { tutorialId, rate }; + } + async getAllCompletionRates(filters) { + this.logger.log('Getting all tutorial completion rates'); + return this.analyticsService.getAllCompletionRates(filters); + } + async getStepCompletionRates(tutorialId) { + this.logger.log(`Getting step completion rates for tutorial: ${tutorialId}`); + return this.analyticsService.getStepCompletionRates(tutorialId); + } + async getDropOffAnalysis(tutorialId) { + this.logger.log(`Getting drop-off analysis for tutorial: ${tutorialId}`); + return this.analyticsService.getDropOffAnalysis(tutorialId); + } + async getCommonDropOffPoints() { + this.logger.log('Getting common drop-off points across all tutorials'); + return this.analyticsService.getCommonDropOffPoints(); + } + async getEffectivenessReport(tutorialId, filters) { + this.logger.log(`Getting effectiveness report for tutorial: ${tutorialId}`); + return this.analyticsService.getEffectivenessReport(tutorialId, filters); + } + async getStepEffectiveness(stepId) { + this.logger.log(`Getting effectiveness for step: ${stepId}`); + return this.analyticsService.getStepEffectiveness(stepId); + } + async getUserLearningProfile(userId) { + this.logger.log(`Getting learning profile for user: ${userId}`); + return this.analyticsService.getUserLearningProfile(userId); + } + async getAverageCompletionTime(tutorialId) { + this.logger.log(`Getting average completion time for tutorial: ${tutorialId}`); + const time = await this.analyticsService.getAverageTimeToCompletion(tutorialId); + return { tutorialId, averageCompletionTimeSeconds: time }; + } + async getHintUsageAnalytics(tutorialId) { + this.logger.log(`Getting hint usage analytics for tutorial: ${tutorialId}`); + return this.analyticsService.getHintUsageAnalytics(tutorialId); + } + async getErrorPatterns(tutorialId) { + this.logger.log(`Getting error patterns for tutorial: ${tutorialId}`); + return this.analyticsService.getErrorPatterns(tutorialId); + } + async getDashboardReport(dateRange) { + this.logger.log('Generating tutorial analytics dashboard'); + return this.analyticsService.generateDashboardReport(dateRange); + } + async getActiveUsers() { + this.logger.log('Getting active tutorial users count'); + const count = await this.analyticsService.getActiveUsers(); + return { count }; + } + async getCurrentCompletions(interval) { + this.logger.log(`Getting completions for interval: ${interval}`); + const count = await this.analyticsService.getCurrentCompletions(interval); + return { interval, count }; + } + async exportAnalytics(filters) { + this.logger.log('Exporting tutorial analytics'); + return this.analyticsService.exportAnalyticsData(filters); + } + async getEvents(filters) { + this.logger.log(`Querying tutorial analytics events`); + return this.analyticsService.queryEvents(filters); + } +}; +exports.TutorialAnalyticsController = TutorialAnalyticsController; +__decorate([ + (0, common_1.Get)('completion-rate/:tutorialId'), + __param(0, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_b = typeof dto_1.DateRangeDto !== "undefined" && dto_1.DateRangeDto) === "function" ? _b : Object]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getCompletionRate", null); +__decorate([ + (0, common_1.Get)('completion-rates'), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_c = typeof dto_1.TutorialAnalyticsFilterDto !== "undefined" && dto_1.TutorialAnalyticsFilterDto) === "function" ? _c : Object]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getAllCompletionRates", null); +__decorate([ + (0, common_1.Get)('step-completion-rates/:tutorialId'), + __param(0, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getStepCompletionRates", null); +__decorate([ + (0, common_1.Get)('drop-off/:tutorialId'), + __param(0, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getDropOffAnalysis", null); +__decorate([ + (0, common_1.Get)('drop-off-points'), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getCommonDropOffPoints", null); +__decorate([ + (0, common_1.Get)('effectiveness/:tutorialId'), + __param(0, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_d = typeof dto_1.TutorialEffectivenessFilterDto !== "undefined" && dto_1.TutorialEffectivenessFilterDto) === "function" ? _d : Object]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getEffectivenessReport", null); +__decorate([ + (0, common_1.Get)('step-effectiveness/:stepId'), + __param(0, (0, common_1.Param)('stepId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getStepEffectiveness", null); +__decorate([ + (0, common_1.Get)('user/:userId/learning-profile'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getUserLearningProfile", null); +__decorate([ + (0, common_1.Get)('average-time/:tutorialId'), + __param(0, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getAverageCompletionTime", null); +__decorate([ + (0, common_1.Get)('hint-usage/:tutorialId'), + __param(0, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getHintUsageAnalytics", null); +__decorate([ + (0, common_1.Get)('error-patterns/:tutorialId'), + __param(0, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getErrorPatterns", null); +__decorate([ + (0, common_1.Get)('dashboard'), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_e = typeof dto_1.DateRangeDto !== "undefined" && dto_1.DateRangeDto) === "function" ? _e : Object]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getDashboardReport", null); +__decorate([ + (0, common_1.Get)('active-users'), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getActiveUsers", null); +__decorate([ + (0, common_1.Get)('completions/:interval'), + __param(0, (0, common_1.Param)('interval')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getCurrentCompletions", null); +__decorate([ + (0, common_1.Get)('export'), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_f = typeof dto_1.AnalyticsExportFilterDto !== "undefined" && dto_1.AnalyticsExportFilterDto) === "function" ? _f : Object]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "exportAnalytics", null); +__decorate([ + (0, common_1.Get)('events'), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_g = typeof dto_1.TutorialAnalyticsFilterDto !== "undefined" && dto_1.TutorialAnalyticsFilterDto) === "function" ? _g : Object]), + __metadata("design:returntype", Promise) +], TutorialAnalyticsController.prototype, "getEvents", null); +exports.TutorialAnalyticsController = TutorialAnalyticsController = TutorialAnalyticsController_1 = __decorate([ + (0, common_1.Controller)('tutorial-analytics'), + __metadata("design:paramtypes", [typeof (_a = typeof tutorial_analytics_service_1.TutorialAnalyticsService !== "undefined" && tutorial_analytics_service_1.TutorialAnalyticsService) === "function" ? _a : Object]) +], TutorialAnalyticsController); + + +/***/ }), + +/***/ "./src/tutorial/controllers/tutorial-progress.controller.ts": +/*!******************************************************************!*\ + !*** ./src/tutorial/controllers/tutorial-progress.controller.ts ***! + \******************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var TutorialProgressController_1; +var _a, _b, _c, _d, _e, _f, _g; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TutorialProgressController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const tutorial_progress_service_1 = __webpack_require__(/*! ../services/tutorial-progress.service */ "./src/tutorial/services/tutorial-progress.service.ts"); +const dto_1 = __webpack_require__(/*! ../dto */ "./src/tutorial/dto/index.ts"); +let TutorialProgressController = TutorialProgressController_1 = class TutorialProgressController { + constructor(progressService) { + this.progressService = progressService; + this.logger = new common_1.Logger(TutorialProgressController_1.name); + } + async startTutorial(userId, dto) { + this.logger.log(`User ${userId} starting tutorial: ${dto.tutorialId}`); + return this.progressService.startTutorial(userId, dto); + } + async getAllProgress(userId) { + this.logger.log(`Fetching all progress for user: ${userId}`); + return this.progressService.getAllUserProgress(userId); + } + async getProgress(userId, tutorialId) { + this.logger.log(`Fetching progress for user ${userId} on tutorial ${tutorialId}`); + return this.progressService.getUserProgress(userId, tutorialId); + } + async updateStepProgress(userId, dto) { + this.logger.log(`Updating step progress for user ${userId}`); + return this.progressService.updateStepProgress(userId, dto); + } + async skipTutorial(userId, dto) { + this.logger.log(`User ${userId} skipping tutorial: ${dto.tutorialId}`); + return this.progressService.skipTutorial(userId, dto); + } + async skipStep(userId, dto) { + this.logger.log(`User ${userId} skipping step: ${dto.stepId}`); + return this.progressService.skipStep(userId, dto); + } + async resumeTutorial(userId, dto) { + this.logger.log(`User ${userId} resuming tutorial: ${dto.tutorialId}`); + return this.progressService.resumeTutorial(userId, dto); + } + async saveCheckpoint(userId, dto) { + this.logger.log(`Saving checkpoint for user ${userId} on tutorial ${dto.tutorialId}`); + await this.progressService.saveCheckpoint(userId, dto); + return { message: 'Checkpoint saved successfully' }; + } + async getNextStep(userId, tutorialId) { + this.logger.log(`Getting next step for user ${userId} on tutorial ${tutorialId}`); + return this.progressService.getNextStep(userId, tutorialId); + } + async getAdaptiveState(userId, tutorialId) { + this.logger.log(`Getting adaptive state for user ${userId} on tutorial ${tutorialId}`); + return this.progressService.getAdaptiveState(userId, tutorialId); + } + async completeTutorial(userId, tutorialId) { + this.logger.log(`Completing tutorial ${tutorialId} for user ${userId}`); + return this.progressService.completeTutorial(userId, tutorialId); + } + async getCompletedTutorials(userId) { + this.logger.log(`Getting completed tutorials for user ${userId}`); + return this.progressService.getCompletedTutorials(userId); + } +}; +exports.TutorialProgressController = TutorialProgressController; +__decorate([ + (0, common_1.Post)('user/:userId/start'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_b = typeof dto_1.StartTutorialDto !== "undefined" && dto_1.StartTutorialDto) === "function" ? _b : Object]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "startTutorial", null); +__decorate([ + (0, common_1.Get)('user/:userId'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "getAllProgress", null); +__decorate([ + (0, common_1.Get)('user/:userId/tutorial/:tutorialId'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "getProgress", null); +__decorate([ + (0, common_1.Post)('user/:userId/step'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_c = typeof dto_1.UpdateStepProgressDto !== "undefined" && dto_1.UpdateStepProgressDto) === "function" ? _c : Object]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "updateStepProgress", null); +__decorate([ + (0, common_1.Post)('user/:userId/skip'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_d = typeof dto_1.SkipTutorialDto !== "undefined" && dto_1.SkipTutorialDto) === "function" ? _d : Object]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "skipTutorial", null); +__decorate([ + (0, common_1.Post)('user/:userId/skip-step'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_e = typeof dto_1.SkipStepDto !== "undefined" && dto_1.SkipStepDto) === "function" ? _e : Object]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "skipStep", null); +__decorate([ + (0, common_1.Post)('user/:userId/resume'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_f = typeof dto_1.ResumeTutorialDto !== "undefined" && dto_1.ResumeTutorialDto) === "function" ? _f : Object]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "resumeTutorial", null); +__decorate([ + (0, common_1.Post)('user/:userId/checkpoint'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_g = typeof dto_1.SaveCheckpointDto !== "undefined" && dto_1.SaveCheckpointDto) === "function" ? _g : Object]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "saveCheckpoint", null); +__decorate([ + (0, common_1.Get)('user/:userId/tutorial/:tutorialId/next-step'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "getNextStep", null); +__decorate([ + (0, common_1.Get)('user/:userId/tutorial/:tutorialId/adaptive-state'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "getAdaptiveState", null); +__decorate([ + (0, common_1.Post)('user/:userId/tutorial/:tutorialId/complete'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "completeTutorial", null); +__decorate([ + (0, common_1.Get)('user/:userId/completed'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialProgressController.prototype, "getCompletedTutorials", null); +exports.TutorialProgressController = TutorialProgressController = TutorialProgressController_1 = __decorate([ + (0, common_1.Controller)('tutorial-progress'), + __metadata("design:paramtypes", [typeof (_a = typeof tutorial_progress_service_1.TutorialProgressService !== "undefined" && tutorial_progress_service_1.TutorialProgressService) === "function" ? _a : Object]) +], TutorialProgressController); + + +/***/ }), + +/***/ "./src/tutorial/controllers/tutorial.controller.ts": +/*!*********************************************************!*\ + !*** ./src/tutorial/controllers/tutorial.controller.ts ***! + \*********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var TutorialController_1; +var _a, _b, _c, _d, _e, _f, _g, _h; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TutorialController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const tutorial_service_1 = __webpack_require__(/*! ../services/tutorial.service */ "./src/tutorial/services/tutorial.service.ts"); +const localization_service_1 = __webpack_require__(/*! ../services/localization.service */ "./src/tutorial/services/localization.service.ts"); +const dto_1 = __webpack_require__(/*! ../dto */ "./src/tutorial/dto/index.ts"); +let TutorialController = TutorialController_1 = class TutorialController { + constructor(tutorialService, localizationService) { + this.tutorialService = tutorialService; + this.localizationService = localizationService; + this.logger = new common_1.Logger(TutorialController_1.name); + } + async create(dto) { + this.logger.log(`Creating tutorial: ${dto.name}`); + return this.tutorialService.create(dto); + } + async findAll(filters) { + this.logger.log(`Fetching tutorials with filters: ${JSON.stringify(filters)}`); + return this.tutorialService.findAll(filters); + } + async getOnboardingCurriculum() { + this.logger.log('Fetching onboarding curriculum'); + return this.tutorialService.getOnboardingCurriculum(); + } + async getRecommendedTutorials(userId) { + this.logger.log(`Fetching recommended tutorials for user: ${userId}`); + return this.tutorialService.getRecommendedTutorials(userId); + } + async getTutorialsByMechanic(mechanic) { + this.logger.log(`Fetching tutorials for mechanic: ${mechanic}`); + return this.tutorialService.getTutorialsByMechanic(mechanic); + } + async findOne(id, locale) { + this.logger.log(`Fetching tutorial: ${id}`); + const tutorial = await this.tutorialService.findById(id); + if (locale) { + return this.localizationService.localizeTutorial(tutorial, locale); + } + return tutorial; + } + async update(id, dto) { + this.logger.log(`Updating tutorial: ${id}`); + return this.tutorialService.update(id, dto); + } + async delete(id) { + this.logger.log(`Deleting tutorial: ${id}`); + await this.tutorialService.delete(id); + } + async validatePrerequisites(id, userId) { + this.logger.log(`Validating prerequisites for tutorial ${id} and user ${userId}`); + return this.tutorialService.validatePrerequisites(userId, id); + } + async createStep(tutorialId, dto) { + this.logger.log(`Creating step for tutorial: ${tutorialId}`); + dto.tutorialId = tutorialId; + return this.tutorialService.createStep(dto); + } + async getSteps(tutorialId, locale) { + this.logger.log(`Fetching steps for tutorial: ${tutorialId}`); + const steps = await this.tutorialService.getStepsByTutorial(tutorialId); + if (locale) { + return Promise.all(steps.map((step) => this.localizationService.localizeStep(step, locale))); + } + return steps; + } + async getStep(stepId, locale) { + this.logger.log(`Fetching step: ${stepId}`); + const step = await this.tutorialService.getStepById(stepId); + if (locale) { + return this.localizationService.localizeStep(step, locale); + } + return step; + } + async updateStep(stepId, dto) { + this.logger.log(`Updating step: ${stepId}`); + return this.tutorialService.updateStep(stepId, dto); + } + async deleteStep(stepId) { + this.logger.log(`Deleting step: ${stepId}`); + await this.tutorialService.deleteStep(stepId); + } + async reorderSteps(tutorialId, orders) { + this.logger.log(`Reordering steps for tutorial: ${tutorialId}`); + await this.tutorialService.reorderSteps(tutorialId, orders); + return { message: 'Steps reordered successfully' }; + } + async getSupportedLocales() { + return this.localizationService.getSupportedLocales(); + } + async importTranslations(locale, translations) { + await this.localizationService.importTranslations(locale, translations); + return { message: `Imported translations for locale: ${locale}` }; + } + async getTranslations(locale) { + return this.localizationService.getTranslationsForLocale(locale); + } + async validateTranslations(locale) { + return this.localizationService.validateTranslations(locale); + } +}; +exports.TutorialController = TutorialController; +__decorate([ + (0, common_1.Post)(), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_c = typeof dto_1.CreateTutorialDto !== "undefined" && dto_1.CreateTutorialDto) === "function" ? _c : Object]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "create", null); +__decorate([ + (0, common_1.Get)(), + __param(0, (0, common_1.Query)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_d = typeof dto_1.TutorialFilterDto !== "undefined" && dto_1.TutorialFilterDto) === "function" ? _d : Object]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "findAll", null); +__decorate([ + (0, common_1.Get)('onboarding'), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "getOnboardingCurriculum", null); +__decorate([ + (0, common_1.Get)('recommended/:userId'), + __param(0, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "getRecommendedTutorials", null); +__decorate([ + (0, common_1.Get)('mechanic/:mechanic'), + __param(0, (0, common_1.Param)('mechanic')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "getTutorialsByMechanic", null); +__decorate([ + (0, common_1.Get)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Query)('locale')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "findOne", null); +__decorate([ + (0, common_1.Patch)(':id'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_e = typeof dto_1.UpdateTutorialDto !== "undefined" && dto_1.UpdateTutorialDto) === "function" ? _e : Object]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "update", null); +__decorate([ + (0, common_1.Delete)(':id'), + (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "delete", null); +__decorate([ + (0, common_1.Get)(':id/prerequisites/:userId'), + __param(0, (0, common_1.Param)('id', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Param)('userId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "validatePrerequisites", null); +__decorate([ + (0, common_1.Post)(':tutorialId/steps'), + __param(0, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_f = typeof dto_1.CreateTutorialStepDto !== "undefined" && dto_1.CreateTutorialStepDto) === "function" ? _f : Object]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "createStep", null); +__decorate([ + (0, common_1.Get)(':tutorialId/steps'), + __param(0, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Query)('locale')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "getSteps", null); +__decorate([ + (0, common_1.Get)(':tutorialId/steps/:stepId'), + __param(0, (0, common_1.Param)('stepId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Query)('locale')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, String]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "getStep", null); +__decorate([ + (0, common_1.Patch)(':tutorialId/steps/:stepId'), + __param(0, (0, common_1.Param)('stepId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_g = typeof dto_1.UpdateTutorialStepDto !== "undefined" && dto_1.UpdateTutorialStepDto) === "function" ? _g : Object]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "updateStep", null); +__decorate([ + (0, common_1.Delete)(':tutorialId/steps/:stepId'), + (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT), + __param(0, (0, common_1.Param)('stepId', common_1.ParseUUIDPipe)), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "deleteStep", null); +__decorate([ + (0, common_1.Post)(':tutorialId/steps/reorder'), + __param(0, (0, common_1.Param)('tutorialId', common_1.ParseUUIDPipe)), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, Array]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "reorderSteps", null); +__decorate([ + (0, common_1.Get)(':id/locales'), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "getSupportedLocales", null); +__decorate([ + (0, common_1.Post)(':id/translations/:locale'), + __param(0, (0, common_1.Param)('locale')), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_h = typeof Record !== "undefined" && Record) === "function" ? _h : Object]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "importTranslations", null); +__decorate([ + (0, common_1.Get)(':id/translations/:locale'), + __param(0, (0, common_1.Param)('locale')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "getTranslations", null); +__decorate([ + (0, common_1.Get)(':id/translations/:locale/validate'), + __param(0, (0, common_1.Param)('locale')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], TutorialController.prototype, "validateTranslations", null); +exports.TutorialController = TutorialController = TutorialController_1 = __decorate([ + (0, common_1.Controller)('tutorials'), + __metadata("design:paramtypes", [typeof (_a = typeof tutorial_service_1.TutorialService !== "undefined" && tutorial_service_1.TutorialService) === "function" ? _a : Object, typeof (_b = typeof localization_service_1.LocalizationService !== "undefined" && localization_service_1.LocalizationService) === "function" ? _b : Object]) +], TutorialController); + + +/***/ }), + +/***/ "./src/tutorial/dto/analytics.dto.ts": +/*!*******************************************!*\ + !*** ./src/tutorial/dto/analytics.dto.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f, _g, _h; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AnalyticsExportFilterDto = exports.TutorialEffectivenessFilterDto = exports.TutorialAnalyticsFilterDto = exports.DateRangeDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +class DateRangeDto { +} +exports.DateRangeDto = DateRangeDto; +__decorate([ + (0, class_validator_1.IsDate)(), + (0, class_transformer_1.Type)(() => Date), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], DateRangeDto.prototype, "startDate", void 0); +__decorate([ + (0, class_validator_1.IsDate)(), + (0, class_transformer_1.Type)(() => Date), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], DateRangeDto.prototype, "endDate", void 0); +class TutorialAnalyticsFilterDto { +} +exports.TutorialAnalyticsFilterDto = TutorialAnalyticsFilterDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], TutorialAnalyticsFilterDto.prototype, "tutorialId", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], TutorialAnalyticsFilterDto.prototype, "stepId", void 0); +__decorate([ + (0, class_validator_1.IsDate)(), + (0, class_transformer_1.Type)(() => Date), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], TutorialAnalyticsFilterDto.prototype, "startDate", void 0); +__decorate([ + (0, class_validator_1.IsDate)(), + (0, class_transformer_1.Type)(() => Date), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], TutorialAnalyticsFilterDto.prototype, "endDate", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], TutorialAnalyticsFilterDto.prototype, "eventType", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(['day', 'week', 'month']), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], TutorialAnalyticsFilterDto.prototype, "groupBy", void 0); +class TutorialEffectivenessFilterDto { +} +exports.TutorialEffectivenessFilterDto = TutorialEffectivenessFilterDto; +__decorate([ + (0, class_validator_1.IsDate)(), + (0, class_transformer_1.Type)(() => Date), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], TutorialEffectivenessFilterDto.prototype, "startDate", void 0); +__decorate([ + (0, class_validator_1.IsDate)(), + (0, class_transformer_1.Type)(() => Date), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_f = typeof Date !== "undefined" && Date) === "function" ? _f : Object) +], TutorialEffectivenessFilterDto.prototype, "endDate", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], TutorialEffectivenessFilterDto.prototype, "includeStepBreakdown", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], TutorialEffectivenessFilterDto.prototype, "includeDropOffAnalysis", void 0); +class AnalyticsExportFilterDto { +} +exports.AnalyticsExportFilterDto = AnalyticsExportFilterDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], AnalyticsExportFilterDto.prototype, "tutorialId", void 0); +__decorate([ + (0, class_validator_1.IsDate)(), + (0, class_transformer_1.Type)(() => Date), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_g = typeof Date !== "undefined" && Date) === "function" ? _g : Object) +], AnalyticsExportFilterDto.prototype, "startDate", void 0); +__decorate([ + (0, class_validator_1.IsDate)(), + (0, class_transformer_1.Type)(() => Date), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_h = typeof Date !== "undefined" && Date) === "function" ? _h : Object) +], AnalyticsExportFilterDto.prototype, "endDate", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(['csv', 'json']), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], AnalyticsExportFilterDto.prototype, "format", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], AnalyticsExportFilterDto.prototype, "includeUserDetails", void 0); + + +/***/ }), + +/***/ "./src/tutorial/dto/contextual-help.dto.ts": +/*!*************************************************!*\ + !*** ./src/tutorial/dto/contextual-help.dto.ts ***! + \*************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.RecordHelpInteractionDto = exports.TriggerContextualHelpDto = exports.ContextualHelpFilterDto = exports.UpdateContextualHelpDto = exports.CreateContextualHelpDto = exports.DisplayRulesDto = exports.TriggerConditionsDto = exports.HelpContentDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +const mapped_types_1 = __webpack_require__(/*! @nestjs/mapped-types */ "@nestjs/mapped-types"); +const contextual_help_entity_1 = __webpack_require__(/*! ../entities/contextual-help.entity */ "./src/tutorial/entities/contextual-help.entity.ts"); +const contextual_help_interaction_entity_1 = __webpack_require__(/*! ../entities/contextual-help-interaction.entity */ "./src/tutorial/entities/contextual-help-interaction.entity.ts"); +class HelpContentDto { +} +exports.HelpContentDto = HelpContentDto; +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(3), + __metadata("design:type", String) +], HelpContentDto.prototype, "title", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(10), + __metadata("design:type", String) +], HelpContentDto.prototype, "body", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(['tooltip', 'modal', 'overlay', 'sidebar', 'banner']), + __metadata("design:type", typeof (_a = typeof contextual_help_entity_1.HelpDisplayType !== "undefined" && contextual_help_entity_1.HelpDisplayType) === "function" ? _a : Object) +], HelpContentDto.prototype, "type", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Object) +], HelpContentDto.prototype, "media", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_b = typeof Array !== "undefined" && Array) === "function" ? _b : Object) +], HelpContentDto.prototype, "actions", void 0); +class TriggerConditionsDto { +} +exports.TriggerConditionsDto = TriggerConditionsDto; +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], TriggerConditionsDto.prototype, "minAttempts", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], TriggerConditionsDto.prototype, "maxAttempts", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], TriggerConditionsDto.prototype, "timeThreshold", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Array) +], TriggerConditionsDto.prototype, "errorPatterns", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Object) +], TriggerConditionsDto.prototype, "userLevel", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], TriggerConditionsDto.prototype, "hasCompletedTutorial", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], TriggerConditionsDto.prototype, "tutorialId", void 0); +class DisplayRulesDto { +} +exports.DisplayRulesDto = DisplayRulesDto; +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], DisplayRulesDto.prototype, "maxShowCount", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], DisplayRulesDto.prototype, "cooldownSeconds", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], DisplayRulesDto.prototype, "showOnce", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], DisplayRulesDto.prototype, "dismissable", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], DisplayRulesDto.prototype, "autoHideAfter", void 0); +class CreateContextualHelpDto { +} +exports.CreateContextualHelpDto = CreateContextualHelpDto; +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(3), + (0, class_validator_1.MaxLength)(100), + __metadata("design:type", String) +], CreateContextualHelpDto.prototype, "name", void 0); +__decorate([ + (0, class_validator_1.IsEnum)([ + 'puzzle_start', + 'hint_needed', + 'repeated_failure', + 'first_visit', + 'feature_discovery', + 'idle_timeout', + 'achievement_near', + 'custom', + ]), + __metadata("design:type", typeof (_c = typeof contextual_help_entity_1.TriggerContext !== "undefined" && contextual_help_entity_1.TriggerContext) === "function" ? _c : Object) +], CreateContextualHelpDto.prototype, "triggerContext", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], CreateContextualHelpDto.prototype, "targetFeature", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], CreateContextualHelpDto.prototype, "targetPuzzleType", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], CreateContextualHelpDto.prototype, "priority", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => HelpContentDto), + __metadata("design:type", HelpContentDto) +], CreateContextualHelpDto.prototype, "content", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => TriggerConditionsDto), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", TriggerConditionsDto) +], CreateContextualHelpDto.prototype, "triggerConditions", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => DisplayRulesDto), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", DisplayRulesDto) +], CreateContextualHelpDto.prototype, "displayRules", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], CreateContextualHelpDto.prototype, "isActive", void 0); +class UpdateContextualHelpDto extends (0, mapped_types_1.PartialType)(CreateContextualHelpDto) { +} +exports.UpdateContextualHelpDto = UpdateContextualHelpDto; +class ContextualHelpFilterDto { +} +exports.ContextualHelpFilterDto = ContextualHelpFilterDto; +__decorate([ + (0, class_validator_1.IsEnum)([ + 'puzzle_start', + 'hint_needed', + 'repeated_failure', + 'first_visit', + 'feature_discovery', + 'idle_timeout', + 'achievement_near', + 'custom', + ]), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_d = typeof contextual_help_entity_1.TriggerContext !== "undefined" && contextual_help_entity_1.TriggerContext) === "function" ? _d : Object) +], ContextualHelpFilterDto.prototype, "triggerContext", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], ContextualHelpFilterDto.prototype, "targetFeature", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], ContextualHelpFilterDto.prototype, "targetPuzzleType", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], ContextualHelpFilterDto.prototype, "isActive", void 0); +class TriggerContextualHelpDto { +} +exports.TriggerContextualHelpDto = TriggerContextualHelpDto; +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], TriggerContextualHelpDto.prototype, "context", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], TriggerContextualHelpDto.prototype, "puzzleId", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], TriggerContextualHelpDto.prototype, "puzzleType", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], TriggerContextualHelpDto.prototype, "feature", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], TriggerContextualHelpDto.prototype, "attempts", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], TriggerContextualHelpDto.prototype, "timeSpent", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Array) +], TriggerContextualHelpDto.prototype, "recentErrors", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], TriggerContextualHelpDto.prototype, "userLevel", void 0); +class RecordHelpInteractionDto { +} +exports.RecordHelpInteractionDto = RecordHelpInteractionDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], RecordHelpInteractionDto.prototype, "helpId", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(['shown', 'dismissed', 'clicked', 'completed', 'auto_hidden']), + __metadata("design:type", typeof (_e = typeof contextual_help_interaction_entity_1.InteractionAction !== "undefined" && contextual_help_interaction_entity_1.InteractionAction) === "function" ? _e : Object) +], RecordHelpInteractionDto.prototype, "action", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], RecordHelpInteractionDto.prototype, "viewDuration", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], RecordHelpInteractionDto.prototype, "actionTaken", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Object) +], RecordHelpInteractionDto.prototype, "context", void 0); + + +/***/ }), + +/***/ "./src/tutorial/dto/index.ts": +/*!***********************************!*\ + !*** ./src/tutorial/dto/index.ts ***! + \***********************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__webpack_require__(/*! ./tutorial.dto */ "./src/tutorial/dto/tutorial.dto.ts"), exports); +__exportStar(__webpack_require__(/*! ./progress.dto */ "./src/tutorial/dto/progress.dto.ts"), exports); +__exportStar(__webpack_require__(/*! ./contextual-help.dto */ "./src/tutorial/dto/contextual-help.dto.ts"), exports); +__exportStar(__webpack_require__(/*! ./analytics.dto */ "./src/tutorial/dto/analytics.dto.ts"), exports); + + +/***/ }), + +/***/ "./src/tutorial/dto/progress.dto.ts": +/*!******************************************!*\ + !*** ./src/tutorial/dto/progress.dto.ts ***! + \******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UserProgressFilterDto = exports.CompleteTutorialDto = exports.SaveCheckpointDto = exports.ResumeTutorialDto = exports.SkipStepDto = exports.SkipTutorialDto = exports.UpdateStepProgressDto = exports.StartTutorialDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const user_tutorial_progress_entity_1 = __webpack_require__(/*! ../entities/user-tutorial-progress.entity */ "./src/tutorial/entities/user-tutorial-progress.entity.ts"); +class StartTutorialDto { +} +exports.StartTutorialDto = StartTutorialDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], StartTutorialDto.prototype, "tutorialId", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], StartTutorialDto.prototype, "sessionId", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], StartTutorialDto.prototype, "resumeFromCheckpoint", void 0); +class UpdateStepProgressDto { +} +exports.UpdateStepProgressDto = UpdateStepProgressDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], UpdateStepProgressDto.prototype, "tutorialId", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], UpdateStepProgressDto.prototype, "stepId", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(['in_progress', 'completed', 'skipped', 'failed']), + __metadata("design:type", typeof (_a = typeof user_tutorial_progress_entity_1.StepProgressStatus !== "undefined" && user_tutorial_progress_entity_1.StepProgressStatus) === "function" ? _a : Object) +], UpdateStepProgressDto.prototype, "status", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], UpdateStepProgressDto.prototype, "timeSpent", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.Max)(100), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], UpdateStepProgressDto.prototype, "score", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], UpdateStepProgressDto.prototype, "hintsUsed", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Array) +], UpdateStepProgressDto.prototype, "errors", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Object) +], UpdateStepProgressDto.prototype, "interactiveResult", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Object) +], UpdateStepProgressDto.prototype, "saveState", void 0); +class SkipTutorialDto { +} +exports.SkipTutorialDto = SkipTutorialDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], SkipTutorialDto.prototype, "tutorialId", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], SkipTutorialDto.prototype, "reason", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], SkipTutorialDto.prototype, "confirmSkip", void 0); +class SkipStepDto { +} +exports.SkipStepDto = SkipStepDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], SkipStepDto.prototype, "tutorialId", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], SkipStepDto.prototype, "stepId", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], SkipStepDto.prototype, "reason", void 0); +class ResumeTutorialDto { +} +exports.ResumeTutorialDto = ResumeTutorialDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], ResumeTutorialDto.prototype, "tutorialId", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], ResumeTutorialDto.prototype, "fromStepId", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], ResumeTutorialDto.prototype, "fromCheckpoint", void 0); +class SaveCheckpointDto { +} +exports.SaveCheckpointDto = SaveCheckpointDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], SaveCheckpointDto.prototype, "tutorialId", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], SaveCheckpointDto.prototype, "stepId", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], SaveCheckpointDto.prototype, "state", void 0); +class CompleteTutorialDto { +} +exports.CompleteTutorialDto = CompleteTutorialDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], CompleteTutorialDto.prototype, "tutorialId", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.Max)(100), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], CompleteTutorialDto.prototype, "finalScore", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], CompleteTutorialDto.prototype, "feedback", void 0); +class UserProgressFilterDto { +} +exports.UserProgressFilterDto = UserProgressFilterDto; +__decorate([ + (0, class_validator_1.IsEnum)(['not_started', 'in_progress', 'completed', 'skipped', 'abandoned']), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], UserProgressFilterDto.prototype, "status", void 0); +__decorate([ + (0, class_validator_1.IsUUID)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], UserProgressFilterDto.prototype, "tutorialId", void 0); + + +/***/ }), + +/***/ "./src/tutorial/dto/tutorial.dto.ts": +/*!******************************************!*\ + !*** ./src/tutorial/dto/tutorial.dto.ts ***! + \******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ReorderStepsDto = exports.StepOrderDto = exports.UpdateTutorialStepDto = exports.CreateTutorialStepDto = exports.StepAccessibilityDto = exports.AdaptivePacingDto = exports.CompletionCriteriaDto = exports.InteractiveConfigDto = exports.StepContentDto = exports.TutorialFilterDto = exports.UpdateTutorialDto = exports.CreateTutorialDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); +const mapped_types_1 = __webpack_require__(/*! @nestjs/mapped-types */ "@nestjs/mapped-types"); +const tutorial_entity_1 = __webpack_require__(/*! ../entities/tutorial.entity */ "./src/tutorial/entities/tutorial.entity.ts"); +const tutorial_step_entity_1 = __webpack_require__(/*! ../entities/tutorial-step.entity */ "./src/tutorial/entities/tutorial-step.entity.ts"); +class CreateTutorialDto { +} +exports.CreateTutorialDto = CreateTutorialDto; +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(3), + (0, class_validator_1.MaxLength)(100), + __metadata("design:type", String) +], CreateTutorialDto.prototype, "name", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(10), + __metadata("design:type", String) +], CreateTutorialDto.prototype, "description", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(['onboarding', 'mechanic', 'advanced', 'refresher']), + __metadata("design:type", typeof (_a = typeof tutorial_entity_1.TutorialType !== "undefined" && tutorial_entity_1.TutorialType) === "function" ? _a : Object) +], CreateTutorialDto.prototype, "type", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(2), + (0, class_validator_1.MaxLength)(50), + __metadata("design:type", String) +], CreateTutorialDto.prototype, "category", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(['beginner', 'easy', 'medium', 'hard', 'expert']), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_b = typeof tutorial_entity_1.DifficultyLevel !== "undefined" && tutorial_entity_1.DifficultyLevel) === "function" ? _b : Object) +], CreateTutorialDto.prototype, "difficultyLevel", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], CreateTutorialDto.prototype, "order", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], CreateTutorialDto.prototype, "estimatedDurationMinutes", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsUUID)(4, { each: true }), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Array) +], CreateTutorialDto.prototype, "prerequisites", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Array) +], CreateTutorialDto.prototype, "targetMechanics", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], CreateTutorialDto.prototype, "isSkippable", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], CreateTutorialDto.prototype, "isActive", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_c = typeof tutorial_entity_1.TutorialMetadata !== "undefined" && tutorial_entity_1.TutorialMetadata) === "function" ? _c : Object) +], CreateTutorialDto.prototype, "metadata", void 0); +class UpdateTutorialDto extends (0, mapped_types_1.PartialType)(CreateTutorialDto) { +} +exports.UpdateTutorialDto = UpdateTutorialDto; +class TutorialFilterDto { +} +exports.TutorialFilterDto = TutorialFilterDto; +__decorate([ + (0, class_validator_1.IsEnum)(['onboarding', 'mechanic', 'advanced', 'refresher']), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_d = typeof tutorial_entity_1.TutorialType !== "undefined" && tutorial_entity_1.TutorialType) === "function" ? _d : Object) +], TutorialFilterDto.prototype, "type", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], TutorialFilterDto.prototype, "category", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(['beginner', 'easy', 'medium', 'hard', 'expert']), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_e = typeof tutorial_entity_1.DifficultyLevel !== "undefined" && tutorial_entity_1.DifficultyLevel) === "function" ? _e : Object) +], TutorialFilterDto.prototype, "difficultyLevel", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], TutorialFilterDto.prototype, "isActive", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], TutorialFilterDto.prototype, "targetMechanic", void 0); +class StepContentDto { +} +exports.StepContentDto = StepContentDto; +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(5), + __metadata("design:type", String) +], StepContentDto.prototype, "instructions", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Object) +], StepContentDto.prototype, "richContent", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Object) +], StepContentDto.prototype, "media", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_f = typeof Array !== "undefined" && Array) === "function" ? _f : Object) +], StepContentDto.prototype, "highlights", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_g = typeof Array !== "undefined" && Array) === "function" ? _g : Object) +], StepContentDto.prototype, "tooltips", void 0); +class InteractiveConfigDto { +} +exports.InteractiveConfigDto = InteractiveConfigDto; +__decorate([ + (0, class_validator_1.IsEnum)(['drag-drop', 'click-sequence', 'input', 'selection', 'puzzle-mini']), + __metadata("design:type", String) +], InteractiveConfigDto.prototype, "type", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + __metadata("design:type", typeof (_h = typeof Record !== "undefined" && Record) === "function" ? _h : Object) +], InteractiveConfigDto.prototype, "config", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], InteractiveConfigDto.prototype, "expectedOutcome", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Array) +], InteractiveConfigDto.prototype, "hints", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], InteractiveConfigDto.prototype, "maxAttempts", void 0); +class CompletionCriteriaDto { +} +exports.CompletionCriteriaDto = CompletionCriteriaDto; +__decorate([ + (0, class_validator_1.IsEnum)(['auto', 'action', 'quiz', 'time', 'manual']), + __metadata("design:type", String) +], CompletionCriteriaDto.prototype, "type", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_j = typeof Array !== "undefined" && Array) === "function" ? _j : Object) +], CompletionCriteriaDto.prototype, "conditions", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.Max)(100), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], CompletionCriteriaDto.prototype, "minimumScore", void 0); +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.IsString)({ each: true }), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Array) +], CompletionCriteriaDto.prototype, "requiredActions", void 0); +class AdaptivePacingDto { +} +exports.AdaptivePacingDto = AdaptivePacingDto; +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], AdaptivePacingDto.prototype, "minTimeOnStep", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], AdaptivePacingDto.prototype, "skipIfProficient", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.Max)(1), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], AdaptivePacingDto.prototype, "proficiencyThreshold", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.Max)(1), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], AdaptivePacingDto.prototype, "repeatIfStrugglingThreshold", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], AdaptivePacingDto.prototype, "adaptiveHints", void 0); +class StepAccessibilityDto { +} +exports.StepAccessibilityDto = StepAccessibilityDto; +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], StepAccessibilityDto.prototype, "ariaLabel", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", String) +], StepAccessibilityDto.prototype, "screenReaderText", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_k = typeof Record !== "undefined" && Record) === "function" ? _k : Object) +], StepAccessibilityDto.prototype, "keyboardShortcuts", void 0); +__decorate([ + (0, class_validator_1.IsObject)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Object) +], StepAccessibilityDto.prototype, "reducedMotionAlternative", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], StepAccessibilityDto.prototype, "highContrastSupport", void 0); +class CreateTutorialStepDto { +} +exports.CreateTutorialStepDto = CreateTutorialStepDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], CreateTutorialStepDto.prototype, "tutorialId", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + __metadata("design:type", Number) +], CreateTutorialStepDto.prototype, "order", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(3), + (0, class_validator_1.MaxLength)(100), + __metadata("design:type", String) +], CreateTutorialStepDto.prototype, "title", void 0); +__decorate([ + (0, class_validator_1.IsEnum)(['instruction', 'interactive', 'practice', 'quiz', 'demonstration', 'checkpoint']), + __metadata("design:type", typeof (_l = typeof tutorial_step_entity_1.StepType !== "undefined" && tutorial_step_entity_1.StepType) === "function" ? _l : Object) +], CreateTutorialStepDto.prototype, "type", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => StepContentDto), + __metadata("design:type", StepContentDto) +], CreateTutorialStepDto.prototype, "content", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => InteractiveConfigDto), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", InteractiveConfigDto) +], CreateTutorialStepDto.prototype, "interactive", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => CompletionCriteriaDto), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", CompletionCriteriaDto) +], CreateTutorialStepDto.prototype, "completionCriteria", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => AdaptivePacingDto), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", AdaptivePacingDto) +], CreateTutorialStepDto.prototype, "adaptivePacing", void 0); +__decorate([ + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => StepAccessibilityDto), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", StepAccessibilityDto) +], CreateTutorialStepDto.prototype, "accessibility", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], CreateTutorialStepDto.prototype, "isOptional", void 0); +__decorate([ + (0, class_validator_1.IsBoolean)(), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Boolean) +], CreateTutorialStepDto.prototype, "isActive", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(0), + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Number) +], CreateTutorialStepDto.prototype, "timeLimit", void 0); +class UpdateTutorialStepDto extends (0, mapped_types_1.PartialType)((0, mapped_types_1.OmitType)(CreateTutorialStepDto, ['tutorialId'])) { +} +exports.UpdateTutorialStepDto = UpdateTutorialStepDto; +class StepOrderDto { +} +exports.StepOrderDto = StepOrderDto; +__decorate([ + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], StepOrderDto.prototype, "id", void 0); +__decorate([ + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(1), + __metadata("design:type", Number) +], StepOrderDto.prototype, "order", void 0); +class ReorderStepsDto { +} +exports.ReorderStepsDto = ReorderStepsDto; +__decorate([ + (0, class_validator_1.IsArray)(), + (0, class_validator_1.ValidateNested)({ each: true }), + (0, class_transformer_1.Type)(() => StepOrderDto), + __metadata("design:type", Array) +], ReorderStepsDto.prototype, "orders", void 0); + + +/***/ }), + +/***/ "./src/tutorial/entities/contextual-help-interaction.entity.ts": +/*!*********************************************************************!*\ + !*** ./src/tutorial/entities/contextual-help-interaction.entity.ts ***! + \*********************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ContextualHelpInteraction = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const contextual_help_entity_1 = __webpack_require__(/*! ./contextual-help.entity */ "./src/tutorial/entities/contextual-help.entity.ts"); +let ContextualHelpInteraction = class ContextualHelpInteraction { +}; +exports.ContextualHelpInteraction = ContextualHelpInteraction; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], ContextualHelpInteraction.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], ContextualHelpInteraction.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], ContextualHelpInteraction.prototype, "helpId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + __metadata("design:type", String) +], ContextualHelpInteraction.prototype, "triggerContext", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20 }), + __metadata("design:type", String) +], ContextualHelpInteraction.prototype, "action", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', nullable: true }), + __metadata("design:type", Number) +], ContextualHelpInteraction.prototype, "viewDuration", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50, nullable: true }), + __metadata("design:type", String) +], ContextualHelpInteraction.prototype, "actionTaken", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', nullable: true }), + __metadata("design:type", Object) +], ContextualHelpInteraction.prototype, "context", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ type: 'timestamptz' }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], ContextualHelpInteraction.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => contextual_help_entity_1.ContextualHelp, (help) => help.interactions, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'helpId' }), + __metadata("design:type", typeof (_b = typeof contextual_help_entity_1.ContextualHelp !== "undefined" && contextual_help_entity_1.ContextualHelp) === "function" ? _b : Object) +], ContextualHelpInteraction.prototype, "help", void 0); +exports.ContextualHelpInteraction = ContextualHelpInteraction = __decorate([ + (0, typeorm_1.Entity)('contextual_help_interactions'), + (0, typeorm_1.Index)(['userId', 'helpId']), + (0, typeorm_1.Index)(['userId', 'triggerContext']), + (0, typeorm_1.Index)(['helpId', 'action']) +], ContextualHelpInteraction); + + +/***/ }), + +/***/ "./src/tutorial/entities/contextual-help.entity.ts": +/*!*********************************************************!*\ + !*** ./src/tutorial/entities/contextual-help.entity.ts ***! + \*********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ContextualHelp = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const contextual_help_interaction_entity_1 = __webpack_require__(/*! ./contextual-help-interaction.entity */ "./src/tutorial/entities/contextual-help-interaction.entity.ts"); +let ContextualHelp = class ContextualHelp { +}; +exports.ContextualHelp = ContextualHelp; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], ContextualHelp.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100 }), + __metadata("design:type", String) +], ContextualHelp.prototype, "name", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], ContextualHelp.prototype, "triggerContext", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50, nullable: true }), + __metadata("design:type", String) +], ContextualHelp.prototype, "targetFeature", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50, nullable: true }), + __metadata("design:type", String) +], ContextualHelp.prototype, "targetPuzzleType", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], ContextualHelp.prototype, "priority", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb' }), + __metadata("design:type", Object) +], ContextualHelp.prototype, "content", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], ContextualHelp.prototype, "triggerConditions", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], ContextualHelp.prototype, "displayRules", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", Boolean) +], ContextualHelp.prototype, "isActive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], ContextualHelp.prototype, "localization", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], ContextualHelp.prototype, "analytics", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ type: 'timestamptz' }), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], ContextualHelp.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)({ type: 'timestamptz' }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], ContextualHelp.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => contextual_help_interaction_entity_1.ContextualHelpInteraction, (interaction) => interaction.help), + __metadata("design:type", Array) +], ContextualHelp.prototype, "interactions", void 0); +exports.ContextualHelp = ContextualHelp = __decorate([ + (0, typeorm_1.Entity)('contextual_help'), + (0, typeorm_1.Index)(['triggerContext', 'isActive']), + (0, typeorm_1.Index)(['targetFeature']), + (0, typeorm_1.Index)(['targetPuzzleType']) +], ContextualHelp); + + +/***/ }), + +/***/ "./src/tutorial/entities/index.ts": +/*!****************************************!*\ + !*** ./src/tutorial/entities/index.ts ***! + \****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__webpack_require__(/*! ./tutorial.entity */ "./src/tutorial/entities/tutorial.entity.ts"), exports); +__exportStar(__webpack_require__(/*! ./tutorial-step.entity */ "./src/tutorial/entities/tutorial-step.entity.ts"), exports); +__exportStar(__webpack_require__(/*! ./user-tutorial-progress.entity */ "./src/tutorial/entities/user-tutorial-progress.entity.ts"), exports); +__exportStar(__webpack_require__(/*! ./contextual-help.entity */ "./src/tutorial/entities/contextual-help.entity.ts"), exports); +__exportStar(__webpack_require__(/*! ./contextual-help-interaction.entity */ "./src/tutorial/entities/contextual-help-interaction.entity.ts"), exports); +__exportStar(__webpack_require__(/*! ./tutorial-analytics-event.entity */ "./src/tutorial/entities/tutorial-analytics-event.entity.ts"), exports); + + +/***/ }), + +/***/ "./src/tutorial/entities/tutorial-analytics-event.entity.ts": +/*!******************************************************************!*\ + !*** ./src/tutorial/entities/tutorial-analytics-event.entity.ts ***! + \******************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TutorialAnalyticsEvent = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +let TutorialAnalyticsEvent = class TutorialAnalyticsEvent { +}; +exports.TutorialAnalyticsEvent = TutorialAnalyticsEvent; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], TutorialAnalyticsEvent.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TutorialAnalyticsEvent.prototype, "eventType", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TutorialAnalyticsEvent.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TutorialAnalyticsEvent.prototype, "tutorialId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TutorialAnalyticsEvent.prototype, "stepId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + __metadata("design:type", String) +], TutorialAnalyticsEvent.prototype, "sessionId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb' }), + __metadata("design:type", Object) +], TutorialAnalyticsEvent.prototype, "payload", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ type: 'timestamptz' }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], TutorialAnalyticsEvent.prototype, "createdAt", void 0); +exports.TutorialAnalyticsEvent = TutorialAnalyticsEvent = __decorate([ + (0, typeorm_1.Entity)('tutorial_analytics_events'), + (0, typeorm_1.Index)(['eventType', 'createdAt']), + (0, typeorm_1.Index)(['userId', 'tutorialId']), + (0, typeorm_1.Index)(['tutorialId', 'stepId']), + (0, typeorm_1.Index)(['sessionId']) +], TutorialAnalyticsEvent); + + +/***/ }), + +/***/ "./src/tutorial/entities/tutorial-step.entity.ts": +/*!*******************************************************!*\ + !*** ./src/tutorial/entities/tutorial-step.entity.ts ***! + \*******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TutorialStep = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const tutorial_entity_1 = __webpack_require__(/*! ./tutorial.entity */ "./src/tutorial/entities/tutorial.entity.ts"); +let TutorialStep = class TutorialStep { +}; +exports.TutorialStep = TutorialStep; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], TutorialStep.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], TutorialStep.prototype, "tutorialId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], TutorialStep.prototype, "order", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100 }), + __metadata("design:type", String) +], TutorialStep.prototype, "title", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20 }), + __metadata("design:type", String) +], TutorialStep.prototype, "type", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: true }), + __metadata("design:type", Boolean) +], TutorialStep.prototype, "isActive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], TutorialStep.prototype, "isOptional", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', nullable: true }), + __metadata("design:type", Number) +], TutorialStep.prototype, "timeLimit", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb' }), + __metadata("design:type", Object) +], TutorialStep.prototype, "content", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', nullable: true }), + __metadata("design:type", Object) +], TutorialStep.prototype, "interactive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TutorialStep.prototype, "completionCriteria", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TutorialStep.prototype, "adaptivePacing", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TutorialStep.prototype, "localization", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TutorialStep.prototype, "accessibility", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], TutorialStep.prototype, "analytics", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ type: 'timestamptz' }), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], TutorialStep.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)({ type: 'timestamptz' }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], TutorialStep.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => tutorial_entity_1.Tutorial, (tutorial) => tutorial.steps, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'tutorialId' }), + __metadata("design:type", typeof (_c = typeof tutorial_entity_1.Tutorial !== "undefined" && tutorial_entity_1.Tutorial) === "function" ? _c : Object) +], TutorialStep.prototype, "tutorial", void 0); +exports.TutorialStep = TutorialStep = __decorate([ + (0, typeorm_1.Entity)('tutorial_steps'), + (0, typeorm_1.Index)(['tutorialId', 'order']), + (0, typeorm_1.Index)(['type', 'isActive']) +], TutorialStep); + + +/***/ }), + +/***/ "./src/tutorial/entities/tutorial.entity.ts": +/*!**************************************************!*\ + !*** ./src/tutorial/entities/tutorial.entity.ts ***! + \**************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Tutorial = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const tutorial_step_entity_1 = __webpack_require__(/*! ./tutorial-step.entity */ "./src/tutorial/entities/tutorial-step.entity.ts"); +const user_tutorial_progress_entity_1 = __webpack_require__(/*! ./user-tutorial-progress.entity */ "./src/tutorial/entities/user-tutorial-progress.entity.ts"); +let Tutorial = class Tutorial { +}; +exports.Tutorial = Tutorial; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], Tutorial.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100 }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Tutorial.prototype, "name", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'text' }), + __metadata("design:type", String) +], Tutorial.prototype, "description", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'onboarding' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Tutorial.prototype, "type", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Tutorial.prototype, "category", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'easy' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], Tutorial.prototype, "difficultyLevel", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], Tutorial.prototype, "order", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], Tutorial.prototype, "estimatedDurationMinutes", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'simple-array', default: '' }), + __metadata("design:type", Array) +], Tutorial.prototype, "prerequisites", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'simple-array', default: '' }), + __metadata("design:type", Array) +], Tutorial.prototype, "targetMechanics", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", Boolean) +], Tutorial.prototype, "isActive", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], Tutorial.prototype, "isSkippable", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Tutorial.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], Tutorial.prototype, "analytics", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ type: 'timestamptz' }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], Tutorial.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)({ type: 'timestamptz' }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], Tutorial.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.DeleteDateColumn)({ type: 'timestamptz' }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], Tutorial.prototype, "deletedAt", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => tutorial_step_entity_1.TutorialStep, (step) => step.tutorial), + __metadata("design:type", Array) +], Tutorial.prototype, "steps", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => user_tutorial_progress_entity_1.UserTutorialProgress, (progress) => progress.tutorial), + __metadata("design:type", Array) +], Tutorial.prototype, "userProgress", void 0); +exports.Tutorial = Tutorial = __decorate([ + (0, typeorm_1.Entity)('tutorials'), + (0, typeorm_1.Index)(['type', 'isActive']), + (0, typeorm_1.Index)(['difficultyLevel', 'order']), + (0, typeorm_1.Index)(['category']) +], Tutorial); + + +/***/ }), + +/***/ "./src/tutorial/entities/user-tutorial-progress.entity.ts": +/*!****************************************************************!*\ + !*** ./src/tutorial/entities/user-tutorial-progress.entity.ts ***! + \****************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UserTutorialProgress = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const tutorial_entity_1 = __webpack_require__(/*! ./tutorial.entity */ "./src/tutorial/entities/tutorial.entity.ts"); +let UserTutorialProgress = class UserTutorialProgress { +}; +exports.UserTutorialProgress = UserTutorialProgress; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], UserTutorialProgress.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], UserTutorialProgress.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], UserTutorialProgress.prototype, "tutorialId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'not_started' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], UserTutorialProgress.prototype, "status", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserTutorialProgress.prototype, "currentStepOrder", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), + __metadata("design:type", String) +], UserTutorialProgress.prototype, "currentStepId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserTutorialProgress.prototype, "completedSteps", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserTutorialProgress.prototype, "totalSteps", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), + __metadata("design:type", Number) +], UserTutorialProgress.prototype, "progressPercentage", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserTutorialProgress.prototype, "totalTimeSpent", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, nullable: true }), + __metadata("design:type", Number) +], UserTutorialProgress.prototype, "overallScore", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamptz', nullable: true }), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], UserTutorialProgress.prototype, "startedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamptz', nullable: true }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], UserTutorialProgress.prototype, "completedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamptz', nullable: true }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], UserTutorialProgress.prototype, "lastActivityAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: [] }), + __metadata("design:type", Array) +], UserTutorialProgress.prototype, "stepProgress", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: { learningSpeed: 'normal', proficiencyLevel: 0 } }), + __metadata("design:type", Object) +], UserTutorialProgress.prototype, "adaptiveState", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], UserTutorialProgress.prototype, "sessionData", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], UserTutorialProgress.prototype, "analytics", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)({ type: 'timestamptz' }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], UserTutorialProgress.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)({ type: 'timestamptz' }), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], UserTutorialProgress.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => tutorial_entity_1.Tutorial, (tutorial) => tutorial.userProgress, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'tutorialId' }), + __metadata("design:type", typeof (_f = typeof tutorial_entity_1.Tutorial !== "undefined" && tutorial_entity_1.Tutorial) === "function" ? _f : Object) +], UserTutorialProgress.prototype, "tutorial", void 0); +exports.UserTutorialProgress = UserTutorialProgress = __decorate([ + (0, typeorm_1.Entity)('user_tutorial_progress'), + (0, typeorm_1.Index)(['userId', 'tutorialId'], { unique: true }), + (0, typeorm_1.Index)(['userId', 'status']), + (0, typeorm_1.Index)(['tutorialId', 'status']) +], UserTutorialProgress); + + +/***/ }), + +/***/ "./src/tutorial/services/contextual-help.service.ts": +/*!**********************************************************!*\ + !*** ./src/tutorial/services/contextual-help.service.ts ***! + \**********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var ContextualHelpService_1; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ContextualHelpService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const contextual_help_entity_1 = __webpack_require__(/*! ../entities/contextual-help.entity */ "./src/tutorial/entities/contextual-help.entity.ts"); +const contextual_help_interaction_entity_1 = __webpack_require__(/*! ../entities/contextual-help-interaction.entity */ "./src/tutorial/entities/contextual-help-interaction.entity.ts"); +let ContextualHelpService = ContextualHelpService_1 = class ContextualHelpService { + constructor(helpRepo, interactionRepo) { + this.helpRepo = helpRepo; + this.interactionRepo = interactionRepo; + this.logger = new common_1.Logger(ContextualHelpService_1.name); + } + async create(dto) { + const help = this.helpRepo.create({ + ...dto, + triggerConditions: dto.triggerConditions || {}, + displayRules: dto.displayRules || {}, + localization: {}, + analytics: {}, + }); + const saved = await this.helpRepo.save(help); + this.logger.log(`Created contextual help: ${saved.id} - ${saved.name}`); + return saved; + } + async findById(id) { + const help = await this.helpRepo.findOne({ where: { id } }); + if (!help) { + throw new common_1.NotFoundException(`Contextual help not found: ${id}`); + } + return help; + } + async findAll(filters) { + const query = this.helpRepo.createQueryBuilder('help'); + if (filters?.triggerContext) { + query.andWhere('help.triggerContext = :triggerContext', { + triggerContext: filters.triggerContext, + }); + } + if (filters?.targetFeature) { + query.andWhere('help.targetFeature = :targetFeature', { + targetFeature: filters.targetFeature, + }); + } + if (filters?.targetPuzzleType) { + query.andWhere('help.targetPuzzleType = :targetPuzzleType', { + targetPuzzleType: filters.targetPuzzleType, + }); + } + if (filters?.isActive !== undefined) { + query.andWhere('help.isActive = :isActive', { isActive: filters.isActive }); + } + query.orderBy('help.priority', 'DESC'); + return query.getMany(); + } + async update(id, dto) { + const help = await this.findById(id); + Object.assign(help, dto); + const updated = await this.helpRepo.save(help); + this.logger.log(`Updated contextual help: ${id}`); + return updated; + } + async delete(id) { + const help = await this.findById(id); + await this.helpRepo.remove(help); + this.logger.log(`Deleted contextual help: ${id}`); + } + async triggerHelp(userId, dto) { + const applicable = await this.getApplicableHelp(userId, dto); + if (applicable.length === 0) { + return null; + } + for (const help of applicable) { + if (await this.shouldShowHelp(userId, help.id)) { + await this.recordInteraction(userId, { + helpId: help.id, + action: 'shown', + context: { + puzzleId: dto.puzzleId, + }, + }); + await this.updateHelpAnalytics(help.id, 'shown'); + return help; + } + } + return null; + } + async getApplicableHelp(userId, dto) { + const query = this.helpRepo + .createQueryBuilder('help') + .where('help.isActive = true') + .andWhere('help.triggerContext = :context', { context: dto.context }); + if (dto.feature) { + query.andWhere('(help.targetFeature IS NULL OR help.targetFeature = :feature)', { + feature: dto.feature, + }); + } + if (dto.puzzleType) { + query.andWhere('(help.targetPuzzleType IS NULL OR help.targetPuzzleType = :puzzleType)', { + puzzleType: dto.puzzleType, + }); + } + const candidates = await query.orderBy('help.priority', 'DESC').getMany(); + const filtered = candidates.filter((help) => this.checkTriggerConditions(help, dto)); + return filtered; + } + async shouldShowHelp(userId, helpId) { + const help = await this.findById(helpId); + const rules = help.displayRules; + if (rules.showOnce) { + const shown = await this.interactionRepo.findOne({ + where: { userId, helpId, action: 'shown' }, + }); + if (shown) + return false; + } + if (rules.maxShowCount) { + const showCount = await this.getShowCount(userId, helpId); + if (showCount >= rules.maxShowCount) + return false; + } + if (rules.cooldownSeconds) { + const lastShown = await this.getLastShownTime(userId, helpId); + if (lastShown) { + const cooldownEnd = new Date(lastShown.getTime() + rules.cooldownSeconds * 1000); + if (new Date() < cooldownEnd) + return false; + } + } + return true; + } + checkTriggerConditions(help, dto) { + const conditions = help.triggerConditions; + if (conditions.minAttempts !== undefined && dto.attempts !== undefined) { + if (dto.attempts < conditions.minAttempts) + return false; + } + if (conditions.maxAttempts !== undefined && dto.attempts !== undefined) { + if (dto.attempts > conditions.maxAttempts) + return false; + } + if (conditions.timeThreshold !== undefined && dto.timeSpent !== undefined) { + if (dto.timeSpent < conditions.timeThreshold) + return false; + } + if (conditions.userLevel && dto.userLevel !== undefined) { + if (conditions.userLevel.min !== undefined && dto.userLevel < conditions.userLevel.min) { + return false; + } + if (conditions.userLevel.max !== undefined && dto.userLevel > conditions.userLevel.max) { + return false; + } + } + if (conditions.errorPatterns && dto.recentErrors) { + const hasMatchingError = conditions.errorPatterns.some((pattern) => dto.recentErrors.some((error) => error.includes(pattern))); + if (!hasMatchingError) + return false; + } + return true; + } + async recordInteraction(userId, dto) { + const help = await this.findById(dto.helpId); + const interaction = this.interactionRepo.create({ + userId, + helpId: dto.helpId, + triggerContext: help.triggerContext, + action: dto.action, + viewDuration: dto.viewDuration, + actionTaken: dto.actionTaken, + context: dto.context, + }); + await this.interactionRepo.save(interaction); + await this.updateHelpAnalytics(dto.helpId, dto.action); + } + async getUserHelpHistory(userId, helpId) { + const where = { userId }; + if (helpId) { + where.helpId = helpId; + } + return this.interactionRepo.find({ + where, + order: { createdAt: 'DESC' }, + take: 50, + }); + } + async getShowCount(userId, helpId) { + return this.interactionRepo.count({ + where: { userId, helpId, action: 'shown' }, + }); + } + async getLastShownTime(userId, helpId) { + const interaction = await this.interactionRepo.findOne({ + where: { userId, helpId, action: 'shown' }, + order: { createdAt: 'DESC' }, + }); + return interaction?.createdAt || null; + } + async getHelpForPuzzleStart(userId, puzzleType) { + return this.triggerHelp(userId, { + context: 'puzzle_start', + puzzleType, + }); + } + async getHelpForRepeatedFailure(userId, puzzleId, attempts) { + return this.triggerHelp(userId, { + context: 'repeated_failure', + puzzleId, + attempts, + }); + } + async getHelpForFeature(userId, feature) { + return this.triggerHelp(userId, { + context: 'feature_discovery', + feature, + }); + } + async updateHelpAnalytics(helpId, action) { + const help = await this.findById(helpId); + const analytics = help.analytics || {}; + if (action === 'shown') { + analytics.totalShown = (analytics.totalShown || 0) + 1; + } + if (action === 'dismissed') { + const totalShown = analytics.totalShown || 1; + const dismissed = await this.interactionRepo.count({ + where: { helpId, action: 'dismissed' }, + }); + analytics.dismissRate = dismissed / totalShown; + } + if (action === 'clicked' || action === 'completed') { + const totalShown = analytics.totalShown || 1; + const actioned = await this.interactionRepo.count({ + where: { helpId, action: 'clicked' }, + }); + analytics.actionTakenRate = actioned / totalShown; + } + await this.helpRepo.update(helpId, { analytics }); + } +}; +exports.ContextualHelpService = ContextualHelpService; +exports.ContextualHelpService = ContextualHelpService = ContextualHelpService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(contextual_help_entity_1.ContextualHelp)), + __param(1, (0, typeorm_1.InjectRepository)(contextual_help_interaction_entity_1.ContextualHelpInteraction)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object]) +], ContextualHelpService); + + +/***/ }), + +/***/ "./src/tutorial/services/index.ts": +/*!****************************************!*\ + !*** ./src/tutorial/services/index.ts ***! + \****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__webpack_require__(/*! ./tutorial.service */ "./src/tutorial/services/tutorial.service.ts"), exports); +__exportStar(__webpack_require__(/*! ./tutorial-progress.service */ "./src/tutorial/services/tutorial-progress.service.ts"), exports); +__exportStar(__webpack_require__(/*! ./contextual-help.service */ "./src/tutorial/services/contextual-help.service.ts"), exports); +__exportStar(__webpack_require__(/*! ./tutorial-analytics.service */ "./src/tutorial/services/tutorial-analytics.service.ts"), exports); +__exportStar(__webpack_require__(/*! ./localization.service */ "./src/tutorial/services/localization.service.ts"), exports); + + +/***/ }), + +/***/ "./src/tutorial/services/localization.service.ts": +/*!*******************************************************!*\ + !*** ./src/tutorial/services/localization.service.ts ***! + \*******************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var LocalizationService_1; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.LocalizationService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +let LocalizationService = LocalizationService_1 = class LocalizationService { + constructor() { + this.logger = new common_1.Logger(LocalizationService_1.name); + this.translations = new Map(); + this.supportedLocales = ['en', 'es', 'fr', 'de', 'ja', 'zh', 'ko', 'pt', 'ru', 'ar']; + this.defaultLocale = 'en'; + this.translations.set('en', new Map()); + } + async getTranslation(key, locale, params) { + const localeTranslations = this.translations.get(locale); + let translation = localeTranslations?.get(key); + if (!translation && locale !== this.defaultLocale) { + const defaultTranslations = this.translations.get(this.defaultLocale); + translation = defaultTranslations?.get(key); + } + if (!translation) { + this.logger.warn(`Missing translation for key: ${key} in locale: ${locale}`); + return key; + } + if (params) { + Object.entries(params).forEach(([param, value]) => { + translation = translation.replace(new RegExp(`{{${param}}}`, 'g'), String(value)); + }); + } + return translation; + } + async setTranslation(key, locale, value) { + if (!this.translations.has(locale)) { + this.translations.set(locale, new Map()); + } + this.translations.get(locale).set(key, value); + } + async getTranslationsForLocale(locale) { + const localeTranslations = this.translations.get(locale); + if (!localeTranslations) { + return {}; + } + return Object.fromEntries(localeTranslations); + } + async importTranslations(locale, translations) { + if (!this.translations.has(locale)) { + this.translations.set(locale, new Map()); + } + const localeMap = this.translations.get(locale); + Object.entries(translations).forEach(([key, value]) => { + localeMap.set(key, value); + }); + this.logger.log(`Imported ${Object.keys(translations).length} translations for locale: ${locale}`); + } + async exportTranslations(locale) { + return this.getTranslationsForLocale(locale); + } + async getSupportedLocales() { + return this.supportedLocales; + } + async addLocale(locale) { + if (!this.supportedLocales.includes(locale)) { + this.supportedLocales.push(locale); + this.translations.set(locale, new Map()); + this.logger.log(`Added new locale: ${locale}`); + } + } + async setDefaultLocale(locale) { + if (!this.supportedLocales.includes(locale)) { + throw new Error(`Locale ${locale} is not supported`); + } + this.defaultLocale = locale; + } + async detectUserLocale(userId) { + return this.defaultLocale; + } + async localizeTutorial(tutorial, locale) { + const nameKey = `tutorial.${tutorial.id}.name`; + const descriptionKey = `tutorial.${tutorial.id}.description`; + const localizedName = await this.getTranslation(nameKey, locale); + const localizedDescription = await this.getTranslation(descriptionKey, locale); + return { + ...tutorial, + name: localizedName !== nameKey ? localizedName : tutorial.name, + description: localizedDescription !== descriptionKey ? localizedDescription : tutorial.description, + locale, + }; + } + async localizeStep(step, locale) { + const titleKey = step.localization?.titleKey || `tutorial.step.${step.id}.title`; + const instructionsKey = step.localization?.instructionsKey || `tutorial.step.${step.id}.instructions`; + const localizedTitle = await this.getTranslation(titleKey, locale); + const localizedInstructions = await this.getTranslation(instructionsKey, locale); + const localizedContent = { ...step.content }; + localizedContent.instructions = + localizedInstructions !== instructionsKey ? localizedInstructions : step.content.instructions; + if (step.localization?.contentKeys) { + for (const [field, key] of Object.entries(step.localization.contentKeys)) { + const localizedValue = await this.getTranslation(key, locale); + if (localizedValue !== key) { + localizedContent[field] = localizedValue; + } + } + } + return { + ...step, + title: localizedTitle !== titleKey ? localizedTitle : step.title, + content: localizedContent, + locale, + }; + } + async localizeHelp(help, locale) { + const titleKey = help.localization?.titleKey || `contextual_help.${help.id}.title`; + const bodyKey = help.localization?.bodyKey || `contextual_help.${help.id}.body`; + const localizedTitle = await this.getTranslation(titleKey, locale); + const localizedBody = await this.getTranslation(bodyKey, locale); + const localizedContent = { + ...help.content, + title: localizedTitle !== titleKey ? localizedTitle : help.content.title, + body: localizedBody !== bodyKey ? localizedBody : help.content.body, + }; + if (help.content.actions && help.localization?.actionsKeys) { + localizedContent.actions = await Promise.all(help.content.actions.map(async (action, index) => { + const labelKey = help.localization?.actionsKeys?.[`action_${index}_label`]; + if (labelKey) { + const localizedLabel = await this.getTranslation(labelKey, locale); + return { + ...action, + label: localizedLabel !== labelKey ? localizedLabel : action.label, + }; + } + return action; + })); + } + return { + ...help, + content: localizedContent, + locale, + }; + } + async getMissingTranslations(locale) { + const defaultKeys = Array.from(this.translations.get(this.defaultLocale)?.keys() || []); + const localeKeys = Array.from(this.translations.get(locale)?.keys() || []); + const localeKeySet = new Set(localeKeys); + return defaultKeys.filter((key) => !localeKeySet.has(key)); + } + async validateTranslations(locale) { + const missingKeys = await this.getMissingTranslations(locale); + const totalKeys = this.translations.get(this.defaultLocale)?.size || 0; + return { + locale, + totalKeys, + missingKeys, + isComplete: missingKeys.length === 0, + }; + } + generateTutorialKeys(tutorialId) { + return [ + `tutorial.${tutorialId}.name`, + `tutorial.${tutorialId}.description`, + ]; + } + generateStepKeys(stepId) { + return [ + `tutorial.step.${stepId}.title`, + `tutorial.step.${stepId}.instructions`, + ]; + } + generateHelpKeys(helpId) { + return [ + `contextual_help.${helpId}.title`, + `contextual_help.${helpId}.body`, + ]; + } +}; +exports.LocalizationService = LocalizationService; +exports.LocalizationService = LocalizationService = LocalizationService_1 = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", []) +], LocalizationService); + + +/***/ }), + +/***/ "./src/tutorial/services/tutorial-analytics.service.ts": +/*!*************************************************************!*\ + !*** ./src/tutorial/services/tutorial-analytics.service.ts ***! + \*************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var TutorialAnalyticsService_1; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TutorialAnalyticsService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const tutorial_entity_1 = __webpack_require__(/*! ../entities/tutorial.entity */ "./src/tutorial/entities/tutorial.entity.ts"); +const tutorial_step_entity_1 = __webpack_require__(/*! ../entities/tutorial-step.entity */ "./src/tutorial/entities/tutorial-step.entity.ts"); +const user_tutorial_progress_entity_1 = __webpack_require__(/*! ../entities/user-tutorial-progress.entity */ "./src/tutorial/entities/user-tutorial-progress.entity.ts"); +const tutorial_analytics_event_entity_1 = __webpack_require__(/*! ../entities/tutorial-analytics-event.entity */ "./src/tutorial/entities/tutorial-analytics-event.entity.ts"); +let TutorialAnalyticsService = TutorialAnalyticsService_1 = class TutorialAnalyticsService { + constructor(eventRepo, progressRepo, tutorialRepo, stepRepo) { + this.eventRepo = eventRepo; + this.progressRepo = progressRepo; + this.tutorialRepo = tutorialRepo; + this.stepRepo = stepRepo; + this.logger = new common_1.Logger(TutorialAnalyticsService_1.name); + } + async trackEvent(event) { + const analyticsEvent = this.eventRepo.create({ + eventType: event.eventType, + userId: event.userId, + tutorialId: event.tutorialId, + stepId: event.stepId, + sessionId: event.sessionId, + payload: event.payload, + }); + await this.eventRepo.save(analyticsEvent); + } + async getTutorialCompletionRate(tutorialId, dateRange) { + const whereClause = { tutorialId }; + if (dateRange?.startDate) { + whereClause.createdAt = (0, typeorm_2.MoreThanOrEqual)(dateRange.startDate); + } + const total = await this.progressRepo.count({ where: whereClause }); + const completed = await this.progressRepo.count({ + where: { ...whereClause, status: 'completed' }, + }); + return total > 0 ? (completed / total) * 100 : 0; + } + async getStepCompletionRates(tutorialId) { + const steps = await this.stepRepo.find({ + where: { tutorialId, isActive: true }, + order: { order: 'ASC' }, + }); + const progress = await this.progressRepo.find({ + where: { tutorialId }, + }); + return steps.map((step) => { + const stepProgressData = progress.flatMap((p) => p.stepProgress.filter((sp) => sp.stepId === step.id)); + const completed = stepProgressData.filter((sp) => sp.status === 'completed').length; + const total = stepProgressData.length || 1; + const skipped = stepProgressData.filter((sp) => sp.status === 'skipped').length; + const attempts = stepProgressData.map((sp) => sp.attempts); + const times = stepProgressData.map((sp) => sp.timeSpent); + const hints = stepProgressData.map((sp) => sp.hintsUsed); + const errors = {}; + stepProgressData.forEach((sp) => { + (sp.errors || []).forEach((error) => { + errors[error] = (errors[error] || 0) + 1; + }); + }); + return { + stepId: step.id, + stepTitle: step.title, + completionRate: (completed / total) * 100, + averageAttempts: attempts.length > 0 ? attempts.reduce((a, b) => a + b, 0) / attempts.length : 0, + averageTimeSpent: times.length > 0 ? times.reduce((a, b) => a + b, 0) / times.length : 0, + hintUsageRate: hints.length > 0 ? hints.filter((h) => h > 0).length / hints.length : 0, + commonErrors: Object.entries(errors) + .map(([error, count]) => ({ error, count })) + .sort((a, b) => b.count - a.count) + .slice(0, 5), + skipRate: (skipped / total) * 100, + }; + }); + } + async getOverallCompletionRate(dateRange) { + const whereClause = {}; + if (dateRange?.startDate && dateRange?.endDate) { + whereClause.createdAt = (0, typeorm_2.Between)(dateRange.startDate, dateRange.endDate); + } + const total = await this.progressRepo.count({ where: whereClause }); + const completed = await this.progressRepo.count({ + where: { ...whereClause, status: 'completed' }, + }); + return total > 0 ? (completed / total) * 100 : 0; + } + async getDropOffAnalysis(tutorialId) { + const tutorial = await this.tutorialRepo.findOne({ where: { id: tutorialId } }); + const steps = await this.stepRepo.find({ + where: { tutorialId, isActive: true }, + order: { order: 'ASC' }, + }); + const progress = await this.progressRepo.find({ + where: { tutorialId }, + }); + const totalStarted = progress.length; + const dropOffPoints = steps.map((step) => { + const usersReached = progress.filter((p) => p.stepProgress.some((sp) => sp.stepId === step.id)).length; + const usersCompleted = progress.filter((p) => p.stepProgress.some((sp) => sp.stepId === step.id && sp.status === 'completed')).length; + const usersDropped = usersReached - usersCompleted; + const timesBeforeDrop = progress + .filter((p) => p.status !== 'completed' && + p.stepProgress.some((sp) => sp.stepId === step.id && sp.status !== 'completed')) + .map((p) => p.stepProgress.find((sp) => sp.stepId === step.id)?.timeSpent || 0); + return { + stepId: step.id, + stepTitle: step.title, + stepOrder: step.order, + usersReached, + usersDropped, + dropOffRate: usersReached > 0 ? (usersDropped / usersReached) * 100 : 0, + averageTimeBeforeDropOff: timesBeforeDrop.length > 0 + ? timesBeforeDrop.reduce((a, b) => a + b, 0) / timesBeforeDrop.length + : 0, + }; + }); + const totalCompleted = progress.filter((p) => p.status === 'completed').length; + const overallDropOffRate = totalStarted > 0 ? ((totalStarted - totalCompleted) / totalStarted) * 100 : 0; + return { + tutorialId, + tutorialName: tutorial?.name || '', + totalStarted, + dropOffPoints, + overallDropOffRate, + }; + } + async getCommonDropOffPoints() { + const tutorials = await this.tutorialRepo.find({ where: { isActive: true } }); + const allDropOffs = []; + for (const tutorial of tutorials) { + const analysis = await this.getDropOffAnalysis(tutorial.id); + analysis.dropOffPoints.forEach((point) => { + if (point.dropOffRate > 20) { + allDropOffs.push({ + stepId: point.stepId, + tutorialId: tutorial.id, + dropOffRate: point.dropOffRate, + }); + } + }); + } + return allDropOffs.sort((a, b) => b.dropOffRate - a.dropOffRate).slice(0, 10); + } + async getTutorialEffectivenessReport(tutorialId, filters) { + const tutorial = await this.tutorialRepo.findOne({ where: { id: tutorialId } }); + if (!tutorial) { + throw new Error(`Tutorial not found: ${tutorialId}`); + } + const whereClause = { tutorialId }; + if (filters?.startDate && filters?.endDate) { + whereClause.createdAt = (0, typeorm_2.Between)(filters.startDate, filters.endDate); + } + const progress = await this.progressRepo.find({ where: whereClause }); + const completed = progress.filter((p) => p.status === 'completed'); + const scores = completed.filter((p) => p.overallScore).map((p) => Number(p.overallScore)); + const times = completed.filter((p) => p.totalTimeSpent > 0).map((p) => p.totalTimeSpent); + const metrics = { + completionRate: progress.length > 0 ? (completed.length / progress.length) * 100 : 0, + averageScore: scores.length > 0 ? scores.reduce((a, b) => a + b, 0) / scores.length : 0, + averageCompletionTime: times.length > 0 ? times.reduce((a, b) => a + b, 0) / times.length : 0, + totalUsers: progress.length, + activeUsers: progress.filter((p) => p.lastActivityAt && new Date().getTime() - p.lastActivityAt.getTime() < 7 * 24 * 60 * 60 * 1000).length, + }; + const report = { + tutorialId, + tutorialName: tutorial.name, + period: { + startDate: filters?.startDate || new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), + endDate: filters?.endDate || new Date(), + }, + metrics, + trends: [], + }; + if (filters?.includeStepBreakdown) { + report.stepBreakdown = await this.getStepCompletionRates(tutorialId); + } + if (filters?.includeDropOffAnalysis) { + report.dropOffAnalysis = await this.getDropOffAnalysis(tutorialId); + } + return report; + } + async getUserLearningProfile(userId) { + const progress = await this.progressRepo.find({ + where: { userId }, + relations: ['tutorial'], + }); + const completed = progress.filter((p) => p.status === 'completed'); + const speeds = progress.map((p) => p.adaptiveState.learningSpeed); + const speedCounts = { slow: 0, normal: 0, fast: 0 }; + speeds.forEach((s) => (speedCounts[s] = (speedCounts[s] || 0) + 1)); + const averageSpeed = Object.entries(speedCounts).sort((a, b) => b[1] - a[1])[0]?.[0]; + const strongAreas = new Set(); + const improvementAreas = new Set(); + progress.forEach((p) => { + (p.adaptiveState.strongAreas || []).forEach((area) => strongAreas.add(area)); + (p.adaptiveState.strugglingAreas || []).forEach((area) => improvementAreas.add(area)); + }); + const totalTimeSpent = progress.reduce((sum, p) => sum + p.totalTimeSpent, 0); + return { + userId, + totalTutorialsStarted: progress.length, + totalTutorialsCompleted: completed.length, + overallCompletionRate: progress.length > 0 ? (completed.length / progress.length) * 100 : 0, + averageLearningSpeed: averageSpeed || 'normal', + strongAreas: Array.from(strongAreas), + improvementAreas: Array.from(improvementAreas), + preferredContentTypes: [], + totalTimeSpent, + recentActivity: progress + .sort((a, b) => (b.lastActivityAt?.getTime() || 0) - (a.lastActivityAt?.getTime() || 0)) + .slice(0, 5) + .map((p) => ({ + tutorialId: p.tutorialId, + tutorialName: p.tutorial?.name || '', + status: p.status, + lastActivityAt: p.lastActivityAt || p.updatedAt, + })), + }; + } + async generateDashboardReport(dateRange) { + const startDate = dateRange?.startDate || new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); + const endDate = dateRange?.endDate || new Date(); + const tutorials = await this.tutorialRepo.find({ where: { isActive: true } }); + const progress = await this.progressRepo.find({ + where: { createdAt: (0, typeorm_2.Between)(startDate, endDate) }, + relations: ['tutorial'], + }); + const completed = progress.filter((p) => p.status === 'completed'); + const today = new Date(); + today.setHours(0, 0, 0, 0); + const activeToday = progress.filter((p) => p.lastActivityAt && p.lastActivityAt >= today).length; + const tutorialStats = await Promise.all(tutorials.slice(0, 10).map(async (t) => { + const rate = await this.getTutorialCompletionRate(t.id, dateRange); + const completions = progress.filter((p) => p.tutorialId === t.id && p.status === 'completed').length; + return { + tutorialId: t.id, + tutorialName: t.name, + completionRate: rate, + totalCompletions: completions, + }; + })); + const needsAttention = tutorialStats + .filter((t) => t.completionRate < 50 && t.totalCompletions > 0) + .map((t) => ({ + tutorialId: t.tutorialId, + tutorialName: t.tutorialName, + issue: 'Low completion rate', + metric: t.completionRate, + })); + return { + period: { startDate, endDate }, + overview: { + totalTutorials: tutorials.length, + activeTutorials: tutorials.filter((t) => t.isActive).length, + totalUsersOnboarded: completed.length, + averageCompletionRate: await this.getOverallCompletionRate(dateRange), + activeUsersToday: activeToday, + }, + topTutorials: tutorialStats.sort((a, b) => b.completionRate - a.completionRate).slice(0, 5), + needsAttention, + recentCompletions: completed + .sort((a, b) => (b.completedAt?.getTime() || 0) - (a.completedAt?.getTime() || 0)) + .slice(0, 10) + .map((p) => ({ + userId: p.userId, + tutorialId: p.tutorialId, + tutorialName: p.tutorial?.name || '', + completedAt: p.completedAt || p.updatedAt, + score: Number(p.overallScore) || 0, + })), + trends: [], + }; + } + async getActiveUsers() { + const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000); + return this.progressRepo.count({ + where: { + status: 'in_progress', + lastActivityAt: (0, typeorm_2.MoreThanOrEqual)(oneHourAgo), + }, + }); + } + async getCurrentCompletions(interval) { + const since = interval === 'hour' + ? new Date(Date.now() - 60 * 60 * 1000) + : new Date(Date.now() - 24 * 60 * 60 * 1000); + return this.progressRepo.count({ + where: { + status: 'completed', + completedAt: (0, typeorm_2.MoreThanOrEqual)(since), + }, + }); + } +}; +exports.TutorialAnalyticsService = TutorialAnalyticsService; +exports.TutorialAnalyticsService = TutorialAnalyticsService = TutorialAnalyticsService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(tutorial_analytics_event_entity_1.TutorialAnalyticsEvent)), + __param(1, (0, typeorm_1.InjectRepository)(user_tutorial_progress_entity_1.UserTutorialProgress)), + __param(2, (0, typeorm_1.InjectRepository)(tutorial_entity_1.Tutorial)), + __param(3, (0, typeorm_1.InjectRepository)(tutorial_step_entity_1.TutorialStep)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object]) +], TutorialAnalyticsService); + + +/***/ }), + +/***/ "./src/tutorial/services/tutorial-progress.service.ts": +/*!************************************************************!*\ + !*** ./src/tutorial/services/tutorial-progress.service.ts ***! + \************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var TutorialProgressService_1; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TutorialProgressService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const tutorial_step_entity_1 = __webpack_require__(/*! ../entities/tutorial-step.entity */ "./src/tutorial/entities/tutorial-step.entity.ts"); +const user_tutorial_progress_entity_1 = __webpack_require__(/*! ../entities/user-tutorial-progress.entity */ "./src/tutorial/entities/user-tutorial-progress.entity.ts"); +const tutorial_service_1 = __webpack_require__(/*! ./tutorial.service */ "./src/tutorial/services/tutorial.service.ts"); +const tutorial_analytics_service_1 = __webpack_require__(/*! ./tutorial-analytics.service */ "./src/tutorial/services/tutorial-analytics.service.ts"); +let TutorialProgressService = TutorialProgressService_1 = class TutorialProgressService { + constructor(progressRepo, stepRepo, tutorialService, analyticsService) { + this.progressRepo = progressRepo; + this.stepRepo = stepRepo; + this.tutorialService = tutorialService; + this.analyticsService = analyticsService; + this.logger = new common_1.Logger(TutorialProgressService_1.name); + } + async startTutorial(userId, dto) { + const tutorial = await this.tutorialService.findById(dto.tutorialId); + const { valid, missing } = await this.tutorialService.validatePrerequisites(userId, dto.tutorialId); + if (!valid) { + throw new common_1.ForbiddenException(`Prerequisites not met. Missing tutorials: ${missing.join(', ')}`); + } + let progress = await this.progressRepo.findOne({ + where: { userId, tutorialId: dto.tutorialId }, + }); + if (progress) { + if (progress.status === 'completed') { + progress.status = 'in_progress'; + progress.currentStepOrder = 0; + progress.currentStepId = undefined; + progress.completedSteps = 0; + progress.progressPercentage = 0; + progress.totalTimeSpent = 0; + progress.stepProgress = []; + progress.startedAt = new Date(); + progress.completedAt = undefined; + } + else if (dto.resumeFromCheckpoint && progress.sessionData?.checkpoints?.length) { + progress.lastActivityAt = new Date(); + return this.progressRepo.save(progress); + } + } + else { + const steps = await this.tutorialService.getStepsByTutorial(dto.tutorialId); + progress = this.progressRepo.create({ + userId, + tutorialId: dto.tutorialId, + status: 'in_progress', + currentStepOrder: 0, + totalSteps: steps.length, + completedSteps: 0, + progressPercentage: 0, + totalTimeSpent: 0, + stepProgress: [], + adaptiveState: { learningSpeed: 'normal', proficiencyLevel: 0 }, + sessionData: { lastSessionId: dto.sessionId }, + startedAt: new Date(), + lastActivityAt: new Date(), + }); + } + const saved = await this.progressRepo.save(progress); + await this.analyticsService.trackEvent({ + eventType: 'tutorial_started', + userId, + tutorialId: dto.tutorialId, + payload: { sessionId: dto.sessionId }, + }); + this.logger.log(`User ${userId} started tutorial: ${dto.tutorialId}`); + return saved; + } + async updateStepProgress(userId, dto) { + const progress = await this.getOrCreateProgress(userId, dto.tutorialId); + const step = await this.tutorialService.getStepById(dto.stepId); + let stepProgress = progress.stepProgress.find((sp) => sp.stepId === dto.stepId); + if (!stepProgress) { + stepProgress = { + stepId: dto.stepId, + stepOrder: step.order, + status: 'pending', + attempts: 0, + timeSpent: 0, + hintsUsed: 0, + }; + progress.stepProgress.push(stepProgress); + } + stepProgress.status = dto.status; + stepProgress.attempts += 1; + stepProgress.timeSpent += dto.timeSpent || 0; + stepProgress.score = dto.score; + stepProgress.hintsUsed += dto.hintsUsed || 0; + if (dto.errors) { + stepProgress.errors = [...(stepProgress.errors || []), ...dto.errors]; + } + if (dto.status === 'completed') { + stepProgress.completedAt = new Date(); + progress.completedSteps = progress.stepProgress.filter((sp) => sp.status === 'completed').length; + await this.analyticsService.trackEvent({ + eventType: 'step_completed', + userId, + tutorialId: dto.tutorialId, + stepId: dto.stepId, + payload: { + timeSpent: dto.timeSpent, + score: dto.score, + attempts: stepProgress.attempts, + hintsUsed: stepProgress.hintsUsed, + }, + }); + } + const nextStep = await this.getNextStep(userId, dto.tutorialId); + if (nextStep) { + progress.currentStepId = nextStep.id; + progress.currentStepOrder = nextStep.order; + } + progress.progressPercentage = + progress.totalSteps > 0 + ? Math.round((progress.completedSteps / progress.totalSteps) * 100) + : 0; + progress.totalTimeSpent += dto.timeSpent || 0; + progress.lastActivityAt = new Date(); + if (dto.saveState) { + await this.saveCheckpoint(userId, { + tutorialId: dto.tutorialId, + stepId: dto.stepId, + state: dto.saveState, + }); + } + await this.adjustAdaptivePacing(progress, stepProgress); + const saved = await this.progressRepo.save(progress); + if (progress.completedSteps >= progress.totalSteps) { + await this.completeTutorial(userId, dto.tutorialId); + } + return saved; + } + async completeTutorial(userId, tutorialId) { + const progress = await this.getUserProgress(userId, tutorialId); + progress.status = 'completed'; + progress.completedAt = new Date(); + progress.progressPercentage = 100; + const scores = progress.stepProgress + .filter((sp) => sp.score !== undefined) + .map((sp) => sp.score); + if (scores.length > 0) { + progress.overallScore = scores.reduce((a, b) => a + b, 0) / scores.length; + } + const saved = await this.progressRepo.save(progress); + await this.analyticsService.trackEvent({ + eventType: 'tutorial_completed', + userId, + tutorialId, + payload: { + completionSummary: { + totalTime: progress.totalTimeSpent, + totalSteps: progress.totalSteps, + completedSteps: progress.completedSteps, + overallScore: progress.overallScore || 0, + }, + }, + }); + await this.tutorialService.updateTutorialAnalytics(tutorialId); + this.logger.log(`User ${userId} completed tutorial: ${tutorialId}`); + return saved; + } + async getUserProgress(userId, tutorialId) { + const progress = await this.progressRepo.findOne({ + where: { userId, tutorialId }, + relations: ['tutorial'], + }); + if (!progress) { + throw new common_1.NotFoundException(`Progress not found for user ${userId} on tutorial ${tutorialId}`); + } + return progress; + } + async getAllUserProgress(userId) { + return this.progressRepo.find({ + where: { userId }, + relations: ['tutorial'], + order: { lastActivityAt: 'DESC' }, + }); + } + async skipTutorial(userId, dto) { + const tutorial = await this.tutorialService.findById(dto.tutorialId); + if (!tutorial.isSkippable && !dto.confirmSkip) { + throw new common_1.BadRequestException('This tutorial is not skippable. Set confirmSkip to true to force skip.'); + } + let progress = await this.progressRepo.findOne({ + where: { userId, tutorialId: dto.tutorialId }, + }); + if (!progress) { + const steps = await this.tutorialService.getStepsByTutorial(dto.tutorialId); + progress = this.progressRepo.create({ + userId, + tutorialId: dto.tutorialId, + totalSteps: steps.length, + adaptiveState: { learningSpeed: 'normal', proficiencyLevel: 0 }, + sessionData: {}, + }); + } + progress.status = 'skipped'; + progress.lastActivityAt = new Date(); + const saved = await this.progressRepo.save(progress); + await this.analyticsService.trackEvent({ + eventType: 'tutorial_skipped', + userId, + tutorialId: dto.tutorialId, + payload: { skipReason: dto.reason }, + }); + this.logger.log(`User ${userId} skipped tutorial: ${dto.tutorialId}`); + return saved; + } + async skipStep(userId, dto) { + const progress = await this.getUserProgress(userId, dto.tutorialId); + const step = await this.tutorialService.getStepById(dto.stepId); + if (!step.isOptional) { + throw new common_1.BadRequestException('This step is not optional and cannot be skipped.'); + } + let stepProgress = progress.stepProgress.find((sp) => sp.stepId === dto.stepId); + if (!stepProgress) { + stepProgress = { + stepId: dto.stepId, + stepOrder: step.order, + status: 'skipped', + attempts: 0, + timeSpent: 0, + hintsUsed: 0, + }; + progress.stepProgress.push(stepProgress); + } + else { + stepProgress.status = 'skipped'; + } + progress.lastActivityAt = new Date(); + const nextStep = await this.getNextStep(userId, dto.tutorialId); + if (nextStep) { + progress.currentStepId = nextStep.id; + progress.currentStepOrder = nextStep.order; + } + return this.progressRepo.save(progress); + } + async resumeTutorial(userId, dto) { + const progress = await this.getUserProgress(userId, dto.tutorialId); + if (progress.status === 'completed') { + throw new common_1.BadRequestException('Tutorial already completed. Start again to restart.'); + } + progress.status = 'in_progress'; + progress.lastActivityAt = new Date(); + let nextStep = null; + let checkpoint = undefined; + if (dto.fromStepId) { + nextStep = await this.tutorialService.getStepById(dto.fromStepId); + progress.currentStepId = dto.fromStepId; + progress.currentStepOrder = nextStep.order; + } + else if (dto.fromCheckpoint && progress.sessionData?.checkpoints?.length) { + const latestCheckpoint = progress.sessionData.checkpoints[progress.sessionData.checkpoints.length - 1]; + nextStep = await this.tutorialService.getStepById(latestCheckpoint.stepId); + checkpoint = latestCheckpoint.state; + progress.currentStepId = latestCheckpoint.stepId; + } + else { + nextStep = await this.getNextStep(userId, dto.tutorialId); + } + await this.progressRepo.save(progress); + return { progress, nextStep, checkpoint }; + } + async saveCheckpoint(userId, dto) { + const progress = await this.getUserProgress(userId, dto.tutorialId); + const checkpoints = progress.sessionData?.checkpoints || []; + checkpoints.push({ + stepId: dto.stepId, + state: dto.state, + savedAt: new Date(), + }); + if (checkpoints.length > 5) { + checkpoints.shift(); + } + progress.sessionData = { + ...progress.sessionData, + checkpoints, + }; + await this.progressRepo.save(progress); + await this.analyticsService.trackEvent({ + eventType: 'checkpoint_saved', + userId, + tutorialId: dto.tutorialId, + stepId: dto.stepId, + payload: {}, + }); + } + async getNextStep(userId, tutorialId) { + const progress = await this.progressRepo.findOne({ + where: { userId, tutorialId }, + }); + const completedStepIds = new Set(progress?.stepProgress + .filter((sp) => sp.status === 'completed' || sp.status === 'skipped') + .map((sp) => sp.stepId) || []); + const steps = await this.tutorialService.getStepsByTutorial(tutorialId); + const nextStep = steps.find((step) => step.isActive && !completedStepIds.has(step.id)); + if (!nextStep) + return null; + if (progress && await this.shouldSkipStep(progress, nextStep)) { + await this.updateStepProgress(userId, { + tutorialId, + stepId: nextStep.id, + status: 'skipped', + }); + return this.getNextStep(userId, tutorialId); + } + return nextStep; + } + async getAdaptiveState(userId, tutorialId) { + const progress = await this.getUserProgress(userId, tutorialId); + return progress.adaptiveState; + } + async shouldSkipStep(progress, step) { + if (!step.adaptivePacing?.skipIfProficient) + return false; + const threshold = step.adaptivePacing.proficiencyThreshold || 0.8; + return progress.adaptiveState.proficiencyLevel >= threshold; + } + async adjustAdaptivePacing(progress, stepProgress) { + const state = progress.adaptiveState; + const avgStepTime = progress.totalTimeSpent / (progress.completedSteps || 1); + if (stepProgress.timeSpent < avgStepTime * 0.5) { + state.learningSpeed = 'fast'; + } + else if (stepProgress.timeSpent > avgStepTime * 1.5) { + state.learningSpeed = 'slow'; + } + else { + state.learningSpeed = 'normal'; + } + if (stepProgress.score !== undefined) { + const performanceScore = (stepProgress.score / 100) * (1 / stepProgress.attempts); + state.proficiencyLevel = (state.proficiencyLevel + performanceScore) / 2; + } + if (stepProgress.errors && stepProgress.errors.length > 2) { + state.strugglingAreas = state.strugglingAreas || []; + state.strugglingAreas.push(stepProgress.stepId); + } + if (stepProgress.score && stepProgress.score >= 90 && stepProgress.attempts === 1) { + state.strongAreas = state.strongAreas || []; + state.strongAreas.push(stepProgress.stepId); + } + progress.adaptiveState = state; + } + async getOrCreateProgress(userId, tutorialId) { + let progress = await this.progressRepo.findOne({ + where: { userId, tutorialId }, + }); + if (!progress) { + const steps = await this.tutorialService.getStepsByTutorial(tutorialId); + progress = this.progressRepo.create({ + userId, + tutorialId, + status: 'in_progress', + totalSteps: steps.length, + completedSteps: 0, + progressPercentage: 0, + totalTimeSpent: 0, + stepProgress: [], + adaptiveState: { learningSpeed: 'normal', proficiencyLevel: 0 }, + sessionData: {}, + startedAt: new Date(), + lastActivityAt: new Date(), + }); + progress = await this.progressRepo.save(progress); + } + return progress; + } + async getCompletedTutorials(userId) { + const progress = await this.progressRepo.find({ + where: { userId, status: 'completed' }, + select: ['tutorialId'], + }); + return progress.map((p) => p.tutorialId); + } +}; +exports.TutorialProgressService = TutorialProgressService; +exports.TutorialProgressService = TutorialProgressService = TutorialProgressService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(user_tutorial_progress_entity_1.UserTutorialProgress)), + __param(1, (0, typeorm_1.InjectRepository)(tutorial_step_entity_1.TutorialStep)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof tutorial_service_1.TutorialService !== "undefined" && tutorial_service_1.TutorialService) === "function" ? _c : Object, typeof (_d = typeof tutorial_analytics_service_1.TutorialAnalyticsService !== "undefined" && tutorial_analytics_service_1.TutorialAnalyticsService) === "function" ? _d : Object]) +], TutorialProgressService); + + +/***/ }), + +/***/ "./src/tutorial/services/tutorial.service.ts": +/*!***************************************************!*\ + !*** ./src/tutorial/services/tutorial.service.ts ***! + \***************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var TutorialService_1; +var _a, _b, _c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TutorialService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const typeorm_2 = __webpack_require__(/*! typeorm */ "typeorm"); +const tutorial_entity_1 = __webpack_require__(/*! ../entities/tutorial.entity */ "./src/tutorial/entities/tutorial.entity.ts"); +const tutorial_step_entity_1 = __webpack_require__(/*! ../entities/tutorial-step.entity */ "./src/tutorial/entities/tutorial-step.entity.ts"); +const user_tutorial_progress_entity_1 = __webpack_require__(/*! ../entities/user-tutorial-progress.entity */ "./src/tutorial/entities/user-tutorial-progress.entity.ts"); +let TutorialService = TutorialService_1 = class TutorialService { + constructor(tutorialRepo, stepRepo, progressRepo) { + this.tutorialRepo = tutorialRepo; + this.stepRepo = stepRepo; + this.progressRepo = progressRepo; + this.logger = new common_1.Logger(TutorialService_1.name); + } + async create(dto) { + const tutorial = this.tutorialRepo.create({ + ...dto, + prerequisites: dto.prerequisites || [], + targetMechanics: dto.targetMechanics || [], + metadata: dto.metadata || {}, + analytics: {}, + }); + const saved = await this.tutorialRepo.save(tutorial); + this.logger.log(`Created tutorial: ${saved.id} - ${saved.name}`); + return saved; + } + async findById(id) { + const tutorial = await this.tutorialRepo.findOne({ + where: { id }, + relations: ['steps'], + }); + if (!tutorial) { + throw new common_1.NotFoundException(`Tutorial not found: ${id}`); + } + return tutorial; + } + async findAll(filters) { + const query = this.tutorialRepo.createQueryBuilder('tutorial'); + if (filters?.type) { + query.andWhere('tutorial.type = :type', { type: filters.type }); + } + if (filters?.category) { + query.andWhere('tutorial.category = :category', { category: filters.category }); + } + if (filters?.difficultyLevel) { + query.andWhere('tutorial.difficultyLevel = :difficultyLevel', { + difficultyLevel: filters.difficultyLevel, + }); + } + if (filters?.isActive !== undefined) { + query.andWhere('tutorial.isActive = :isActive', { isActive: filters.isActive }); + } + if (filters?.targetMechanic) { + query.andWhere(':mechanic = ANY(tutorial.targetMechanics)', { + mechanic: filters.targetMechanic, + }); + } + query.orderBy('tutorial.order', 'ASC'); + return query.getMany(); + } + async update(id, dto) { + const tutorial = await this.findById(id); + Object.assign(tutorial, dto); + const updated = await this.tutorialRepo.save(tutorial); + this.logger.log(`Updated tutorial: ${id}`); + return updated; + } + async delete(id) { + const tutorial = await this.findById(id); + await this.tutorialRepo.softRemove(tutorial); + this.logger.log(`Soft deleted tutorial: ${id}`); + } + async getOnboardingCurriculum() { + return this.tutorialRepo.find({ + where: { type: 'onboarding', isActive: true }, + relations: ['steps'], + order: { order: 'ASC' }, + }); + } + async getTutorialsByMechanic(mechanic) { + return this.tutorialRepo + .createQueryBuilder('tutorial') + .where('tutorial.isActive = true') + .andWhere(':mechanic = ANY(tutorial.targetMechanics)', { mechanic }) + .orderBy('tutorial.difficultyLevel', 'ASC') + .addOrderBy('tutorial.order', 'ASC') + .getMany(); + } + async getRecommendedTutorials(userId) { + const userProgress = await this.progressRepo.find({ + where: { userId, status: 'completed' }, + select: ['tutorialId'], + }); + const completedIds = userProgress.map((p) => p.tutorialId); + const inProgress = await this.progressRepo.find({ + where: { userId, status: 'in_progress' }, + relations: ['tutorial'], + }); + const query = this.tutorialRepo + .createQueryBuilder('tutorial') + .where('tutorial.isActive = true'); + if (completedIds.length > 0) { + query.andWhere('tutorial.id NOT IN (:...completedIds)', { completedIds }); + } + const available = await query.orderBy('tutorial.order', 'ASC').getMany(); + const recommended = available.filter((t) => { + if (!t.prerequisites || t.prerequisites.length === 0) + return true; + return t.prerequisites.every((prereq) => completedIds.includes(prereq)); + }); + const inProgressTutorials = inProgress.map((p) => p.tutorial).filter(Boolean); + const notStarted = recommended.filter((t) => !inProgressTutorials.some((ip) => ip?.id === t.id)); + return [...inProgressTutorials, ...notStarted].slice(0, 10); + } + async validatePrerequisites(userId, tutorialId) { + const tutorial = await this.findById(tutorialId); + if (!tutorial.prerequisites || tutorial.prerequisites.length === 0) { + return { valid: true, missing: [] }; + } + const completedProgress = await this.progressRepo.find({ + where: { + userId, + tutorialId: (0, typeorm_2.In)(tutorial.prerequisites), + status: 'completed', + }, + }); + const completedIds = new Set(completedProgress.map((p) => p.tutorialId)); + const missing = tutorial.prerequisites.filter((prereq) => !completedIds.has(prereq)); + return { + valid: missing.length === 0, + missing, + }; + } + async createStep(dto) { + await this.findById(dto.tutorialId); + const step = this.stepRepo.create({ + ...dto, + completionCriteria: dto.completionCriteria || { type: 'auto' }, + adaptivePacing: dto.adaptivePacing || {}, + accessibility: dto.accessibility || {}, + analytics: {}, + localization: {}, + }); + const saved = await this.stepRepo.save(step); + this.logger.log(`Created step: ${saved.id} for tutorial: ${dto.tutorialId}`); + return saved; + } + async getStepsByTutorial(tutorialId) { + return this.stepRepo.find({ + where: { tutorialId, isActive: true }, + order: { order: 'ASC' }, + }); + } + async getStepById(stepId) { + const step = await this.stepRepo.findOne({ where: { id: stepId } }); + if (!step) { + throw new common_1.NotFoundException(`Step not found: ${stepId}`); + } + return step; + } + async updateStep(stepId, dto) { + const step = await this.getStepById(stepId); + Object.assign(step, dto); + const updated = await this.stepRepo.save(step); + this.logger.log(`Updated step: ${stepId}`); + return updated; + } + async deleteStep(stepId) { + const step = await this.getStepById(stepId); + await this.stepRepo.remove(step); + this.logger.log(`Deleted step: ${stepId}`); + } + async reorderSteps(tutorialId, orders) { + await this.findById(tutorialId); + const updates = orders.map((order) => this.stepRepo.update(order.id, { order: order.order })); + await Promise.all(updates); + this.logger.log(`Reordered ${orders.length} steps for tutorial: ${tutorialId}`); + } + async updateTutorialAnalytics(tutorialId) { + const progress = await this.progressRepo.find({ + where: { tutorialId }, + }); + const totalStarted = progress.length; + const completed = progress.filter((p) => p.status === 'completed'); + const totalCompleted = completed.length; + const completionTimes = completed + .filter((p) => p.totalTimeSpent > 0) + .map((p) => p.totalTimeSpent); + const averageCompletionTime = completionTimes.length > 0 + ? completionTimes.reduce((a, b) => a + b, 0) / completionTimes.length + : 0; + const dropOffRate = totalStarted > 0 ? (totalStarted - totalCompleted) / totalStarted : 0; + await this.tutorialRepo.update(tutorialId, { + analytics: { + totalStarted, + totalCompleted, + averageCompletionTime, + dropOffRate, + lastCalculatedAt: new Date(), + }, + }); + } +}; +exports.TutorialService = TutorialService; +exports.TutorialService = TutorialService = TutorialService_1 = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, typeorm_1.InjectRepository)(tutorial_entity_1.Tutorial)), + __param(1, (0, typeorm_1.InjectRepository)(tutorial_step_entity_1.TutorialStep)), + __param(2, (0, typeorm_1.InjectRepository)(user_tutorial_progress_entity_1.UserTutorialProgress)), + __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object]) +], TutorialService); + + +/***/ }), + +/***/ "./src/tutorial/tutorial.module.ts": +/*!*****************************************!*\ + !*** ./src/tutorial/tutorial.module.ts ***! + \*****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TutorialModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const typeorm_1 = __webpack_require__(/*! @nestjs/typeorm */ "@nestjs/typeorm"); +const entities_1 = __webpack_require__(/*! ./entities */ "./src/tutorial/entities/index.ts"); +const services_1 = __webpack_require__(/*! ./services */ "./src/tutorial/services/index.ts"); +const controllers_1 = __webpack_require__(/*! ./controllers */ "./src/tutorial/controllers/index.ts"); +const users_module_1 = __webpack_require__(/*! ../users/users.module */ "./src/users/users.module.ts"); +const notifications_module_1 = __webpack_require__(/*! ../notifications/notifications.module */ "./src/notifications/notifications.module.ts"); +let TutorialModule = class TutorialModule { +}; +exports.TutorialModule = TutorialModule; +exports.TutorialModule = TutorialModule = __decorate([ + (0, common_1.Module)({ + imports: [ + typeorm_1.TypeOrmModule.forFeature([ + entities_1.Tutorial, + entities_1.TutorialStep, + entities_1.UserTutorialProgress, + entities_1.ContextualHelp, + entities_1.ContextualHelpInteraction, + entities_1.TutorialAnalyticsEvent, + ]), + (0, common_1.forwardRef)(() => users_module_1.UsersModule), + (0, common_1.forwardRef)(() => notifications_module_1.NotificationsModule), + ], + controllers: [ + controllers_1.TutorialController, + controllers_1.TutorialProgressController, + controllers_1.ContextualHelpController, + controllers_1.TutorialAnalyticsController, + ], + providers: [ + services_1.TutorialService, + services_1.TutorialProgressService, + services_1.ContextualHelpService, + services_1.TutorialAnalyticsService, + services_1.LocalizationService, + ], + exports: [ + services_1.TutorialService, + services_1.TutorialProgressService, + services_1.ContextualHelpService, + services_1.TutorialAnalyticsService, + services_1.LocalizationService, + ], + }) +], TutorialModule); + + +/***/ }), + +/***/ "./src/user-progress/entities/user-collection-progress.entity.ts": +/*!***********************************************************************!*\ + !*** ./src/user-progress/entities/user-collection-progress.entity.ts ***! + \***********************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UserCollectionProgress = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +const collection_entity_1 = __webpack_require__(/*! ../../puzzles/entities/collection.entity */ "./src/puzzles/entities/collection.entity.ts"); +const puzzle_entity_1 = __webpack_require__(/*! ../../puzzles/entities/puzzle.entity */ "./src/puzzles/entities/puzzle.entity.ts"); +let UserCollectionProgress = class UserCollectionProgress { +}; +exports.UserCollectionProgress = UserCollectionProgress; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], UserCollectionProgress.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => user_entity_1.User, (user) => user.collectionProgress), + (0, typeorm_1.JoinColumn)({ name: 'userId' }), + __metadata("design:type", typeof (_a = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _a : Object) +], UserCollectionProgress.prototype, "user", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + __metadata("design:type", String) +], UserCollectionProgress.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => collection_entity_1.Collection, (collection) => collection.userProgress), + (0, typeorm_1.JoinColumn)({ name: 'collectionId' }), + __metadata("design:type", typeof (_b = typeof collection_entity_1.Collection !== "undefined" && collection_entity_1.Collection) === "function" ? _b : Object) +], UserCollectionProgress.prototype, "collection", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + __metadata("design:type", String) +], UserCollectionProgress.prototype, "collectionId", void 0); +__decorate([ + (0, typeorm_1.ManyToMany)(() => puzzle_entity_1.Puzzle), + (0, typeorm_1.JoinTable)({ name: 'user_collection_progress_completed_puzzles' }), + __metadata("design:type", Array) +], UserCollectionProgress.prototype, "completedPuzzles", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserCollectionProgress.prototype, "percentageComplete", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'boolean', default: false }), + __metadata("design:type", Boolean) +], UserCollectionProgress.prototype, "isCompleted", void 0); +exports.UserCollectionProgress = UserCollectionProgress = __decorate([ + (0, typeorm_1.Entity)('user_collection_progress') +], UserCollectionProgress); + + +/***/ }), + +/***/ "./src/users/dto/create-user.dto.ts": +/*!******************************************!*\ + !*** ./src/users/dto/create-user.dto.ts ***! + \******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreateUserDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class CreateUserDto { +} +exports.CreateUserDto = CreateUserDto; +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(3), + __metadata("design:type", String) +], CreateUserDto.prototype, "username", void 0); +__decorate([ + (0, class_validator_1.IsEmail)(), + __metadata("design:type", String) +], CreateUserDto.prototype, "email", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(6), + __metadata("design:type", String) +], CreateUserDto.prototype, "password", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], CreateUserDto.prototype, "firstName", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], CreateUserDto.prototype, "lastName", void 0); + + +/***/ }), + +/***/ "./src/users/dto/update-user.dto.ts": +/*!******************************************!*\ + !*** ./src/users/dto/update-user.dto.ts ***! + \******************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UpdateUserDto = void 0; +const mapped_types_1 = __webpack_require__(/*! @nestjs/mapped-types */ "@nestjs/mapped-types"); +const create_user_dto_1 = __webpack_require__(/*! ./create-user.dto */ "./src/users/dto/create-user.dto.ts"); +class UpdateUserDto extends (0, mapped_types_1.PartialType)(create_user_dto_1.CreateUserDto) { +} +exports.UpdateUserDto = UpdateUserDto; + + +/***/ }), + +/***/ "./src/users/entities/user-puzzle-completion.entity.ts": +/*!*************************************************************!*\ + !*** ./src/users/entities/user-puzzle-completion.entity.ts ***! + \*************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UserPuzzleCompletion = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +const puzzle_entity_1 = __webpack_require__(/*! ../../puzzles/entities/puzzle.entity */ "./src/puzzles/entities/puzzle.entity.ts"); +let UserPuzzleCompletion = class UserPuzzleCompletion { +}; +exports.UserPuzzleCompletion = UserPuzzleCompletion; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], UserPuzzleCompletion.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => user_entity_1.User, (user) => user.puzzleCompletions, { onDelete: 'CASCADE' }), + __metadata("design:type", typeof (_a = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _a : Object) +], UserPuzzleCompletion.prototype, "user", void 0); +__decorate([ + (0, typeorm_1.ManyToOne)(() => puzzle_entity_1.Puzzle, (puzzle) => puzzle.completions, { onDelete: 'CASCADE' }), + __metadata("design:type", typeof (_b = typeof puzzle_entity_1.Puzzle !== "undefined" && puzzle_entity_1.Puzzle) === "function" ? _b : Object) +], UserPuzzleCompletion.prototype, "puzzle", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone' }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], UserPuzzleCompletion.prototype, "completedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ nullable: true }), + __metadata("design:type", Number) +], UserPuzzleCompletion.prototype, "comboMultiplier", void 0); +exports.UserPuzzleCompletion = UserPuzzleCompletion = __decorate([ + (0, typeorm_1.Entity)('user_puzzle_completions') +], UserPuzzleCompletion); + + +/***/ }), + +/***/ "./src/users/entities/user-stats.entity.ts": +/*!*************************************************!*\ + !*** ./src/users/entities/user-stats.entity.ts ***! + \*************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d, _e, _f; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UserStats = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ../../users/entities/user.entity */ "./src/users/entities/user.entity.ts"); +let UserStats = class UserStats { +}; +exports.UserStats = UserStats; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], UserStats.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'uuid' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], UserStats.prototype, "userId", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], UserStats.prototype, "totalPuzzlesAttempted", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], UserStats.prototype, "totalPuzzlesCompleted", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserStats.prototype, "totalPuzzlesFailed", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserStats.prototype, "totalScore", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserStats.prototype, "totalTimeSpent", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserStats.prototype, "totalHintsUsed", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserStats.prototype, "currentStreak", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], UserStats.prototype, "longestStreak", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], UserStats.prototype, "overallAccuracy", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'decimal', precision: 10, scale: 2, default: 0 }), + __metadata("design:type", Number) +], UserStats.prototype, "averageCompletionTime", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserStats.prototype, "totalAchievements", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], UserStats.prototype, "totalGameSessions", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], UserStats.prototype, "difficultyStats", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", typeof (_a = typeof Record !== "undefined" && Record) === "function" ? _a : Object) +], UserStats.prototype, "categoryStats", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], UserStats.prototype, "timeStats", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], UserStats.prototype, "trends", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], UserStats.prototype, "milestones", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], UserStats.prototype, "rankings", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], UserStats.prototype, "lastActivityAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], UserStats.prototype, "lastCalculatedAt", void 0); +__decorate([ + (0, typeorm_1.CreateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], UserStats.prototype, "createdAt", void 0); +__decorate([ + (0, typeorm_1.UpdateDateColumn)(), + (0, typeorm_1.Index)(), + __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) +], UserStats.prototype, "updatedAt", void 0); +__decorate([ + (0, typeorm_1.OneToOne)(() => user_entity_1.User, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)({ name: 'userId' }), + __metadata("design:type", typeof (_f = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _f : Object) +], UserStats.prototype, "user", void 0); +exports.UserStats = UserStats = __decorate([ + (0, typeorm_1.Entity)('user_stats'), + (0, typeorm_1.Index)(['userId'], { unique: true }) +], UserStats); + + +/***/ }), + +/***/ "./src/users/entities/user-streak.entity.ts": +/*!**************************************************!*\ + !*** ./src/users/entities/user-streak.entity.ts ***! + \**************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UserStreak = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_entity_1 = __webpack_require__(/*! ./user.entity */ "./src/users/entities/user.entity.ts"); +let UserStreak = class UserStreak { +}; +exports.UserStreak = UserStreak; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], UserStreak.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.OneToOne)(() => user_entity_1.User, (user) => user.streak, { onDelete: 'CASCADE' }), + (0, typeorm_1.JoinColumn)(), + __metadata("design:type", typeof (_a = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _a : Object) +], UserStreak.prototype, "user", void 0); +__decorate([ + (0, typeorm_1.Column)({ default: 0 }), + __metadata("design:type", Number) +], UserStreak.prototype, "currentStreak", void 0); +__decorate([ + (0, typeorm_1.Column)({ nullable: true }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], UserStreak.prototype, "lastPuzzleCompletedAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ nullable: true }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], UserStreak.prototype, "streakStartDate", void 0); +__decorate([ + (0, typeorm_1.Column)({ nullable: true }), + __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) +], UserStreak.prototype, "streakRecoveryGracePeriodEnd", void 0); +exports.UserStreak = UserStreak = __decorate([ + (0, typeorm_1.Entity)('user_streaks') +], UserStreak); + + +/***/ }), + +/***/ "./src/users/entities/user.entity.ts": +/*!*******************************************!*\ + !*** ./src/users/entities/user.entity.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.User = void 0; +const typeorm_1 = __webpack_require__(/*! typeorm */ "typeorm"); +const user_achievement_entity_1 = __webpack_require__(/*! ../../achievements/entities/user-achievement.entity */ "./src/achievements/entities/user-achievement.entity.ts"); +const game_session_entity_1 = __webpack_require__(/*! ../../game-engine/entities/game-session.entity */ "./src/game-engine/entities/game-session.entity.ts"); +const user_streak_entity_1 = __webpack_require__(/*! ./user-streak.entity */ "./src/users/entities/user-streak.entity.ts"); +const user_puzzle_completion_entity_1 = __webpack_require__(/*! ./user-puzzle-completion.entity */ "./src/users/entities/user-puzzle-completion.entity.ts"); +let User = class User { +}; +exports.User = User; +__decorate([ + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], User.prototype, "id", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50, unique: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], User.prototype, "username", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100 }), + __metadata("design:type", String) +], User.prototype, "firstName", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 100 }), + __metadata("design:type", String) +], User.prototype, "lastName", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 255, unique: true }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], User.prototype, "email", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 255 }), + __metadata("design:type", String) +], User.prototype, "password", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 255, nullable: true }), + __metadata("design:type", String) +], User.prototype, "avatar", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'date', nullable: true }), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], User.prototype, "dateOfBirth", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 50, nullable: true }), + __metadata("design:type", String) +], User.prototype, "country", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'active' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], User.prototype, "status", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'player' }), + (0, typeorm_1.Index)(), + __metadata("design:type", String) +], User.prototype, "role", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, typeorm_1.Index)(), + __metadata("design:type", Number) +], User.prototype, "totalScore", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 1 }), + __metadata("design:type", Number) +], User.prototype, "level", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], User.prototype, "experience", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], User.prototype, "puzzlesSolved", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], User.prototype, "achievementsCount", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) +], User.prototype, "lastLoginAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) +], User.prototype, "lastActiveAt", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], User.prototype, "preferences", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], User.prototype, "profile", void 0); +__decorate([ + (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), + __metadata("design:type", Object) +], User.prototype, "metadata", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => user_achievement_entity_1.UserAchievement, (userAchievement) => userAchievement.user), + __metadata("design:type", Array) +], User.prototype, "achievements", void 0); +__decorate([ + (0, typeorm_1.OneToMany)('PuzzleProgress', 'user'), + __metadata("design:type", Array) +], User.prototype, "puzzleProgress", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => game_session_entity_1.GameSession, (session) => session.user), + __metadata("design:type", Array) +], User.prototype, "gameSessions", void 0); +__decorate([ + (0, typeorm_1.OneToOne)(() => user_streak_entity_1.UserStreak, (streak) => streak.user, { cascade: true }), + __metadata("design:type", typeof (_d = typeof user_streak_entity_1.UserStreak !== "undefined" && user_streak_entity_1.UserStreak) === "function" ? _d : Object) +], User.prototype, "streak", void 0); +__decorate([ + (0, typeorm_1.OneToMany)(() => user_puzzle_completion_entity_1.UserPuzzleCompletion, (completion) => completion.user, { cascade: true }), + __metadata("design:type", Array) +], User.prototype, "puzzleCompletions", void 0); +exports.User = User = __decorate([ + (0, typeorm_1.Entity)('users'), + (0, typeorm_1.Index)(['email'], { unique: true }), + (0, typeorm_1.Index)(['username'], { unique: true }) +], User); + + +/***/ }), + +/***/ "./src/users/users.controller.ts": +/*!***************************************!*\ + !*** ./src/users/users.controller.ts ***! + \***************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d, _e; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UsersController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const platform_express_1 = __webpack_require__(/*! @nestjs/platform-express */ "@nestjs/platform-express"); +const file_upload_validator_1 = __webpack_require__(/*! ../common/validators/file-upload.validator */ "./src/common/validators/file-upload.validator.ts"); +const users_service_1 = __webpack_require__(/*! ./users.service */ "./src/users/users.service.ts"); +const create_user_dto_1 = __webpack_require__(/*! ./dto/create-user.dto */ "./src/users/dto/create-user.dto.ts"); +const update_user_dto_1 = __webpack_require__(/*! ./dto/update-user.dto */ "./src/users/dto/update-user.dto.ts"); +let UsersController = class UsersController { + constructor(usersService) { + this.usersService = usersService; + } + create(createUserDto) { + return this.usersService.create(createUserDto); + } + findAll() { + return this.usersService.findAll(); + } + findOne(id) { + return this.usersService.findOne(id); + } + update(id, updateUserDto) { + return this.usersService.update(id, updateUserDto); + } + remove(id) { + return this.usersService.remove(id); + } + uploadAvatar(file) { + return { message: 'Avatar uploaded successfully', filename: file.originalname }; + } +}; +exports.UsersController = UsersController; +__decorate([ + (0, common_1.Post)(), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof create_user_dto_1.CreateUserDto !== "undefined" && create_user_dto_1.CreateUserDto) === "function" ? _b : Object]), + __metadata("design:returntype", void 0) +], UsersController.prototype, "create", null); +__decorate([ + (0, common_1.Get)(), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", void 0) +], UsersController.prototype, "findAll", null); +__decorate([ + (0, common_1.Get)(':id'), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", void 0) +], UsersController.prototype, "findOne", null); +__decorate([ + (0, common_1.Patch)(':id'), + __param(0, (0, common_1.Param)('id')), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String, typeof (_c = typeof update_user_dto_1.UpdateUserDto !== "undefined" && update_user_dto_1.UpdateUserDto) === "function" ? _c : Object]), + __metadata("design:returntype", void 0) +], UsersController.prototype, "update", null); +__decorate([ + (0, common_1.Delete)(':id'), + __param(0, (0, common_1.Param)('id')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", void 0) +], UsersController.prototype, "remove", null); +__decorate([ + (0, common_1.Post)('avatar'), + (0, common_1.UseInterceptors)((0, platform_express_1.FileInterceptor)('file', { + fileFilter: (0, file_upload_validator_1.fileFilter)(['.png', '.jpg', '.jpeg'], ['image/png', 'image/jpeg']), + limits: { fileSize: 2 * 1024 * 1024 }, + })), + __param(0, (0, common_1.UploadedFile)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_e = typeof Express !== "undefined" && (_d = Express.Multer) !== void 0 && _d.File) === "function" ? _e : Object]), + __metadata("design:returntype", void 0) +], UsersController.prototype, "uploadAvatar", null); +exports.UsersController = UsersController = __decorate([ + (0, common_1.Controller)('users'), + __metadata("design:paramtypes", [typeof (_a = typeof users_service_1.UsersService !== "undefined" && users_service_1.UsersService) === "function" ? _a : Object]) +], UsersController); + + +/***/ }), + +/***/ "./src/users/users.module.ts": +/*!***********************************!*\ + !*** ./src/users/users.module.ts ***! + \***********************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UsersModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const users_service_1 = __webpack_require__(/*! ./users.service */ "./src/users/users.service.ts"); +const users_controller_1 = __webpack_require__(/*! ./users.controller */ "./src/users/users.controller.ts"); +let UsersModule = class UsersModule { +}; +exports.UsersModule = UsersModule; +exports.UsersModule = UsersModule = __decorate([ + (0, common_1.Module)({ + controllers: [users_controller_1.UsersController], + providers: [users_service_1.UsersService], + }) +], UsersModule); + + +/***/ }), + +/***/ "./src/users/users.service.ts": +/*!************************************!*\ + !*** ./src/users/users.service.ts ***! + \************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UsersService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +let UsersService = class UsersService { + create(createUserDto) { + return 'This action adds a new user'; + } + findAll() { + return `This action returns all users`; + } + findOne(id) { + return `This action returns a user with id #${id}`; + } + update(id, updateUserDto) { + return `This action updates a user with id #${id}`; + } + remove(id) { + return `This action removes a user with id #${id}`; + } +}; +exports.UsersService = UsersService; +exports.UsersService = UsersService = __decorate([ + (0, common_1.Injectable)() +], UsersService); + + +/***/ }), + +/***/ "./src/wallet/dto/connect-wallet.dto.ts": +/*!**********************************************!*\ + !*** ./src/wallet/dto/connect-wallet.dto.ts ***! + \**********************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ConnectWalletDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class ConnectWalletDto { +} +exports.ConnectWalletDto = ConnectWalletDto; +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ConnectWalletDto.prototype, "publicKey", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ConnectWalletDto.prototype, "network", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ConnectWalletDto.prototype, "signature", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ConnectWalletDto.prototype, "nonce", void 0); + + +/***/ }), + +/***/ "./src/wallet/dto/record-transaction.dto.ts": +/*!**************************************************!*\ + !*** ./src/wallet/dto/record-transaction.dto.ts ***! + \**************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.RecordTransactionDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class RecordTransactionDto { +} +exports.RecordTransactionDto = RecordTransactionDto; +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], RecordTransactionDto.prototype, "assetCode", void 0); +__decorate([ + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], RecordTransactionDto.prototype, "issuer", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], RecordTransactionDto.prototype, "amount", void 0); +__decorate([ + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], RecordTransactionDto.prototype, "transactionHash", void 0); + + +/***/ }), + +/***/ "./src/wallet/guards/wallet-session.guard.ts": +/*!***************************************************!*\ + !*** ./src/wallet/guards/wallet-session.guard.ts ***! + \***************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.WalletSessionGuard = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const wallet_service_1 = __webpack_require__(/*! ../wallet.service */ "./src/wallet/wallet.service.ts"); +let WalletSessionGuard = class WalletSessionGuard { + constructor(walletService) { + this.walletService = walletService; + } + canActivate(context) { + const request = context.switchToHttp().getRequest(); + const token = this.extractSessionToken(request); + if (!token) { + throw new common_1.UnauthorizedException('Wallet session token is required'); + } + const session = this.walletService.getSession(token); + request.walletSession = session; + return true; + } + extractSessionToken(request) { + const headerToken = request.headers['x-wallet-session']; + if (typeof headerToken === 'string' && headerToken.trim()) { + return headerToken.trim(); + } + const authHeader = request.headers['authorization']; + if (typeof authHeader === 'string') { + const [scheme, credentials] = authHeader.split(' '); + if (scheme === 'Wallet' && credentials) { + return credentials.trim(); + } + } + return null; + } +}; +exports.WalletSessionGuard = WalletSessionGuard; +exports.WalletSessionGuard = WalletSessionGuard = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [typeof (_a = typeof wallet_service_1.WalletService !== "undefined" && wallet_service_1.WalletService) === "function" ? _a : Object]) +], WalletSessionGuard); + + +/***/ }), + +/***/ "./src/wallet/utils/stellar.ts": +/*!*************************************!*\ + !*** ./src/wallet/utils/stellar.ts ***! + \*************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isValidStellarPublicKey = isValidStellarPublicKey; +exports.decodeStellarPublicKey = decodeStellarPublicKey; +exports.verifyEd25519Signature = verifyEd25519Signature; +exports.parseAmountToInt = parseAmountToInt; +exports.normalizeAsset = normalizeAsset; +exports.getAssetKey = getAssetKey; +exports.getDefaultTokenMetadata = getDefaultTokenMetadata; +const crypto_1 = __webpack_require__(/*! crypto */ "crypto"); +const BASE32_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; +const VERSION_BYTE_ED25519_PUBLIC_KEY = 6 << 3; +const ED25519_SPKI_PREFIX = Buffer.from('302a300506032b6570032100', 'hex'); +function isValidStellarPublicKey(publicKey) { + try { + decodeStellarPublicKey(publicKey); + return true; + } + catch { + return false; + } +} +function decodeStellarPublicKey(publicKey) { + const decoded = base32Decode(publicKey); + if (decoded.length !== 35) { + throw new Error('Invalid public key length'); + } + const payload = decoded.subarray(0, decoded.length - 2); + const checksum = decoded.subarray(decoded.length - 2); + const expectedChecksum = crc16Xmodem(payload); + const expectedBytes = Buffer.from([ + expectedChecksum & 0xff, + (expectedChecksum >> 8) & 0xff, + ]); + if (checksum[0] !== expectedBytes[0] || checksum[1] !== expectedBytes[1]) { + throw new Error('Invalid public key checksum'); + } + if (payload[0] !== VERSION_BYTE_ED25519_PUBLIC_KEY) { + throw new Error('Invalid public key version'); + } + return Buffer.from(payload.subarray(1)); +} +function verifyEd25519Signature(publicKey, message, signature) { + const rawKey = decodeStellarPublicKey(publicKey); + const keyDer = Buffer.concat([ED25519_SPKI_PREFIX, rawKey]); + const keyObject = (0, crypto_1.createPublicKey)({ key: keyDer, format: 'der', type: 'spki' }); + const signatureBuffer = decodeSignature(signature); + return (0, crypto_1.verify)(null, Buffer.from(message, 'utf8'), keyObject, signatureBuffer); +} +function parseAmountToInt(amount, decimals = 7) { + if (typeof amount !== 'string') { + throw new Error('Amount must be a string'); + } + const normalized = amount.trim(); + if (!normalized || !/^\d+(\.\d+)?$/.test(normalized)) { + throw new Error('Invalid amount format'); + } + const parts = normalized.split('.'); + const whole = parts[0] || '0'; + const fraction = parts[1] || ''; + if (fraction.length > decimals) { + throw new Error('Amount exceeds allowed decimals'); + } + const paddedFraction = fraction.padEnd(decimals, '0'); + const base = BigInt(whole) * 10n ** BigInt(decimals); + const fractionValue = paddedFraction ? BigInt(paddedFraction) : 0n; + return base + fractionValue; +} +function normalizeAsset(assetCode, issuer) { + const code = assetCode.trim(); + if (!code) { + throw new Error('Asset code is required'); + } + if (code.toUpperCase() === 'XLM' || code.toLowerCase() === 'native') { + return { type: 'native', code: 'XLM' }; + } + if (!issuer) { + throw new Error('Asset issuer is required for custom assets'); + } + if (code.length < 1 || code.length > 12) { + throw new Error('Asset code must be between 1 and 12 characters'); + } + if (!isValidStellarPublicKey(issuer)) { + throw new Error('Invalid asset issuer'); + } + const type = code.length <= 4 ? 'credit_alphanum4' : 'credit_alphanum12'; + return { type, code, issuer }; +} +function getAssetKey(asset) { + if (asset.type === 'native') { + return 'XLM'; + } + return `${asset.code}:${asset.issuer}`; +} +function getDefaultTokenMetadata(asset) { + if (asset.type === 'native') { + return { + code: 'XLM', + name: 'Stellar Lumens', + symbol: 'XLM', + decimals: 7, + }; + } + return { + code: asset.code, + issuer: asset.issuer, + name: asset.code, + symbol: asset.code, + decimals: 7, + }; +} +function decodeSignature(signature) { + const trimmed = signature.trim(); + if (/^[0-9a-fA-F]+$/.test(trimmed) && trimmed.length === 128) { + return Buffer.from(trimmed, 'hex'); + } + return Buffer.from(trimmed, 'base64'); +} +function base32Decode(input) { + const normalized = input.trim().toUpperCase().replace(/=+$/, ''); + let bits = 0; + let value = 0; + const bytes = []; + for (const char of normalized) { + const index = BASE32_ALPHABET.indexOf(char); + if (index === -1) { + throw new Error('Invalid base32 character'); + } + value = (value << 5) | index; + bits += 5; + if (bits >= 8) { + bytes.push((value >>> (bits - 8)) & 0xff); + bits -= 8; + } + } + return Buffer.from(bytes); +} +function crc16Xmodem(payload) { + let crc = 0x0000; + for (const byte of payload) { + crc ^= byte << 8; + for (let i = 0; i < 8; i += 1) { + if (crc & 0x8000) { + crc = (crc << 1) ^ 0x1021; + } + else { + crc <<= 1; + } + crc &= 0xffff; + } + } + return crc; +} + + +/***/ }), + +/***/ "./src/wallet/wallet.controller.ts": +/*!*****************************************!*\ + !*** ./src/wallet/wallet.controller.ts ***! + \*****************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.WalletController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const swagger_1 = __webpack_require__(/*! @nestjs/swagger */ "@nestjs/swagger"); +const connect_wallet_dto_1 = __webpack_require__(/*! ./dto/connect-wallet.dto */ "./src/wallet/dto/connect-wallet.dto.ts"); +const record_transaction_dto_1 = __webpack_require__(/*! ./dto/record-transaction.dto */ "./src/wallet/dto/record-transaction.dto.ts"); +const wallet_session_guard_1 = __webpack_require__(/*! ./guards/wallet-session.guard */ "./src/wallet/guards/wallet-session.guard.ts"); +const wallet_service_1 = __webpack_require__(/*! ./wallet.service */ "./src/wallet/wallet.service.ts"); +let WalletController = class WalletController { + constructor(walletService) { + this.walletService = walletService; + } + connect(body) { + if ((body.signature && !body.nonce) || (!body.signature && body.nonce)) { + return { + status: 'error', + message: 'Signature and nonce must be provided together', + }; + } + if (!body.signature || !body.nonce) { + return this.walletService.createChallenge(body.publicKey, body.network); + } + return this.walletService.verifyChallenge(body.publicKey, body.network, body.nonce, body.signature); + } + getSession(req) { + const session = req.walletSession; + return { + publicKey: session.publicKey, + network: session.network, + expiresAt: session.expiresAt.toISOString(), + }; + } + disconnect(req) { + const session = req.walletSession; + return this.walletService.disconnect(session.sessionToken); + } + getBalances(req) { + return this.walletService.getBalances(req.walletSession); + } + getTransactions(req, limit, cursor) { + const parsedLimit = limit ? Number.parseInt(limit, 10) : undefined; + const safeLimit = parsedLimit !== undefined && !Number.isNaN(parsedLimit) + ? parsedLimit + : undefined; + return this.walletService.getTransactionHistory(req.walletSession, safeLimit, cursor); + } + recordPurchase(req, body) { + return this.walletService.recordPurchase(req.walletSession, body); + } + recordSpend(req, body) { + return this.walletService.recordSpend(req.walletSession, body); + } +}; +exports.WalletController = WalletController; +__decorate([ + (0, common_1.Post)('connect'), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof connect_wallet_dto_1.ConnectWalletDto !== "undefined" && connect_wallet_dto_1.ConnectWalletDto) === "function" ? _b : Object]), + __metadata("design:returntype", void 0) +], WalletController.prototype, "connect", null); +__decorate([ + (0, common_1.Get)('session'), + (0, common_1.UseGuards)(wallet_session_guard_1.WalletSessionGuard), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Req)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", void 0) +], WalletController.prototype, "getSession", null); +__decorate([ + (0, common_1.Post)('disconnect'), + (0, common_1.UseGuards)(wallet_session_guard_1.WalletSessionGuard), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Req)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", void 0) +], WalletController.prototype, "disconnect", null); +__decorate([ + (0, common_1.Get)('balances'), + (0, common_1.UseGuards)(wallet_session_guard_1.WalletSessionGuard), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Req)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", void 0) +], WalletController.prototype, "getBalances", null); +__decorate([ + (0, common_1.Get)('transactions'), + (0, common_1.UseGuards)(wallet_session_guard_1.WalletSessionGuard), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Query)('limit')), + __param(2, (0, common_1.Query)('cursor')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, String, String]), + __metadata("design:returntype", void 0) +], WalletController.prototype, "getTransactions", null); +__decorate([ + (0, common_1.Post)('purchase'), + (0, common_1.UseGuards)(wallet_session_guard_1.WalletSessionGuard), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, typeof (_c = typeof record_transaction_dto_1.RecordTransactionDto !== "undefined" && record_transaction_dto_1.RecordTransactionDto) === "function" ? _c : Object]), + __metadata("design:returntype", void 0) +], WalletController.prototype, "recordPurchase", null); +__decorate([ + (0, common_1.Post)('spend'), + (0, common_1.UseGuards)(wallet_session_guard_1.WalletSessionGuard), + (0, common_1.HttpCode)(common_1.HttpStatus.OK), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, typeof (_d = typeof record_transaction_dto_1.RecordTransactionDto !== "undefined" && record_transaction_dto_1.RecordTransactionDto) === "function" ? _d : Object]), + __metadata("design:returntype", void 0) +], WalletController.prototype, "recordSpend", null); +exports.WalletController = WalletController = __decorate([ + (0, swagger_1.ApiTags)('Wallet'), + (0, common_1.Controller)('wallet'), + __metadata("design:paramtypes", [typeof (_a = typeof wallet_service_1.WalletService !== "undefined" && wallet_service_1.WalletService) === "function" ? _a : Object]) +], WalletController); + + +/***/ }), + +/***/ "./src/wallet/wallet.module.ts": +/*!*************************************!*\ + !*** ./src/wallet/wallet.module.ts ***! + \*************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.WalletModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const wallet_controller_1 = __webpack_require__(/*! ./wallet.controller */ "./src/wallet/wallet.controller.ts"); +const wallet_service_1 = __webpack_require__(/*! ./wallet.service */ "./src/wallet/wallet.service.ts"); +const wallet_session_guard_1 = __webpack_require__(/*! ./guards/wallet-session.guard */ "./src/wallet/guards/wallet-session.guard.ts"); +let WalletModule = class WalletModule { +}; +exports.WalletModule = WalletModule; +exports.WalletModule = WalletModule = __decorate([ + (0, common_1.Module)({ + imports: [config_1.ConfigModule], + controllers: [wallet_controller_1.WalletController], + providers: [wallet_service_1.WalletService, wallet_session_guard_1.WalletSessionGuard], + exports: [wallet_service_1.WalletService], + }) +], WalletModule); + + +/***/ }), + +/***/ "./src/wallet/wallet.service.ts": +/*!**************************************!*\ + !*** ./src/wallet/wallet.service.ts ***! + \**************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + +"use strict"; + +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.WalletService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const config_1 = __webpack_require__(/*! @nestjs/config */ "@nestjs/config"); +const crypto_1 = __webpack_require__(/*! crypto */ "crypto"); +const stellar_1 = __webpack_require__(/*! ./utils/stellar */ "./src/wallet/utils/stellar.ts"); +let WalletService = class WalletService { + constructor(configService) { + this.configService = configService; + this.challenges = new Map(); + this.sessions = new Map(); + this.recordedTransactions = new Map(); + this.challengeTtlMs = this.readNumber('WALLET_CHALLENGE_TTL_MS', 5 * 60 * 1000); + this.sessionTtlMs = this.readNumber('WALLET_SESSION_TTL_MS', 24 * 60 * 60 * 1000); + this.maxRecordedTransactions = this.readNumber('WALLET_MAX_RECORDED_TRANSACTIONS', 1000); + this.allowedNetworks = this.parseAllowedNetworks(); + this.tokenMetadata = this.loadTokenMetadata(); + } + createChallenge(publicKey, network) { + this.ensureValidPublicKey(publicKey); + const normalizedNetwork = this.normalizeNetwork(network); + this.ensureAllowedNetwork(normalizedNetwork); + const nonce = (0, crypto_1.randomBytes)(16).toString('hex'); + const issuedAt = new Date(); + const message = [ + 'LogiQuest Wallet Authentication', + `Public Key: ${publicKey}`, + `Nonce: ${nonce}`, + `Network: ${normalizedNetwork}`, + `Issued At: ${issuedAt.toISOString()}`, + ].join('\n'); + const expiresAt = new Date(issuedAt.getTime() + this.challengeTtlMs); + this.challenges.set(nonce, { + nonce, + publicKey, + network: normalizedNetwork, + message, + expiresAt, + }); + return { + status: 'challenge', + nonce, + message, + expiresAt: expiresAt.toISOString(), + }; + } + verifyChallenge(publicKey, network, nonce, signature) { + this.ensureValidPublicKey(publicKey); + const normalizedNetwork = this.normalizeNetwork(network); + this.ensureAllowedNetwork(normalizedNetwork); + const challenge = this.challenges.get(nonce); + if (!challenge) { + throw new common_1.UnauthorizedException('Challenge not found or already used'); + } + if (challenge.publicKey !== publicKey || challenge.network !== normalizedNetwork) { + throw new common_1.UnauthorizedException('Challenge does not match wallet'); + } + if (challenge.expiresAt.getTime() < Date.now()) { + this.challenges.delete(nonce); + throw new common_1.UnauthorizedException('Challenge expired'); + } + const isValid = (0, stellar_1.verifyEd25519Signature)(publicKey, challenge.message, signature); + if (!isValid) { + throw new common_1.UnauthorizedException('Invalid wallet signature'); + } + this.challenges.delete(nonce); + const sessionToken = (0, crypto_1.randomUUID)(); + const now = new Date(); + const expiresAt = new Date(now.getTime() + this.sessionTtlMs); + const session = { + sessionToken, + publicKey, + network: normalizedNetwork, + createdAt: now, + expiresAt, + lastUsedAt: now, + }; + this.sessions.set(sessionToken, session); + return { + status: 'connected', + sessionToken, + publicKey, + network: normalizedNetwork, + expiresAt: expiresAt.toISOString(), + }; + } + getSession(sessionToken) { + const session = this.sessions.get(sessionToken); + if (!session) { + throw new common_1.UnauthorizedException('Wallet session not found'); + } + if (session.expiresAt.getTime() < Date.now()) { + this.sessions.delete(sessionToken); + throw new common_1.UnauthorizedException('Wallet session expired'); + } + session.lastUsedAt = new Date(); + return session; + } + disconnect(sessionToken) { + if (!this.sessions.has(sessionToken)) { + throw new common_1.UnauthorizedException('Wallet session not found'); + } + this.sessions.delete(sessionToken); + return { status: 'disconnected' }; + } + async getBalances(session) { + const account = await this.fetchAccount(session.publicKey, session.network); + const balances = account?.balances ?? []; + const mappedBalances = balances.map((balance) => { + const asset = this.mapBalanceToAsset(balance); + const metadata = this.tokenMetadata.get((0, stellar_1.getAssetKey)(asset)) || + (0, stellar_1.getDefaultTokenMetadata)(asset); + return { + asset, + balance: balance.balance, + decimals: metadata.decimals ?? 7, + symbol: metadata.symbol || metadata.code, + name: metadata.name || metadata.code, + }; + }); + if (!mappedBalances.some((balance) => balance.asset.type === 'native')) { + const asset = { type: 'native', code: 'XLM' }; + const metadata = (0, stellar_1.getDefaultTokenMetadata)(asset); + mappedBalances.unshift({ + asset, + balance: '0', + decimals: metadata.decimals ?? 7, + symbol: metadata.symbol || metadata.code, + name: metadata.name || metadata.code, + }); + } + return { balances: mappedBalances }; + } + async getTransactionHistory(session, limit = 20, cursor) { + const safeLimit = Math.min(Math.max(limit, 1), 100); + const onChain = await this.fetchOnChainOperations(session.publicKey, session.network, safeLimit, cursor); + const recorded = this.getRecordedTransactions(session.publicKey).map((transaction) => ({ + id: transaction.id, + source: 'recorded', + type: transaction.type, + status: transaction.status, + asset: transaction.asset, + amount: transaction.amount, + transactionHash: transaction.transactionHash, + createdAt: transaction.createdAt.toISOString(), + })); + const combined = [...recorded, ...onChain]; + combined.sort((a, b) => { + const left = new Date(a.createdAt).getTime(); + const right = new Date(b.createdAt).getTime(); + return right - left; + }); + return { transactions: combined }; + } + async recordPurchase(session, payload) { + return this.recordTransaction(session, payload, 'purchase'); + } + async recordSpend(session, payload) { + return this.recordTransaction(session, payload, 'spend'); + } + async recordTransaction(session, payload, type) { + const asset = this.ensureValidAsset(payload.assetCode, payload.issuer); + const amountInt = this.ensureValidAmount(payload.amount); + const transactionHash = this.ensureValidTransactionHash(payload.transactionHash); + const existing = this.findRecordedTransaction(session.publicKey, transactionHash, type); + if (existing) { + return existing; + } + const matches = await this.verifyPaymentOnChain(session.publicKey, session.network, transactionHash, asset, amountInt, type); + if (!matches) { + throw new common_1.BadRequestException('Transaction does not match requested transfer'); + } + const transaction = { + id: (0, crypto_1.randomUUID)(), + publicKey: session.publicKey, + network: session.network, + type, + status: 'confirmed', + asset, + amount: payload.amount, + transactionHash, + createdAt: new Date(), + }; + const list = this.getRecordedTransactions(session.publicKey); + list.unshift(transaction); + if (list.length > this.maxRecordedTransactions) { + list.splice(this.maxRecordedTransactions); + } + this.recordedTransactions.set(session.publicKey, list); + return transaction; + } + ensureValidPublicKey(publicKey) { + if (!(0, stellar_1.isValidStellarPublicKey)(publicKey)) { + throw new common_1.BadRequestException('Invalid Stellar public key'); + } + } + ensureValidAsset(assetCode, issuer) { + try { + return (0, stellar_1.normalizeAsset)(assetCode, issuer); + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + ensureValidAmount(amount) { + try { + const value = (0, stellar_1.parseAmountToInt)(amount, 7); + if (value <= 0n) { + throw new Error('Amount must be greater than zero'); + } + return value; + } + catch (error) { + throw new common_1.BadRequestException(error.message); + } + } + ensureValidTransactionHash(transactionHash) { + const normalized = transactionHash.trim().toLowerCase(); + if (!/^[0-9a-f]{64}$/.test(normalized)) { + throw new common_1.BadRequestException('Invalid transaction hash'); + } + return normalized; + } + normalizeNetwork(network) { + const normalized = network.trim().toLowerCase(); + if (!normalized) { + throw new common_1.BadRequestException('Network is required'); + } + return normalized; + } + ensureAllowedNetwork(network) { + if (!this.allowedNetworks.includes(network)) { + throw new common_1.BadRequestException('Unsupported Stellar network'); + } + } + parseAllowedNetworks() { + const raw = this.configService.get('STELLAR_ALLOWED_NETWORKS') || process.env.STELLAR_ALLOWED_NETWORKS; + const value = typeof raw === 'string' && raw.trim() ? raw : 'testnet'; + return value + .split(',') + .map((entry) => entry.trim().toLowerCase()) + .filter(Boolean); + } + loadTokenMetadata() { + const raw = this.configService.get('STELLAR_TOKEN_LIST') || process.env.STELLAR_TOKEN_LIST; + if (typeof raw !== 'string' || !raw.trim()) { + return new Map(); + } + try { + const parsed = JSON.parse(raw); + if (!Array.isArray(parsed)) { + return new Map(); + } + const map = new Map(); + for (const entry of parsed) { + if (!entry || typeof entry.code !== 'string') { + continue; + } + const asset = entry.code.toUpperCase() === 'XLM' + ? { type: 'native', code: 'XLM' } + : (0, stellar_1.normalizeAsset)(entry.code, entry.issuer); + map.set((0, stellar_1.getAssetKey)(asset), { + code: entry.code, + issuer: entry.issuer, + name: entry.name, + symbol: entry.symbol, + decimals: typeof entry.decimals === 'number' ? entry.decimals : 7, + }); + } + return map; + } + catch { + return new Map(); + } + } + async fetchAccount(publicKey, network) { + const url = `${this.getHorizonUrl(network)}/accounts/${publicKey}`; + const response = await fetch(url, { headers: { Accept: 'application/json' } }); + if (response.status === 404) { + return null; + } + if (!response.ok) { + throw new common_1.BadRequestException('Failed to fetch Stellar account'); + } + return response.json(); + } + mapBalanceToAsset(balance) { + if (balance.asset_type === 'native') { + return { type: 'native', code: 'XLM' }; + } + return { + type: balance.asset_type, + code: balance.asset_code || 'UNKNOWN', + issuer: balance.asset_issuer, + }; + } + async fetchOnChainOperations(publicKey, network, limit, cursor) { + const params = new URLSearchParams({ + limit: limit.toString(), + order: 'desc', + }); + if (cursor) { + params.set('cursor', cursor); + } + const url = `${this.getHorizonUrl(network)}/accounts/${publicKey}/operations?${params.toString()}`; + const response = await fetch(url, { headers: { Accept: 'application/json' } }); + if (!response.ok) { + throw new common_1.BadRequestException('Failed to fetch transaction history'); + } + const data = (await response.json()); + const records = data._embedded?.records ?? []; + return records + .map((record) => this.mapOperationToHistory(record)) + .filter((entry) => entry !== null); + } + mapOperationToHistory(record) { + const type = record.type; + const createdAt = record.created_at || new Date().toISOString(); + if (type === 'payment' || type?.startsWith('path_payment')) { + const asset = record.asset_type === 'native' + ? { type: 'native', code: 'XLM' } + : { + type: record.asset_type, + code: record.asset_code, + issuer: record.asset_issuer, + }; + return { + id: record.id, + source: 'chain', + type: record.type, + status: record.transaction_successful ? 'confirmed' : 'failed', + asset, + amount: record.amount, + from: record.from, + to: record.to, + transactionHash: record.transaction_hash, + createdAt, + }; + } + if (type === 'create_account') { + return { + id: record.id, + source: 'chain', + type: record.type, + status: record.transaction_successful ? 'confirmed' : 'failed', + asset: { type: 'native', code: 'XLM' }, + amount: record.starting_balance, + from: record.funder, + to: record.account, + transactionHash: record.transaction_hash, + createdAt, + }; + } + return null; + } + async verifyPaymentOnChain(publicKey, network, transactionHash, asset, amount, type) { + const baseUrl = this.getHorizonUrl(network); + const transactionUrl = `${baseUrl}/transactions/${transactionHash}`; + const transactionResponse = await fetch(transactionUrl, { + headers: { Accept: 'application/json' }, + }); + if (transactionResponse.status === 404) { + throw new common_1.NotFoundException('Transaction not found on network'); + } + if (!transactionResponse.ok) { + throw new common_1.BadRequestException('Failed to verify transaction'); + } + const transaction = await transactionResponse.json(); + if (!transaction.successful) { + throw new common_1.BadRequestException('Transaction was not successful'); + } + const operationsUrl = `${baseUrl}/transactions/${transactionHash}/operations?limit=200`; + const operationsResponse = await fetch(operationsUrl, { + headers: { Accept: 'application/json' }, + }); + if (!operationsResponse.ok) { + throw new common_1.BadRequestException('Failed to load transaction operations'); + } + const operations = (await operationsResponse.json()); + const records = operations._embedded?.records ?? []; + for (const record of records) { + if (record.type !== 'payment' && !record.type?.startsWith('path_payment')) { + continue; + } + const from = record.from || record.source_account; + const to = record.to; + if (type === 'purchase' && to !== publicKey) { + continue; + } + if (type === 'spend' && from !== publicKey) { + continue; + } + if (!this.assetMatchesRecord(asset, record)) { + continue; + } + try { + const opAmount = (0, stellar_1.parseAmountToInt)(record.amount, 7); + if (opAmount !== amount) { + continue; + } + } + catch { + continue; + } + return true; + } + return false; + } + assetMatchesRecord(asset, record) { + if (asset.type === 'native') { + return record.asset_type === 'native'; + } + return (record.asset_type === asset.type && + record.asset_code === asset.code && + record.asset_issuer === asset.issuer); + } + getRecordedTransactions(publicKey) { + return this.recordedTransactions.get(publicKey) || []; + } + findRecordedTransaction(publicKey, transactionHash, type) { + const transactions = this.getRecordedTransactions(publicKey); + return transactions.find((transaction) => transaction.transactionHash === transactionHash && transaction.type === type); + } + getHorizonUrl(network) { + const override = this.configService.get('STELLAR_HORIZON_URL') || process.env.STELLAR_HORIZON_URL; + if (override) { + return override; + } + if (network === 'public') { + return (this.configService.get('STELLAR_HORIZON_URL_PUBLIC') || + process.env.STELLAR_HORIZON_URL_PUBLIC || + 'https://horizon.stellar.org'); + } + if (network === 'testnet') { + return (this.configService.get('STELLAR_HORIZON_URL_TESTNET') || + process.env.STELLAR_HORIZON_URL_TESTNET || + 'https://horizon-testnet.stellar.org'); + } + const custom = this.configService.get(`STELLAR_HORIZON_URL_${network.toUpperCase()}`); + if (custom) { + return custom; + } + throw new common_1.BadRequestException('Horizon URL not configured for network'); + } + readNumber(key, fallback) { + const value = this.configService.get(key) || process.env[key]; + if (typeof value === 'string' && value.trim()) { + const parsed = Number.parseInt(value, 10); + if (!Number.isNaN(parsed)) { + return parsed; + } + } + if (typeof value === 'number') { + return value; + } + return fallback; + } +}; +exports.WalletService = WalletService; +exports.WalletService = WalletService = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object]) +], WalletService); + + +/***/ }), + +/***/ "@nestjs/common": +/*!*********************************!*\ + !*** external "@nestjs/common" ***! + \*********************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/common"); + +/***/ }), + +/***/ "@nestjs/config": +/*!*********************************!*\ + !*** external "@nestjs/config" ***! + \*********************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/config"); + +/***/ }), + +/***/ "@nestjs/core": +/*!*******************************!*\ + !*** external "@nestjs/core" ***! + \*******************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/core"); + +/***/ }), + +/***/ "@nestjs/mapped-types": +/*!***************************************!*\ + !*** external "@nestjs/mapped-types" ***! + \***************************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/mapped-types"); + +/***/ }), + +/***/ "@nestjs/microservices": +/*!****************************************!*\ + !*** external "@nestjs/microservices" ***! + \****************************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/microservices"); + +/***/ }), + +/***/ "@nestjs/passport": +/*!***********************************!*\ + !*** external "@nestjs/passport" ***! + \***********************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/passport"); + +/***/ }), + +/***/ "@nestjs/platform-express": +/*!*******************************************!*\ + !*** external "@nestjs/platform-express" ***! + \*******************************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/platform-express"); + +/***/ }), + +/***/ "@nestjs/schedule": +/*!***********************************!*\ + !*** external "@nestjs/schedule" ***! + \***********************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/schedule"); + +/***/ }), + +/***/ "@nestjs/swagger": +/*!**********************************!*\ + !*** external "@nestjs/swagger" ***! + \**********************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/swagger"); + +/***/ }), + +/***/ "@nestjs/terminus": +/*!***********************************!*\ + !*** external "@nestjs/terminus" ***! + \***********************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/terminus"); + +/***/ }), + +/***/ "@nestjs/throttler": +/*!************************************!*\ + !*** external "@nestjs/throttler" ***! + \************************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/throttler"); + +/***/ }), + +/***/ "@nestjs/typeorm": +/*!**********************************!*\ + !*** external "@nestjs/typeorm" ***! + \**********************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@nestjs/typeorm"); + +/***/ }), + +/***/ "@sentry/node": +/*!*******************************!*\ + !*** external "@sentry/node" ***! + \*******************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@sentry/node"); + +/***/ }), + +/***/ "@stellar/stellar-sdk": +/*!***************************************!*\ + !*** external "@stellar/stellar-sdk" ***! + \***************************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("@stellar/stellar-sdk"); + +/***/ }), + +/***/ "buffer": +/*!*************************!*\ + !*** external "buffer" ***! + \*************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("buffer"); + +/***/ }), + +/***/ "class-transformer": +/*!************************************!*\ + !*** external "class-transformer" ***! + \************************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("class-transformer"); + +/***/ }), + +/***/ "class-validator": +/*!**********************************!*\ + !*** external "class-validator" ***! + \**********************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("class-validator"); + +/***/ }), + +/***/ "dotenv": +/*!*************************!*\ + !*** external "dotenv" ***! + \*************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("dotenv"); + +/***/ }), + +/***/ "helmet": +/*!*************************!*\ + !*** external "helmet" ***! + \*************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("helmet"); + +/***/ }), + +/***/ "nest-winston": +/*!*******************************!*\ + !*** external "nest-winston" ***! + \*******************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("nest-winston"); + +/***/ }), + +/***/ "nodemailer": +/*!*****************************!*\ + !*** external "nodemailer" ***! + \*****************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("nodemailer"); + +/***/ }), + +/***/ "rxjs/operators": +/*!*********************************!*\ + !*** external "rxjs/operators" ***! + \*********************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("rxjs/operators"); + +/***/ }), + +/***/ "typeorm": +/*!**************************!*\ + !*** external "typeorm" ***! + \**************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("typeorm"); + +/***/ }), + +/***/ "winston": +/*!**************************!*\ + !*** external "winston" ***! + \**************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("winston"); + +/***/ }), + +/***/ "xss": +/*!**********************!*\ + !*** external "xss" ***! + \**********************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("xss"); + +/***/ }), + +/***/ "crypto": +/*!*************************!*\ + !*** external "crypto" ***! + \*************************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("crypto"); + +/***/ }), + +/***/ "path": +/*!***********************!*\ + !*** external "path" ***! + \***********************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("path"); + +/***/ }), + +/***/ "util": +/*!***********************!*\ + !*** external "util" ***! + \***********************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("util"); + +/***/ }), + +/***/ "zlib": +/*!***********************!*\ + !*** external "zlib" ***! + \***********************/ +/***/ ((module) => { + +"use strict"; +module.exports = require("zlib"); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module is referenced by other modules so it can't be inlined +/******/ var __webpack_exports__ = __webpack_require__("./src/main.ts"); +/******/ +/******/ })() +; \ No newline at end of file diff --git a/microservices/achievement-service/.env.example b/microservices/achievement-service/.env.example new file mode 100644 index 0000000..5bef2fd --- /dev/null +++ b/microservices/achievement-service/.env.example @@ -0,0 +1,17 @@ +NODE_ENV=development +PORT=3002 + +# Database Configuration +DB_HOST=localhost +DB_PORT=5432 +DB_USERNAME=postgres +DB_PASSWORD=password +DB_NAME=quest_economy + +# Payment Provider Configuration +STRIPE_SECRET_KEY=sk_test_... +STRIPE_WEBHOOK_SECRET=whsec_... + +PAYPAL_CLIENT_ID=your_paypal_client_id +PAYPAL_CLIENT_SECRET=your_paypal_client_secret +PAYPAL_SANDBOX=true diff --git a/microservices/achievement-service/Dockerfile b/microservices/achievement-service/Dockerfile new file mode 100644 index 0000000..d656121 --- /dev/null +++ b/microservices/achievement-service/Dockerfile @@ -0,0 +1,15 @@ +FROM node:18-alpine + +WORKDIR /app + +COPY package*.json ./ + +RUN npm ci --only=production + +COPY . . + +RUN npm run build + +EXPOSE 3006 + +CMD ["npm", "run", "start:prod"] diff --git a/microservices/achievement-service/README.md b/microservices/achievement-service/README.md new file mode 100644 index 0000000..446e089 --- /dev/null +++ b/microservices/achievement-service/README.md @@ -0,0 +1,147 @@ +# Economy Service + +A NestJS microservice for managing energy/stamina systems, hint purchases, in-game shop, and transactions. + +## Features + +- **Energy Management**: Automatic energy regeneration with configurable rates +- **Shop System**: Manage in-game items with different types (hints, power-ups, cosmetics) +- **Transaction Ledger**: Complete transaction history and balance tracking +- **Payment Integration**: Support for multiple payment providers (Stripe, PayPal) +- **Docker Support**: Fully containerized for easy deployment + +## API Endpoints + +### Energy Management + +- `GET /energy/:userId` - Get user's current energy +- `POST /energy/:userId/consume` - Consume energy +- `POST /energy/:userId/add` - Add energy +- `POST /energy/:userId/refill` - Refill energy to max +- `GET /energy/:userId/status` - Get regeneration status + +### Shop Management + +- `GET /shop` - Get all shop items +- `POST /shop` - Create new shop item +- `GET /shop/:id` - Get specific shop item +- `PUT /shop/:id` - Update shop item +- `DELETE /shop/:id` - Delete shop item +- `POST /shop/:shopItemId/purchase` - Purchase shop item + +### Transactions + +- `GET /transactions/user/:userId` - Get user transactions +- `POST /transactions` - Create transaction +- `GET /transactions/:id` - Get transaction details +- `POST /transactions/:id/complete` - Complete transaction +- `POST /transactions/:id/refund` - Refund transaction + +### Payment + +- `GET /payment/providers` - Get available payment providers +- `POST /payment/:provider/process` - Process payment +- `POST /payment/:provider/refund` - Refund payment + +## Setup + +### Prerequisites + +- Node.js 18+ +- PostgreSQL 15+ +- Docker (optional) + +### Installation + +1. Clone the repository +2. Install dependencies: + + ```bash + npm install + ``` + +3. Set up environment variables: + + ```bash + cp .env.example .env + # Edit .env with your configuration + ``` + +4. Run database migrations: + ```bash + npm run migration:run + ``` + +### Running with Docker + +1. Build and start services: + ```bash + docker-compose up --build + ``` + +The service will be available at `http://localhost:3002` + +### Running Locally + +1. Start PostgreSQL database +2. Run the service: + ```bash + npm run start:dev + ``` + +## Configuration + +### Energy System + +- Default max energy: 100 +- Regeneration rate: 300 energy per interval +- Regeneration interval: 60 seconds +- Automatic regeneration runs every 30 seconds + +### Shop Items + +- Types: HINT, POWER_UP, COSMETIC, ENERGY_REFILL +- Status: ACTIVE, INACTIVE, LIMITED +- Purchase limits and expiration support + +### Payment Providers + +- Stripe (test mode by default) +- PayPal (sandbox mode by default) +- Extensible provider system + +## Database Schema + +The service uses the following main entities: + +- `user_energy` - User energy/stamina tracking +- `shop_items` - Shop item catalog +- `transactions` - Transaction ledger + +## Development + +### Running Tests + +```bash +npm test +``` + +### Code Formatting + +```bash +npm run format +``` + +### Type Checking + +```bash +npm run type-check +``` + +## Environment Variables + +See `.env.example` for all available configuration options. + +## License + +UNLICENSED diff --git a/microservices/achievement-service/docker-compose.yml b/microservices/achievement-service/docker-compose.yml new file mode 100644 index 0000000..f144ef0 --- /dev/null +++ b/microservices/achievement-service/docker-compose.yml @@ -0,0 +1,35 @@ +version: '3.8' + +services: + achievement-service: + build: . + ports: + - '3006:3006' + environment: + NODE_ENV: development + DB_HOST: postgres + DB_PORT: 5432 + DB_USERNAME: postgres + DB_PASSWORD: password + DB_NAME: quest_achievement + PORT: 3006 + depends_on: + - postgres + volumes: + - .:/app + - /app/node_modules + command: npm run start:dev + + postgres: + image: postgres:15-alpine + environment: + POSTGRES_DB: quest_achievement + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + ports: + - '5433:5432' + volumes: + - postgres_data:/var/lib/postgresql/data + +volumes: + postgres_data: diff --git a/microservices/achievement-service/nest-cli.json b/microservices/achievement-service/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/microservices/achievement-service/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/microservices/achievement-service/package-lock.json b/microservices/achievement-service/package-lock.json new file mode 100644 index 0000000..b3723e4 --- /dev/null +++ b/microservices/achievement-service/package-lock.json @@ -0,0 +1,10091 @@ +{ + "name": "achievement-service", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "achievement-service", + "version": "0.0.1", + "license": "UNLICENSED", + "dependencies": { + "@nestjs/common": "^10.4.4", + "@nestjs/config": "^3.2.3", + "@nestjs/core": "^10.4.4", + "@nestjs/platform-express": "^10.4.4", + "@nestjs/schedule": "^6.0.0", + "@nestjs/typeorm": "^11.0.0", + "@quest-service/shared": "file:../shared", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.1", + "pg": "^8.16.3", + "reflect-metadata": "^0.1.14", + "rxjs": "^7.8.1", + "typeorm": "^0.3.25" + }, + "devDependencies": { + "@nestjs/cli": "^10.4.5", + "@nestjs/schematics": "^10.1.4", + "@nestjs/testing": "^10.4.4", + "@types/express": "^4.17.21", + "@types/jest": "^29.5.12", + "@types/node": "^20.14.15", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.0.0", + "@typescript-eslint/parser": "^8.0.0", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "jest": "^29.7.0", + "prettier": "^3.3.3", + "source-map-support": "^0.5.21", + "ts-jest": "^29.2.4", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.5.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "../shared": { + "name": "@quest-service/shared", + "version": "0.0.1", + "dependencies": { + "@grpc/grpc-js": "^1.9.14", + "@grpc/proto-loader": "^0.7.10", + "@nestjs/common": "^10.4.4", + "@nestjs/config": "^3.2.3", + "@nestjs/microservices": "^10.4.4", + "amqp-connection-manager": "^4.1.14", + "amqplib": "^0.10.4", + "bullmq": "^5.34.8", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.1", + "ioredis": "^5.4.2", + "reflect-metadata": "^0.2.2", + "rxjs": "^7.8.1", + "uuid": "^9.0.1" + }, + "devDependencies": { + "@nestjs/testing": "^10.4.4", + "@types/amqplib": "^0.10.5", + "@types/jest": "^29.5.12", + "@types/node": "^20.14.15", + "@types/uuid": "^9.0.8", + "@typescript-eslint/eslint-plugin": "^8.0.0", + "@typescript-eslint/parser": "^8.0.0", + "eslint": "^8.57.0", + "jest": "^29.7.0", + "rimraf": "^5.0.10", + "ts-jest": "^29.2.4", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "typescript": "^5.5.4" + } + }, + "node_modules/@angular-devkit/core": { + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.11.tgz", + "integrity": "sha512-vTNDYNsLIWpYk2I969LMQFH29GTsLzxNk/0cLw5q56ARF0v5sIWfHYwGTS88jdDqIpuuettcSczbxeA7EuAmqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.1", + "picomatch": "4.0.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/core/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@angular-devkit/schematics": { + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.11.tgz", + "integrity": "sha512-I5wviiIqiFwar9Pdk30Lujk8FczEEc18i22A5c6Z9lbmhPQdTroDnEQdsfXjy404wPe8H62s0I15o4pmMGfTYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "17.3.11", + "jsonc-parser": "3.2.1", + "magic-string": "0.30.8", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics-cli": { + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-17.3.11.tgz", + "integrity": "sha512-kcOMqp+PHAKkqRad7Zd7PbpqJ0LqLaNZdY1+k66lLWmkEBozgq8v4ASn/puPWf9Bo0HpCiK+EzLf0VHE8Z/y6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", + "ansi-colors": "4.1.3", + "inquirer": "9.2.15", + "symbol-observable": "4.0.0", + "yargs-parser": "21.1.1" + }, + "bin": { + "schematics": "bin/schematics.js" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics-cli/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, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/inquirer": { + "version": "9.2.15", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz", + "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ljharb/through": "^2.3.12", + "ansi-escapes": "^4.3.2", + "chalk": "^5.3.0", + "cli-cursor": "^3.1.0", + "cli-width": "^4.1.0", + "external-editor": "^3.1.0", + "figures": "^3.2.0", + "lodash": "^4.17.21", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", + "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", + "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", + "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", + "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", + "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", + "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", + "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@borewit/text-codec": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.1.tgz", + "integrity": "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.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/eslintrc/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/eslintrc/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/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.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/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.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/@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": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.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/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/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/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==", + "devOptional": 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==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@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/@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/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/@nestjs/cli/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nestjs/cli/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "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/cli/node_modules/webpack": { + "version": "5.97.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", + "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "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/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/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/schedule": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-6.1.0.tgz", + "integrity": "sha512-W25Ydc933Gzb1/oo7+bWzzDiOissE+h/dhIAPugA39b9MuIzBbLybuXpc1AjoQLczO3v0ldmxaffVl87W0uqoQ==", + "license": "MIT", + "dependencies": { + "cron": "4.3.5" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0" + } + }, + "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/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/typeorm": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-11.0.0.tgz", + "integrity": "sha512-SOeUQl70Lb2OfhGkvnh4KXWlsd+zA08RuuQgT7kKbzivngxzSo1Oc7Usu5VxCxACQC9wc2l9esOHILSJeK7rJA==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0", + "reflect-metadata": "^0.1.13 || ^0.2.0", + "rxjs": "^7.2.0", + "typeorm": "^0.3.0" + } + }, + "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/@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/@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/@quest-service/shared": { + "resolved": "../shared", + "link": true + }, + "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/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/@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/@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==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/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/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/luxon": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.7.1.tgz", + "integrity": "sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg==", + "license": "MIT" + }, + "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/node": { + "version": "20.19.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", + "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "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/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/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/superagent": { + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/supertest": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.3.tgz", + "integrity": "sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } + }, + "node_modules/@types/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": { + "@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": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.1.tgz", + "integrity": "sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/type-utils": "8.53.1", + "@typescript-eslint/utils": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.53.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.1.tgz", + "integrity": "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.1.tgz", + "integrity": "sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.53.1", + "@typescript-eslint/types": "^8.53.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.1.tgz", + "integrity": "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.1.tgz", + "integrity": "sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.1.tgz", + "integrity": "sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1", + "@typescript-eslint/utils": "8.53.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz", + "integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.1.tgz", + "integrity": "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.53.1", + "@typescript-eslint/tsconfig-utils": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.1.tgz", + "integrity": "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.1.tgz", + "integrity": "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.53.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/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/@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/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/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "devOptional": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.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-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": "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": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/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": ">=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/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-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/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "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/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/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.18", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.18.tgz", + "integrity": "sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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/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/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "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-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001766", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", + "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", + "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/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/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": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/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": { + "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-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/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/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/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-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/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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/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/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-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/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/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "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/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/cron": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/cron/-/cron-4.3.5.tgz", + "integrity": "sha512-hKPP7fq1+OfyCqoePkKfVq7tNAdFwiQORr4lZUHwrf0tebC65fYEeWgOrXOL6prn1/fegGOdTfrM6e34PJfksg==", + "license": "MIT", + "dependencies": { + "@types/luxon": "~3.7.0", + "luxon": "~3.7.0" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dayjs": { + "version": "1.11.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/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/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/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "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/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-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/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/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/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/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/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.278", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.278.tgz", + "integrity": "sha512-dQ0tM1svDRQOwxnXxm+twlGTjr9Upvt8UFWAgmLsxEzFQxhbti4VwxmMjsDxVC51Zo84swW7FVCXEV+VAkhuPw==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/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/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/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": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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/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/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/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/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/execa/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": "ISC" + }, + "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": { + "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/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/express/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/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/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-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-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/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "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-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==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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/finalhandler/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/finalhandler/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/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.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/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/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/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==", + "dev": true, + "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/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "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/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/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==", + "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", + "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/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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": { + "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==", + "dev": true, + "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/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "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": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "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": ">=8" + } + }, + "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", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/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": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/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": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.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": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "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": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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/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/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/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": ">=12.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-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", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-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", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-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/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-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/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-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": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-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": ">=0.10.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==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-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", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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": "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-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": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-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", + "engines": { + "node": ">=8.6" + }, + "funding": { + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/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": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/libphonenumber-js": { + "version": "1.12.35", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.35.tgz", + "integrity": "sha512-T/Cz6iLcsZdb5jDncDcUNhSAJ0VlSC9TnsqtBNdpkaAmy24/R1RhErtNWVWBrcUZKs9hSgaVsBkc7HxYnazIfw==", + "license": "MIT" + }, + "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/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": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "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/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": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "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" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/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": "Unlicense", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "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/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/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": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "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": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/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" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "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" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "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/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "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/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-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-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 + } + } + }, + "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/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/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": { + "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": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/path-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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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": { + "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": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.3.0" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", + "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.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" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "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, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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": ">=4" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", + "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/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": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "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/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/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": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-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/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/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": ">=8" + } + }, + "node_modules/restore-cursor/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": "ISC" + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/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/rimraf/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/rimraf/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/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", + "engines": { + "node": ">=0.12.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==", + "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/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": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "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", + "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/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": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "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/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" + }, + "engines": { + "node": ">=10" + } + }, + "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/send/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/send/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/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/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/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "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/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/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": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "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": { + "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==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/sql-highlight": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sql-highlight/-/sql-highlight-6.1.0.tgz", + "integrity": "sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA==", + "funding": [ + "https://github.com/scriptcoded/sql-highlight?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/scriptcoded" + } + ], + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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": { + "@tokenizer/token": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "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": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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": ">=0.10" + } + }, + "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": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "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": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "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/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": { + "@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" + }, + "engines": { + "node": ">= 10.13.0" + }, + "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/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": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.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": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "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": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "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/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.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/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": { + "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/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": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.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-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/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": ">=14.16" + }, + "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" + } + }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "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": { + "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.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/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ts-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": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths-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": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tapable": "^2.2.1", + "tsconfig-paths": "^4.1.2" + }, + "engines": { + "node": ">=10.13.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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/typeorm": { + "version": "0.3.28", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.28.tgz", + "integrity": "sha512-6GH7wXhtfq2D33ZuRXYwIsl/qM5685WZcODZb7noOOcRMteM9KF2x2ap3H0EBjnSV0VO4gNAfJT5Ukp0PkOlvg==", + "license": "MIT", + "dependencies": { + "@sqltools/formatter": "^1.2.5", + "ansis": "^4.2.0", + "app-root-path": "^3.1.0", + "buffer": "^6.0.3", + "dayjs": "^1.11.19", + "debug": "^4.4.3", + "dedent": "^1.7.0", + "dotenv": "^16.6.1", + "glob": "^10.5.0", + "reflect-metadata": "^0.2.2", + "sha.js": "^2.4.12", + "sql-highlight": "^6.1.0", + "tslib": "^2.8.1", + "uuid": "^11.1.0", + "yargs": "^17.7.2" + }, + "bin": { + "typeorm": "cli.js", + "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", + "typeorm-ts-node-esm": "cli-ts-node-esm.js" + }, + "engines": { + "node": ">=16.13.0" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@sap/hana-client": "^2.14.22", + "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0", + "ioredis": "^5.0.4", + "mongodb": "^5.8.0 || ^6.0.0", + "mssql": "^9.1.1 || ^10.0.0 || ^11.0.0 || ^12.0.0", + "mysql2": "^2.2.5 || ^3.0.1", + "oracledb": "^6.3.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1 || ^4.0.0 || ^5.0.14", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.3", + "ts-node": "^10.7.0", + "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" + }, + "peerDependenciesMeta": { + "@google-cloud/spanner": { + "optional": true + }, + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "ts-node": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/typeorm/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/typeorm/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/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/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "license": "MIT", + "dependencies": { + "@lukeed/csprng": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/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": ">= 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/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/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": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/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/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/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": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "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": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/webpack": { + "version": "5.104.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", + "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.4", + "es-module-lexer": "^2.0.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.3.1", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.16", + "watchpack": "^2.4.4", + "webpack-sources": "^3.3.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/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", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "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": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/write-file-atomic/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": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/microservices/achievement-service/package.json b/microservices/achievement-service/package.json new file mode 100644 index 0000000..ffa6599 --- /dev/null +++ b/microservices/achievement-service/package.json @@ -0,0 +1,89 @@ +{ + "name": "achievement-service", + "version": "0.0.1", + "description": "Achievement service for tracking, unlocking, and managing player achievements and badges", + "author": "", + "private": true, + "license": "UNLICENSED", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "node dist/main", + "lint": "eslint \"{src,test}/**/*.ts\" --fix", + "lint:check": "eslint \"{src,test}/**/*.ts\"", + "type-check": "tsc --noEmit", + "test": "jest", + "test:unit": "jest --testPathPattern=\\.spec\\.ts$", + "test:integration": "jest --testPathPattern=\\.integration\\.spec\\.ts$", + "test:e2e": "jest --config ./test/jest-e2e.json --testPathPattern=\\.e2e\\.spec\\.ts$", + "test:watch": "jest --watch", + "test:cov": "jest --coverage --testPathPattern=\\.spec\\.ts$", + "test:cov:integration": "jest --coverage --testPathPattern=\\.integration\\.spec\\.ts$", + "test:cov:e2e": "jest --coverage --config ./test/jest-e2e.json --testPathPattern=\\.e2e\\.spec\\.ts$", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "migration:generate": "ts-node ./node_modules/typeorm/cli -d ormconfig.ts migration:generate", + "migration:run": "ts-node ./node_modules/typeorm/cli -d ormconfig.ts migration:run", + "migration:revert": "ts-node ./node_modules/typeorm/cli -d ormconfig.ts migration:revert" + }, + "dependencies": { + "@nestjs/common": "^10.4.4", + "@nestjs/config": "^3.2.3", + "@nestjs/core": "^10.4.4", + "@nestjs/platform-express": "^10.4.4", + "@nestjs/schedule": "^6.0.0", + "@nestjs/typeorm": "^11.0.0", + "@quest-service/shared": "file:../shared", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.1", + "pg": "^8.16.3", + "reflect-metadata": "^0.1.14", + "rxjs": "^7.8.1", + "typeorm": "^0.3.25" + }, + "devDependencies": { + "@nestjs/cli": "^10.4.5", + "@nestjs/schematics": "^10.1.4", + "@nestjs/testing": "^10.4.4", + "@types/express": "^4.17.21", + "@types/jest": "^29.5.12", + "@types/node": "^20.14.15", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.0.0", + "@typescript-eslint/parser": "^8.0.0", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "jest": "^29.7.0", + "prettier": "^3.3.3", + "source-map-support": "^0.5.21", + "ts-jest": "^29.2.4", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.5.4" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "ts" + ], + "rootDir": "src", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/microservices/achievement-service/src/achievement/achievement.module.ts b/microservices/achievement-service/src/achievement/achievement.module.ts new file mode 100644 index 0000000..004001b --- /dev/null +++ b/microservices/achievement-service/src/achievement/achievement.module.ts @@ -0,0 +1,27 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { ConfigModule } from '@nestjs/config'; +import { Achievement } from './entities/achievement.entity'; +import { AchievementProgress } from './entities/achievement-progress.entity'; +import { Badge } from './entities/badge.entity'; +import { AchievementService } from './services/achievement.service'; +import { AchievementProgressService } from './services/achievement-progress.service'; +import { AchievementUnlockService } from './services/achievement-unlock.service'; +import { BadgeService } from './services/badge.service'; +import { AchievementHistoryService } from './services/achievement-history.service'; +import { AchievementNotificationService } from './services/achievement-notification.service'; +import { AchievementController } from './controllers/achievement.controller'; + +@Module({ + imports: [ConfigModule, TypeOrmModule.forFeature([Achievement, AchievementProgress, Badge])], + providers: [ + AchievementService, + AchievementProgressService, + AchievementUnlockService, + BadgeService, + AchievementHistoryService, + AchievementNotificationService, + ], + controllers: [AchievementController], +}) +export class AchievementModule {} diff --git a/microservices/achievement-service/src/achievement/controllers/achievement.controller.ts b/microservices/achievement-service/src/achievement/controllers/achievement.controller.ts new file mode 100644 index 0000000..9bb1ac5 --- /dev/null +++ b/microservices/achievement-service/src/achievement/controllers/achievement.controller.ts @@ -0,0 +1,28 @@ +import { Controller, Get, Param } from '@nestjs/common'; +import { AchievementService } from '../services/achievement.service'; +import { AchievementProgressService } from '../services/achievement-progress.service'; +import { AchievementHistoryService } from '../services/achievement-history.service'; + +@Controller() +export class AchievementController { + constructor( + private readonly achievementService: AchievementService, + private readonly progressService: AchievementProgressService, + private readonly historyService: AchievementHistoryService, + ) {} + + @Get('achievements') + getAchievements() { + return this.achievementService.findAll(); + } + + @Get('users/:userId/achievements') + getUserAchievements(@Param('userId') userId: string) { + return this.progressService.getUserProgress(userId); + } + + @Get('users/:userId/achievement-history') + getUserAchievementHistory(@Param('userId') userId: string) { + return this.historyService.getUserHistory(userId); + } +} diff --git a/microservices/achievement-service/src/achievement/entities/achievement-progress.entity.ts b/microservices/achievement-service/src/achievement/entities/achievement-progress.entity.ts new file mode 100644 index 0000000..d8cffbc --- /dev/null +++ b/microservices/achievement-service/src/achievement/entities/achievement-progress.entity.ts @@ -0,0 +1,30 @@ +import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, Unique, UpdateDateColumn } from 'typeorm'; +import { Achievement } from './achievement.entity'; + +@Entity({ name: 'achievement_progress' }) +@Unique(['userId', 'achievement']) +export class AchievementProgress { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + userId: string; + + @ManyToOne(() => Achievement, { eager: true }) + achievement: Achievement; + + @Column({ type: 'integer', default: 0 }) + currentValue: number; + + @Column({ default: false }) + isUnlocked: boolean; + + @Column({ type: 'timestamp', nullable: true }) + unlockedAt?: Date | null; + + @CreateDateColumn() + createdAt: Date; + + @UpdateDateColumn() + lastUpdatedAt: Date; +} diff --git a/microservices/achievement-service/src/achievement/entities/achievement.entity.ts b/microservices/achievement-service/src/achievement/entities/achievement.entity.ts new file mode 100644 index 0000000..8c871c8 --- /dev/null +++ b/microservices/achievement-service/src/achievement/entities/achievement.entity.ts @@ -0,0 +1,45 @@ +import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; + +export enum AchievementRarity { + COMMON = 'COMMON', + UNCOMMON = 'UNCOMMON', + RARE = 'RARE', + EPIC = 'EPIC', + LEGENDARY = 'LEGENDARY', +} + +@Entity({ name: 'achievements' }) +export class Achievement { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ unique: true }) + code: string; + + @Column() + name: string; + + @Column({ type: 'text' }) + description: string; + + @Column({ nullable: true }) + category: string; + + @Column({ type: 'enum', enum: AchievementRarity, default: AchievementRarity.COMMON }) + rarity: AchievementRarity; + + @Column({ type: 'varchar' }) + metric: string; // e.g. PUZZLES_COMPLETED + + @Column({ type: 'integer', default: 1 }) + targetValue: number; + + @Column({ default: true }) + isActive: boolean; + + @CreateDateColumn() + createdAt: Date; + + @UpdateDateColumn() + updatedAt: Date; +} diff --git a/microservices/achievement-service/src/achievement/entities/badge.entity.ts b/microservices/achievement-service/src/achievement/entities/badge.entity.ts new file mode 100644 index 0000000..c36df10 --- /dev/null +++ b/microservices/achievement-service/src/achievement/entities/badge.entity.ts @@ -0,0 +1,27 @@ +import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, Unique } from 'typeorm'; +import { Achievement, AchievementRarity } from './achievement.entity'; + +@Entity({ name: 'badges' }) +@Unique(['userId', 'achievement']) +export class Badge { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + userId: string; + + @ManyToOne(() => Achievement, { eager: true }) + achievement: Achievement; + + @Column() + name: string; + + @Column({ type: 'enum', enum: AchievementRarity }) + rarity: AchievementRarity; + + @Column({ nullable: true }) + iconUrl?: string; + + @CreateDateColumn() + awardedAt: Date; +} diff --git a/microservices/achievement-service/src/achievement/services/achievement-history.service.ts b/microservices/achievement-service/src/achievement/services/achievement-history.service.ts new file mode 100644 index 0000000..59277da --- /dev/null +++ b/microservices/achievement-service/src/achievement/services/achievement-history.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Badge } from '../entities/badge.entity'; + +@Injectable() +export class AchievementHistoryService { + constructor( + @InjectRepository(Badge) + private readonly badgeRepo: Repository, + ) {} + + async getUserHistory(userId: string): Promise { + return this.badgeRepo.find({ + where: { userId }, + order: { awardedAt: 'DESC' }, + }); + } +} diff --git a/microservices/achievement-service/src/achievement/services/achievement-notification.service.ts b/microservices/achievement-service/src/achievement/services/achievement-notification.service.ts new file mode 100644 index 0000000..a5a436e --- /dev/null +++ b/microservices/achievement-service/src/achievement/services/achievement-notification.service.ts @@ -0,0 +1,15 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { Achievement } from '../entities/achievement.entity'; +import { Badge } from '../entities/badge.entity'; + +@Injectable() +export class AchievementNotificationService { + private readonly logger = new Logger(AchievementNotificationService.name); + + async notifyUnlock(userId: string, achievement: Achievement, badge: Badge): Promise { + // TODO: Integrate with real notification infrastructure (e.g., event bus or notification-service) + this.logger.log( + `Notification: user ${userId} unlocked achievement ${achievement.code} (${achievement.name}), badge ${badge.id}`, + ); + } +} diff --git a/microservices/achievement-service/src/achievement/services/achievement-progress.service.ts b/microservices/achievement-service/src/achievement/services/achievement-progress.service.ts new file mode 100644 index 0000000..45f2bda --- /dev/null +++ b/microservices/achievement-service/src/achievement/services/achievement-progress.service.ts @@ -0,0 +1,47 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Achievement } from '../entities/achievement.entity'; +import { AchievementProgress } from '../entities/achievement-progress.entity'; +import { AchievementUnlockService } from './achievement-unlock.service'; + +@Injectable() +export class AchievementProgressService { + constructor( + @InjectRepository(Achievement) + private readonly achievementRepo: Repository, + @InjectRepository(AchievementProgress) + private readonly progressRepo: Repository, + private readonly unlockService: AchievementUnlockService, + ) {} + + /** + * Record progress for a user on all achievements that track the given metric. + */ + async recordProgress(userId: string, metric: string, increment: number): Promise { + const achievements = await this.achievementRepo.find({ where: { metric, isActive: true } }); + if (!achievements.length) return; + + for (const achievement of achievements) { + let progress = await this.progressRepo.findOne({ where: { userId, achievement: { id: achievement.id } } }); + + if (!progress) { + progress = this.progressRepo.create({ + userId, + achievement, + currentValue: 0, + isUnlocked: false, + }); + } + + progress.currentValue += increment; + await this.progressRepo.save(progress); + + await this.unlockService.evaluateAndUnlock(progress); + } + } + + async getUserProgress(userId: string): Promise { + return this.progressRepo.find({ where: { userId } }); + } +} diff --git a/microservices/achievement-service/src/achievement/services/achievement-unlock.service.ts b/microservices/achievement-service/src/achievement/services/achievement-unlock.service.ts new file mode 100644 index 0000000..aeeb3c7 --- /dev/null +++ b/microservices/achievement-service/src/achievement/services/achievement-unlock.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { AchievementProgress } from '../entities/achievement-progress.entity'; +import { BadgeService } from './badge.service'; +import { AchievementNotificationService } from './achievement-notification.service'; + +@Injectable() +export class AchievementUnlockService { + constructor( + @InjectRepository(AchievementProgress) + private readonly progressRepo: Repository, + private readonly badgeService: BadgeService, + private readonly notificationService: AchievementNotificationService, + ) {} + + async evaluateAndUnlock(progress: AchievementProgress): Promise { + const { achievement } = progress; + + if (progress.isUnlocked) { + return; + } + + if (progress.currentValue >= achievement.targetValue) { + progress.isUnlocked = true; + progress.unlockedAt = new Date(); + await this.progressRepo.save(progress); + + const badge = await this.badgeService.awardBadge(progress.userId, achievement); + + await this.notificationService.notifyUnlock(progress.userId, achievement, badge); + } + } +} diff --git a/microservices/achievement-service/src/achievement/services/achievement.service.ts b/microservices/achievement-service/src/achievement/services/achievement.service.ts new file mode 100644 index 0000000..9f34e1d --- /dev/null +++ b/microservices/achievement-service/src/achievement/services/achievement.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Achievement } from '../entities/achievement.entity'; + +@Injectable() +export class AchievementService { + constructor( + @InjectRepository(Achievement) + private readonly achievementRepo: Repository, + ) {} + + findAll(): Promise { + return this.achievementRepo.find(); + } + + findByCode(code: string): Promise { + return this.achievementRepo.findOne({ where: { code } }); + } + + async upsert(achievement: Partial): Promise { + const existing = achievement.code + ? await this.achievementRepo.findOne({ where: { code: achievement.code } }) + : null; + + if (existing) { + Object.assign(existing, achievement); + return this.achievementRepo.save(existing); + } + + const created = this.achievementRepo.create(achievement); + return this.achievementRepo.save(created); + } +} diff --git a/microservices/achievement-service/src/achievement/services/badge.service.ts b/microservices/achievement-service/src/achievement/services/badge.service.ts new file mode 100644 index 0000000..2f2cb8a --- /dev/null +++ b/microservices/achievement-service/src/achievement/services/badge.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Badge } from '../entities/badge.entity'; +import { Achievement } from '../entities/achievement.entity'; + +@Injectable() +export class BadgeService { + constructor( + @InjectRepository(Badge) + private readonly badgeRepo: Repository, + ) {} + + async awardBadge(userId: string, achievement: Achievement): Promise { + const existing = await this.badgeRepo.findOne({ where: { userId, achievement: { id: achievement.id } } }); + if (existing) { + return existing; + } + + const badge = this.badgeRepo.create({ + userId, + achievement, + name: achievement.name, + rarity: achievement.rarity, + }); + + return this.badgeRepo.save(badge); + } + + async getUserBadges(userId: string): Promise { + return this.badgeRepo.find({ where: { userId } }); + } +} diff --git a/microservices/achievement-service/src/app.module.ts b/microservices/achievement-service/src/app.module.ts new file mode 100644 index 0000000..782e7d4 --- /dev/null +++ b/microservices/achievement-service/src/app.module.ts @@ -0,0 +1,26 @@ +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { ScheduleModule } from '@nestjs/schedule'; +import { AchievementModule } from './achievement/achievement.module'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + }), + TypeOrmModule.forRoot({ + type: 'postgres', + host: process.env.DB_HOST || 'localhost', + port: parseInt(process.env.DB_PORT || '5432'), + username: process.env.DB_USERNAME || 'postgres', + password: process.env.DB_PASSWORD || 'password', + database: process.env.DB_NAME || 'quest_achievement', + autoLoadEntities: true, + synchronize: process.env.NODE_ENV !== 'production', + }), + ScheduleModule.forRoot(), + AchievementModule, + ], +}) +export class AppModule {} diff --git a/microservices/achievement-service/src/energy/energy-regeneration.service.ts b/microservices/achievement-service/src/energy/energy-regeneration.service.ts new file mode 100644 index 0000000..0258f4d --- /dev/null +++ b/microservices/achievement-service/src/energy/energy-regeneration.service.ts @@ -0,0 +1,105 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { Cron } from '@nestjs/schedule'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository, LessThan } from 'typeorm'; +import { UserEnergy, EnergyType } from './energy.entity'; + +@Injectable() +export class EnergyRegenerationService { + private readonly logger = new Logger(EnergyRegenerationService.name); + + constructor( + @InjectRepository(UserEnergy) + private readonly energyRepository: Repository, + ) {} + + @Cron('*/30 * * * * *') + async regenerateEnergy(): Promise { + try { + const now = new Date(); + const thirtySecondsAgo = new Date(now.getTime() - 30 * 1000); + + const usersNeedingRegeneration = await this.energyRepository.find({ + where: { + currentAmount: LessThan(999), + lastRegenerationTime: LessThan(thirtySecondsAgo), + }, + }); + + for (const userEnergy of usersNeedingRegeneration) { + await this.regenerateUserEnergy(userEnergy); + } + + if (usersNeedingRegeneration.length > 0) { + this.logger.log( + `Regenerated energy for ${usersNeedingRegeneration.length} users`, + ); + } + } catch (error) { + this.logger.error('Error during energy regeneration:', error); + } + } + + async regenerateUserEnergy(userEnergy: UserEnergy): Promise { + const now = new Date(); + const timeDiffInSeconds = Math.floor( + (now.getTime() - userEnergy.lastRegenerationTime.getTime()) / 1000, + ); + + if (timeDiffInSeconds >= userEnergy.regenerationInterval) { + const intervalsPassed = Math.floor( + timeDiffInSeconds / userEnergy.regenerationInterval, + ); + const energyToRegenerate = intervalsPassed * userEnergy.regenerationRate; + + userEnergy.currentAmount = Math.min( + userEnergy.currentAmount + energyToRegenerate, + userEnergy.maxAmount, + ); + + userEnergy.lastRegenerationTime = new Date( + userEnergy.lastRegenerationTime.getTime() + + intervalsPassed * userEnergy.regenerationInterval * 1000, + ); + + return this.energyRepository.save(userEnergy); + } + + return userEnergy; + } + + async getEnergyRegenerationStatus( + userId: string, + energyType: EnergyType = EnergyType.ENERGY, + ): Promise<{ + currentAmount: number; + maxAmount: number; + timeToNextRegeneration: number; + regenerationRate: number; + }> { + const userEnergy = await this.energyRepository.findOne({ + where: { userId, energyType }, + }); + + if (!userEnergy) { + throw new Error('User energy not found'); + } + + const now = new Date(); + const timeSinceLastRegeneration = Math.floor( + (now.getTime() - userEnergy.lastRegenerationTime.getTime()) / 1000, + ); + + const timeToNextRegeneration = Math.max( + 0, + userEnergy.regenerationInterval - timeSinceLastRegeneration, + ); + + return { + currentAmount: userEnergy.currentAmount, + maxAmount: userEnergy.maxAmount, + timeToNextRegeneration, + regenerationRate: userEnergy.regenerationRate, + }; + } +} diff --git a/microservices/achievement-service/src/energy/energy.controller.ts b/microservices/achievement-service/src/energy/energy.controller.ts new file mode 100644 index 0000000..c7744e4 --- /dev/null +++ b/microservices/achievement-service/src/energy/energy.controller.ts @@ -0,0 +1,105 @@ +import { + Controller, + Get, + Post, + Put, + Param, + Body, + HttpCode, + HttpStatus, +} from '@nestjs/common'; +import { EnergyService } from './energy.service'; +import { EnergyRegenerationService } from './energy-regeneration.service'; +import { EnergyType } from './energy.entity'; + +export class ConsumeEnergyDto { + amount: number; + energyType?: EnergyType = EnergyType.ENERGY; +} + +export class AddEnergyDto { + amount: number; + energyType?: EnergyType = EnergyType.ENERGY; +} + +export class UpdateMaxEnergyDto { + maxAmount: number; + energyType?: EnergyType = EnergyType.ENERGY; +} + +@Controller('energy') +export class EnergyController { + constructor( + private readonly energyService: EnergyService, + private readonly energyRegenerationService: EnergyRegenerationService, + ) {} + + @Get(':userId') + async getUserEnergy( + @Param('userId') userId: string, + @Body() body: { energyType?: EnergyType }, + ) { + const energyType = body.energyType || EnergyType.ENERGY; + return this.energyService.getUserEnergy(userId, energyType); + } + + @Get(':userId/status') + async getEnergyStatus( + @Param('userId') userId: string, + @Body() body: { energyType?: EnergyType }, + ) { + const energyType = body.energyType || EnergyType.ENERGY; + return this.energyRegenerationService.getEnergyRegenerationStatus( + userId, + energyType, + ); + } + + @Post(':userId/consume') + @HttpCode(HttpStatus.OK) + async consumeEnergy( + @Param('userId') userId: string, + @Body() consumeEnergyDto: ConsumeEnergyDto, + ) { + return this.energyService.consumeEnergy( + userId, + consumeEnergyDto.amount, + consumeEnergyDto.energyType, + ); + } + + @Post(':userId/add') + @HttpCode(HttpStatus.OK) + async addEnergy( + @Param('userId') userId: string, + @Body() addEnergyDto: AddEnergyDto, + ) { + return this.energyService.addEnergy( + userId, + addEnergyDto.amount, + addEnergyDto.energyType, + ); + } + + @Post(':userId/refill') + @HttpCode(HttpStatus.OK) + async refillEnergy( + @Param('userId') userId: string, + @Body() body: { energyType?: EnergyType }, + ) { + const energyType = body.energyType || EnergyType.ENERGY; + return this.energyService.refillEnergy(userId, energyType); + } + + @Put(':userId/max') + async updateMaxEnergy( + @Param('userId') userId: string, + @Body() updateMaxEnergyDto: UpdateMaxEnergyDto, + ) { + return this.energyService.updateMaxEnergy( + userId, + updateMaxEnergyDto.maxAmount, + updateMaxEnergyDto.energyType, + ); + } +} diff --git a/microservices/achievement-service/src/energy/energy.entity.ts b/microservices/achievement-service/src/energy/energy.entity.ts new file mode 100644 index 0000000..43edaf4 --- /dev/null +++ b/microservices/achievement-service/src/energy/energy.entity.ts @@ -0,0 +1,49 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, +} from 'typeorm'; + +export enum EnergyType { + STAMINA = 'stamina', + ENERGY = 'energy', +} + +@Entity('user_energy') +export class UserEnergy { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + userId: string; + + @Column({ + type: 'enum', + enum: EnergyType, + default: EnergyType.ENERGY, + }) + energyType: EnergyType; + + @Column({ default: 100 }) + currentAmount: number; + + @Column({ default: 100 }) + maxAmount: number; + + @Column({ type: 'timestamp', nullable: true }) + lastRegenerationTime: Date; + + @Column({ default: 300 }) + regenerationRate: number; + + @Column({ default: 60 }) + regenerationInterval: number; + + @CreateDateColumn() + createdAt: Date; + + @UpdateDateColumn() + updatedAt: Date; +} diff --git a/microservices/achievement-service/src/energy/energy.module.ts b/microservices/achievement-service/src/energy/energy.module.ts new file mode 100644 index 0000000..f618649 --- /dev/null +++ b/microservices/achievement-service/src/energy/energy.module.ts @@ -0,0 +1,14 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { UserEnergy } from './energy.entity'; +import { EnergyService } from './energy.service'; +import { EnergyController } from './energy.controller'; +import { EnergyRegenerationService } from './energy-regeneration.service'; + +@Module({ + imports: [TypeOrmModule.forFeature([UserEnergy])], + controllers: [EnergyController], + providers: [EnergyService, EnergyRegenerationService], + exports: [EnergyService], +}) +export class EnergyModule {} diff --git a/microservices/achievement-service/src/energy/energy.service.ts b/microservices/achievement-service/src/energy/energy.service.ts new file mode 100644 index 0000000..0c203c7 --- /dev/null +++ b/microservices/achievement-service/src/energy/energy.service.ts @@ -0,0 +1,90 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { UserEnergy, EnergyType } from './energy.entity'; + +@Injectable() +export class EnergyService { + constructor( + @InjectRepository(UserEnergy) + private readonly energyRepository: Repository, + ) {} + + async getUserEnergy( + userId: string, + energyType: EnergyType = EnergyType.ENERGY, + ): Promise { + let userEnergy = await this.energyRepository.findOne({ + where: { userId, energyType }, + }); + + if (!userEnergy) { + userEnergy = this.energyRepository.create({ + userId, + energyType, + currentAmount: 100, + maxAmount: 100, + regenerationRate: 300, + regenerationInterval: 60, + lastRegenerationTime: new Date(), + }); + await this.energyRepository.save(userEnergy); + } + + return userEnergy; + } + + async consumeEnergy( + userId: string, + amount: number, + energyType: EnergyType = EnergyType.ENERGY, + ): Promise { + const userEnergy = await this.getUserEnergy(userId, energyType); + + if (userEnergy.currentAmount < amount) { + throw new Error('Insufficient energy'); + } + + userEnergy.currentAmount -= amount; + return this.energyRepository.save(userEnergy); + } + + async addEnergy( + userId: string, + amount: number, + energyType: EnergyType = EnergyType.ENERGY, + ): Promise { + const userEnergy = await this.getUserEnergy(userId, energyType); + + userEnergy.currentAmount = Math.min( + userEnergy.currentAmount + amount, + userEnergy.maxAmount, + ); + return this.energyRepository.save(userEnergy); + } + + async refillEnergy( + userId: string, + energyType: EnergyType = EnergyType.ENERGY, + ): Promise { + const userEnergy = await this.getUserEnergy(userId, energyType); + userEnergy.currentAmount = userEnergy.maxAmount; + userEnergy.lastRegenerationTime = new Date(); + return this.energyRepository.save(userEnergy); + } + + async updateMaxEnergy( + userId: string, + maxAmount: number, + energyType: EnergyType = EnergyType.ENERGY, + ): Promise { + const userEnergy = await this.getUserEnergy(userId, energyType); + userEnergy.maxAmount = maxAmount; + + if (userEnergy.currentAmount > maxAmount) { + userEnergy.currentAmount = maxAmount; + } + + return this.energyRepository.save(userEnergy); + } +} diff --git a/microservices/achievement-service/src/main.ts b/microservices/achievement-service/src/main.ts new file mode 100644 index 0000000..39c4d46 --- /dev/null +++ b/microservices/achievement-service/src/main.ts @@ -0,0 +1,23 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; +import { ValidationPipe } from '@nestjs/common'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + whitelist: true, + forbidNonWhitelisted: true, + }), + ); + + app.enableCors(); + + const port = process.env.PORT || 3006; + await app.listen(port); + + console.log(`Achievement Service is running on port ${port}`); +} +bootstrap(); diff --git a/microservices/achievement-service/src/payment/payment.controller.ts b/microservices/achievement-service/src/payment/payment.controller.ts new file mode 100644 index 0000000..2ee9977 --- /dev/null +++ b/microservices/achievement-service/src/payment/payment.controller.ts @@ -0,0 +1,40 @@ +import { + Controller, + Post, + Get, + Body, + Param, + HttpCode, + HttpStatus, +} from '@nestjs/common'; +import { PaymentService, PaymentData } from './payment.service'; + +@Controller('payment') +export class PaymentController { + constructor(private readonly paymentService: PaymentService) {} + + @Get('providers') + getAvailableProviders() { + return { + providers: this.paymentService.getAvailableProviders(), + }; + } + + @Post(':provider/process') + @HttpCode(HttpStatus.OK) + async processPayment( + @Body() paymentData: PaymentData, + @Param('provider') provider: string, + ) { + return this.paymentService.processPayment(provider, paymentData); + } + + @Post(':provider/refund') + @HttpCode(HttpStatus.OK) + async refundPayment( + @Body() body: { transactionId: string }, + @Param('provider') provider: string, + ) { + return this.paymentService.refundPayment(provider, body.transactionId); + } +} diff --git a/microservices/achievement-service/src/payment/payment.module.ts b/microservices/achievement-service/src/payment/payment.module.ts new file mode 100644 index 0000000..7bbf754 --- /dev/null +++ b/microservices/achievement-service/src/payment/payment.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { PaymentService } from './payment.service'; +import { PaymentController } from './payment.controller'; + +@Module({ + controllers: [PaymentController], + providers: [PaymentService], + exports: [PaymentService], +}) +export class PaymentModule {} diff --git a/microservices/achievement-service/src/payment/payment.service.ts b/microservices/achievement-service/src/payment/payment.service.ts new file mode 100644 index 0000000..09ad360 --- /dev/null +++ b/microservices/achievement-service/src/payment/payment.service.ts @@ -0,0 +1,181 @@ +import { Injectable, Logger } from '@nestjs/common'; + +export interface PaymentProvider { + processPayment(paymentData: PaymentData): Promise; + refundPayment(transactionId: string): Promise; +} + +export interface PaymentData { + amount: number; + currency: string; + userId: string; + description?: string; + metadata?: Record; + paymentMethod: string; +} + +export interface PaymentResult { + success: boolean; + transactionId?: string; + error?: string; + metadata?: Record; +} + +export interface RefundResult { + success: boolean; + refundId?: string; + error?: string; +} + +@Injectable() +export class PaymentService { + private readonly logger = new Logger(PaymentService.name); + private providers: Map = new Map(); + + constructor() { + this.initializeProviders(); + } + + private initializeProviders(): void { + this.providers.set('stripe', new StripePaymentProvider()); + this.providers.set('paypal', new PayPalPaymentProvider()); + } + + async processPayment( + providerName: string, + paymentData: PaymentData, + ): Promise { + const provider = this.providers.get(providerName); + + if (!provider) { + throw new Error(`Payment provider ${providerName} not found`); + } + + try { + this.logger.log( + `Processing payment with ${providerName} for user ${paymentData.userId}`, + ); + const result = await provider.processPayment(paymentData); + + if (result.success) { + this.logger.log( + `Payment successful with transaction ID: ${result.transactionId}`, + ); + } else { + this.logger.error(`Payment failed: ${result.error}`); + } + + return result; + } catch (error) { + this.logger.error(`Payment processing error:`, error); + throw error; + } + } + + async refundPayment( + providerName: string, + transactionId: string, + ): Promise { + const provider = this.providers.get(providerName); + + if (!provider) { + throw new Error(`Payment provider ${providerName} not found`); + } + + try { + this.logger.log(`Processing refund for transaction ${transactionId}`); + const result = await provider.refundPayment(transactionId); + + if (result.success) { + this.logger.log(`Refund successful with refund ID: ${result.refundId}`); + } else { + this.logger.error(`Refund failed: ${result.error}`); + } + + return result; + } catch (error) { + this.logger.error(`Refund processing error:`, error); + throw error; + } + } + + getAvailableProviders(): string[] { + return Array.from(this.providers.keys()); + } +} + +class StripePaymentProvider implements PaymentProvider { + async processPayment(paymentData: PaymentData): Promise { + await new Promise((resolve) => setTimeout(resolve, 1000)); + + if (Math.random() > 0.1) { + return { + success: true, + transactionId: `stripe_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, + metadata: { + provider: 'stripe', + processedAt: new Date().toISOString(), + }, + }; + } else { + return { + success: false, + error: 'Insufficient funds', + }; + } + } + + async refundPayment(transactionId: string): Promise { + await new Promise((resolve) => setTimeout(resolve, 500)); + + if (Math.random() > 0.05) { + return { + success: true, + refundId: `stripe_refund_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, + }; + } else { + return { + success: false, + error: 'Refund period expired', + }; + } + } +} + +class PayPalPaymentProvider implements PaymentProvider { + async processPayment(paymentData: PaymentData): Promise { + await new Promise((resolve) => setTimeout(resolve, 1500)); + + if (Math.random() > 0.15) { + return { + success: true, + transactionId: `paypal_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, + metadata: { + provider: 'paypal', + processedAt: new Date().toISOString(), + }, + }; + } else { + return { + success: false, + error: 'Payment declined', + }; + } + } + + async refundPayment(transactionId: string): Promise { + await new Promise((resolve) => setTimeout(resolve, 700)); + + if (Math.random() > 0.08) { + return { + success: true, + refundId: `paypal_refund_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, + }; + } else { + return { + success: false, + error: 'Transaction not refundable', + }; + } + } +} diff --git a/microservices/achievement-service/src/shop/shop-item.entity.ts b/microservices/achievement-service/src/shop/shop-item.entity.ts new file mode 100644 index 0000000..3956450 --- /dev/null +++ b/microservices/achievement-service/src/shop/shop-item.entity.ts @@ -0,0 +1,72 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, +} from 'typeorm'; + +export enum ShopItemType { + HINT = 'hint', + POWER_UP = 'power_up', + COSMETIC = 'cosmetic', + ENERGY_REFILL = 'energy_refill', +} + +export enum ShopItemStatus { + ACTIVE = 'active', + INACTIVE = 'inactive', + LIMITED = 'limited', +} + +@Entity('shop_items') +export class ShopItem { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + name: string; + + @Column({ nullable: true }) + description: string; + + @Column({ + type: 'enum', + enum: ShopItemType, + }) + itemType: ShopItemType; + + @Column({ type: 'decimal', precision: 10, scale: 2 }) + price: number; + + @Column({ default: 'coins' }) + currency: string; + + @Column({ + type: 'enum', + enum: ShopItemStatus, + default: ShopItemStatus.ACTIVE, + }) + status: ShopItemStatus; + + @Column({ nullable: true }) + imageUrl: string; + + @Column({ type: 'jsonb', nullable: true }) + metadata: Record; + + @Column({ nullable: true }) + maxPurchaseLimit: number; + + @Column({ default: 0 }) + currentPurchaseCount: number; + + @Column({ type: 'timestamp', nullable: true }) + expiresAt: Date; + + @CreateDateColumn() + createdAt: Date; + + @UpdateDateColumn() + updatedAt: Date; +} diff --git a/microservices/achievement-service/src/shop/shop.controller.ts b/microservices/achievement-service/src/shop/shop.controller.ts new file mode 100644 index 0000000..9e67c4d --- /dev/null +++ b/microservices/achievement-service/src/shop/shop.controller.ts @@ -0,0 +1,85 @@ +import { + Controller, + Get, + Post, + Put, + Delete, + Param, + Body, + HttpCode, + HttpStatus, +} from '@nestjs/common'; +import { + ShopService, + CreateShopItemDto, + UpdateShopItemDto, +} from './shop.service'; +import { ShopItemStatus, ShopItemType } from './shop-item.entity'; + +@Controller('shop') +export class ShopController { + constructor(private readonly shopService: ShopService) {} + + @Post() + async createShopItem(@Body() createShopItemDto: CreateShopItemDto) { + return this.shopService.createShopItem(createShopItemDto); + } + + @Get() + async getAllShopItems(@Body() body: { status?: ShopItemStatus }) { + return this.shopService.getAllShopItems(body.status); + } + + @Get('type/:itemType') + async getShopItemsByType(@Param('itemType') itemType: ShopItemType) { + return this.shopService.getShopItemsByType(itemType); + } + + @Get('hints') + async getHintItems() { + return this.shopService.getHintItems(); + } + + @Get('energy-refills') + async getEnergyRefillItems() { + return this.shopService.getEnergyRefillItems(); + } + + @Get('power-ups') + async getPowerUpItems() { + return this.shopService.getPowerUpItems(); + } + + @Get('cosmetics') + async getCosmeticItems() { + return this.shopService.getCosmeticItems(); + } + + @Get(':id') + async getShopItemById(@Param('id') id: string) { + return this.shopService.getShopItemById(id); + } + + @Put(':id') + async updateShopItem( + @Param('id') id: string, + @Body() updateShopItemDto: UpdateShopItemDto, + ) { + return this.shopService.updateShopItem(id, updateShopItemDto); + } + + @Delete(':id') + @HttpCode(HttpStatus.NO_CONTENT) + async deleteShopItem(@Param('id') id: string) { + return this.shopService.deleteShopItem(id); + } + + @Post(':shopItemId/purchase') + @HttpCode(HttpStatus.OK) + async purchaseShopItem( + @Param('shopItemId') shopItemId: string, + @Body() body: { userId: string }, + ) { + return this.shopService.purchaseShopItem(body.userId, shopItemId); + } +} diff --git a/microservices/achievement-service/src/shop/shop.module.ts b/microservices/achievement-service/src/shop/shop.module.ts new file mode 100644 index 0000000..d8f79dd --- /dev/null +++ b/microservices/achievement-service/src/shop/shop.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { ShopItem } from './shop-item.entity'; +import { ShopService } from './shop.service'; +import { ShopController } from './shop.controller'; + +@Module({ + imports: [TypeOrmModule.forFeature([ShopItem])], + controllers: [ShopController], + providers: [ShopService], + exports: [ShopService], +}) +export class ShopModule {} diff --git a/microservices/achievement-service/src/shop/shop.service.ts b/microservices/achievement-service/src/shop/shop.service.ts new file mode 100644 index 0000000..6690bda --- /dev/null +++ b/microservices/achievement-service/src/shop/shop.service.ts @@ -0,0 +1,147 @@ +import { + Injectable, + NotFoundException, + BadRequestException, +} from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { ShopItem, ShopItemType, ShopItemStatus } from './shop-item.entity'; + +export class CreateShopItemDto { + name: string; + description?: string; + itemType: ShopItemType; + price: number; + currency?: string; + imageUrl?: string; + metadata?: Record; + maxPurchaseLimit?: number; + expiresAt?: Date; +} + +export class UpdateShopItemDto { + name?: string; + description?: string; + itemType?: ShopItemType; + price?: number; + currency?: string; + status?: ShopItemStatus; + imageUrl?: string; + metadata?: Record; + maxPurchaseLimit?: number; + expiresAt?: Date; +} + +@Injectable() +export class ShopService { + constructor( + @InjectRepository(ShopItem) + private readonly shopItemRepository: Repository, + ) {} + + async createShopItem( + createShopItemDto: CreateShopItemDto, + ): Promise { + const shopItem = this.shopItemRepository.create(createShopItemDto); + return this.shopItemRepository.save(shopItem); + } + + async getAllShopItems(status?: ShopItemStatus): Promise { + const whereClause = status ? { status } : {}; + return this.shopItemRepository.find({ + where: whereClause, + order: { createdAt: 'ASC' }, + }); + } + + async getShopItemById(id: string): Promise { + const shopItem = await this.shopItemRepository.findOne({ where: { id } }); + if (!shopItem) { + throw new NotFoundException(`Shop item with ID ${id} not found`); + } + return shopItem; + } + + async getShopItemsByType(itemType: ShopItemType): Promise { + return this.shopItemRepository.find({ + where: { itemType, status: ShopItemStatus.ACTIVE }, + order: { createdAt: 'ASC' }, + }); + } + + async updateShopItem( + id: string, + updateShopItemDto: UpdateShopItemDto, + ): Promise { + const shopItem = await this.getShopItemById(id); + Object.assign(shopItem, updateShopItemDto); + return this.shopItemRepository.save(shopItem); + } + + async deleteShopItem(id: string): Promise { + const shopItem = await this.getShopItemById(id); + await this.shopItemRepository.remove(shopItem); + } + + async purchaseShopItem( + userId: string, + shopItemId: string, + ): Promise<{ + shopItem: ShopItem; + canPurchase: boolean; + reason?: string; + }> { + const shopItem = await this.getShopItemById(shopItemId); + + if (shopItem.status !== ShopItemStatus.ACTIVE) { + return { + shopItem, + canPurchase: false, + reason: 'Item is not available for purchase', + }; + } + + if (shopItem.expiresAt && new Date() > shopItem.expiresAt) { + return { + shopItem, + canPurchase: false, + reason: 'Item has expired', + }; + } + + if ( + shopItem.maxPurchaseLimit && + shopItem.currentPurchaseCount >= shopItem.maxPurchaseLimit + ) { + return { + shopItem, + canPurchase: false, + reason: 'Purchase limit reached', + }; + } + + shopItem.currentPurchaseCount += 1; + await this.shopItemRepository.save(shopItem); + + return { + shopItem, + canPurchase: true, + }; + } + + async getHintItems(): Promise { + return this.getShopItemsByType(ShopItemType.HINT); + } + + async getEnergyRefillItems(): Promise { + return this.getShopItemsByType(ShopItemType.ENERGY_REFILL); + } + + async getPowerUpItems(): Promise { + return this.getShopItemsByType(ShopItemType.POWER_UP); + } + + async getCosmeticItems(): Promise { + return this.getShopItemsByType(ShopItemType.COSMETIC); + } +} diff --git a/microservices/achievement-service/src/transaction/transaction.controller.ts b/microservices/achievement-service/src/transaction/transaction.controller.ts new file mode 100644 index 0000000..f2d0f44 --- /dev/null +++ b/microservices/achievement-service/src/transaction/transaction.controller.ts @@ -0,0 +1,173 @@ +import { + Controller, + Get, + Post, + Put, + Param, + Body, + HttpCode, + HttpStatus, +} from '@nestjs/common'; +import { + TransactionService, + CreateTransactionDto, + UpdateTransactionStatusDto, +} from './transaction.service'; +import { + TransactionType, + TransactionStatus, + CurrencyType, +} from './transaction.entity'; + +@Controller('transactions') +export class TransactionController { + constructor(private readonly transactionService: TransactionService) {} + + @Post() + async createTransaction(@Body() createTransactionDto: CreateTransactionDto) { + return this.transactionService.createTransaction(createTransactionDto); + } + + @Get(':id') + async getTransactionById(@Param('id') id: string) { + return this.transactionService.getTransactionById(id); + } + + @Get('user/:userId') + async getUserTransactions( + @Param('userId') userId: string, + @Body() + body: { + type?: TransactionType; + status?: TransactionStatus; + currency?: CurrencyType; + limit?: number; + offset?: number; + }, + ) { + return this.transactionService.getUserTransactions(userId, body); + } + + @Get('user/:userId/balance/:currency') + async getUserBalance( + @Param('userId') userId: string, + @Param('currency') currency: CurrencyType, + ) { + const balance = await this.transactionService.getUserBalance( + userId, + currency, + ); + return { userId, currency, balance }; + } + + @Get('user/:userId/history') + async getTransactionHistory( + @Param('userId') userId: string, + @Body() body: { startDate?: Date; endDate?: Date }, + ) { + return this.transactionService.getTransactionHistory( + userId, + body.startDate, + body.endDate, + ); + } + + @Put(':id/status') + async updateTransactionStatus( + @Param('id') id: string, + @Body() updateTransactionStatusDto: UpdateTransactionStatusDto, + ) { + return this.transactionService.updateTransactionStatus( + id, + updateTransactionStatusDto, + ); + } + + @Post(':id/complete') + @HttpCode(HttpStatus.OK) + async completeTransaction( + @Param('id') id: string, + @Body() body: { externalTransactionId?: string }, + ) { + return this.transactionService.completeTransaction( + id, + body.externalTransactionId, + ); + } + + @Post(':id/fail') + @HttpCode(HttpStatus.OK) + async failTransaction( + @Param('id') id: string, + @Body() body: { failureReason: string }, + ) { + return this.transactionService.failTransaction(id, body.failureReason); + } + + @Post(':id/refund') + @HttpCode(HttpStatus.OK) + async refundTransaction(@Param('id') id: string) { + return this.transactionService.refundTransaction(id); + } + + @Post('purchase') + @HttpCode(HttpStatus.OK) + async createPurchaseTransaction( + @Body() + body: { + userId: string; + shopItemId: string; + amount: number; + currency: CurrencyType; + description?: string; + }, + ) { + return this.transactionService.createPurchaseTransaction( + body.userId, + body.shopItemId, + body.amount, + body.currency, + body.description, + ); + } + + @Post('energy-refill') + @HttpCode(HttpStatus.OK) + async createEnergyRefillTransaction( + @Body() + body: { + userId: string; + amount: number; + currency: CurrencyType; + description?: string; + }, + ) { + return this.transactionService.createEnergyRefillTransaction( + body.userId, + body.amount, + body.currency, + body.description, + ); + } + + @Post('bonus') + @HttpCode(HttpStatus.OK) + async createBonusTransaction( + @Body() + body: { + userId: string; + amount: number; + currency: CurrencyType; + description?: string; + metadata?: Record; + }, + ) { + return this.transactionService.createBonusTransaction( + body.userId, + body.amount, + body.currency, + body.description, + body.metadata, + ); + } +} diff --git a/microservices/achievement-service/src/transaction/transaction.entity.ts b/microservices/achievement-service/src/transaction/transaction.entity.ts new file mode 100644 index 0000000..78e50ec --- /dev/null +++ b/microservices/achievement-service/src/transaction/transaction.entity.ts @@ -0,0 +1,89 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, +} from 'typeorm'; + +export enum TransactionType { + PURCHASE = 'purchase', + REFILL = 'refill', + REFUND = 'refund', + BONUS = 'bonus', + PENALTY = 'penalty', +} + +export enum TransactionStatus { + PENDING = 'pending', + COMPLETED = 'completed', + FAILED = 'failed', + REFUNDED = 'refunded', +} + +export enum CurrencyType { + COINS = 'coins', + GEMS = 'gems', + ENERGY = 'energy', +} + +@Entity('transactions') +export class Transaction { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + userId: string; + + @Column({ + type: 'enum', + enum: TransactionType, + }) + type: TransactionType; + + @Column({ + type: 'enum', + enum: TransactionStatus, + default: TransactionStatus.PENDING, + }) + status: TransactionStatus; + + @Column({ + type: 'enum', + enum: CurrencyType, + }) + currency: CurrencyType; + + @Column({ type: 'decimal', precision: 10, scale: 2 }) + amount: number; + + @Column({ nullable: true }) + description: string; + + @Column({ nullable: true }) + referenceId: string; + + @Column({ nullable: true }) + shopItemId: string; + + @Column({ type: 'jsonb', nullable: true }) + metadata: Record; + + @Column({ nullable: true }) + externalTransactionId: string; + + @Column({ type: 'timestamp', nullable: true }) + completedAt: Date; + + @Column({ type: 'timestamp', nullable: true }) + failedAt: Date; + + @Column({ nullable: true }) + failureReason: string; + + @CreateDateColumn() + createdAt: Date; + + @UpdateDateColumn() + updatedAt: Date; +} diff --git a/microservices/achievement-service/src/transaction/transaction.module.ts b/microservices/achievement-service/src/transaction/transaction.module.ts new file mode 100644 index 0000000..e02bd54 --- /dev/null +++ b/microservices/achievement-service/src/transaction/transaction.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Transaction } from './transaction.entity'; +import { TransactionService } from '../transaction/transaction.service'; +import { TransactionController } from '../transaction/transaction.controller'; + +@Module({ + imports: [TypeOrmModule.forFeature([Transaction])], + controllers: [TransactionController], + providers: [TransactionService], + exports: [TransactionService], +}) +export class TransactionModule {} diff --git a/microservices/achievement-service/src/transaction/transaction.service.ts b/microservices/achievement-service/src/transaction/transaction.service.ts new file mode 100644 index 0000000..9d3768b --- /dev/null +++ b/microservices/achievement-service/src/transaction/transaction.service.ts @@ -0,0 +1,235 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { + Transaction, + TransactionType, + TransactionStatus, + CurrencyType, +} from './transaction.entity'; + +export class CreateTransactionDto { + userId: string; + type: TransactionType; + currency: CurrencyType; + amount: number; + description?: string; + referenceId?: string; + shopItemId?: string; + metadata?: Record; + externalTransactionId?: string; +} + +export class UpdateTransactionStatusDto { + status: TransactionStatus; + failureReason?: string; + externalTransactionId?: string; +} + +@Injectable() +export class TransactionService { + constructor( + @InjectRepository(Transaction) + private readonly transactionRepository: Repository, + ) {} + + async createTransaction( + createTransactionDto: CreateTransactionDto, + ): Promise { + const transaction = this.transactionRepository.create(createTransactionDto); + return this.transactionRepository.save(transaction); + } + + async getTransactionById(id: string): Promise { + const transaction = await this.transactionRepository.findOne({ + where: { id }, + }); + if (!transaction) { + throw new NotFoundException(`Transaction with ID ${id} not found`); + } + return transaction; + } + + async getUserTransactions( + userId: string, + options: { + type?: TransactionType; + status?: TransactionStatus; + currency?: CurrencyType; + limit?: number; + offset?: number; + } = {}, + ): Promise { + const { type, status, currency, limit = 50, offset = 0 } = options; + + const whereClause: any = { userId }; + if (type) whereClause.type = type; + if (status) whereClause.status = status; + if (currency) whereClause.currency = currency; + + return this.transactionRepository.find({ + where: whereClause, + order: { createdAt: 'DESC' }, + take: limit, + skip: offset, + }); + } + + async updateTransactionStatus( + id: string, + updateTransactionStatusDto: UpdateTransactionStatusDto, + ): Promise { + const transaction = await this.getTransactionById(id); + + Object.assign(transaction, updateTransactionStatusDto); + + if (updateTransactionStatusDto.status === TransactionStatus.COMPLETED) { + transaction.completedAt = new Date(); + } else if (updateTransactionStatusDto.status === TransactionStatus.FAILED) { + transaction.failedAt = new Date(); + } + + return this.transactionRepository.save(transaction); + } + + async completeTransaction( + id: string, + externalTransactionId?: string, + ): Promise { + return this.updateTransactionStatus(id, { + status: TransactionStatus.COMPLETED, + externalTransactionId, + }); + } + + async failTransaction( + id: string, + failureReason: string, + ): Promise { + return this.updateTransactionStatus(id, { + status: TransactionStatus.FAILED, + failureReason, + }); + } + + async refundTransaction(id: string): Promise { + const originalTransaction = await this.getTransactionById(id); + + if (originalTransaction.status !== TransactionStatus.COMPLETED) { + throw new Error('Cannot refund a transaction that was not completed'); + } + + const refundTransaction = this.createTransaction({ + userId: originalTransaction.userId, + type: TransactionType.REFUND, + currency: originalTransaction.currency, + amount: originalTransaction.amount, + description: `Refund for transaction ${id}`, + referenceId: id, + metadata: originalTransaction.metadata, + }); + + await this.updateTransactionStatus(id, { + status: TransactionStatus.REFUNDED, + }); + + return refundTransaction; + } + + async getUserBalance( + userId: string, + currency: CurrencyType, + ): Promise { + const result = await this.transactionRepository + .createQueryBuilder('transaction') + .select( + 'SUM(CASE WHEN transaction.status = :completed THEN transaction.amount ELSE 0 END)', + 'total', + ) + .addSelect( + 'SUM(CASE WHEN transaction.status = :completed AND transaction.type = :refund THEN transaction.amount ELSE 0 END)', + 'refunds', + ) + .where('transaction.userId = :userId', { userId }) + .andWhere('transaction.currency = :currency', { currency }) + .setParameter('completed', TransactionStatus.COMPLETED) + .setParameter('refund', TransactionType.REFUND) + .getRawOne(); + + const total = parseFloat(result.total) || 0; + const refunds = parseFloat(result.refunds) || 0; + + return total - refunds; + } + + async getTransactionHistory( + userId: string, + startDate?: Date, + endDate?: Date, + ): Promise { + const queryBuilder = this.transactionRepository + .createQueryBuilder('transaction') + .where('transaction.userId = :userId', { userId }); + + if (startDate) { + queryBuilder.andWhere('transaction.createdAt >= :startDate', { + startDate, + }); + } + + if (endDate) { + queryBuilder.andWhere('transaction.createdAt <= :endDate', { endDate }); + } + + return queryBuilder.orderBy('transaction.createdAt', 'DESC').getMany(); + } + + async createPurchaseTransaction( + userId: string, + shopItemId: string, + amount: number, + currency: CurrencyType, + description?: string, + ): Promise { + return this.createTransaction({ + userId, + type: TransactionType.PURCHASE, + currency, + amount, + description: description || `Purchase of shop item ${shopItemId}`, + shopItemId, + }); + } + + async createEnergyRefillTransaction( + userId: string, + amount: number, + currency: CurrencyType, + description?: string, + ): Promise { + return this.createTransaction({ + userId, + type: TransactionType.REFILL, + currency, + amount, + description: description || 'Energy refill', + }); + } + + async createBonusTransaction( + userId: string, + amount: number, + currency: CurrencyType, + description?: string, + metadata?: Record, + ): Promise { + return this.createTransaction({ + userId, + type: TransactionType.BONUS, + currency, + amount, + description: description || 'Bonus reward', + metadata, + }); + } +} diff --git a/microservices/achievement-service/tsconfig.json b/microservices/achievement-service/tsconfig.json new file mode 100644 index 0000000..38739b7 --- /dev/null +++ b/microservices/achievement-service/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2021", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false, + "paths": { + "@/*": ["src/*"] + } + } +} diff --git a/package.json b/package.json index 7ab3db5..dc4f797 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,134 @@ -"amqp-connection-manager": "^5.0.0", -"amqplib": "^0.10.9", -"cache-manager": "^7.2.8", -"class-transformer": "^0.5.1", -"class-validator": "^0.14.1", -"date-fns": "^4.1.0", -"firebase-admin": "^13.6.0", +{ + "name": "quest-service", + "version": "0.0.1", + "description": "", + "author": "", + "private": true, + "license": "UNLICENSED", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "lint:check": "eslint \"{src,apps,libs,test}/**/*.ts\"", + "type-check": "tsc --noEmit", + "test": "jest", + "test:unit": "jest --testPathPattern=\\.spec\\.ts$", + "test:integration": "jest --testPathPattern=\\.integration\\.spec\\.ts$", + "test:e2e": "jest --config ./test/jest-e2e.json --testPathPattern=\\.e2e\\.spec\\.ts$", + "test:watch": "jest --watch", + "test:cov": "jest --coverage --testPathPattern=\\.spec\\.ts$", + "test:cov:integration": "jest --coverage --testPathPattern=\\.integration\\.spec\\.ts$", + "test:cov:e2e": "jest --coverage --config ./test/jest-e2e.json --testPathPattern=\\.e2e\\.spec\\.ts$", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "test:performance": "jest --config ./test/jest-performance.json", + "test:smoke": "jest --config ./test/jest-smoke.json", + "test:all": "npm run test:unit && npm run test:integration && npm run test:e2e", + "migration:generate": "ts-node ./node_modules/typeorm/cli -d ormconfig.ts migration:generate", + "migration:run": "ts-node ./node_modules/typeorm/cli -d ormconfig.ts migration:run", + "migration:revert": "ts-node ./node_modules/typeorm/cli -d ormconfig.ts migration:revert", + "seed:run": "ts-node src/database/seeds/run-seeds.ts", + "seed:perf": "ts-node src/database/seeds/run-performance-seeds.ts", + "typeorm:migration:generate": "ts-node ./node_modules/typeorm/cli -d ormconfig.ts migration:generate src/migrations/Init", + "typeorm:migration:run": "ts-node ./node_modules/typeorm/cli -d ormconfig.ts migration:run", + "typeorm:migration:revert": "ts-node ./node_modules/typeorm/cli -d ormconfig.ts migration:revert" + }, + "dependencies": { + "@nestjs/common": "^10.4.4", + "@nestjs/config": "^3.3.0", + "@nestjs/core": "^10.4.4", + "@nestjs/mapped-types": "^2.0.5", + "@nestjs/microservices": "^10.4.4", + "@nestjs/platform-express": "^10.4.4", + "@nestjs/schedule": "^6.0.0", + "@nestjs/terminus": "^11.0.0", + "@nestjs/throttler": "^5.2.0", + "@nestjs/typeorm": "^11.0.0", + "@sentry/integrations": "^7.114.0", + "@sentry/node": "^10.5.0", + "@stellar/stellar-sdk": "^14.4.3", + "@willsoto/nestjs-prometheus": "^6.0.2", + "amqp-connection-manager": "^5.0.0", + "amqplib": "^0.10.9", + "cache-manager": "^7.1.1", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.1", + "date-fns": "^4.1.0", + "helmet": "^7.2.0", + "nest-winston": "^1.9.7", + "nodemailer": "^7.0.5", + "pg": "^8.16.3", + "prom-client": "^15.1.3", + "reflect-metadata": "^0.1.14", + "rxjs": "^7.8.1", + "typeorm": "^0.3.25", + "winston": "^3.11.0", + "winston-daily-rotate-file": "^5.0.0", + "winston-elasticsearch": "^0.19.0", + "xss": "^1.0.15" + }, + "devDependencies": { + "@nestjs/cli": "^10.4.5", + "@nestjs/jwt": "^11.0.0", + "@nestjs/passport": "^11.0.5", + "@nestjs/schematics": "^10.1.4", + "@nestjs/swagger": "^7.4.2", + "@nestjs/testing": "^10.4.4", + "@types/bcrypt": "^6.0.0", + "@types/express": "^4.17.21", + "@types/jest": "^29.5.12", + "@types/multer": "^2.0.0", + "@types/node": "^20.19.30", + "@types/passport-jwt": "^4.0.1", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.0.0", + "@typescript-eslint/parser": "^8.0.0", + "bcrypt": "^6.0.0", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "husky": "^8.0.3", + "jest": "^29.7.0", + "lint-staged": "^15.2.8", + "passport-jwt": "^4.0.1", + "prettier": "^3.3.3", + "source-map-support": "^0.5.21", + "supertest": "^6.3.4", + "ts-jest": "^29.2.4", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.5.4", + "webpack": "^5.101.0" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "ts" + ], + "rootDir": "src", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node" + }, + "lint-staged": { + "*.{ts,js}": [ + "eslint --fix", + "prettier --write" + ] + }, + "engines": { + "node": ">=18.0.0" + } +} From 02e059184ad4bca22535615dbf80ec779efd4790 Mon Sep 17 00:00:00 2001 From: Fawaz Oduola Date: Sat, 24 Jan 2026 21:11:26 +0100 Subject: [PATCH 2/2] refactor: remove energy, payment, shop, and transaction modules from the achievement microservice --- .../src/energy/energy-regeneration.service.ts | 105 -------- .../src/energy/energy.controller.ts | 105 -------- .../src/energy/energy.entity.ts | 49 ---- .../src/energy/energy.module.ts | 14 -- .../src/energy/energy.service.ts | 90 ------- .../src/payment/payment.controller.ts | 40 --- .../src/payment/payment.module.ts | 10 - .../src/payment/payment.service.ts | 181 -------------- .../src/shop/shop-item.entity.ts | 72 ------ .../src/shop/shop.controller.ts | 85 ------- .../src/shop/shop.module.ts | 13 - .../src/shop/shop.service.ts | 147 ----------- .../src/transaction/transaction.controller.ts | 173 ------------- .../src/transaction/transaction.entity.ts | 89 ------- .../src/transaction/transaction.module.ts | 13 - .../src/transaction/transaction.service.ts | 235 ------------------ 16 files changed, 1421 deletions(-) delete mode 100644 microservices/achievement-service/src/energy/energy-regeneration.service.ts delete mode 100644 microservices/achievement-service/src/energy/energy.controller.ts delete mode 100644 microservices/achievement-service/src/energy/energy.entity.ts delete mode 100644 microservices/achievement-service/src/energy/energy.module.ts delete mode 100644 microservices/achievement-service/src/energy/energy.service.ts delete mode 100644 microservices/achievement-service/src/payment/payment.controller.ts delete mode 100644 microservices/achievement-service/src/payment/payment.module.ts delete mode 100644 microservices/achievement-service/src/payment/payment.service.ts delete mode 100644 microservices/achievement-service/src/shop/shop-item.entity.ts delete mode 100644 microservices/achievement-service/src/shop/shop.controller.ts delete mode 100644 microservices/achievement-service/src/shop/shop.module.ts delete mode 100644 microservices/achievement-service/src/shop/shop.service.ts delete mode 100644 microservices/achievement-service/src/transaction/transaction.controller.ts delete mode 100644 microservices/achievement-service/src/transaction/transaction.entity.ts delete mode 100644 microservices/achievement-service/src/transaction/transaction.module.ts delete mode 100644 microservices/achievement-service/src/transaction/transaction.service.ts diff --git a/microservices/achievement-service/src/energy/energy-regeneration.service.ts b/microservices/achievement-service/src/energy/energy-regeneration.service.ts deleted file mode 100644 index 0258f4d..0000000 --- a/microservices/achievement-service/src/energy/energy-regeneration.service.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { Cron } from '@nestjs/schedule'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository, LessThan } from 'typeorm'; -import { UserEnergy, EnergyType } from './energy.entity'; - -@Injectable() -export class EnergyRegenerationService { - private readonly logger = new Logger(EnergyRegenerationService.name); - - constructor( - @InjectRepository(UserEnergy) - private readonly energyRepository: Repository, - ) {} - - @Cron('*/30 * * * * *') - async regenerateEnergy(): Promise { - try { - const now = new Date(); - const thirtySecondsAgo = new Date(now.getTime() - 30 * 1000); - - const usersNeedingRegeneration = await this.energyRepository.find({ - where: { - currentAmount: LessThan(999), - lastRegenerationTime: LessThan(thirtySecondsAgo), - }, - }); - - for (const userEnergy of usersNeedingRegeneration) { - await this.regenerateUserEnergy(userEnergy); - } - - if (usersNeedingRegeneration.length > 0) { - this.logger.log( - `Regenerated energy for ${usersNeedingRegeneration.length} users`, - ); - } - } catch (error) { - this.logger.error('Error during energy regeneration:', error); - } - } - - async regenerateUserEnergy(userEnergy: UserEnergy): Promise { - const now = new Date(); - const timeDiffInSeconds = Math.floor( - (now.getTime() - userEnergy.lastRegenerationTime.getTime()) / 1000, - ); - - if (timeDiffInSeconds >= userEnergy.regenerationInterval) { - const intervalsPassed = Math.floor( - timeDiffInSeconds / userEnergy.regenerationInterval, - ); - const energyToRegenerate = intervalsPassed * userEnergy.regenerationRate; - - userEnergy.currentAmount = Math.min( - userEnergy.currentAmount + energyToRegenerate, - userEnergy.maxAmount, - ); - - userEnergy.lastRegenerationTime = new Date( - userEnergy.lastRegenerationTime.getTime() + - intervalsPassed * userEnergy.regenerationInterval * 1000, - ); - - return this.energyRepository.save(userEnergy); - } - - return userEnergy; - } - - async getEnergyRegenerationStatus( - userId: string, - energyType: EnergyType = EnergyType.ENERGY, - ): Promise<{ - currentAmount: number; - maxAmount: number; - timeToNextRegeneration: number; - regenerationRate: number; - }> { - const userEnergy = await this.energyRepository.findOne({ - where: { userId, energyType }, - }); - - if (!userEnergy) { - throw new Error('User energy not found'); - } - - const now = new Date(); - const timeSinceLastRegeneration = Math.floor( - (now.getTime() - userEnergy.lastRegenerationTime.getTime()) / 1000, - ); - - const timeToNextRegeneration = Math.max( - 0, - userEnergy.regenerationInterval - timeSinceLastRegeneration, - ); - - return { - currentAmount: userEnergy.currentAmount, - maxAmount: userEnergy.maxAmount, - timeToNextRegeneration, - regenerationRate: userEnergy.regenerationRate, - }; - } -} diff --git a/microservices/achievement-service/src/energy/energy.controller.ts b/microservices/achievement-service/src/energy/energy.controller.ts deleted file mode 100644 index c7744e4..0000000 --- a/microservices/achievement-service/src/energy/energy.controller.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { - Controller, - Get, - Post, - Put, - Param, - Body, - HttpCode, - HttpStatus, -} from '@nestjs/common'; -import { EnergyService } from './energy.service'; -import { EnergyRegenerationService } from './energy-regeneration.service'; -import { EnergyType } from './energy.entity'; - -export class ConsumeEnergyDto { - amount: number; - energyType?: EnergyType = EnergyType.ENERGY; -} - -export class AddEnergyDto { - amount: number; - energyType?: EnergyType = EnergyType.ENERGY; -} - -export class UpdateMaxEnergyDto { - maxAmount: number; - energyType?: EnergyType = EnergyType.ENERGY; -} - -@Controller('energy') -export class EnergyController { - constructor( - private readonly energyService: EnergyService, - private readonly energyRegenerationService: EnergyRegenerationService, - ) {} - - @Get(':userId') - async getUserEnergy( - @Param('userId') userId: string, - @Body() body: { energyType?: EnergyType }, - ) { - const energyType = body.energyType || EnergyType.ENERGY; - return this.energyService.getUserEnergy(userId, energyType); - } - - @Get(':userId/status') - async getEnergyStatus( - @Param('userId') userId: string, - @Body() body: { energyType?: EnergyType }, - ) { - const energyType = body.energyType || EnergyType.ENERGY; - return this.energyRegenerationService.getEnergyRegenerationStatus( - userId, - energyType, - ); - } - - @Post(':userId/consume') - @HttpCode(HttpStatus.OK) - async consumeEnergy( - @Param('userId') userId: string, - @Body() consumeEnergyDto: ConsumeEnergyDto, - ) { - return this.energyService.consumeEnergy( - userId, - consumeEnergyDto.amount, - consumeEnergyDto.energyType, - ); - } - - @Post(':userId/add') - @HttpCode(HttpStatus.OK) - async addEnergy( - @Param('userId') userId: string, - @Body() addEnergyDto: AddEnergyDto, - ) { - return this.energyService.addEnergy( - userId, - addEnergyDto.amount, - addEnergyDto.energyType, - ); - } - - @Post(':userId/refill') - @HttpCode(HttpStatus.OK) - async refillEnergy( - @Param('userId') userId: string, - @Body() body: { energyType?: EnergyType }, - ) { - const energyType = body.energyType || EnergyType.ENERGY; - return this.energyService.refillEnergy(userId, energyType); - } - - @Put(':userId/max') - async updateMaxEnergy( - @Param('userId') userId: string, - @Body() updateMaxEnergyDto: UpdateMaxEnergyDto, - ) { - return this.energyService.updateMaxEnergy( - userId, - updateMaxEnergyDto.maxAmount, - updateMaxEnergyDto.energyType, - ); - } -} diff --git a/microservices/achievement-service/src/energy/energy.entity.ts b/microservices/achievement-service/src/energy/energy.entity.ts deleted file mode 100644 index 43edaf4..0000000 --- a/microservices/achievement-service/src/energy/energy.entity.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - CreateDateColumn, - UpdateDateColumn, -} from 'typeorm'; - -export enum EnergyType { - STAMINA = 'stamina', - ENERGY = 'energy', -} - -@Entity('user_energy') -export class UserEnergy { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column() - userId: string; - - @Column({ - type: 'enum', - enum: EnergyType, - default: EnergyType.ENERGY, - }) - energyType: EnergyType; - - @Column({ default: 100 }) - currentAmount: number; - - @Column({ default: 100 }) - maxAmount: number; - - @Column({ type: 'timestamp', nullable: true }) - lastRegenerationTime: Date; - - @Column({ default: 300 }) - regenerationRate: number; - - @Column({ default: 60 }) - regenerationInterval: number; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; -} diff --git a/microservices/achievement-service/src/energy/energy.module.ts b/microservices/achievement-service/src/energy/energy.module.ts deleted file mode 100644 index f618649..0000000 --- a/microservices/achievement-service/src/energy/energy.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { UserEnergy } from './energy.entity'; -import { EnergyService } from './energy.service'; -import { EnergyController } from './energy.controller'; -import { EnergyRegenerationService } from './energy-regeneration.service'; - -@Module({ - imports: [TypeOrmModule.forFeature([UserEnergy])], - controllers: [EnergyController], - providers: [EnergyService, EnergyRegenerationService], - exports: [EnergyService], -}) -export class EnergyModule {} diff --git a/microservices/achievement-service/src/energy/energy.service.ts b/microservices/achievement-service/src/energy/energy.service.ts deleted file mode 100644 index 0c203c7..0000000 --- a/microservices/achievement-service/src/energy/energy.service.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { UserEnergy, EnergyType } from './energy.entity'; - -@Injectable() -export class EnergyService { - constructor( - @InjectRepository(UserEnergy) - private readonly energyRepository: Repository, - ) {} - - async getUserEnergy( - userId: string, - energyType: EnergyType = EnergyType.ENERGY, - ): Promise { - let userEnergy = await this.energyRepository.findOne({ - where: { userId, energyType }, - }); - - if (!userEnergy) { - userEnergy = this.energyRepository.create({ - userId, - energyType, - currentAmount: 100, - maxAmount: 100, - regenerationRate: 300, - regenerationInterval: 60, - lastRegenerationTime: new Date(), - }); - await this.energyRepository.save(userEnergy); - } - - return userEnergy; - } - - async consumeEnergy( - userId: string, - amount: number, - energyType: EnergyType = EnergyType.ENERGY, - ): Promise { - const userEnergy = await this.getUserEnergy(userId, energyType); - - if (userEnergy.currentAmount < amount) { - throw new Error('Insufficient energy'); - } - - userEnergy.currentAmount -= amount; - return this.energyRepository.save(userEnergy); - } - - async addEnergy( - userId: string, - amount: number, - energyType: EnergyType = EnergyType.ENERGY, - ): Promise { - const userEnergy = await this.getUserEnergy(userId, energyType); - - userEnergy.currentAmount = Math.min( - userEnergy.currentAmount + amount, - userEnergy.maxAmount, - ); - return this.energyRepository.save(userEnergy); - } - - async refillEnergy( - userId: string, - energyType: EnergyType = EnergyType.ENERGY, - ): Promise { - const userEnergy = await this.getUserEnergy(userId, energyType); - userEnergy.currentAmount = userEnergy.maxAmount; - userEnergy.lastRegenerationTime = new Date(); - return this.energyRepository.save(userEnergy); - } - - async updateMaxEnergy( - userId: string, - maxAmount: number, - energyType: EnergyType = EnergyType.ENERGY, - ): Promise { - const userEnergy = await this.getUserEnergy(userId, energyType); - userEnergy.maxAmount = maxAmount; - - if (userEnergy.currentAmount > maxAmount) { - userEnergy.currentAmount = maxAmount; - } - - return this.energyRepository.save(userEnergy); - } -} diff --git a/microservices/achievement-service/src/payment/payment.controller.ts b/microservices/achievement-service/src/payment/payment.controller.ts deleted file mode 100644 index 2ee9977..0000000 --- a/microservices/achievement-service/src/payment/payment.controller.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { - Controller, - Post, - Get, - Body, - Param, - HttpCode, - HttpStatus, -} from '@nestjs/common'; -import { PaymentService, PaymentData } from './payment.service'; - -@Controller('payment') -export class PaymentController { - constructor(private readonly paymentService: PaymentService) {} - - @Get('providers') - getAvailableProviders() { - return { - providers: this.paymentService.getAvailableProviders(), - }; - } - - @Post(':provider/process') - @HttpCode(HttpStatus.OK) - async processPayment( - @Body() paymentData: PaymentData, - @Param('provider') provider: string, - ) { - return this.paymentService.processPayment(provider, paymentData); - } - - @Post(':provider/refund') - @HttpCode(HttpStatus.OK) - async refundPayment( - @Body() body: { transactionId: string }, - @Param('provider') provider: string, - ) { - return this.paymentService.refundPayment(provider, body.transactionId); - } -} diff --git a/microservices/achievement-service/src/payment/payment.module.ts b/microservices/achievement-service/src/payment/payment.module.ts deleted file mode 100644 index 7bbf754..0000000 --- a/microservices/achievement-service/src/payment/payment.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Module } from '@nestjs/common'; -import { PaymentService } from './payment.service'; -import { PaymentController } from './payment.controller'; - -@Module({ - controllers: [PaymentController], - providers: [PaymentService], - exports: [PaymentService], -}) -export class PaymentModule {} diff --git a/microservices/achievement-service/src/payment/payment.service.ts b/microservices/achievement-service/src/payment/payment.service.ts deleted file mode 100644 index 09ad360..0000000 --- a/microservices/achievement-service/src/payment/payment.service.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; - -export interface PaymentProvider { - processPayment(paymentData: PaymentData): Promise; - refundPayment(transactionId: string): Promise; -} - -export interface PaymentData { - amount: number; - currency: string; - userId: string; - description?: string; - metadata?: Record; - paymentMethod: string; -} - -export interface PaymentResult { - success: boolean; - transactionId?: string; - error?: string; - metadata?: Record; -} - -export interface RefundResult { - success: boolean; - refundId?: string; - error?: string; -} - -@Injectable() -export class PaymentService { - private readonly logger = new Logger(PaymentService.name); - private providers: Map = new Map(); - - constructor() { - this.initializeProviders(); - } - - private initializeProviders(): void { - this.providers.set('stripe', new StripePaymentProvider()); - this.providers.set('paypal', new PayPalPaymentProvider()); - } - - async processPayment( - providerName: string, - paymentData: PaymentData, - ): Promise { - const provider = this.providers.get(providerName); - - if (!provider) { - throw new Error(`Payment provider ${providerName} not found`); - } - - try { - this.logger.log( - `Processing payment with ${providerName} for user ${paymentData.userId}`, - ); - const result = await provider.processPayment(paymentData); - - if (result.success) { - this.logger.log( - `Payment successful with transaction ID: ${result.transactionId}`, - ); - } else { - this.logger.error(`Payment failed: ${result.error}`); - } - - return result; - } catch (error) { - this.logger.error(`Payment processing error:`, error); - throw error; - } - } - - async refundPayment( - providerName: string, - transactionId: string, - ): Promise { - const provider = this.providers.get(providerName); - - if (!provider) { - throw new Error(`Payment provider ${providerName} not found`); - } - - try { - this.logger.log(`Processing refund for transaction ${transactionId}`); - const result = await provider.refundPayment(transactionId); - - if (result.success) { - this.logger.log(`Refund successful with refund ID: ${result.refundId}`); - } else { - this.logger.error(`Refund failed: ${result.error}`); - } - - return result; - } catch (error) { - this.logger.error(`Refund processing error:`, error); - throw error; - } - } - - getAvailableProviders(): string[] { - return Array.from(this.providers.keys()); - } -} - -class StripePaymentProvider implements PaymentProvider { - async processPayment(paymentData: PaymentData): Promise { - await new Promise((resolve) => setTimeout(resolve, 1000)); - - if (Math.random() > 0.1) { - return { - success: true, - transactionId: `stripe_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, - metadata: { - provider: 'stripe', - processedAt: new Date().toISOString(), - }, - }; - } else { - return { - success: false, - error: 'Insufficient funds', - }; - } - } - - async refundPayment(transactionId: string): Promise { - await new Promise((resolve) => setTimeout(resolve, 500)); - - if (Math.random() > 0.05) { - return { - success: true, - refundId: `stripe_refund_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, - }; - } else { - return { - success: false, - error: 'Refund period expired', - }; - } - } -} - -class PayPalPaymentProvider implements PaymentProvider { - async processPayment(paymentData: PaymentData): Promise { - await new Promise((resolve) => setTimeout(resolve, 1500)); - - if (Math.random() > 0.15) { - return { - success: true, - transactionId: `paypal_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, - metadata: { - provider: 'paypal', - processedAt: new Date().toISOString(), - }, - }; - } else { - return { - success: false, - error: 'Payment declined', - }; - } - } - - async refundPayment(transactionId: string): Promise { - await new Promise((resolve) => setTimeout(resolve, 700)); - - if (Math.random() > 0.08) { - return { - success: true, - refundId: `paypal_refund_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, - }; - } else { - return { - success: false, - error: 'Transaction not refundable', - }; - } - } -} diff --git a/microservices/achievement-service/src/shop/shop-item.entity.ts b/microservices/achievement-service/src/shop/shop-item.entity.ts deleted file mode 100644 index 3956450..0000000 --- a/microservices/achievement-service/src/shop/shop-item.entity.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - CreateDateColumn, - UpdateDateColumn, -} from 'typeorm'; - -export enum ShopItemType { - HINT = 'hint', - POWER_UP = 'power_up', - COSMETIC = 'cosmetic', - ENERGY_REFILL = 'energy_refill', -} - -export enum ShopItemStatus { - ACTIVE = 'active', - INACTIVE = 'inactive', - LIMITED = 'limited', -} - -@Entity('shop_items') -export class ShopItem { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column() - name: string; - - @Column({ nullable: true }) - description: string; - - @Column({ - type: 'enum', - enum: ShopItemType, - }) - itemType: ShopItemType; - - @Column({ type: 'decimal', precision: 10, scale: 2 }) - price: number; - - @Column({ default: 'coins' }) - currency: string; - - @Column({ - type: 'enum', - enum: ShopItemStatus, - default: ShopItemStatus.ACTIVE, - }) - status: ShopItemStatus; - - @Column({ nullable: true }) - imageUrl: string; - - @Column({ type: 'jsonb', nullable: true }) - metadata: Record; - - @Column({ nullable: true }) - maxPurchaseLimit: number; - - @Column({ default: 0 }) - currentPurchaseCount: number; - - @Column({ type: 'timestamp', nullable: true }) - expiresAt: Date; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; -} diff --git a/microservices/achievement-service/src/shop/shop.controller.ts b/microservices/achievement-service/src/shop/shop.controller.ts deleted file mode 100644 index 9e67c4d..0000000 --- a/microservices/achievement-service/src/shop/shop.controller.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { - Controller, - Get, - Post, - Put, - Delete, - Param, - Body, - HttpCode, - HttpStatus, -} from '@nestjs/common'; -import { - ShopService, - CreateShopItemDto, - UpdateShopItemDto, -} from './shop.service'; -import { ShopItemStatus, ShopItemType } from './shop-item.entity'; - -@Controller('shop') -export class ShopController { - constructor(private readonly shopService: ShopService) {} - - @Post() - async createShopItem(@Body() createShopItemDto: CreateShopItemDto) { - return this.shopService.createShopItem(createShopItemDto); - } - - @Get() - async getAllShopItems(@Body() body: { status?: ShopItemStatus }) { - return this.shopService.getAllShopItems(body.status); - } - - @Get('type/:itemType') - async getShopItemsByType(@Param('itemType') itemType: ShopItemType) { - return this.shopService.getShopItemsByType(itemType); - } - - @Get('hints') - async getHintItems() { - return this.shopService.getHintItems(); - } - - @Get('energy-refills') - async getEnergyRefillItems() { - return this.shopService.getEnergyRefillItems(); - } - - @Get('power-ups') - async getPowerUpItems() { - return this.shopService.getPowerUpItems(); - } - - @Get('cosmetics') - async getCosmeticItems() { - return this.shopService.getCosmeticItems(); - } - - @Get(':id') - async getShopItemById(@Param('id') id: string) { - return this.shopService.getShopItemById(id); - } - - @Put(':id') - async updateShopItem( - @Param('id') id: string, - @Body() updateShopItemDto: UpdateShopItemDto, - ) { - return this.shopService.updateShopItem(id, updateShopItemDto); - } - - @Delete(':id') - @HttpCode(HttpStatus.NO_CONTENT) - async deleteShopItem(@Param('id') id: string) { - return this.shopService.deleteShopItem(id); - } - - @Post(':shopItemId/purchase') - @HttpCode(HttpStatus.OK) - async purchaseShopItem( - @Param('shopItemId') shopItemId: string, - @Body() body: { userId: string }, - ) { - return this.shopService.purchaseShopItem(body.userId, shopItemId); - } -} diff --git a/microservices/achievement-service/src/shop/shop.module.ts b/microservices/achievement-service/src/shop/shop.module.ts deleted file mode 100644 index d8f79dd..0000000 --- a/microservices/achievement-service/src/shop/shop.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { ShopItem } from './shop-item.entity'; -import { ShopService } from './shop.service'; -import { ShopController } from './shop.controller'; - -@Module({ - imports: [TypeOrmModule.forFeature([ShopItem])], - controllers: [ShopController], - providers: [ShopService], - exports: [ShopService], -}) -export class ShopModule {} diff --git a/microservices/achievement-service/src/shop/shop.service.ts b/microservices/achievement-service/src/shop/shop.service.ts deleted file mode 100644 index 6690bda..0000000 --- a/microservices/achievement-service/src/shop/shop.service.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { - Injectable, - NotFoundException, - BadRequestException, -} from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { ShopItem, ShopItemType, ShopItemStatus } from './shop-item.entity'; - -export class CreateShopItemDto { - name: string; - description?: string; - itemType: ShopItemType; - price: number; - currency?: string; - imageUrl?: string; - metadata?: Record; - maxPurchaseLimit?: number; - expiresAt?: Date; -} - -export class UpdateShopItemDto { - name?: string; - description?: string; - itemType?: ShopItemType; - price?: number; - currency?: string; - status?: ShopItemStatus; - imageUrl?: string; - metadata?: Record; - maxPurchaseLimit?: number; - expiresAt?: Date; -} - -@Injectable() -export class ShopService { - constructor( - @InjectRepository(ShopItem) - private readonly shopItemRepository: Repository, - ) {} - - async createShopItem( - createShopItemDto: CreateShopItemDto, - ): Promise { - const shopItem = this.shopItemRepository.create(createShopItemDto); - return this.shopItemRepository.save(shopItem); - } - - async getAllShopItems(status?: ShopItemStatus): Promise { - const whereClause = status ? { status } : {}; - return this.shopItemRepository.find({ - where: whereClause, - order: { createdAt: 'ASC' }, - }); - } - - async getShopItemById(id: string): Promise { - const shopItem = await this.shopItemRepository.findOne({ where: { id } }); - if (!shopItem) { - throw new NotFoundException(`Shop item with ID ${id} not found`); - } - return shopItem; - } - - async getShopItemsByType(itemType: ShopItemType): Promise { - return this.shopItemRepository.find({ - where: { itemType, status: ShopItemStatus.ACTIVE }, - order: { createdAt: 'ASC' }, - }); - } - - async updateShopItem( - id: string, - updateShopItemDto: UpdateShopItemDto, - ): Promise { - const shopItem = await this.getShopItemById(id); - Object.assign(shopItem, updateShopItemDto); - return this.shopItemRepository.save(shopItem); - } - - async deleteShopItem(id: string): Promise { - const shopItem = await this.getShopItemById(id); - await this.shopItemRepository.remove(shopItem); - } - - async purchaseShopItem( - userId: string, - shopItemId: string, - ): Promise<{ - shopItem: ShopItem; - canPurchase: boolean; - reason?: string; - }> { - const shopItem = await this.getShopItemById(shopItemId); - - if (shopItem.status !== ShopItemStatus.ACTIVE) { - return { - shopItem, - canPurchase: false, - reason: 'Item is not available for purchase', - }; - } - - if (shopItem.expiresAt && new Date() > shopItem.expiresAt) { - return { - shopItem, - canPurchase: false, - reason: 'Item has expired', - }; - } - - if ( - shopItem.maxPurchaseLimit && - shopItem.currentPurchaseCount >= shopItem.maxPurchaseLimit - ) { - return { - shopItem, - canPurchase: false, - reason: 'Purchase limit reached', - }; - } - - shopItem.currentPurchaseCount += 1; - await this.shopItemRepository.save(shopItem); - - return { - shopItem, - canPurchase: true, - }; - } - - async getHintItems(): Promise { - return this.getShopItemsByType(ShopItemType.HINT); - } - - async getEnergyRefillItems(): Promise { - return this.getShopItemsByType(ShopItemType.ENERGY_REFILL); - } - - async getPowerUpItems(): Promise { - return this.getShopItemsByType(ShopItemType.POWER_UP); - } - - async getCosmeticItems(): Promise { - return this.getShopItemsByType(ShopItemType.COSMETIC); - } -} diff --git a/microservices/achievement-service/src/transaction/transaction.controller.ts b/microservices/achievement-service/src/transaction/transaction.controller.ts deleted file mode 100644 index f2d0f44..0000000 --- a/microservices/achievement-service/src/transaction/transaction.controller.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { - Controller, - Get, - Post, - Put, - Param, - Body, - HttpCode, - HttpStatus, -} from '@nestjs/common'; -import { - TransactionService, - CreateTransactionDto, - UpdateTransactionStatusDto, -} from './transaction.service'; -import { - TransactionType, - TransactionStatus, - CurrencyType, -} from './transaction.entity'; - -@Controller('transactions') -export class TransactionController { - constructor(private readonly transactionService: TransactionService) {} - - @Post() - async createTransaction(@Body() createTransactionDto: CreateTransactionDto) { - return this.transactionService.createTransaction(createTransactionDto); - } - - @Get(':id') - async getTransactionById(@Param('id') id: string) { - return this.transactionService.getTransactionById(id); - } - - @Get('user/:userId') - async getUserTransactions( - @Param('userId') userId: string, - @Body() - body: { - type?: TransactionType; - status?: TransactionStatus; - currency?: CurrencyType; - limit?: number; - offset?: number; - }, - ) { - return this.transactionService.getUserTransactions(userId, body); - } - - @Get('user/:userId/balance/:currency') - async getUserBalance( - @Param('userId') userId: string, - @Param('currency') currency: CurrencyType, - ) { - const balance = await this.transactionService.getUserBalance( - userId, - currency, - ); - return { userId, currency, balance }; - } - - @Get('user/:userId/history') - async getTransactionHistory( - @Param('userId') userId: string, - @Body() body: { startDate?: Date; endDate?: Date }, - ) { - return this.transactionService.getTransactionHistory( - userId, - body.startDate, - body.endDate, - ); - } - - @Put(':id/status') - async updateTransactionStatus( - @Param('id') id: string, - @Body() updateTransactionStatusDto: UpdateTransactionStatusDto, - ) { - return this.transactionService.updateTransactionStatus( - id, - updateTransactionStatusDto, - ); - } - - @Post(':id/complete') - @HttpCode(HttpStatus.OK) - async completeTransaction( - @Param('id') id: string, - @Body() body: { externalTransactionId?: string }, - ) { - return this.transactionService.completeTransaction( - id, - body.externalTransactionId, - ); - } - - @Post(':id/fail') - @HttpCode(HttpStatus.OK) - async failTransaction( - @Param('id') id: string, - @Body() body: { failureReason: string }, - ) { - return this.transactionService.failTransaction(id, body.failureReason); - } - - @Post(':id/refund') - @HttpCode(HttpStatus.OK) - async refundTransaction(@Param('id') id: string) { - return this.transactionService.refundTransaction(id); - } - - @Post('purchase') - @HttpCode(HttpStatus.OK) - async createPurchaseTransaction( - @Body() - body: { - userId: string; - shopItemId: string; - amount: number; - currency: CurrencyType; - description?: string; - }, - ) { - return this.transactionService.createPurchaseTransaction( - body.userId, - body.shopItemId, - body.amount, - body.currency, - body.description, - ); - } - - @Post('energy-refill') - @HttpCode(HttpStatus.OK) - async createEnergyRefillTransaction( - @Body() - body: { - userId: string; - amount: number; - currency: CurrencyType; - description?: string; - }, - ) { - return this.transactionService.createEnergyRefillTransaction( - body.userId, - body.amount, - body.currency, - body.description, - ); - } - - @Post('bonus') - @HttpCode(HttpStatus.OK) - async createBonusTransaction( - @Body() - body: { - userId: string; - amount: number; - currency: CurrencyType; - description?: string; - metadata?: Record; - }, - ) { - return this.transactionService.createBonusTransaction( - body.userId, - body.amount, - body.currency, - body.description, - body.metadata, - ); - } -} diff --git a/microservices/achievement-service/src/transaction/transaction.entity.ts b/microservices/achievement-service/src/transaction/transaction.entity.ts deleted file mode 100644 index 78e50ec..0000000 --- a/microservices/achievement-service/src/transaction/transaction.entity.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - CreateDateColumn, - UpdateDateColumn, -} from 'typeorm'; - -export enum TransactionType { - PURCHASE = 'purchase', - REFILL = 'refill', - REFUND = 'refund', - BONUS = 'bonus', - PENALTY = 'penalty', -} - -export enum TransactionStatus { - PENDING = 'pending', - COMPLETED = 'completed', - FAILED = 'failed', - REFUNDED = 'refunded', -} - -export enum CurrencyType { - COINS = 'coins', - GEMS = 'gems', - ENERGY = 'energy', -} - -@Entity('transactions') -export class Transaction { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column() - userId: string; - - @Column({ - type: 'enum', - enum: TransactionType, - }) - type: TransactionType; - - @Column({ - type: 'enum', - enum: TransactionStatus, - default: TransactionStatus.PENDING, - }) - status: TransactionStatus; - - @Column({ - type: 'enum', - enum: CurrencyType, - }) - currency: CurrencyType; - - @Column({ type: 'decimal', precision: 10, scale: 2 }) - amount: number; - - @Column({ nullable: true }) - description: string; - - @Column({ nullable: true }) - referenceId: string; - - @Column({ nullable: true }) - shopItemId: string; - - @Column({ type: 'jsonb', nullable: true }) - metadata: Record; - - @Column({ nullable: true }) - externalTransactionId: string; - - @Column({ type: 'timestamp', nullable: true }) - completedAt: Date; - - @Column({ type: 'timestamp', nullable: true }) - failedAt: Date; - - @Column({ nullable: true }) - failureReason: string; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; -} diff --git a/microservices/achievement-service/src/transaction/transaction.module.ts b/microservices/achievement-service/src/transaction/transaction.module.ts deleted file mode 100644 index e02bd54..0000000 --- a/microservices/achievement-service/src/transaction/transaction.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { Transaction } from './transaction.entity'; -import { TransactionService } from '../transaction/transaction.service'; -import { TransactionController } from '../transaction/transaction.controller'; - -@Module({ - imports: [TypeOrmModule.forFeature([Transaction])], - controllers: [TransactionController], - providers: [TransactionService], - exports: [TransactionService], -}) -export class TransactionModule {} diff --git a/microservices/achievement-service/src/transaction/transaction.service.ts b/microservices/achievement-service/src/transaction/transaction.service.ts deleted file mode 100644 index 9d3768b..0000000 --- a/microservices/achievement-service/src/transaction/transaction.service.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { - Transaction, - TransactionType, - TransactionStatus, - CurrencyType, -} from './transaction.entity'; - -export class CreateTransactionDto { - userId: string; - type: TransactionType; - currency: CurrencyType; - amount: number; - description?: string; - referenceId?: string; - shopItemId?: string; - metadata?: Record; - externalTransactionId?: string; -} - -export class UpdateTransactionStatusDto { - status: TransactionStatus; - failureReason?: string; - externalTransactionId?: string; -} - -@Injectable() -export class TransactionService { - constructor( - @InjectRepository(Transaction) - private readonly transactionRepository: Repository, - ) {} - - async createTransaction( - createTransactionDto: CreateTransactionDto, - ): Promise { - const transaction = this.transactionRepository.create(createTransactionDto); - return this.transactionRepository.save(transaction); - } - - async getTransactionById(id: string): Promise { - const transaction = await this.transactionRepository.findOne({ - where: { id }, - }); - if (!transaction) { - throw new NotFoundException(`Transaction with ID ${id} not found`); - } - return transaction; - } - - async getUserTransactions( - userId: string, - options: { - type?: TransactionType; - status?: TransactionStatus; - currency?: CurrencyType; - limit?: number; - offset?: number; - } = {}, - ): Promise { - const { type, status, currency, limit = 50, offset = 0 } = options; - - const whereClause: any = { userId }; - if (type) whereClause.type = type; - if (status) whereClause.status = status; - if (currency) whereClause.currency = currency; - - return this.transactionRepository.find({ - where: whereClause, - order: { createdAt: 'DESC' }, - take: limit, - skip: offset, - }); - } - - async updateTransactionStatus( - id: string, - updateTransactionStatusDto: UpdateTransactionStatusDto, - ): Promise { - const transaction = await this.getTransactionById(id); - - Object.assign(transaction, updateTransactionStatusDto); - - if (updateTransactionStatusDto.status === TransactionStatus.COMPLETED) { - transaction.completedAt = new Date(); - } else if (updateTransactionStatusDto.status === TransactionStatus.FAILED) { - transaction.failedAt = new Date(); - } - - return this.transactionRepository.save(transaction); - } - - async completeTransaction( - id: string, - externalTransactionId?: string, - ): Promise { - return this.updateTransactionStatus(id, { - status: TransactionStatus.COMPLETED, - externalTransactionId, - }); - } - - async failTransaction( - id: string, - failureReason: string, - ): Promise { - return this.updateTransactionStatus(id, { - status: TransactionStatus.FAILED, - failureReason, - }); - } - - async refundTransaction(id: string): Promise { - const originalTransaction = await this.getTransactionById(id); - - if (originalTransaction.status !== TransactionStatus.COMPLETED) { - throw new Error('Cannot refund a transaction that was not completed'); - } - - const refundTransaction = this.createTransaction({ - userId: originalTransaction.userId, - type: TransactionType.REFUND, - currency: originalTransaction.currency, - amount: originalTransaction.amount, - description: `Refund for transaction ${id}`, - referenceId: id, - metadata: originalTransaction.metadata, - }); - - await this.updateTransactionStatus(id, { - status: TransactionStatus.REFUNDED, - }); - - return refundTransaction; - } - - async getUserBalance( - userId: string, - currency: CurrencyType, - ): Promise { - const result = await this.transactionRepository - .createQueryBuilder('transaction') - .select( - 'SUM(CASE WHEN transaction.status = :completed THEN transaction.amount ELSE 0 END)', - 'total', - ) - .addSelect( - 'SUM(CASE WHEN transaction.status = :completed AND transaction.type = :refund THEN transaction.amount ELSE 0 END)', - 'refunds', - ) - .where('transaction.userId = :userId', { userId }) - .andWhere('transaction.currency = :currency', { currency }) - .setParameter('completed', TransactionStatus.COMPLETED) - .setParameter('refund', TransactionType.REFUND) - .getRawOne(); - - const total = parseFloat(result.total) || 0; - const refunds = parseFloat(result.refunds) || 0; - - return total - refunds; - } - - async getTransactionHistory( - userId: string, - startDate?: Date, - endDate?: Date, - ): Promise { - const queryBuilder = this.transactionRepository - .createQueryBuilder('transaction') - .where('transaction.userId = :userId', { userId }); - - if (startDate) { - queryBuilder.andWhere('transaction.createdAt >= :startDate', { - startDate, - }); - } - - if (endDate) { - queryBuilder.andWhere('transaction.createdAt <= :endDate', { endDate }); - } - - return queryBuilder.orderBy('transaction.createdAt', 'DESC').getMany(); - } - - async createPurchaseTransaction( - userId: string, - shopItemId: string, - amount: number, - currency: CurrencyType, - description?: string, - ): Promise { - return this.createTransaction({ - userId, - type: TransactionType.PURCHASE, - currency, - amount, - description: description || `Purchase of shop item ${shopItemId}`, - shopItemId, - }); - } - - async createEnergyRefillTransaction( - userId: string, - amount: number, - currency: CurrencyType, - description?: string, - ): Promise { - return this.createTransaction({ - userId, - type: TransactionType.REFILL, - currency, - amount, - description: description || 'Energy refill', - }); - } - - async createBonusTransaction( - userId: string, - amount: number, - currency: CurrencyType, - description?: string, - metadata?: Record, - ): Promise { - return this.createTransaction({ - userId, - type: TransactionType.BONUS, - currency, - amount, - description: description || 'Bonus reward', - metadata, - }); - } -}