From 502182c9b606abff9606a573f45a191ec0634859 Mon Sep 17 00:00:00 2001 From: sadeeq Date: Sat, 24 Jan 2026 16:54:19 +0000 Subject: [PATCH] Player Service Setup --- dist/main.js | 11886 +++++++++++++-------- package-lock.json | 225 +- package.json | 9 +- src/app.module.ts | 6 + src/player/dto/create-player.dto.ts | 1 + src/player/dto/update-player.dto.ts | 4 + src/player/entities/player.entity.ts | 1 + src/player/player.controller.ts | 34 + src/player/player.module.ts | 9 + src/player/player.service.ts | 26 + src/profile/dto/create-profile.dto.ts | 1 + src/profile/dto/update-profile.dto.ts | 4 + src/profile/entities/profile.entity.ts | 1 + src/profile/profile.controller.ts | 34 + src/profile/profile.module.ts | 9 + src/profile/profile.service.ts | 26 + src/progress/dto/create-progress.dto.ts | 1 + src/progress/dto/update-progress.dto.ts | 4 + src/progress/entities/progress.entity.ts | 1 + src/progress/progress.controller.ts | 34 + src/progress/progress.module.ts | 9 + src/progress/progress.service.ts | 26 + 22 files changed, 7862 insertions(+), 4489 deletions(-) create mode 100644 src/player/dto/create-player.dto.ts create mode 100644 src/player/dto/update-player.dto.ts create mode 100644 src/player/entities/player.entity.ts create mode 100644 src/player/player.controller.ts create mode 100644 src/player/player.module.ts create mode 100644 src/player/player.service.ts create mode 100644 src/profile/dto/create-profile.dto.ts create mode 100644 src/profile/dto/update-profile.dto.ts create mode 100644 src/profile/entities/profile.entity.ts create mode 100644 src/profile/profile.controller.ts create mode 100644 src/profile/profile.module.ts create mode 100644 src/profile/profile.service.ts create mode 100644 src/progress/dto/create-progress.dto.ts create mode 100644 src/progress/dto/update-progress.dto.ts create mode 100644 src/progress/entities/progress.entity.ts create mode 100644 src/progress/progress.controller.ts create mode 100644 src/progress/progress.module.ts create mode 100644 src/progress/progress.service.ts diff --git a/dist/main.js b/dist/main.js index 72dc5f4..7daacce 100644 --- a/dist/main.js +++ b/dist/main.js @@ -331,8 +331,15 @@ const puzzles_module_1 = __webpack_require__(/*! ./puzzles/puzzles.module */ "./ 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 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 player_module_1 = __webpack_require__(/*! ./player/player.module */ "./src/player/player.module.ts"); +const profile_module_1 = __webpack_require__(/*! ./profile/profile.module */ "./src/profile/profile.module.ts"); +const progress_module_1 = __webpack_require__(/*! ./progress/progress.module */ "./src/progress/progress.module.ts"); let AppModule = class AppModule { }; exports.AppModule = AppModule; @@ -345,6 +352,7 @@ exports.AppModule = AppModule = __decorate([ 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], @@ -361,10 +369,16 @@ exports.AppModule = AppModule = __decorate([ 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, + referrals_module_1.ReferralsModule, + save_game_module_1.SaveGameModule, + player_module_1.PlayerModule, + profile_module_1.ProfileModule, + progress_module_1.ProgressModule, ], controllers: [app_controller_1.AppController], providers: [ @@ -4013,71 +4027,44 @@ exports.PushService = PushService = PushService_1 = __decorate([ /***/ }), -/***/ "./src/puzzles/community-puzzles.module.ts": -/*!*************************************************!*\ - !*** ./src/puzzles/community-puzzles.module.ts ***! - \*************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { +/***/ "./src/player/dto/create-player.dto.ts": +/*!*********************************************!*\ + !*** ./src/player/dto/create-player.dto.ts ***! + \*********************************************/ +/***/ ((__unused_webpack_module, exports) => { -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.CommunityPuzzlesModule = 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 jwt_auth_guard_1 = __webpack_require__(/*! ../auth/guards/jwt-auth.guard */ "./src/auth/guards/jwt-auth.guard.ts"); -const user_puzzle_submission_entity_1 = __webpack_require__(/*! ./entities/user-puzzle-submission.entity */ "./src/puzzles/entities/user-puzzle-submission.entity.ts"); -const puzzle_comment_entity_1 = __webpack_require__(/*! ./entities/puzzle-comment.entity */ "./src/puzzles/entities/puzzle-comment.entity.ts"); -const user_puzzle_submission_service_1 = __webpack_require__(/*! ./services/user-puzzle-submission.service */ "./src/puzzles/services/user-puzzle-submission.service.ts"); -const puzzle_validation_service_1 = __webpack_require__(/*! ./services/puzzle-validation.service */ "./src/puzzles/services/puzzle-validation.service.ts"); -const puzzle_moderation_service_1 = __webpack_require__(/*! ./services/puzzle-moderation.service */ "./src/puzzles/services/puzzle-moderation.service.ts"); -const community_puzzles_service_1 = __webpack_require__(/*! ./services/community-puzzles.service */ "./src/puzzles/services/community-puzzles.service.ts"); -const featured_puzzles_service_1 = __webpack_require__(/*! ./services/featured-puzzles.service */ "./src/puzzles/services/featured-puzzles.service.ts"); -const creator_rewards_service_1 = __webpack_require__(/*! ./services/creator-rewards.service */ "./src/puzzles/services/creator-rewards.service.ts"); -const community_puzzles_controller_1 = __webpack_require__(/*! ./controllers/community-puzzles.controller */ "./src/puzzles/controllers/community-puzzles.controller.ts"); -let CommunityPuzzlesModule = class CommunityPuzzlesModule { -}; -exports.CommunityPuzzlesModule = CommunityPuzzlesModule; -exports.CommunityPuzzlesModule = CommunityPuzzlesModule = __decorate([ - (0, common_1.Module)({ - imports: [ - typeorm_1.TypeOrmModule.forFeature([user_puzzle_submission_entity_1.UserPuzzleSubmission, puzzle_comment_entity_1.PuzzleComment]), - schedule_1.ScheduleModule.forRoot(), - ], - controllers: [community_puzzles_controller_1.CommunityPuzzlesController], - providers: [ - user_puzzle_submission_service_1.UserPuzzleSubmissionService, - puzzle_validation_service_1.PuzzleValidationService, - puzzle_moderation_service_1.PuzzleModerationService, - community_puzzles_service_1.CommunityPuzzlesService, - featured_puzzles_service_1.FeaturedPuzzlesService, - creator_rewards_service_1.CreatorRewardsService, - jwt_auth_guard_1.JwtAuthGuard, - ], - exports: [ - user_puzzle_submission_service_1.UserPuzzleSubmissionService, - puzzle_validation_service_1.PuzzleValidationService, - puzzle_moderation_service_1.PuzzleModerationService, - community_puzzles_service_1.CommunityPuzzlesService, - featured_puzzles_service_1.FeaturedPuzzlesService, - creator_rewards_service_1.CreatorRewardsService, - ], - }) -], CommunityPuzzlesModule); +exports.CreatePlayerDto = void 0; +class CreatePlayerDto { +} +exports.CreatePlayerDto = CreatePlayerDto; /***/ }), -/***/ "./src/puzzles/controllers/community-puzzles.controller.ts": -/*!*****************************************************************!*\ - !*** ./src/puzzles/controllers/community-puzzles.controller.ts ***! - \*****************************************************************/ +/***/ "./src/player/dto/update-player.dto.ts": +/*!*********************************************!*\ + !*** ./src/player/dto/update-player.dto.ts ***! + \*********************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UpdatePlayerDto = void 0; +const swagger_1 = __webpack_require__(/*! @nestjs/swagger */ "@nestjs/swagger"); +const create_player_dto_1 = __webpack_require__(/*! ./create-player.dto */ "./src/player/dto/create-player.dto.ts"); +class UpdatePlayerDto extends (0, swagger_1.PartialType)(create_player_dto_1.CreatePlayerDto) { +} +exports.UpdatePlayerDto = UpdatePlayerDto; + + +/***/ }), + +/***/ "./src/player/player.controller.ts": +/*!*****************************************!*\ + !*** ./src/player/player.controller.ts ***! + \*****************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -4093,595 +4080,277 @@ var __metadata = (this && this.__metadata) || function (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, _p; +var _a, _b, _c; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.CommunityPuzzlesController = void 0; +exports.PlayerController = 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 user_puzzle_submission_service_1 = __webpack_require__(/*! ../services/user-puzzle-submission.service */ "./src/puzzles/services/user-puzzle-submission.service.ts"); -const community_puzzles_service_1 = __webpack_require__(/*! ../services/community-puzzles.service */ "./src/puzzles/services/community-puzzles.service.ts"); -const featured_puzzles_service_1 = __webpack_require__(/*! ../services/featured-puzzles.service */ "./src/puzzles/services/featured-puzzles.service.ts"); -const creator_rewards_service_1 = __webpack_require__(/*! ../services/creator-rewards.service */ "./src/puzzles/services/creator-rewards.service.ts"); -const puzzle_moderation_service_1 = __webpack_require__(/*! ../services/puzzle-moderation.service */ "./src/puzzles/services/puzzle-moderation.service.ts"); -const user_puzzle_submission_dto_1 = __webpack_require__(/*! ../dto/user-puzzle-submission.dto */ "./src/puzzles/dto/user-puzzle-submission.dto.ts"); -const community_puzzles_dto_1 = __webpack_require__(/*! ../dto/community-puzzles.dto */ "./src/puzzles/dto/community-puzzles.dto.ts"); -let CommunityPuzzlesController = class CommunityPuzzlesController { - constructor(submissionService, communityService, featuredService, rewardsService, moderationService) { - this.submissionService = submissionService; - this.communityService = communityService; - this.featuredService = featuredService; - this.rewardsService = rewardsService; - this.moderationService = moderationService; - } - async createSubmission(req, createDto) { - const submission = await this.submissionService.createSubmission(req.user.id, createDto); - return { - statusCode: common_1.HttpStatus.CREATED, - message: 'Puzzle submission created successfully', - data: submission, - }; - } - async getUserSubmissions(req, status, page, limit) { - const result = await this.submissionService.getUserSubmissions(req.user.id, status, page, limit); - return { - statusCode: common_1.HttpStatus.OK, - message: 'User submissions retrieved successfully', - data: result, - }; - } - async getSubmission(req, id) { - const submission = await this.submissionService.getSubmissionById(id, req.user.id); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Submission retrieved successfully', - data: submission, - }; - } - async updateSubmission(req, id, updateDto) { - const submission = await this.submissionService.updateSubmission(id, req.user.id, updateDto); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Submission updated successfully', - data: submission, - }; - } - async deleteSubmission(req, id) { - await this.submissionService.deleteSubmission(id, req.user.id); - } - async submitForReview(req, id, reviewData) { - const submission = await this.submissionService.submitForReview(id, req.user.id, reviewData); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzle submitted for review', - data: submission, - }; - } - async publishPuzzle(req, id) { - const submission = await this.submissionService.publishPuzzle(id, req.user.id); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzle published successfully', - data: submission, - }; - } - async searchPuzzles(searchDto) { - const result = await this.submissionService.searchCommunityPuzzles(searchDto); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzles retrieved successfully', - data: result, - }; - } - async getFeaturedPuzzles(limit) { - const puzzles = await this.featuredService.getFeaturedPuzzles(limit); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Featured puzzles retrieved successfully', - data: puzzles, - }; - } - async getTrendingPuzzles(limit) { - const puzzles = await this.submissionService.getTrendingPuzzles(limit); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Trending puzzles retrieved successfully', - data: puzzles, - }; - } - async getRecommendedPuzzles(req, limit) { - const puzzles = await this.submissionService.getRecommendedPuzzles(req.user.id, limit); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Recommended puzzles retrieved successfully', - data: puzzles, - }; - } - async getPuzzleByShareableLink(shareableLink) { - const puzzle = await this.submissionService.getSubmissionByShareableLink(shareableLink); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzle retrieved successfully', - data: puzzle, - }; - } - async ratePuzzle(req, id, ratingDto) { - const rating = await this.communityService.ratePuzzle(id, req.user.id, ratingDto); - return { - statusCode: common_1.HttpStatus.CREATED, - message: 'Puzzle rated successfully', - data: rating, - }; - } - async getPuzzleRatings(id, page, limit) { - const result = await this.communityService.getPuzzleRatings(id, page, limit); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzle ratings retrieved successfully', - data: result, - }; - } - async getUserRating(req, id) { - const rating = await this.communityService.getUserRating(id, req.user.id); - return { - statusCode: common_1.HttpStatus.OK, - message: 'User rating retrieved successfully', - data: rating, - }; - } - async createComment(req, id, commentDto) { - const comment = await this.communityService.createComment(id, req.user.id, commentDto); - return { - statusCode: common_1.HttpStatus.CREATED, - message: 'Comment created successfully', - data: comment, - }; - } - async getPuzzleComments(id, page, limit) { - const result = await this.communityService.getPuzzleComments(id, page, limit); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzle comments retrieved successfully', - data: result, - }; - } - async updateComment(req, id, updateDto) { - const comment = await this.communityService.updateComment(id, req.user.id, updateDto); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Comment updated successfully', - data: comment, - }; +const player_service_1 = __webpack_require__(/*! ./player.service */ "./src/player/player.service.ts"); +const create_player_dto_1 = __webpack_require__(/*! ./dto/create-player.dto */ "./src/player/dto/create-player.dto.ts"); +const update_player_dto_1 = __webpack_require__(/*! ./dto/update-player.dto */ "./src/player/dto/update-player.dto.ts"); +let PlayerController = class PlayerController { + constructor(playerService) { + this.playerService = playerService; } - async deleteComment(req, id) { - await this.communityService.deleteComment(id, req.user.id); - } - async voteOnComment(req, id, voteDto) { - const comment = await this.communityService.voteOnComment(id, req.user.id, voteDto); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Vote recorded successfully', - data: comment, - }; + create(createPlayerDto) { + return this.playerService.create(createPlayerDto); } - async sharePuzzle(req, id, shareDto) { - const result = await this.communityService.sharePuzzle(id, req.user.id, shareDto); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzle shared successfully', - data: result, - }; + findAll() { + return this.playerService.findAll(); } - async getShareStats(id) { - const stats = await this.communityService.getShareStats(id); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Share statistics retrieved successfully', - data: stats, - }; + findOne(id) { + return this.playerService.findOne(+id); } - async reportPuzzle(req, id, reportDto) { - await this.communityService.reportPuzzle(id, req.user.id, reportDto.reason, reportDto.category); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzle reported successfully', - }; + update(id, updatePlayerDto) { + return this.playerService.update(+id, updatePlayerDto); } - async reportComment(req, id, reportData) { - await this.communityService.reportComment(id, req.user.id, reportData.reason); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Comment reported successfully', - }; + remove(id) { + return this.playerService.remove(+id); } - async getCreatorStats(req) { - const stats = await this.submissionService.getCreatorStats(req.user.id); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Creator statistics retrieved successfully', - data: stats, - }; +}; +exports.PlayerController = PlayerController; +__decorate([ + (0, common_1.Post)(), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof create_player_dto_1.CreatePlayerDto !== "undefined" && create_player_dto_1.CreatePlayerDto) === "function" ? _b : Object]), + __metadata("design:returntype", void 0) +], PlayerController.prototype, "create", null); +__decorate([ + (0, common_1.Get)(), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", void 0) +], PlayerController.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) +], PlayerController.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_player_dto_1.UpdatePlayerDto !== "undefined" && update_player_dto_1.UpdatePlayerDto) === "function" ? _c : Object]), + __metadata("design:returntype", void 0) +], PlayerController.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) +], PlayerController.prototype, "remove", null); +exports.PlayerController = PlayerController = __decorate([ + (0, common_1.Controller)('player'), + __metadata("design:paramtypes", [typeof (_a = typeof player_service_1.PlayerService !== "undefined" && player_service_1.PlayerService) === "function" ? _a : Object]) +], PlayerController); + + +/***/ }), + +/***/ "./src/player/player.module.ts": +/*!*************************************!*\ + !*** ./src/player/player.module.ts ***! + \*************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +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.PlayerModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const player_service_1 = __webpack_require__(/*! ./player.service */ "./src/player/player.service.ts"); +const player_controller_1 = __webpack_require__(/*! ./player.controller */ "./src/player/player.controller.ts"); +let PlayerModule = class PlayerModule { +}; +exports.PlayerModule = PlayerModule; +exports.PlayerModule = PlayerModule = __decorate([ + (0, common_1.Module)({ + controllers: [player_controller_1.PlayerController], + providers: [player_service_1.PlayerService], + }) +], PlayerModule); + + +/***/ }), + +/***/ "./src/player/player.service.ts": +/*!**************************************!*\ + !*** ./src/player/player.service.ts ***! + \**************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +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.PlayerService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +let PlayerService = class PlayerService { + create(createPlayerDto) { + return 'This action adds a new player'; } - async getLeaderboard(limit, timeframe) { - const leaderboard = await this.rewardsService.getLeaderboard(limit, timeframe); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Leaderboard retrieved successfully', - data: leaderboard, - }; + findAll() { + return `This action returns all player`; } - async getTopCreators(limit) { - const creators = await this.communityService.getTopCreators(limit); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Top creators retrieved successfully', - data: creators, - }; + findOne(id) { + return `This action returns a #${id} player`; } - async getMyRewards(req) { - const stats = await this.rewardsService.getCreatorStats(req.user.id); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Creator rewards retrieved successfully', - data: stats, - }; + update(id, updatePlayerDto) { + return `This action updates a #${id} player`; } - async trackPlay(req, id) { - await this.submissionService.incrementPlayCount(id); - await this.rewardsService.onPuzzlePlayed(id, req.user.id); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Play tracked successfully', - }; + remove(id) { + return `This action removes a #${id} player`; } - async getModerationQueue(status, page, limit) { - const result = await this.moderationService.getModerationQueue(status, page, limit); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Moderation queue retrieved successfully', - data: result, - }; +}; +exports.PlayerService = PlayerService; +exports.PlayerService = PlayerService = __decorate([ + (0, common_1.Injectable)() +], PlayerService); + + +/***/ }), + +/***/ "./src/profile/dto/create-profile.dto.ts": +/*!***********************************************!*\ + !*** ./src/profile/dto/create-profile.dto.ts ***! + \***********************************************/ +/***/ ((__unused_webpack_module, exports) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreateProfileDto = void 0; +class CreateProfileDto { +} +exports.CreateProfileDto = CreateProfileDto; + + +/***/ }), + +/***/ "./src/profile/dto/update-profile.dto.ts": +/*!***********************************************!*\ + !*** ./src/profile/dto/update-profile.dto.ts ***! + \***********************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UpdateProfileDto = void 0; +const swagger_1 = __webpack_require__(/*! @nestjs/swagger */ "@nestjs/swagger"); +const create_profile_dto_1 = __webpack_require__(/*! ./create-profile.dto */ "./src/profile/dto/create-profile.dto.ts"); +class UpdateProfileDto extends (0, swagger_1.PartialType)(create_profile_dto_1.CreateProfileDto) { +} +exports.UpdateProfileDto = UpdateProfileDto; + + +/***/ }), + +/***/ "./src/profile/profile.controller.ts": +/*!*******************************************!*\ + !*** ./src/profile/profile.controller.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +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.ProfileController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const profile_service_1 = __webpack_require__(/*! ./profile.service */ "./src/profile/profile.service.ts"); +const create_profile_dto_1 = __webpack_require__(/*! ./dto/create-profile.dto */ "./src/profile/dto/create-profile.dto.ts"); +const update_profile_dto_1 = __webpack_require__(/*! ./dto/update-profile.dto */ "./src/profile/dto/update-profile.dto.ts"); +let ProfileController = class ProfileController { + constructor(profileService) { + this.profileService = profileService; } - async moderatePuzzle(req, id, decisionDto) { - const submission = await this.moderationService.moderatePuzzle(id, req.user.id, decisionDto); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzle moderated successfully', - data: submission, - }; + create(createProfileDto) { + return this.profileService.create(createProfileDto); } - async featurePuzzle(req, id) { - const puzzle = await this.featuredService.manuallyFeaturePuzzle(id, req.user.id); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzle featured successfully', - data: puzzle, - }; + findAll() { + return this.profileService.findAll(); } - async unfeaturePuzzle(req, id) { - const puzzle = await this.featuredService.unfeaturePuzzle(id, req.user.id); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Puzzle unfeatured successfully', - data: puzzle, - }; + findOne(id) { + return this.profileService.findOne(+id); } - async getFeaturedStats() { - const stats = await this.featuredService.getFeaturedPuzzleStats(); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Featured puzzle statistics retrieved successfully', - data: stats, - }; + update(id, updateProfileDto) { + return this.profileService.update(+id, updateProfileDto); } - async getModerationStats(timeframe) { - const stats = await this.moderationService.getModerationStats(timeframe); - return { - statusCode: common_1.HttpStatus.OK, - message: 'Moderation statistics retrieved successfully', - data: stats, - }; + remove(id) { + return this.profileService.remove(+id); } }; -exports.CommunityPuzzlesController = CommunityPuzzlesController; +exports.ProfileController = ProfileController; __decorate([ - (0, common_1.Post)('submissions'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Body)()), + (0, common_1.Post)(), + __param(0, (0, common_1.Body)()), __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, typeof (_f = typeof user_puzzle_submission_dto_1.CreatePuzzleSubmissionDto !== "undefined" && user_puzzle_submission_dto_1.CreatePuzzleSubmissionDto) === "function" ? _f : Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "createSubmission", null); + __metadata("design:paramtypes", [typeof (_b = typeof create_profile_dto_1.CreateProfileDto !== "undefined" && create_profile_dto_1.CreateProfileDto) === "function" ? _b : Object]), + __metadata("design:returntype", void 0) +], ProfileController.prototype, "create", null); __decorate([ - (0, common_1.Get)('submissions'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Query)('status')), - __param(2, (0, common_1.Query)('page')), - __param(3, (0, common_1.Query)('limit')), + (0, common_1.Get)(), __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, Number, Number]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getUserSubmissions", null); -__decorate([ - (0, common_1.Get)('submissions/:id'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getSubmission", null); -__decorate([ - (0, common_1.Put)('submissions/:id'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __param(2, (0, common_1.Body)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, typeof (_g = typeof user_puzzle_submission_dto_1.UpdatePuzzleSubmissionDto !== "undefined" && user_puzzle_submission_dto_1.UpdatePuzzleSubmissionDto) === "function" ? _g : Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "updateSubmission", null); -__decorate([ - (0, common_1.Delete)('submissions/:id'), - (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "deleteSubmission", null); -__decorate([ - (0, common_1.Post)('submissions/:id/submit-review'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __param(2, (0, common_1.Body)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, typeof (_h = typeof user_puzzle_submission_dto_1.SubmitForReviewDto !== "undefined" && user_puzzle_submission_dto_1.SubmitForReviewDto) === "function" ? _h : Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "submitForReview", null); -__decorate([ - (0, common_1.Post)('submissions/:id/publish'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "publishPuzzle", null); -__decorate([ - (0, common_1.Get)('discover'), - __param(0, (0, common_1.Query)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [typeof (_j = typeof community_puzzles_dto_1.SearchPuzzlesDto !== "undefined" && community_puzzles_dto_1.SearchPuzzlesDto) === "function" ? _j : Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "searchPuzzles", null); -__decorate([ - (0, common_1.Get)('featured'), - __param(0, (0, common_1.Query)('limit')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Number]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getFeaturedPuzzles", null); -__decorate([ - (0, common_1.Get)('trending'), - __param(0, (0, common_1.Query)('limit')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Number]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getTrendingPuzzles", null); -__decorate([ - (0, common_1.Get)('recommended'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Query)('limit')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, Number]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getRecommendedPuzzles", null); -__decorate([ - (0, common_1.Get)('shared/:shareableLink'), - __param(0, (0, common_1.Param)('shareableLink')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getPuzzleByShareableLink", null); -__decorate([ - (0, common_1.Post)(':id/rate'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __param(2, (0, common_1.Body)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, typeof (_k = typeof community_puzzles_dto_1.CreatePuzzleRatingDto !== "undefined" && community_puzzles_dto_1.CreatePuzzleRatingDto) === "function" ? _k : Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "ratePuzzle", null); + __metadata("design:paramtypes", []), + __metadata("design:returntype", void 0) +], ProfileController.prototype, "findAll", null); __decorate([ - (0, common_1.Get)(':id/ratings'), + (0, common_1.Get)(':id'), __param(0, (0, common_1.Param)('id')), - __param(1, (0, common_1.Query)('page')), - __param(2, (0, common_1.Query)('limit')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [String, Number, Number]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getPuzzleRatings", null); -__decorate([ - (0, common_1.Get)(':id/my-rating'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getUserRating", null); -__decorate([ - (0, common_1.Post)(':id/comments'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __param(2, (0, common_1.Body)()), __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, typeof (_l = typeof community_puzzles_dto_1.CreatePuzzleCommentDto !== "undefined" && community_puzzles_dto_1.CreatePuzzleCommentDto) === "function" ? _l : Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "createComment", null); + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", void 0) +], ProfileController.prototype, "findOne", null); __decorate([ - (0, common_1.Get)(':id/comments'), + (0, common_1.Patch)(':id'), __param(0, (0, common_1.Param)('id')), - __param(1, (0, common_1.Query)('page')), - __param(2, (0, common_1.Query)('limit')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [String, Number, Number]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getPuzzleComments", null); -__decorate([ - (0, common_1.Put)('comments/:id'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __param(2, (0, common_1.Body)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "updateComment", null); -__decorate([ - (0, common_1.Delete)('comments/:id'), - (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "deleteComment", null); -__decorate([ - (0, common_1.Post)('comments/:id/vote'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __param(2, (0, common_1.Body)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, typeof (_m = typeof community_puzzles_dto_1.PuzzleCommentVoteDto !== "undefined" && community_puzzles_dto_1.PuzzleCommentVoteDto) === "function" ? _m : Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "voteOnComment", null); -__decorate([ - (0, common_1.Post)(':id/share'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __param(2, (0, common_1.Body)()), + __param(1, (0, common_1.Body)()), __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, typeof (_o = typeof community_puzzles_dto_1.SharePuzzleDto !== "undefined" && community_puzzles_dto_1.SharePuzzleDto) === "function" ? _o : Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "sharePuzzle", null); + __metadata("design:paramtypes", [String, typeof (_c = typeof update_profile_dto_1.UpdateProfileDto !== "undefined" && update_profile_dto_1.UpdateProfileDto) === "function" ? _c : Object]), + __metadata("design:returntype", void 0) +], ProfileController.prototype, "update", null); __decorate([ - (0, common_1.Get)(':id/share-stats'), + (0, common_1.Delete)(':id'), __param(0, (0, common_1.Param)('id')), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getShareStats", null); -__decorate([ - (0, common_1.Post)(':id/report'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __param(2, (0, common_1.Body)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, typeof (_p = typeof community_puzzles_dto_1.ReportPuzzleDto !== "undefined" && community_puzzles_dto_1.ReportPuzzleDto) === "function" ? _p : Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "reportPuzzle", null); -__decorate([ - (0, common_1.Post)('comments/:id/report'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __param(2, (0, common_1.Body)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "reportComment", null); -__decorate([ - (0, common_1.Get)('creator-stats'), - __param(0, (0, common_1.Request)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getCreatorStats", null); -__decorate([ - (0, common_1.Get)('leaderboard'), - __param(0, (0, common_1.Query)('limit')), - __param(1, (0, common_1.Query)('timeframe')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Number, String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getLeaderboard", null); -__decorate([ - (0, common_1.Get)('top-creators'), - __param(0, (0, common_1.Query)('limit')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Number]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getTopCreators", null); -__decorate([ - (0, common_1.Get)('my-rewards'), - __param(0, (0, common_1.Request)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getMyRewards", null); -__decorate([ - (0, common_1.Post)(':id/play'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "trackPlay", null); -__decorate([ - (0, common_1.Get)('admin/moderation-queue'), - __param(0, (0, common_1.Query)('status')), - __param(1, (0, common_1.Query)('page')), - __param(2, (0, common_1.Query)('limit')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [String, Number, Number]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getModerationQueue", null); -__decorate([ - (0, common_1.Post)('admin/:id/moderate'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __param(2, (0, common_1.Body)()), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String, Object]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "moderatePuzzle", null); -__decorate([ - (0, common_1.Post)('admin/:id/feature'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "featurePuzzle", null); -__decorate([ - (0, common_1.Post)('admin/:id/unfeature'), - __param(0, (0, common_1.Request)()), - __param(1, (0, common_1.Param)('id')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object, String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "unfeaturePuzzle", null); -__decorate([ - (0, common_1.Get)('admin/featured-stats'), - __metadata("design:type", Function), - __metadata("design:paramtypes", []), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getFeaturedStats", null); -__decorate([ - (0, common_1.Get)('admin/moderation-stats'), - __param(0, (0, common_1.Query)('timeframe')), - __metadata("design:type", Function), - __metadata("design:paramtypes", [String]), - __metadata("design:returntype", Promise) -], CommunityPuzzlesController.prototype, "getModerationStats", null); -exports.CommunityPuzzlesController = CommunityPuzzlesController = __decorate([ - (0, common_1.Controller)('community-puzzles'), - (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard), - __metadata("design:paramtypes", [typeof (_a = typeof user_puzzle_submission_service_1.UserPuzzleSubmissionService !== "undefined" && user_puzzle_submission_service_1.UserPuzzleSubmissionService) === "function" ? _a : Object, typeof (_b = typeof community_puzzles_service_1.CommunityPuzzlesService !== "undefined" && community_puzzles_service_1.CommunityPuzzlesService) === "function" ? _b : Object, typeof (_c = typeof featured_puzzles_service_1.FeaturedPuzzlesService !== "undefined" && featured_puzzles_service_1.FeaturedPuzzlesService) === "function" ? _c : Object, typeof (_d = typeof creator_rewards_service_1.CreatorRewardsService !== "undefined" && creator_rewards_service_1.CreatorRewardsService) === "function" ? _d : Object, typeof (_e = typeof puzzle_moderation_service_1.PuzzleModerationService !== "undefined" && puzzle_moderation_service_1.PuzzleModerationService) === "function" ? _e : Object]) -], CommunityPuzzlesController); + __metadata("design:returntype", void 0) +], ProfileController.prototype, "remove", null); +exports.ProfileController = ProfileController = __decorate([ + (0, common_1.Controller)('profile'), + __metadata("design:paramtypes", [typeof (_a = typeof profile_service_1.ProfileService !== "undefined" && profile_service_1.ProfileService) === "function" ? _a : Object]) +], ProfileController); /***/ }), -/***/ "./src/puzzles/dto/bulk-operations.dto.ts": -/*!************************************************!*\ - !*** ./src/puzzles/dto/bulk-operations.dto.ts ***! - \************************************************/ +/***/ "./src/profile/profile.module.ts": +/*!***************************************!*\ + !*** ./src/profile/profile.module.ts ***! + \***************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -4691,92 +4360,28 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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); +exports.ProfileModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const profile_service_1 = __webpack_require__(/*! ./profile.service */ "./src/profile/profile.service.ts"); +const profile_controller_1 = __webpack_require__(/*! ./profile.controller */ "./src/profile/profile.controller.ts"); +let ProfileModule = class ProfileModule { +}; +exports.ProfileModule = ProfileModule; +exports.ProfileModule = ProfileModule = __decorate([ + (0, common_1.Module)({ + controllers: [profile_controller_1.ProfileController], + providers: [profile_service_1.ProfileService], + }) +], ProfileModule); /***/ }), -/***/ "./src/puzzles/dto/community-puzzles.dto.ts": -/*!**************************************************!*\ - !*** ./src/puzzles/dto/community-puzzles.dto.ts ***! - \**************************************************/ +/***/ "./src/profile/profile.service.ts": +/*!****************************************!*\ + !*** ./src/profile/profile.service.ts ***! + \****************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -4786,276 +4391,72 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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.SharePuzzleDto = exports.SearchPuzzlesDto = exports.ReportPuzzleDto = exports.ReportPuzzleCommentDto = exports.PuzzleCommentVoteDto = exports.UpdatePuzzleCommentDto = exports.CreatePuzzleCommentDto = exports.RatingMetadataDto = exports.RatingBreakdownDto = exports.CreatePuzzleRatingDto = void 0; -const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); -const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); -class CreatePuzzleRatingDto { -} -exports.CreatePuzzleRatingDto = CreatePuzzleRatingDto; -__decorate([ - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(1), - (0, class_validator_1.Max)(5), - __metadata("design:type", Number) -], CreatePuzzleRatingDto.prototype, "rating", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - (0, class_validator_1.Length)(0, 1000), - __metadata("design:type", String) -], CreatePuzzleRatingDto.prototype, "review", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsObject)(), - (0, class_validator_1.ValidateNested)(), - (0, class_transformer_1.Type)(() => RatingBreakdownDto), - __metadata("design:type", RatingBreakdownDto) -], CreatePuzzleRatingDto.prototype, "ratingBreakdown", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsObject)(), - (0, class_validator_1.ValidateNested)(), - (0, class_transformer_1.Type)(() => RatingMetadataDto), - __metadata("design:type", RatingMetadataDto) -], CreatePuzzleRatingDto.prototype, "metadata", void 0); -class RatingBreakdownDto { -} -exports.RatingBreakdownDto = RatingBreakdownDto; -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(1), - (0, class_validator_1.Max)(5), - __metadata("design:type", Number) -], RatingBreakdownDto.prototype, "creativity", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(1), - (0, class_validator_1.Max)(5), - __metadata("design:type", Number) -], RatingBreakdownDto.prototype, "clarity", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(1), - (0, class_validator_1.Max)(5), - __metadata("design:type", Number) -], RatingBreakdownDto.prototype, "difficulty", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(1), - (0, class_validator_1.Max)(5), - __metadata("design:type", Number) -], RatingBreakdownDto.prototype, "enjoyment", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(1), - (0, class_validator_1.Max)(5), - __metadata("design:type", Number) -], RatingBreakdownDto.prototype, "educational", void 0); -class RatingMetadataDto { -} -exports.RatingMetadataDto = RatingMetadataDto; -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(0), - __metadata("design:type", Number) -], RatingMetadataDto.prototype, "playTime", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(0), - __metadata("design:type", Number) -], RatingMetadataDto.prototype, "hintsUsed", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], RatingMetadataDto.prototype, "completed", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], RatingMetadataDto.prototype, "wouldRecommend", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - __metadata("design:type", String) -], RatingMetadataDto.prototype, "reportReason", void 0); -class CreatePuzzleCommentDto { -} -exports.CreatePuzzleCommentDto = CreatePuzzleCommentDto; -__decorate([ - (0, class_validator_1.IsString)(), - (0, class_validator_1.IsNotEmpty)(), - (0, class_validator_1.Length)(1, 1000), - __metadata("design:type", String) -], CreatePuzzleCommentDto.prototype, "content", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - __metadata("design:type", String) -], CreatePuzzleCommentDto.prototype, "parentId", void 0); -class UpdatePuzzleCommentDto { -} -exports.UpdatePuzzleCommentDto = UpdatePuzzleCommentDto; -__decorate([ - (0, class_validator_1.IsString)(), - (0, class_validator_1.IsNotEmpty)(), - (0, class_validator_1.Length)(1, 1000), - __metadata("design:type", String) -], UpdatePuzzleCommentDto.prototype, "content", void 0); -class PuzzleCommentVoteDto { -} -exports.PuzzleCommentVoteDto = PuzzleCommentVoteDto; -__decorate([ - (0, class_validator_1.IsEnum)(['upvote', 'downvote']), - __metadata("design:type", String) -], PuzzleCommentVoteDto.prototype, "voteType", void 0); -class ReportPuzzleCommentDto { -} -exports.ReportPuzzleCommentDto = ReportPuzzleCommentDto; -__decorate([ - (0, class_validator_1.IsString)(), - (0, class_validator_1.IsNotEmpty)(), - (0, class_validator_1.Length)(5, 500), - __metadata("design:type", String) -], ReportPuzzleCommentDto.prototype, "reason", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - (0, class_validator_1.Length)(0, 1000), - __metadata("design:type", String) -], ReportPuzzleCommentDto.prototype, "additionalDetails", void 0); -class ReportPuzzleDto { -} -exports.ReportPuzzleDto = ReportPuzzleDto; -__decorate([ - (0, class_validator_1.IsString)(), - (0, class_validator_1.IsNotEmpty)(), - (0, class_validator_1.Length)(5, 500), - __metadata("design:type", String) -], ReportPuzzleDto.prototype, "reason", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsEnum)(['inappropriate', 'copyright', 'spam', 'low_quality', 'duplicate', 'other']), - __metadata("design:type", String) -], ReportPuzzleDto.prototype, "category", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - (0, class_validator_1.Length)(0, 1000), - __metadata("design:type", String) -], ReportPuzzleDto.prototype, "additionalDetails", void 0); -class SearchPuzzlesDto { - constructor() { - this.page = 1; - this.limit = 20; +exports.ProfileService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +let ProfileService = class ProfileService { + create(createProfileDto) { + return 'This action adds a new profile'; + } + findAll() { + return `This action returns all profile`; + } + findOne(id) { + return `This action returns a #${id} profile`; + } + update(id, updateProfileDto) { + return `This action updates a #${id} profile`; + } + remove(id) { + return `This action removes a #${id} profile`; } +}; +exports.ProfileService = ProfileService; +exports.ProfileService = ProfileService = __decorate([ + (0, common_1.Injectable)() +], ProfileService); + + +/***/ }), + +/***/ "./src/progress/dto/create-progress.dto.ts": +/*!*************************************************!*\ + !*** ./src/progress/dto/create-progress.dto.ts ***! + \*************************************************/ +/***/ ((__unused_webpack_module, exports) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CreateProgressDto = void 0; +class CreateProgressDto { } -exports.SearchPuzzlesDto = SearchPuzzlesDto; -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - (0, class_validator_1.Length)(0, 100), - __metadata("design:type", String) -], SearchPuzzlesDto.prototype, "query", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsArray)(), - (0, class_validator_1.IsString)({ each: true }), - __metadata("design:type", Array) -], SearchPuzzlesDto.prototype, "categories", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsArray)(), - (0, class_validator_1.IsEnum)(['easy', 'medium', 'hard', 'expert'], { each: true }), - __metadata("design:type", Array) -], SearchPuzzlesDto.prototype, "difficulties", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsArray)(), - (0, class_validator_1.IsString)({ each: true }), - __metadata("design:type", Array) -], SearchPuzzlesDto.prototype, "tags", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsEnum)(['newest', 'oldest', 'popular', 'highest_rated', 'most_played', 'trending']), - __metadata("design:type", String) -], SearchPuzzlesDto.prototype, "sortBy", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsEnum)(['draft', 'submitted', 'under_review', 'approved', 'rejected', 'published', 'featured']), - __metadata("design:type", String) -], SearchPuzzlesDto.prototype, "status", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(1), - __metadata("design:type", Number) -], SearchPuzzlesDto.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) -], SearchPuzzlesDto.prototype, "limit", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - __metadata("design:type", String) -], SearchPuzzlesDto.prototype, "userId", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], SearchPuzzlesDto.prototype, "isPublic", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], SearchPuzzlesDto.prototype, "allowComments", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], SearchPuzzlesDto.prototype, "allowRatings", void 0); -class SharePuzzleDto { +exports.CreateProgressDto = CreateProgressDto; + + +/***/ }), + +/***/ "./src/progress/dto/update-progress.dto.ts": +/*!*************************************************!*\ + !*** ./src/progress/dto/update-progress.dto.ts ***! + \*************************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UpdateProgressDto = void 0; +const swagger_1 = __webpack_require__(/*! @nestjs/swagger */ "@nestjs/swagger"); +const create_progress_dto_1 = __webpack_require__(/*! ./create-progress.dto */ "./src/progress/dto/create-progress.dto.ts"); +class UpdateProgressDto extends (0, swagger_1.PartialType)(create_progress_dto_1.CreateProgressDto) { } -exports.SharePuzzleDto = SharePuzzleDto; -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsEnum)(['link', 'embed', 'social']), - __metadata("design:type", String) -], SharePuzzleDto.prototype, "shareType", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsEnum)(['twitter', 'facebook', 'reddit', 'discord', 'whatsapp']), - __metadata("design:type", String) -], SharePuzzleDto.prototype, "platform", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - (0, class_validator_1.Length)(0, 500), - __metadata("design:type", String) -], SharePuzzleDto.prototype, "customMessage", void 0); +exports.UpdateProgressDto = UpdateProgressDto; /***/ }), -/***/ "./src/puzzles/dto/create-puzzle.dto.ts": -/*!**********************************************!*\ - !*** ./src/puzzles/dto/create-puzzle.dto.ts ***! - \**********************************************/ +/***/ "./src/progress/progress.controller.ts": +/*!*********************************************!*\ + !*** ./src/progress/progress.controller.ts ***! + \*********************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -5068,226 +4469,156 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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.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; +exports.ProgressController = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const progress_service_1 = __webpack_require__(/*! ./progress.service */ "./src/progress/progress.service.ts"); +const create_progress_dto_1 = __webpack_require__(/*! ./dto/create-progress.dto */ "./src/progress/dto/create-progress.dto.ts"); +const update_progress_dto_1 = __webpack_require__(/*! ./dto/update-progress.dto */ "./src/progress/dto/update-progress.dto.ts"); +let ProgressController = class ProgressController { + constructor(progressService) { + this.progressService = progressService; + } + create(createProgressDto) { + return this.progressService.create(createProgressDto); + } + findAll() { + return this.progressService.findAll(); + } + findOne(id) { + return this.progressService.findOne(+id); + } + update(id, updateProgressDto) { + return this.progressService.update(+id, updateProgressDto); + } + remove(id) { + return this.progressService.remove(+id); + } +}; +exports.ProgressController = ProgressController; __decorate([ - (0, class_validator_1.IsEnum)(PuzzleContentType), - __metadata("design:type", String) -], PuzzleContentDto.prototype, "type", void 0); + (0, common_1.Post)(), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [typeof (_b = typeof create_progress_dto_1.CreateProgressDto !== "undefined" && create_progress_dto_1.CreateProgressDto) === "function" ? _b : Object]), + __metadata("design:returntype", void 0) +], ProgressController.prototype, "create", null); __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); + (0, common_1.Get)(), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", void 0) +], ProgressController.prototype, "findAll", null); __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); + (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) +], ProgressController.prototype, "findOne", null); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], CreatePuzzleDto.prototype, "isFeatured", void 0); + (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_progress_dto_1.UpdateProgressDto !== "undefined" && update_progress_dto_1.UpdateProgressDto) === "function" ? _c : Object]), + __metadata("design:returntype", void 0) +], ProgressController.prototype, "update", null); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsUUID)(), - __metadata("design:type", String) -], CreatePuzzleDto.prototype, "parentPuzzleId", void 0); + (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) +], ProgressController.prototype, "remove", null); +exports.ProgressController = ProgressController = __decorate([ + (0, common_1.Controller)('progress'), + __metadata("design:paramtypes", [typeof (_a = typeof progress_service_1.ProgressService !== "undefined" && progress_service_1.ProgressService) === "function" ? _a : Object]) +], ProgressController); /***/ }), -/***/ "./src/puzzles/dto/index.ts": -/*!**********************************!*\ - !*** ./src/puzzles/dto/index.ts ***! - \**********************************/ +/***/ "./src/progress/progress.module.ts": +/*!*****************************************!*\ + !*** ./src/progress/progress.module.ts ***! + \*****************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { -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); +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 })); -__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); +exports.ProgressModule = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +const progress_service_1 = __webpack_require__(/*! ./progress.service */ "./src/progress/progress.service.ts"); +const progress_controller_1 = __webpack_require__(/*! ./progress.controller */ "./src/progress/progress.controller.ts"); +let ProgressModule = class ProgressModule { +}; +exports.ProgressModule = ProgressModule; +exports.ProgressModule = ProgressModule = __decorate([ + (0, common_1.Module)({ + controllers: [progress_controller_1.ProgressController], + providers: [progress_service_1.ProgressService], + }) +], ProgressModule); /***/ }), -/***/ "./src/puzzles/dto/search-puzzle.dto.ts": -/*!**********************************************!*\ - !*** ./src/puzzles/dto/search-puzzle.dto.ts ***! - \**********************************************/ +/***/ "./src/progress/progress.service.ts": +/*!******************************************!*\ + !*** ./src/progress/progress.service.ts ***! + \******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +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.ProgressService = void 0; +const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); +let ProgressService = class ProgressService { + create(createProgressDto) { + return 'This action adds a new progress'; + } + findAll() { + return `This action returns all progress`; + } + findOne(id) { + return `This action returns a #${id} progress`; + } + update(id, updateProgressDto) { + return `This action updates a #${id} progress`; + } + remove(id) { + return `This action removes a #${id} progress`; + } +}; +exports.ProgressService = ProgressService; +exports.ProgressService = ProgressService = __decorate([ + (0, common_1.Injectable)() +], ProgressService); + + +/***/ }), + +/***/ "./src/puzzles/category.controller.ts": +/*!********************************************!*\ + !*** ./src/puzzles/category.controller.ts ***! + \********************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -5300,140 +4631,158 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; -var _a; +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.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.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; } -} -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); + 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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - __metadata("design:type", String) -], SearchPuzzleDto.prototype, "createdBy", void 0); + (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, 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); + (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, 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); + (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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsEnum)(SortBy), - __metadata("design:type", String) -], SearchPuzzleDto.prototype, "sortBy", void 0); + (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, 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'; + (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__) { + + +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; } -} -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); + 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/dto/update-puzzle.dto.ts": +/***/ "./src/puzzles/collection.controller.ts": /*!**********************************************!*\ - !*** ./src/puzzles/dto/update-puzzle.dto.ts ***! + !*** ./src/puzzles/collection.controller.ts ***! \**********************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -5447,38 +4796,103 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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.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"); +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 UpdatePuzzleDto extends (0, mapped_types_1.PartialType)((0, mapped_types_1.OmitType)(create_puzzle_dto_1.CreatePuzzleDto, ['parentPuzzleId'])) { +class CollectionQueryDto { } -exports.UpdatePuzzleDto = UpdatePuzzleDto; __decorate([ (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], UpdatePuzzleDto.prototype, "isPublished", void 0); + IsUUID({}, { each: true }), + __metadata("design:type", Array) +], CollectionQueryDto.prototype, "categoryIds", void 0); __decorate([ (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], UpdatePuzzleDto.prototype, "isArchived", void 0); + IsUUID({}, { each: true }), + __metadata("design:type", Array) +], CollectionQueryDto.prototype, "themeIds", void 0); __decorate([ (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - (0, class_validator_1.MaxLength)(500), + IsString(), __metadata("design:type", String) -], UpdatePuzzleDto.prototype, "updateReason", void 0); +], 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/dto/user-puzzle-submission.dto.ts": -/*!*******************************************************!*\ - !*** ./src/puzzles/dto/user-puzzle-submission.dto.ts ***! - \*******************************************************/ +/***/ "./src/puzzles/collection.service.ts": +/*!*******************************************!*\ + !*** ./src/puzzles/collection.service.ts ***! + \*******************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -5491,396 +4905,3106 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; -var _a; +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.ModerationDecisionDto = exports.SubmitForReviewDto = exports.UpdatePuzzleSubmissionDto = exports.CreatorNotesDto = exports.SharingSettingsDto = exports.PuzzleHintDto = exports.MediaContentDto = exports.PuzzleContentDto = exports.CreatePuzzleSubmissionDto = void 0; -const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); -const class_transformer_1 = __webpack_require__(/*! class-transformer */ "class-transformer"); -const user_puzzle_submission_entity_1 = __webpack_require__(/*! ../entities/user-puzzle-submission.entity */ "./src/puzzles/entities/user-puzzle-submission.entity.ts"); -class CreatePuzzleSubmissionDto { - constructor() { - this.isPublic = false; - this.allowComments = true; - this.allowRatings = 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); } -} -exports.CreatePuzzleSubmissionDto = CreatePuzzleSubmissionDto; -__decorate([ - (0, class_validator_1.IsString)(), - (0, class_validator_1.IsNotEmpty)(), - (0, class_validator_1.Length)(3, 200), - __metadata("design:type", String) -], CreatePuzzleSubmissionDto.prototype, "title", void 0); -__decorate([ - (0, class_validator_1.IsString)(), - (0, class_validator_1.IsNotEmpty)(), - (0, class_validator_1.Length)(10, 2000), + 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__) { + + +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) -], CreatePuzzleSubmissionDto.prototype, "description", void 0); +], BulkUpdateDto.prototype, "action", void 0); __decorate([ + (0, class_validator_1.IsOptional)(), (0, class_validator_1.IsString)(), - (0, class_validator_1.IsNotEmpty)(), - (0, class_validator_1.IsEnum)(['logic', 'math', 'pattern', 'word', 'spatial', 'memory', 'strategy']), __metadata("design:type", String) -], CreatePuzzleSubmissionDto.prototype, "category", void 0); +], BulkUpdateDto.prototype, "value", void 0); __decorate([ - (0, class_validator_1.IsEnum)(['easy', 'medium', 'hard', 'expert']), + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), __metadata("design:type", String) -], CreatePuzzleSubmissionDto.prototype, "difficulty", void 0); -__decorate([ - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(1), - (0, class_validator_1.Max)(10), - __metadata("design:type", Number) -], CreatePuzzleSubmissionDto.prototype, "difficultyRating", void 0); -__decorate([ - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(10), - (0, class_validator_1.Max)(1000), - __metadata("design:type", Number) -], CreatePuzzleSubmissionDto.prototype, "basePoints", void 0); -__decorate([ - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(60), - (0, class_validator_1.Max)(3600), - __metadata("design:type", Number) -], CreatePuzzleSubmissionDto.prototype, "timeLimit", void 0); -__decorate([ - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(0), - (0, class_validator_1.Max)(10), - __metadata("design:type", Number) -], CreatePuzzleSubmissionDto.prototype, "maxHints", void 0); -__decorate([ - (0, class_validator_1.IsObject)(), - (0, class_validator_1.ValidateNested)(), - (0, class_transformer_1.Type)(() => PuzzleContentDto), - __metadata("design:type", PuzzleContentDto) -], CreatePuzzleSubmissionDto.prototype, "content", void 0); -__decorate([ - (0, class_validator_1.IsArray)(), - (0, class_validator_1.ValidateNested)({ each: true }), - (0, class_transformer_1.Type)(() => PuzzleHintDto), - __metadata("design:type", Array) -], CreatePuzzleSubmissionDto.prototype, "hints", void 0); -__decorate([ - (0, class_validator_1.IsArray)(), - (0, class_validator_1.IsString)({ each: true }), - __metadata("design:type", Array) -], CreatePuzzleSubmissionDto.prototype, "tags", void 0); +], 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.IsBoolean)(), - __metadata("design:type", Boolean) -], CreatePuzzleSubmissionDto.prototype, "isPublic", void 0); + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ExportPuzzleDto.prototype, "format", void 0); __decorate([ (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], CreatePuzzleSubmissionDto.prototype, "allowComments", void 0); + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ExportPuzzleDto.prototype, "category", void 0); __decorate([ (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], CreatePuzzleSubmissionDto.prototype, "allowRatings", void 0); + (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.IsObject)(), - (0, class_validator_1.ValidateNested)(), - (0, class_transformer_1.Type)(() => SharingSettingsDto), - __metadata("design:type", SharingSettingsDto) -], CreatePuzzleSubmissionDto.prototype, "sharingSettings", void 0); + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], ImportPuzzleDto.prototype, "importMode", void 0); __decorate([ (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsObject)(), - (0, class_validator_1.ValidateNested)(), - (0, class_transformer_1.Type)(() => CreatorNotesDto), - __metadata("design:type", CreatorNotesDto) -], CreatePuzzleSubmissionDto.prototype, "creatorNotes", void 0); -class PuzzleContentDto { + __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__) { + + +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.PuzzleContentDto = PuzzleContentDto; +exports.CreateCategoryDto = CreateCategoryDto; __decorate([ - (0, class_validator_1.IsEnum)(['multiple-choice', 'fill-blank', 'drag-drop', 'code', 'visual', 'logic-grid']), + (0, class_validator_1.IsString)(), __metadata("design:type", String) -], PuzzleContentDto.prototype, "type", void 0); +], CreateCategoryDto.prototype, "name", void 0); __decorate([ (0, class_validator_1.IsOptional)(), (0, class_validator_1.IsString)(), __metadata("design:type", String) -], PuzzleContentDto.prototype, "question", void 0); +], 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__) { + + +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.IsOptional)(), - (0, class_validator_1.IsArray)(), - (0, class_validator_1.IsString)({ each: true }), - __metadata("design:type", Array) -], PuzzleContentDto.prototype, "options", void 0); + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], RewardDto.prototype, "type", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), __metadata("design:type", Object) -], PuzzleContentDto.prototype, "correctAnswer", void 0); +], 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) -], PuzzleContentDto.prototype, "explanation", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsObject)(), - (0, class_validator_1.ValidateNested)(), - (0, class_transformer_1.Type)(() => MediaContentDto), - __metadata("design:type", MediaContentDto) -], PuzzleContentDto.prototype, "media", void 0); +], CreateCollectionDto.prototype, "name", void 0); __decorate([ (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsObject)(), - __metadata("design:type", Object) -], PuzzleContentDto.prototype, "interactive", void 0); -class MediaContentDto { -} -exports.MediaContentDto = MediaContentDto; + (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.IsString)({ each: true }), + (0, class_validator_1.IsUUID)({}, { each: true }), __metadata("design:type", Array) -], MediaContentDto.prototype, "images", void 0); +], CreateCollectionDto.prototype, "puzzleIds", void 0); __decorate([ (0, class_validator_1.IsOptional)(), (0, class_validator_1.IsArray)(), - (0, class_validator_1.IsString)({ each: true }), + (0, class_validator_1.IsUUID)({}, { each: true }), __metadata("design:type", Array) -], MediaContentDto.prototype, "videos", void 0); +], CreateCollectionDto.prototype, "categoryIds", void 0); __decorate([ (0, class_validator_1.IsOptional)(), (0, class_validator_1.IsArray)(), - (0, class_validator_1.IsString)({ each: true }), + (0, class_validator_1.ValidateNested)({ each: true }), + (0, class_transformer_1.Type)(() => RewardDto), __metadata("design:type", Array) -], MediaContentDto.prototype, "audio", void 0); -class PuzzleHintDto { -} -exports.PuzzleHintDto = PuzzleHintDto; -__decorate([ - (0, class_validator_1.IsInt)(), - (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.IsNotEmpty)(), - (0, class_validator_1.Length)(5, 500), - __metadata("design:type", String) -], PuzzleHintDto.prototype, "text", void 0); -__decorate([ - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(0), - (0, class_validator_1.Max)(50), - __metadata("design:type", Number) -], PuzzleHintDto.prototype, "pointsPenalty", void 0); -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(0), - __metadata("design:type", Number) -], PuzzleHintDto.prototype, "unlockAfter", void 0); -class SharingSettingsDto { - constructor() { - this.allowShare = true; - this.embeddable = false; - this.downloadAllowed = false; - this.attributionRequired = true; - } -} -exports.SharingSettingsDto = SharingSettingsDto; -__decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], SharingSettingsDto.prototype, "allowShare", void 0); +], 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__) { + + +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.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], SharingSettingsDto.prototype, "embeddable", void 0); + (0, class_validator_1.IsEnum)(PuzzleContentType), + __metadata("design:type", String) +], PuzzleContentDto.prototype, "type", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], SharingSettingsDto.prototype, "downloadAllowed", void 0); + (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.IsBoolean)(), - __metadata("design:type", Boolean) -], SharingSettingsDto.prototype, "attributionRequired", void 0); -class CreatorNotesDto { -} -exports.CreatorNotesDto = CreatorNotesDto; + (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)(), - (0, class_validator_1.Length)(0, 500), __metadata("design:type", String) -], CreatorNotesDto.prototype, "inspiration", void 0); +], PuzzleContentDto.prototype, "explanation", void 0); __decorate([ (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - (0, class_validator_1.Length)(0, 200), - __metadata("design:type", String) -], CreatorNotesDto.prototype, "targetAudience", void 0); + (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.Length)(0, 100), + (0, class_validator_1.MinLength)(5), __metadata("design:type", String) -], CreatorNotesDto.prototype, "estimatedTime", void 0); +], PuzzleHintDto.prototype, "text", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsArray)(), - (0, class_validator_1.IsString)({ each: true }), - __metadata("design:type", Array) -], CreatorNotesDto.prototype, "learningObjectives", void 0); + (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.IsArray)(), - (0, class_validator_1.IsString)({ each: true }), - __metadata("design:type", Array) -], CreatorNotesDto.prototype, "prerequisites", void 0); -class UpdatePuzzleSubmissionDto { + (0, class_validator_1.IsNumber)(), + __metadata("design:type", Number) +], PuzzleHintDto.prototype, "unlockAfter", void 0); +class PuzzleScoringDto { } -exports.UpdatePuzzleSubmissionDto = UpdatePuzzleSubmissionDto; +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.Length)(3, 200), + (0, class_validator_1.MinLength)(5), + (0, class_validator_1.MaxLength)(200), __metadata("design:type", String) -], UpdatePuzzleSubmissionDto.prototype, "title", void 0); +], CreatePuzzleDto.prototype, "title", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), (0, class_validator_1.IsString)(), - (0, class_validator_1.Length)(10, 2000), + (0, class_validator_1.MinLength)(20), + (0, class_validator_1.MaxLength)(1000), __metadata("design:type", String) -], UpdatePuzzleSubmissionDto.prototype, "description", void 0); +], CreatePuzzleDto.prototype, "description", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsEnum)(['logic', 'math', 'pattern', 'word', 'spatial', 'memory', 'strategy']), + (0, class_validator_1.IsString)(), + (0, class_validator_1.MinLength)(3), + (0, class_validator_1.MaxLength)(50), __metadata("design:type", String) -], UpdatePuzzleSubmissionDto.prototype, "category", void 0); +], CreatePuzzleDto.prototype, "category", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsEnum)(['easy', 'medium', 'hard', 'expert']), + (0, class_validator_1.IsEnum)(PuzzleDifficulty), __metadata("design:type", String) -], UpdatePuzzleSubmissionDto.prototype, "difficulty", void 0); +], CreatePuzzleDto.prototype, "difficulty", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), + (0, class_validator_1.IsNumber)(), (0, class_validator_1.Min)(1), (0, class_validator_1.Max)(10), __metadata("design:type", Number) -], UpdatePuzzleSubmissionDto.prototype, "difficultyRating", void 0); +], CreatePuzzleDto.prototype, "difficultyRating", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), + (0, class_validator_1.IsNumber)(), (0, class_validator_1.Min)(10), (0, class_validator_1.Max)(1000), __metadata("design:type", Number) -], UpdatePuzzleSubmissionDto.prototype, "basePoints", void 0); +], CreatePuzzleDto.prototype, "basePoints", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(60), + (0, class_validator_1.IsNumber)(), + (0, class_validator_1.Min)(30), (0, class_validator_1.Max)(3600), __metadata("design:type", Number) -], UpdatePuzzleSubmissionDto.prototype, "timeLimit", void 0); +], CreatePuzzleDto.prototype, "timeLimit", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), + (0, class_validator_1.IsNumber)(), (0, class_validator_1.Min)(0), (0, class_validator_1.Max)(10), __metadata("design:type", Number) -], UpdatePuzzleSubmissionDto.prototype, "maxHints", void 0); +], CreatePuzzleDto.prototype, "maxHints", void 0); __decorate([ - (0, class_validator_1.IsOptional)(), - (0, class_validator_1.IsObject)(), + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => PuzzleContentDto), __metadata("design:type", PuzzleContentDto) -], UpdatePuzzleSubmissionDto.prototype, "content", void 0); +], 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__) { + + +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) -], UpdatePuzzleSubmissionDto.prototype, "hints", void 0); +], CreateThemeDto.prototype, "collectionIds", void 0); + + +/***/ }), + +/***/ "./src/puzzles/dto/index.ts": +/*!**********************************!*\ + !*** ./src/puzzles/dto/index.ts ***! + \**********************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +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__) { + + +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__) => { + + +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__) => { + + +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__) { + + +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__) => { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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__) { + + +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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsArray)(), - (0, class_validator_1.IsString)({ each: true }), - __metadata("design:type", Array) -], UpdatePuzzleSubmissionDto.prototype, "tags", void 0); + (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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], UpdatePuzzleSubmissionDto.prototype, "isPublic", void 0); + (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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], UpdatePuzzleSubmissionDto.prototype, "allowComments", void 0); + (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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsBoolean)(), - __metadata("design:type", Boolean) -], UpdatePuzzleSubmissionDto.prototype, "allowRatings", void 0); + (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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsObject)(), - __metadata("design:type", SharingSettingsDto) -], UpdatePuzzleSubmissionDto.prototype, "sharingSettings", void 0); + (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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsObject)(), - __metadata("design:type", CreatorNotesDto) -], UpdatePuzzleSubmissionDto.prototype, "creatorNotes", void 0); -class SubmitForReviewDto { -} -exports.SubmitForReviewDto = SubmitForReviewDto; + (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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsString)(), - (0, class_validator_1.Length)(0, 1000), - __metadata("design:type", String) -], SubmitForReviewDto.prototype, "reviewerNotes", void 0); -class ModerationDecisionDto { -} -exports.ModerationDecisionDto = ModerationDecisionDto; + (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, class_validator_1.IsEnum)(user_puzzle_submission_entity_1.ModerationAction), - __metadata("design:type", typeof (_a = typeof user_puzzle_submission_entity_1.ModerationAction !== "undefined" && user_puzzle_submission_entity_1.ModerationAction) === "function" ? _a : Object) -], ModerationDecisionDto.prototype, "action", void 0); + (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, class_validator_1.IsString)(), - (0, class_validator_1.Length)(0, 1000), - __metadata("design:type", String) -], ModerationDecisionDto.prototype, "reviewNotes", void 0); + (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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsArray)(), - (0, class_validator_1.IsString)({ each: true }), - __metadata("design:type", Array) -], ModerationDecisionDto.prototype, "requiredChanges", void 0); + (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, class_validator_1.IsOptional)(), - (0, class_validator_1.IsInt)(), - (0, class_validator_1.Min)(1), - (0, class_validator_1.Max)(10), - __metadata("design:type", Number) -], ModerationDecisionDto.prototype, "qualityScore", void 0); + (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/puzzles/entities/puzzle-comment.entity.ts": -/*!*******************************************************!*\ - !*** ./src/puzzles/entities/puzzle-comment.entity.ts ***! - \*******************************************************/ +/***/ "./src/referrals/referrals.module.ts": +/*!*******************************************!*\ + !*** ./src/referrals/referrals.module.ts ***! + \*******************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +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__) { @@ -5893,123 +8017,600 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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.PuzzleComment = exports.PuzzleCommentStatus = 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 user_puzzle_submission_entity_1 = __webpack_require__(/*! ./user-puzzle-submission.entity */ "./src/puzzles/entities/user-puzzle-submission.entity.ts"); -var PuzzleCommentStatus; -(function (PuzzleCommentStatus) { - PuzzleCommentStatus["ACTIVE"] = "active"; - PuzzleCommentStatus["HIDDEN"] = "hidden"; - PuzzleCommentStatus["DELETED"] = "deleted"; - PuzzleCommentStatus["FLAGGED"] = "flagged"; -})(PuzzleCommentStatus || (exports.PuzzleCommentStatus = PuzzleCommentStatus = {})); -let PuzzleComment = class PuzzleComment { -}; -exports.PuzzleComment = PuzzleComment; +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/save-game/controllers/save-game.controller.ts": +/*!***********************************************************!*\ + !*** ./src/save-game/controllers/save-game.controller.ts ***! + \***********************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +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, typeorm_1.PrimaryGeneratedColumn)('uuid'), - __metadata("design:type", String) -], PuzzleComment.prototype, "id", void 0); + (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, typeorm_1.Column)({ type: 'uuid' }), - (0, typeorm_1.Index)(), - __metadata("design:type", String) -], PuzzleComment.prototype, "submissionId", void 0); + (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, typeorm_1.ManyToOne)(() => user_puzzle_submission_entity_1.UserPuzzleSubmission, { onDelete: 'CASCADE' }), - (0, typeorm_1.JoinColumn)({ name: 'submissionId' }), - __metadata("design:type", typeof (_a = typeof user_puzzle_submission_entity_1.UserPuzzleSubmission !== "undefined" && user_puzzle_submission_entity_1.UserPuzzleSubmission) === "function" ? _a : Object) -], PuzzleComment.prototype, "submission", void 0); + (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, typeorm_1.Column)({ type: 'uuid' }), - (0, typeorm_1.Index)(), - __metadata("design:type", String) -], PuzzleComment.prototype, "userId", void 0); + (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, typeorm_1.ManyToOne)(() => user_entity_1.User, { onDelete: 'CASCADE' }), - (0, typeorm_1.JoinColumn)({ name: 'userId' }), - __metadata("design:type", typeof (_b = typeof user_entity_1.User !== "undefined" && user_entity_1.User) === "function" ? _b : Object) -], PuzzleComment.prototype, "user", void 0); + (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, typeorm_1.Column)({ type: 'uuid', nullable: true }), - (0, typeorm_1.Index)(), - __metadata("design:type", String) -], PuzzleComment.prototype, "parentId", void 0); + (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, typeorm_1.ManyToOne)(() => PuzzleComment, { nullable: true }), - (0, typeorm_1.JoinColumn)({ name: 'parentId' }), - __metadata("design:type", PuzzleComment) -], PuzzleComment.prototype, "parent", void 0); + (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, typeorm_1.Column)({ type: 'text' }), - __metadata("design:type", String) -], PuzzleComment.prototype, "content", void 0); + (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, typeorm_1.Column)({ type: 'enum', enum: PuzzleCommentStatus, default: PuzzleCommentStatus.ACTIVE }), - (0, typeorm_1.Index)(), - __metadata("design:type", String) -], PuzzleComment.prototype, "status", void 0); + (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, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], PuzzleComment.prototype, "moderationFlags", void 0); + (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, typeorm_1.Column)({ type: 'int', default: 0 }), - (0, typeorm_1.Index)(), - __metadata("design:type", Number) -], PuzzleComment.prototype, "upvotes", void 0); + (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, typeorm_1.Column)({ type: 'int', default: 0 }), - __metadata("design:type", Number) -], PuzzleComment.prototype, "downvotes", void 0); + (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, typeorm_1.Column)({ type: 'int', default: 0 }), - (0, typeorm_1.Index)(), - __metadata("design:type", Number) -], PuzzleComment.prototype, "replyCount", void 0); + (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, typeorm_1.Column)({ type: 'boolean', default: false }), - __metadata("design:type", Boolean) -], PuzzleComment.prototype, "isPinned", void 0); + (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, typeorm_1.Column)({ type: 'boolean', default: false }), - __metadata("design:type", Boolean) -], PuzzleComment.prototype, "isFromCreator", void 0); + (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, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], PuzzleComment.prototype, "metadata", void 0); + (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, typeorm_1.CreateDateColumn)(), - (0, typeorm_1.Index)(), - __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) -], PuzzleComment.prototype, "createdAt", void 0); + (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, typeorm_1.UpdateDateColumn)(), - (0, typeorm_1.Index)(), - __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) -], PuzzleComment.prototype, "updatedAt", void 0); + (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, typeorm_1.OneToMany)(() => PuzzleComment, (comment) => comment.parent), - __metadata("design:type", Array) -], PuzzleComment.prototype, "replies", void 0); -exports.PuzzleComment = PuzzleComment = __decorate([ - (0, typeorm_1.Entity)('puzzle_comments'), - (0, typeorm_1.Index)(['submissionId', 'status']), - (0, typeorm_1.Index)(['userId', 'createdAt']), - (0, typeorm_1.Index)(['parentId']) -], PuzzleComment); + (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/puzzles/entities/puzzle-rating.entity.ts": -/*!******************************************************!*\ - !*** ./src/puzzles/entities/puzzle-rating.entity.ts ***! - \******************************************************/ +/***/ "./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__) { @@ -6024,101 +8625,133 @@ var __metadata = (this && this.__metadata) || function (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; +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, typeorm_1.PrimaryGeneratedColumn)('uuid'), - __metadata("design:type", String) -], PuzzleRating.prototype, "id", void 0); + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsObject)(), + __metadata("design:type", Object) +], PlayerStateDto.prototype, "position", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'uuid' }), - (0, typeorm_1.Index)(), - __metadata("design:type", String) -], PuzzleRating.prototype, "userId", void 0); + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), + __metadata("design:type", Number) +], PlayerStateDto.prototype, "health", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), - (0, typeorm_1.Index)(), - __metadata("design:type", String) -], PuzzleRating.prototype, "submissionId", void 0); + (0, class_validator_1.IsOptional)(), + __metadata("design:type", Array) +], PlayerStateDto.prototype, "inventory", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'uuid', nullable: true }), - (0, typeorm_1.Index)(), - __metadata("design:type", String) -], PuzzleRating.prototype, "puzzleId", void 0); + (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, typeorm_1.Column)({ type: 'decimal', precision: 3, scale: 2 }), - (0, typeorm_1.Index)(), + (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) -], PuzzleRating.prototype, "rating", void 0); +], SaveGameDataDto.prototype, "version", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'varchar', length: 20, nullable: true }), - __metadata("design:type", String) -], PuzzleRating.prototype, "difficultyVote", void 0); + (0, class_validator_1.IsObject)(), + __metadata("design:type", typeof (_b = typeof Record !== "undefined" && Record) === "function" ? _b : Object) +], SaveGameDataDto.prototype, "gameState", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'text', nullable: true }), - __metadata("design:type", String) -], PuzzleRating.prototype, "review", void 0); + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => PlayerStateDto), + __metadata("design:type", PlayerStateDto) +], SaveGameDataDto.prototype, "playerState", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'simple-array', default: [] }), - __metadata("design:type", Array) -], PuzzleRating.prototype, "tags", void 0); + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => ProgressStateDto), + __metadata("design:type", ProgressStateDto) +], SaveGameDataDto.prototype, "progressState", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'boolean', default: false }), - (0, typeorm_1.Index)(), - __metadata("design:type", Boolean) -], PuzzleRating.prototype, "isReported", void 0); + (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, typeorm_1.Column)({ type: 'boolean', default: true }), - (0, typeorm_1.Index)(), - __metadata("design:type", Boolean) -], PuzzleRating.prototype, "isPublic", void 0); + (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, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], PuzzleRating.prototype, "metadata", void 0); + (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, typeorm_1.CreateDateColumn)(), - (0, typeorm_1.Index)(), - __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) -], PuzzleRating.prototype, "createdAt", void 0); + (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, typeorm_1.UpdateDateColumn)(), - (0, typeorm_1.Index)(), - __metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object) -], PuzzleRating.prototype, "updatedAt", void 0); + (0, class_validator_1.ValidateNested)(), + (0, class_transformer_1.Type)(() => SaveGameDataDto), + __metadata("design:type", SaveGameDataDto) +], CreateSaveGameDto.prototype, "data", 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); + (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, 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); + (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, 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); + (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/puzzles/entities/puzzle.entity.ts": -/*!***********************************************!*\ - !*** ./src/puzzles/entities/puzzle.entity.ts ***! - \***********************************************/ +/***/ "./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__) { @@ -6131,170 +8764,93 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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; +var _a, _b, _c, _d; 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); +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, typeorm_1.Column)({ type: 'int', default: 0 }), - (0, typeorm_1.Index)(), + (0, class_validator_1.IsNumber)(), __metadata("design:type", Number) -], Puzzle.prototype, "completions", void 0); +], SyncSaveGameDto.prototype, "slotId", 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); + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], SyncSaveGameDto.prototype, "localChecksum", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'int', default: 0 }), - __metadata("design:type", Number) -], Puzzle.prototype, "ratingCount", void 0); + (0, class_validator_1.IsOptional)(), + __metadata("design:type", typeof (_a = typeof Date !== "undefined" && Date) === "function" ? _a : Object) +], SyncSaveGameDto.prototype, "lastModifiedAt", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'int', default: 0 }), + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsNumber)(), __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); +], SyncSaveGameDto.prototype, "saveVersion", 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); + (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, typeorm_1.Column)({ type: 'uuid', nullable: true }), - (0, typeorm_1.Index)(), + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), __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); +], SyncSaveGameDto.prototype, "deviceId", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], Puzzle.prototype, "metadata", void 0); + (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, typeorm_1.CreateDateColumn)(), - (0, typeorm_1.Index)(), - __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) -], Puzzle.prototype, "createdAt", void 0); + (0, class_validator_1.IsUUID)(), + __metadata("design:type", String) +], ResolveConflictDto.prototype, "saveId", 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); + (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, typeorm_1.DeleteDateColumn)(), - __metadata("design:type", typeof (_f = typeof Date !== "undefined" && Date) === "function" ? _f : Object) -], Puzzle.prototype, "deletedAt", void 0); + (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, typeorm_1.OneToMany)('PuzzleProgress', 'puzzle'), + (0, class_validator_1.ValidateNested)({ each: true }), + (0, class_transformer_1.Type)(() => SyncSaveGameDto), __metadata("design:type", Array) -], Puzzle.prototype, "progress", void 0); +], BatchSyncDto.prototype, "saves", 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); + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsBoolean)(), + __metadata("design:type", Boolean) +], BatchSyncDto.prototype, "forceCloud", 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); + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + __metadata("design:type", String) +], BatchSyncDto.prototype, "deviceId", void 0); /***/ }), -/***/ "./src/puzzles/entities/user-puzzle-submission.entity.ts": -/*!***************************************************************!*\ - !*** ./src/puzzles/entities/user-puzzle-submission.entity.ts ***! - \***************************************************************/ +/***/ "./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__) { @@ -6307,230 +8863,270 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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; +var _a, _b; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.UserPuzzleSubmission = exports.ModerationAction = exports.PuzzleSubmissionStatus = 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"); -var PuzzleSubmissionStatus; -(function (PuzzleSubmissionStatus) { - PuzzleSubmissionStatus["DRAFT"] = "draft"; - PuzzleSubmissionStatus["SUBMITTED"] = "submitted"; - PuzzleSubmissionStatus["UNDER_REVIEW"] = "under_review"; - PuzzleSubmissionStatus["APPROVED"] = "approved"; - PuzzleSubmissionStatus["REJECTED"] = "rejected"; - PuzzleSubmissionStatus["PUBLISHED"] = "published"; - PuzzleSubmissionStatus["FEATURED"] = "featured"; -})(PuzzleSubmissionStatus || (exports.PuzzleSubmissionStatus = PuzzleSubmissionStatus = {})); -var ModerationAction; -(function (ModerationAction) { - ModerationAction["PENDING_REVIEW"] = "pending_review"; - ModerationAction["AUTO_APPROVED"] = "auto_approved"; - ModerationAction["MANUALLY_APPROVED"] = "manually_approved"; - ModerationAction["REJECTED_CONTENT"] = "rejected_content"; - ModerationAction["REJECTED_QUALITY"] = "rejected_quality"; - ModerationAction["REJECTED_DUPLICATE"] = "rejected_duplicate"; - ModerationAction["REJECTED_INAPPROPRIATE"] = "rejected_inappropriate"; - ModerationAction["REQUIRES_CHANGES"] = "requires_changes"; -})(ModerationAction || (exports.ModerationAction = ModerationAction = {})); -let UserPuzzleSubmission = class UserPuzzleSubmission { -}; -exports.UserPuzzleSubmission = UserPuzzleSubmission; +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, typeorm_1.PrimaryGeneratedColumn)('uuid'), + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), + (0, class_validator_1.MaxLength)(100), __metadata("design:type", String) -], UserPuzzleSubmission.prototype, "id", void 0); +], UpdateSaveGameDto.prototype, "slotName", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'uuid' }), - (0, typeorm_1.Index)(), - __metadata("design:type", String) -], UserPuzzleSubmission.prototype, "userId", void 0); + (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, typeorm_1.ManyToOne)(() => 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) -], UserPuzzleSubmission.prototype, "user", void 0); + (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, typeorm_1.Column)({ type: 'varchar', length: 200 }), - (0, typeorm_1.Index)(), + (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) -], UserPuzzleSubmission.prototype, "title", void 0); +], 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__) { + + +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.Column)({ type: 'text' }), + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), __metadata("design:type", String) -], UserPuzzleSubmission.prototype, "description", void 0); +], SaveGameAnalytics.prototype, "id", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'varchar', length: 50 }), - (0, typeorm_1.Index)(), + (0, typeorm_1.Column)({ type: 'uuid' }), __metadata("design:type", String) -], UserPuzzleSubmission.prototype, "category", void 0); +], SaveGameAnalytics.prototype, "userId", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'medium' }), - (0, typeorm_1.Index)(), - __metadata("design:type", String) -], UserPuzzleSubmission.prototype, "difficulty", void 0); + (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: 1 }), + (0, typeorm_1.Column)({ type: 'int', default: 0 }), __metadata("design:type", Number) -], UserPuzzleSubmission.prototype, "difficultyRating", void 0); +], SaveGameAnalytics.prototype, "totalSaves", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'int', default: 100 }), + (0, typeorm_1.Column)({ type: 'int', default: 0 }), __metadata("design:type", Number) -], UserPuzzleSubmission.prototype, "basePoints", void 0); +], SaveGameAnalytics.prototype, "totalLoads", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'int', default: 300 }), + (0, typeorm_1.Column)({ type: 'int', default: 0 }), __metadata("design:type", Number) -], UserPuzzleSubmission.prototype, "timeLimit", void 0); +], SaveGameAnalytics.prototype, "autoSaves", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'int', default: 3 }), + (0, typeorm_1.Column)({ type: 'int', default: 0 }), __metadata("design:type", Number) -], UserPuzzleSubmission.prototype, "maxHints", void 0); -__decorate([ - (0, typeorm_1.Column)({ type: 'jsonb' }), - __metadata("design:type", Object) -], UserPuzzleSubmission.prototype, "content", void 0); -__decorate([ - (0, typeorm_1.Column)({ type: 'jsonb', default: [] }), - __metadata("design:type", typeof (_b = typeof Array !== "undefined" && Array) === "function" ? _b : Object) -], UserPuzzleSubmission.prototype, "hints", void 0); -__decorate([ - (0, typeorm_1.Column)({ type: 'simple-array', default: [] }), - (0, typeorm_1.Index)(), - __metadata("design:type", Array) -], UserPuzzleSubmission.prototype, "tags", void 0); -__decorate([ - (0, typeorm_1.Column)({ type: 'enum', enum: PuzzleSubmissionStatus, default: PuzzleSubmissionStatus.DRAFT }), - (0, typeorm_1.Index)(), - __metadata("design:type", String) -], UserPuzzleSubmission.prototype, "status", void 0); -__decorate([ - (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], UserPuzzleSubmission.prototype, "validationResults", void 0); -__decorate([ - (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], UserPuzzleSubmission.prototype, "moderationData", void 0); -__decorate([ - (0, typeorm_1.Column)({ type: 'boolean', default: false }), - (0, typeorm_1.Index)(), - __metadata("design:type", Boolean) -], UserPuzzleSubmission.prototype, "isPublic", void 0); +], SaveGameAnalytics.prototype, "manualSaves", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'boolean', default: false }), - (0, typeorm_1.Index)(), - __metadata("design:type", Boolean) -], UserPuzzleSubmission.prototype, "allowComments", void 0); + (0, typeorm_1.Column)({ type: 'int', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "quickSaves", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'boolean', default: true }), - __metadata("design:type", Boolean) -], UserPuzzleSubmission.prototype, "allowRatings", void 0); + (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 }), - (0, typeorm_1.Index)(), __metadata("design:type", Number) -], UserPuzzleSubmission.prototype, "views", void 0); +], SaveGameAnalytics.prototype, "syncConflicts", void 0); __decorate([ (0, typeorm_1.Column)({ type: 'int', default: 0 }), - (0, typeorm_1.Index)(), __metadata("design:type", Number) -], UserPuzzleSubmission.prototype, "playCount", void 0); +], SaveGameAnalytics.prototype, "conflictsResolved", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), - (0, typeorm_1.Index)(), + (0, typeorm_1.Column)({ type: 'int', default: 0 }), __metadata("design:type", Number) -], UserPuzzleSubmission.prototype, "averageRating", void 0); +], SaveGameAnalytics.prototype, "corruptionEvents", void 0); __decorate([ (0, typeorm_1.Column)({ type: 'int', default: 0 }), __metadata("design:type", Number) -], UserPuzzleSubmission.prototype, "ratingCount", void 0); +], SaveGameAnalytics.prototype, "recoveryAttempts", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), - (0, typeorm_1.Index)(), + (0, typeorm_1.Column)({ type: 'int', default: 0 }), __metadata("design:type", Number) -], UserPuzzleSubmission.prototype, "averageCompletionRate", void 0); +], SaveGameAnalytics.prototype, "successfulRecoveries", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), - (0, typeorm_1.Index)(), + (0, typeorm_1.Column)({ type: 'bigint', default: 0 }), __metadata("design:type", Number) -], UserPuzzleSubmission.prototype, "communityScore", void 0); +], SaveGameAnalytics.prototype, "totalDataSaved", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], UserPuzzleSubmission.prototype, "sharingSettings", void 0); + (0, typeorm_1.Column)({ type: 'float', default: 0 }), + __metadata("design:type", Number) +], SaveGameAnalytics.prototype, "averageSaveSize", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], UserPuzzleSubmission.prototype, "creatorNotes", void 0); + (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 with time zone', nullable: true }), - (0, typeorm_1.Index)(), + (0, typeorm_1.Column)({ type: 'timestamp', nullable: true }), __metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object) -], UserPuzzleSubmission.prototype, "submittedAt", void 0); +], SaveGameAnalytics.prototype, "lastLoadAt", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), - (0, typeorm_1.Index)(), + (0, typeorm_1.Column)({ type: 'timestamp', nullable: true }), __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) -], UserPuzzleSubmission.prototype, "publishedAt", void 0); +], SaveGameAnalytics.prototype, "lastSyncAt", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), - (0, typeorm_1.Index)(), + (0, typeorm_1.CreateDateColumn)(), __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) -], UserPuzzleSubmission.prototype, "featuredAt", void 0); +], SaveGameAnalytics.prototype, "createdAt", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'timestamp with time zone', nullable: true }), + (0, typeorm_1.UpdateDateColumn)(), __metadata("design:type", typeof (_f = typeof Date !== "undefined" && Date) === "function" ? _f : Object) -], UserPuzzleSubmission.prototype, "lastActivityAt", void 0); +], 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__) { + + +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.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], UserPuzzleSubmission.prototype, "analytics", void 0); + (0, typeorm_1.PrimaryGeneratedColumn)('uuid'), + __metadata("design:type", String) +], SaveGameBackup.prototype, "id", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], UserPuzzleSubmission.prototype, "rewardData", void 0); + (0, typeorm_1.Column)({ type: 'uuid' }), + __metadata("design:type", String) +], SaveGameBackup.prototype, "saveGameId", void 0); __decorate([ - (0, typeorm_1.CreateDateColumn)(), - (0, typeorm_1.Index)(), - __metadata("design:type", typeof (_g = typeof Date !== "undefined" && Date) === "function" ? _g : Object) -], UserPuzzleSubmission.prototype, "createdAt", void 0); + (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.UpdateDateColumn)(), - (0, typeorm_1.Index)(), - __metadata("design:type", typeof (_h = typeof Date !== "undefined" && Date) === "function" ? _h : Object) -], UserPuzzleSubmission.prototype, "updatedAt", void 0); + (0, typeorm_1.Column)({ type: 'uuid' }), + __metadata("design:type", String) +], SaveGameBackup.prototype, "userId", void 0); __decorate([ - (0, typeorm_1.OneToMany)('PuzzleRating', 'submission'), - __metadata("design:type", Array) -], UserPuzzleSubmission.prototype, "ratings", void 0); + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], SaveGameBackup.prototype, "slotId", void 0); __decorate([ - (0, typeorm_1.OneToMany)('PuzzleComment', 'submission'), - __metadata("design:type", Array) -], UserPuzzleSubmission.prototype, "comments", void 0); + (0, typeorm_1.Column)({ type: 'int' }), + __metadata("design:type", Number) +], SaveGameBackup.prototype, "saveVersion", void 0); __decorate([ - (0, typeorm_1.OneToMany)('PuzzlePlay', 'submission'), - __metadata("design:type", Array) -], UserPuzzleSubmission.prototype, "playSessions", void 0); -__decorate([ - (0, typeorm_1.ManyToOne)(() => puzzle_entity_1.Puzzle, { nullable: true }), - (0, typeorm_1.JoinColumn)({ name: 'publishedPuzzleId' }), - __metadata("design:type", typeof (_j = typeof puzzle_entity_1.Puzzle !== "undefined" && puzzle_entity_1.Puzzle) === "function" ? _j : Object) -], UserPuzzleSubmission.prototype, "publishedPuzzle", void 0); -exports.UserPuzzleSubmission = UserPuzzleSubmission = __decorate([ - (0, typeorm_1.Entity)('user_puzzle_submissions'), - (0, typeorm_1.Index)(['userId', 'status']), - (0, typeorm_1.Index)(['status', 'submittedAt']), - (0, typeorm_1.Index)(['isPublic', 'status']) -], UserPuzzleSubmission); + (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/puzzles/puzzles.controller.ts": -/*!*******************************************!*\ - !*** ./src/puzzles/puzzles.controller.ts ***! - \*******************************************/ +/***/ "./src/save-game/entities/save-game.entity.ts": +/*!****************************************************!*\ + !*** ./src/save-game/entities/save-game.entity.ts ***! + \****************************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -6543,188 +9139,174 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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; +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o; 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.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.PuzzlesController = PuzzlesController; +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, 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); + (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, 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); + (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, 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); + (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, 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); + (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, 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); + (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, 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); + (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, 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); + (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, 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); + (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, 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); + (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, 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); + (0, typeorm_1.Column)({ type: 'varchar', length: 64, nullable: true }), + __metadata("design:type", String) +], SaveGame.prototype, "deviceId", void 0); __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); + (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/puzzles/puzzles.module.ts": -/*!***************************************!*\ - !*** ./src/puzzles/puzzles.module.ts ***! - \***************************************/ +/***/ "./src/save-game/interfaces/save-game.interfaces.ts": +/*!**********************************************************!*\ + !*** ./src/save-game/interfaces/save-game.interfaces.ts ***! + \**********************************************************/ +/***/ ((__unused_webpack_module, exports) => { + + +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__) { @@ -6735,41 +9317,61 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, return c > 3 && r && Object.defineProperty(target, key, r), r; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.PuzzlesModule = void 0; +exports.SaveGameModule = 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 community_puzzles_module_1 = __webpack_require__(/*! ./community-puzzles.module */ "./src/puzzles/community-puzzles.module.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"); -let PuzzlesModule = class PuzzlesModule { -}; -exports.PuzzlesModule = PuzzlesModule; -exports.PuzzlesModule = PuzzlesModule = __decorate([ +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([ - puzzle_entity_1.Puzzle, - puzzle_progress_entity_1.PuzzleProgress, - puzzle_rating_entity_1.PuzzleRating - ]), - community_puzzles_module_1.CommunityPuzzlesModule, + 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, ], - controllers: [puzzles_controller_1.PuzzlesController], - providers: [puzzles_service_1.PuzzlesService], - exports: [puzzles_service_1.PuzzlesService] }) -], PuzzlesModule); +], SaveGameModule); /***/ }), -/***/ "./src/puzzles/puzzles.service.ts": -/*!****************************************!*\ - !*** ./src/puzzles/puzzles.service.ts ***! - \****************************************/ +/***/ "./src/save-game/services/auto-save.service.ts": +/*!*****************************************************!*\ + !*** ./src/save-game/services/auto-save.service.ts ***! + \*****************************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -6785,298 +9387,196 @@ var __metadata = (this && this.__metadata) || function (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; +var AutoSaveService_1; +var _a, _b, _c, _d; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.PuzzlesService = void 0; +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 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; +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; } - } - 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`); + if (config?.lastAutoSave) { + const elapsed = Date.now() - config.lastAutoSave.getTime(); + if (elapsed < (config.intervalMs || this.DEFAULT_INTERVAL_MS)) { + return; } - const [enhancedPuzzle] = await this.enhanceWithStats([puzzle]); - return enhancedPuzzle; - } - catch (error) { - this.logger.error(`Failed to find puzzle ${id}: ${error.message}`, error.stack); - throw error; } + this.pendingAutoSaves.push({ + userId, + slotId: targetSlot, + data, + timestamp: new Date(), + }); + this.logger.debug(`Queued auto-save for user ${userId}, slot ${targetSlot}`); } - async update(id, updatePuzzleDto, userId) { + async triggerAutoSave(userId, data) { + const slotId = this.AUTO_SAVE_SLOT; 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 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, + }, + }); } - const updateData = { ...updatePuzzleDto }; - if (updateData.isPublished !== undefined) { - updateData.publishedAt = updateData.isPublished ? new Date() : null; - delete updateData.isPublished; + 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, + }, + }); } - 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; + this.logger.error(`Auto-save failed for user ${userId}: ${error.message}`); + return null; } } - 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 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 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 quickLoad(userId) { + return await this.saveGameService.load(userId, this.QUICK_SAVE_SLOT); } - 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 - } - }; + async processPendingAutoSaves() { + if (this.pendingAutoSaves.length === 0) { + return; } - catch (error) { - this.logger.error(`Failed to get analytics: ${error.message}`, error.stack); - throw error; + 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); + } } - } - 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); + 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}`); + } } } - 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 - })); + getAutoSaveConfig(userId, slotId = this.AUTO_SAVE_SLOT) { + const configKey = this.getConfigKey(userId, slotId); + return this.autoSaveConfigs.get(configKey) || null; } - 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}`); - } + getConfigKey(userId, slotId) { + return `${userId}:${slotId}`; } }; -exports.PuzzlesService = PuzzlesService; -exports.PuzzlesService = PuzzlesService = PuzzlesService_1 = __decorate([ +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)(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); + __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/puzzles/services/community-puzzles.service.ts": -/*!***********************************************************!*\ - !*** ./src/puzzles/services/community-puzzles.service.ts ***! - \***********************************************************/ +/***/ "./src/save-game/services/cloud-sync.service.ts": +/*!******************************************************!*\ + !*** ./src/save-game/services/cloud-sync.service.ts ***! + \******************************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -7092,315 +9592,309 @@ var __metadata = (this && this.__metadata) || function (k, v) { var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; -var CommunityPuzzlesService_1; -var _a, _b, _c; +var CloudSyncService_1; +var _a, _b, _c, _d, _e, _f; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.CommunityPuzzlesService = void 0; +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 user_puzzle_submission_entity_1 = __webpack_require__(/*! ../entities/user-puzzle-submission.entity */ "./src/puzzles/entities/user-puzzle-submission.entity.ts"); -const puzzle_rating_entity_1 = __webpack_require__(/*! ../entities/puzzle-rating.entity */ "./src/puzzles/entities/puzzle-rating.entity.ts"); -const puzzle_comment_entity_1 = __webpack_require__(/*! ../entities/puzzle-comment.entity */ "./src/puzzles/entities/puzzle-comment.entity.ts"); -let CommunityPuzzlesService = CommunityPuzzlesService_1 = class CommunityPuzzlesService { - constructor(submissionRepository, ratingRepository, commentRepository) { - this.submissionRepository = submissionRepository; - this.ratingRepository = ratingRepository; - this.commentRepository = commentRepository; - this.logger = new common_1.Logger(CommunityPuzzlesService_1.name); - } - async ratePuzzle(submissionId, userId, ratingDto) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId, status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED, allowRatings: true }, - }); - if (!submission) { - throw new Error('Puzzle not found or ratings not allowed'); - } - const existingRating = await this.ratingRepository.findOne({ - where: { puzzleId: submissionId, userId }, +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 (existingRating) { - Object.assign(existingRating, ratingDto); - existingRating.lastEditedAt = new Date(); - const updatedRating = await this.ratingRepository.save(existingRating); - await this.updatePuzzleRatingStats(submissionId); - return updatedRating; + if (!cloudSave) { + return { + success: true, + syncStatus: save_game_interfaces_1.SyncStatus.LOCAL_ONLY, + }; } - else { - const newRating = new puzzle_rating_entity_1.PuzzleRating(); - newRating.submissionId = submissionId; - newRating.userId = userId; - newRating.rating = ratingDto.rating; - newRating.review = ratingDto.review; - newRating.metadata = ratingDto.metadata || {}; - newRating.isPublic = true; - newRating.isReported = false; - newRating.tags = []; - const savedRating = await this.ratingRepository.save(newRating); - await this.updatePuzzleRatingStats(submissionId); - return savedRating; - } - } - async getUserRating(submissionId, userId) { - return await this.ratingRepository.findOne({ - where: { submissionId, userId }, - }); - } - async getPuzzleRatings(submissionId, page = 1, limit = 20) { - const [ratings, total] = await this.ratingRepository.findAndCount({ - where: { submissionId }, - order: { createdAt: 'DESC' }, - skip: (page - 1) * limit, - take: limit, - relations: ['user'], - }); - return { - ratings, - total, - page, - totalPages: Math.ceil(total / limit), - }; - } - async updatePuzzleRatingStats(submissionId) { - const ratings = await this.ratingRepository.find({ - where: { submissionId }, - }); - if (ratings.length === 0) - return; - const averageRating = ratings.reduce((sum, rating) => sum + rating.rating, 0) / ratings.length; - await this.submissionRepository.update(submissionId, { - averageRating, - ratingCount: ratings.length, - }); + const syncResult = this.determineSyncStatus(cloudSave, dto); + await this.analyticsService.recordSync(userId, syncResult.syncStatus === save_game_interfaces_1.SyncStatus.CONFLICT); + return syncResult; } - async createComment(submissionId, userId, commentDto) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId, status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED, allowComments: true }, - }); - if (!submission) { - throw new Error('Puzzle not found or comments not allowed'); + 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, + }; } - let isFromCreator = false; - if (commentDto.parentId) { - const parentComment = await this.commentRepository.findOne({ - where: { id: commentDto.parentId, submissionId }, - }); - if (!parentComment) { - throw new Error('Parent comment not found'); - } - await this.commentRepository.increment({ id: commentDto.parentId }, 'replyCount', 1); + if (localInfo.localChecksum === cloudSave.checksum?.value) { + return { + success: true, + syncStatus: save_game_interfaces_1.SyncStatus.SYNCED, + cloudSave: cloudSummary, + }; } - else { - isFromCreator = submission.userId === userId; + 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 comment = this.commentRepository.create({ - submissionId, - userId, - ...commentDto, - isFromCreator, - status: puzzle_comment_entity_1.PuzzleCommentStatus.ACTIVE, - }); - const savedComment = await this.commentRepository.save(comment); - await this.submissionRepository.update(submissionId, { - lastActivityAt: new Date(), - }); - return savedComment; - } - async updateComment(commentId, userId, updateDto) { - const comment = await this.commentRepository.findOne({ - where: { id: commentId, userId }, - }); - if (!comment) { - throw new Error('Comment not found'); + 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 (comment.status !== puzzle_comment_entity_1.PuzzleCommentStatus.ACTIVE) { - throw new Error('Cannot edit non-active comments'); + if (localModified > cloudModified) { + return { + success: true, + syncStatus: save_game_interfaces_1.SyncStatus.LOCAL_NEWER, + cloudSave: cloudSummary, + }; } - Object.assign(comment, updateDto); - comment.metadata = { - ...comment.metadata, - editedAt: new Date(), - editCount: (comment.metadata.editCount || 0) + 1, + return { + success: true, + syncStatus: save_game_interfaces_1.SyncStatus.CLOUD_NEWER, + cloudSave: cloudSummary, }; - return await this.commentRepository.save(comment); } - async deleteComment(commentId, userId) { - const comment = await this.commentRepository.findOne({ - where: { id: commentId, userId }, - }); - if (!comment) { - throw new Error('Comment not found'); - } - comment.status = puzzle_comment_entity_1.PuzzleCommentStatus.DELETED; - await this.commentRepository.save(comment); - if (comment.parentId) { - await this.commentRepository.decrement({ id: comment.parentId }, 'replyCount', 1); + suggestResolution(localModified, cloudModified) { + if (localModified > cloudModified) { + return save_game_interfaces_1.ConflictResolution.USE_LOCAL; } + return save_game_interfaces_1.ConflictResolution.USE_CLOUD; } - async voteOnComment(commentId, userId, voteDto) { - const comment = await this.commentRepository.findOne({ - where: { id: commentId, status: puzzle_comment_entity_1.PuzzleCommentStatus.ACTIVE }, + async resolveConflict(userId, dto) { + const cloudSave = await this.saveGameRepo.findOne({ + where: { id: dto.saveId, userId }, }); - if (!comment) { - throw new Error('Comment not found'); + if (!cloudSave) { + throw new common_1.BadRequestException('Save not found'); } - if (voteDto.voteType === 'upvote') { - await this.commentRepository.increment({ id: commentId }, 'upvotes', 1); - } - else { - await this.commentRepository.increment({ id: commentId }, 'downvotes', 1); + 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; } - return await this.commentRepository.findOne({ where: { id: commentId } }); + 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 getPuzzleComments(submissionId, page = 1, limit = 20) { - const [comments, total] = await this.commentRepository.findAndCount({ - where: { - submissionId, - status: puzzle_comment_entity_1.PuzzleCommentStatus.ACTIVE, - parentId: null, - }, - order: { - isPinned: 'DESC', - upvotes: 'DESC', - createdAt: 'DESC', - }, - relations: ['user', 'replies'], - skip: (page - 1) * limit, - take: limit, + async uploadToCloud(userId, slotId, data, deviceId, platform) { + let cloudSave = await this.saveGameRepo.findOne({ + where: { userId, slotId }, }); - return { - comments, - total, - page, - totalPages: Math.ceil(total / limit), + 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), }; - } - async sharePuzzle(submissionId, userId, shareDto) { - const submission = await this.submissionRepository.findOne({ - where: { - id: submissionId, - status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED, - isPublic: true, - }, + 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 (!submission) { - throw new Error('Puzzle not found or not shareable'); - } - const baseUrl = process.env.FRONTEND_URL || 'https://quest-game.com'; - const puzzleUrl = `${baseUrl}/puzzles/${submissionId}`; - const shareableLink = submission.sharingSettings?.shareableLink - ? `${baseUrl}/shared/${submission.sharingSettings.shareableLink}` - : puzzleUrl; - const result = { - shareUrl: shareableLink, - socialUrls: {}, - }; - if (shareDto.shareType === 'social' || !shareDto.shareType) { - const encodedUrl = encodeURIComponent(shareableLink); - const encodedTitle = encodeURIComponent(submission.title); - const encodedMessage = encodeURIComponent(shareDto.customMessage || `Check out this puzzle: ${submission.title}`); - result.socialUrls = { - twitter: `https://twitter.com/intent/tweet?url=${encodedUrl}&text=${encodedMessage}`, - facebook: `https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`, - reddit: `https://reddit.com/submit?url=${encodedUrl}&title=${encodedTitle}`, - discord: encodedUrl, - whatsapp: `https://wa.me/?text=${encodedMessage}%20${encodedUrl}`, - }; + if (!cloudSave) { + throw new common_1.BadRequestException(`No cloud save found for slot ${slotId}`); } - if (submission.sharingSettings?.embeddable && shareDto.shareType === 'embed') { - result.embedCode = ``; + if (cloudSave.isCorrupted) { + throw new common_1.BadRequestException('Cloud save is corrupted'); } - await this.trackShare(submissionId, userId, shareDto); - return result; - } - async trackShare(submissionId, userId, shareDto) { - this.logger.log(`Puzzle ${submissionId} shared by user ${userId} via ${shareDto.shareType}`); - } - async getShareStats(submissionId) { + 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 { - totalShares: 0, - sharesByPlatform: {}, - recentShares: [], + data: migratedData, + metadata: this.toSummary(cloudSave), }; } - async getTopCreators(limit = 10) { - const query = this.submissionRepository - .createQueryBuilder('submission') - .select([ - 'submission.userId', - 'COUNT(submission.id) as totalPuzzles', - 'AVG(submission.averageRating) as averageRating', - 'SUM(submission.playCount) as totalPlays', - ]) - .where('submission.status = :status', { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED }) - .andWhere('submission.isPublic = :isPublic', { isPublic: true }) - .groupBy('submission.userId') - .orderBy('totalPlays', 'DESC') - .limit(limit); - const results = await query.getRawMany(); - return results.map((result, index) => ({ - userId: result.submission_userId, - username: `user_${result.submission_userId}`, - totalPuzzles: parseInt(result.totalPuzzles), - averageRating: parseFloat(result.averageRating) || 0, - totalPlays: parseInt(result.totalPlays) || 0, - followers: 0, - })); - } - async reportPuzzle(submissionId, userId, reason, category) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId }, - }); - if (!submission) { - throw new Error('Puzzle not found'); - } - if (submission.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED) { - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.UNDER_REVIEW; - submission.moderationData = { - ...submission.moderationData, - action: 'pending_review', - flaggedContent: [reason], - }; - await this.submissionRepository.save(submission); + 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); } - this.logger.log(`Puzzle ${submissionId} reported by user ${userId}: ${reason}`); + return results; } - async reportComment(commentId, userId, reason) { - const comment = await this.commentRepository.findOne({ - where: { id: commentId }, + async getCloudSaves(userId) { + const saves = await this.saveGameRepo.find({ + where: { userId }, + order: { slotId: 'ASC' }, }); - if (!comment) { - throw new Error('Comment not found'); - } - comment.moderationFlags = { - ...comment.moderationFlags, - reportedBy: [...(comment.moderationFlags.reportedBy || []), userId], - reportReasons: [...(comment.moderationFlags.reportReasons || []), reason], - autoFlagged: true, + 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), }; - if (comment.moderationFlags.reportedBy.length >= 3) { - comment.status = puzzle_comment_entity_1.PuzzleCommentStatus.FLAGGED; + save.saveVersion++; + save.lastModifiedAt = new Date(); + if (process.env.NODE_ENV === 'development') { + save.rawData = saveData; } - await this.commentRepository.save(comment); - this.logger.log(`Comment ${commentId} reported by user ${userId}: ${reason}`); + } + 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.CommunityPuzzlesService = CommunityPuzzlesService; -exports.CommunityPuzzlesService = CommunityPuzzlesService = CommunityPuzzlesService_1 = __decorate([ +exports.CloudSyncService = CloudSyncService; +exports.CloudSyncService = CloudSyncService = CloudSyncService_1 = __decorate([ (0, common_1.Injectable)(), - __param(0, (0, typeorm_1.InjectRepository)(user_puzzle_submission_entity_1.UserPuzzleSubmission)), - __param(1, (0, typeorm_1.InjectRepository)(puzzle_rating_entity_1.PuzzleRating)), - __param(2, (0, typeorm_1.InjectRepository)(puzzle_comment_entity_1.PuzzleComment)), - __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]) -], CommunityPuzzlesService); + __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/puzzles/services/creator-rewards.service.ts": -/*!*********************************************************!*\ - !*** ./src/puzzles/services/creator-rewards.service.ts ***! - \*********************************************************/ +/***/ "./src/save-game/services/save-analytics.service.ts": +/*!**********************************************************!*\ + !*** ./src/save-game/services/save-analytics.service.ts ***! + \**********************************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -7416,465 +9910,128 @@ var __metadata = (this && this.__metadata) || function (k, v) { var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; -var CreatorRewardsService_1; -var _a, _b; +var SaveAnalyticsService_1; +var _a; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.CreatorRewardsService = void 0; +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 schedule_1 = __webpack_require__(/*! @nestjs/schedule */ "@nestjs/schedule"); -const user_puzzle_submission_entity_1 = __webpack_require__(/*! ../entities/user-puzzle-submission.entity */ "./src/puzzles/entities/user-puzzle-submission.entity.ts"); -let CreatorRewardsService = CreatorRewardsService_1 = class CreatorRewardsService { - constructor(submissionRepository) { - this.submissionRepository = submissionRepository; - this.logger = new common_1.Logger(CreatorRewardsService_1.name); - this.creatorLevels = [ - { - level: 1, - title: 'Novice Creator', - minPoints: 0, - benefits: ['Basic creator tools', 'Community support'], - badge: 'bronze', - }, - { - level: 2, - title: 'Apprentice Creator', - minPoints: 100, - benefits: ['Advanced analytics', 'Priority support'], - badge: 'bronze', - }, - { - level: 3, - title: 'Journeyman Creator', - minPoints: 500, - benefits: ['Custom themes', 'Enhanced visibility'], - badge: 'silver', - }, - { - level: 4, - title: 'Expert Creator', - minPoints: 1500, - benefits: ['Monetization tools', 'Creator marketplace'], - badge: 'silver', - }, - { - level: 5, - title: 'Master Creator', - minPoints: 5000, - benefits: ['Premium features', 'Revenue sharing'], - badge: 'gold', - }, - { - level: 6, - title: 'Legendary Creator', - minPoints: 15000, - benefits: ['Exclusive content', 'Partner program'], - badge: 'platinum', - }, - ]; - } - async processRewardEvent(event) { - const creatorStats = await this.getCreatorStats(event.userId); - await this.addPointsToCreator(event.userId, event.points); - await this.checkLevelUp(event.userId, creatorStats); - await this.checkAchievements(event.userId, event); - await this.updateMonthlyEarnings(event.userId, event.points); - this.logger.log(`Processed reward event for user ${event.userId}: +${event.points} points`); - } - async onPuzzlePlayed(submissionId, userId) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId }, - }); - if (!submission || !submission.userId) - return; - if (submission.userId === userId) - return; - const points = this.calculatePlayPoints(submission); - await this.processRewardEvent({ - type: 'puzzle_play', - userId: submission.userId, - submissionId, - points, - metadata: { - playedBy: userId, - puzzleRating: submission.averageRating, - }, - }); - } - async onPuzzleRated(submissionId, rating, userId) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId }, - }); - if (!submission || !submission.userId) - return; - if (submission.userId === userId) - return; - const points = this.calculateRatingPoints(rating); - await this.processRewardEvent({ - type: 'puzzle_rating', - userId: submission.userId, - submissionId, - points, - metadata: { - rating, - ratedBy: userId, - }, - }); - } - async onPuzzleFeatured(submissionId, featuredBy) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId }, - }); - if (!submission || !submission.userId) - return; - const points = this.calculateFeaturedPoints(submission); - await this.processRewardEvent({ - type: 'puzzle_featured', - userId: submission.userId, - submissionId, - points, - metadata: { - featuredBy, - featuredAt: new Date(), - }, - }); - const currentFeaturedCount = submission.rewardData?.featuredCount || 0; - submission.rewardData = { - ...submission.rewardData, - featuredCount: currentFeaturedCount + 1, - }; - await this.submissionRepository.save(submission); - } - async onPuzzleShared(submissionId, platform, userId) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId }, - }); - if (!submission || !submission.userId) - return; - const points = this.calculateSharePoints(platform); - await this.processRewardEvent({ - type: 'puzzle_shared', - userId: submission.userId, - submissionId, - points, - metadata: { - platform, - sharedBy: userId, - }, - }); - } - async getCreatorStats(userId) { - const submissions = await this.submissionRepository.find({ - where: { userId }, - }); - const publishedPuzzles = submissions.filter(s => s.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED); - const featuredPuzzles = submissions.filter(s => s.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED); - const totalPlays = publishedPuzzles.reduce((sum, s) => sum + s.playCount, 0); - const averageRating = publishedPuzzles.length > 0 - ? publishedPuzzles.reduce((sum, s) => sum + s.averageRating, 0) / publishedPuzzles.length - : 0; - const totalPoints = await this.getTotalPoints(userId); - const currentLevel = this.getCreatorLevel(totalPoints); - const nextLevel = this.creatorLevels[currentLevel.level + 1] || this.creatorLevels[currentLevel.level]; - return { - userId, - totalPoints, - currentLevel: currentLevel.level, - totalPuzzles: submissions.length, - publishedPuzzles: publishedPuzzles.length, - featuredPuzzles: featuredPuzzles.length, - totalPlays, - averageRating, - monthlyEarnings: await this.getMonthlyEarnings(userId), - achievements: await this.getCreatorAchievements(userId), - nextLevelPoints: nextLevel.minPoints, - pointsToNextLevel: Math.max(0, nextLevel.minPoints - totalPoints), - }; - } - async getLeaderboard(limit = 50, timeframe = 'all') { - let dateFilter = {}; - if (timeframe === 'week') { - const oneWeekAgo = new Date(); - oneWeekAgo.setDate(oneWeekAgo.getDate() - 7); - dateFilter = { createdAt: (0, typeorm_2.Between)(oneWeekAgo, new Date()) }; - } - else if (timeframe === 'month') { - const oneMonthAgo = new Date(); - oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); - dateFilter = { createdAt: (0, typeorm_2.Between)(oneMonthAgo, new Date()) }; +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; } - const query = this.submissionRepository - .createQueryBuilder('submission') - .select([ - 'submission.userId', - 'COUNT(submission.id) as puzzleCount', - 'SUM(submission.playCount) as totalPlays', - 'AVG(submission.averageRating) as avgRating', - ]) - .where('submission.status = :status', { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED }) - .groupBy('submission.userId') - .orderBy('totalPlays', 'DESC') - .limit(limit); - const results = await query.getRawMany(); - return results.map((result, index) => { - const points = this.calculatePointsFromStats(result); - const level = this.getCreatorLevel(points); - return { - userId: result.submission_userId, - username: `creator_${result.submission_userId}`, - points, - level: level.level, - title: level.title, - badge: level.badge, - rank: index + 1, - }; - }); + await this.analyticsRepo.save(analytics); } - async getTopCreators(limit = 10) { - const query = this.submissionRepository - .createQueryBuilder('submission') - .select([ - 'submission.userId', - 'COUNT(CASE WHEN submission.status = :published THEN 1 END) as publishedCount', - 'COUNT(CASE WHEN submission.status = :featured THEN 1 END) as featuredCount', - 'SUM(submission.playCount) as totalPlays', - 'AVG(submission.averageRating) as avgRating', - ]) - .setParameter('published', user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED) - .setParameter('featured', user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED) - .where('submission.status IN (:...statuses)', { - statuses: [user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED, user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED] - }) - .groupBy('submission.userId') - .having('publishedCount > 0') - .orderBy('totalPlays', 'DESC') - .limit(limit); - const results = await query.getRawMany(); - return results.map((result) => { - const points = this.calculatePointsFromStats(result); - const level = this.getCreatorLevel(points); - return { - userId: result.submission_userId, - username: `creator_${result.submission_userId}`, - totalPuzzles: parseInt(result.publishedCount) || 0, - featuredPuzzles: parseInt(result.featuredCount) || 0, - totalPlays: parseInt(result.totalPlays) || 0, - averageRating: parseFloat(result.avgRating) || 0, - level: level.level, - badge: level.badge, - }; - }); + async recordLoad(userId) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.totalLoads++; + analytics.lastLoadAt = new Date(); + await this.analyticsRepo.save(analytics); } - async processMonthlyRewards() { - this.logger.log('Processing monthly creator rewards'); - try { - const topCreators = await this.getLeaderboard(100, 'month'); - for (let i = 0; i < topCreators.length; i++) { - const creator = topCreators[i]; - const bonusPoints = this.calculateMonthlyBonus(i + 1, creator.points); - await this.processRewardEvent({ - type: 'milestone_reached', - userId: creator.userId, - points: bonusPoints, - metadata: { - milestone: 'monthly_top_creator', - rank: i + 1, - timeframe: 'month', - }, - }); - } - this.logger.log(`Processed monthly rewards for ${topCreators.length} creators`); - } - catch (error) { - this.logger.error('Error processing monthly rewards:', error); - } - } - calculatePlayPoints(submission) { - let points = 1; - if (submission.averageRating >= 4.5) - points += 2; - else if (submission.averageRating >= 4.0) - points += 1; - if (submission.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED) - points += 3; - if (submission.difficulty === 'expert') - points += 2; - else if (submission.difficulty === 'hard') - points += 1; - return Math.min(points, 10); - } - calculateRatingPoints(rating) { - if (rating === 5) - return 10; - if (rating === 4) - return 5; - if (rating === 3) - return 2; - return 0; - } - calculateFeaturedPoints(submission) { - let points = 50; - if (submission.averageRating >= 4.5) - points += 25; - else if (submission.averageRating >= 4.0) - points += 15; - if (submission.playCount >= 1000) - points += 25; - else if (submission.playCount >= 500) - points += 15; - else if (submission.playCount >= 100) - points += 5; - return points; - } - calculateSharePoints(platform) { - const platformPoints = { - twitter: 3, - facebook: 2, - reddit: 5, - discord: 4, - whatsapp: 1, - link: 1, - embed: 2, - }; - return platformPoints[platform] || 1; - } - calculateMonthlyBonus(rank, points) { - if (rank === 1) - return 1000; - if (rank === 2) - return 500; - if (rank === 3) - return 250; - if (rank <= 10) - return 100; - if (rank <= 25) - return 50; - if (rank <= 50) - return 25; - if (rank <= 100) - return 10; - return 0; - } - calculatePointsFromStats(stats) { - let points = 0; - points += Math.floor((stats.totalPlays || 0) / 10); - points += (stats.avgRating || 0) * (stats.puzzleCount || 0) * 5; - points += (stats.featuredCount || 0) * 50; - points += (stats.publishedCount || 0) * 10; - return points; - } - getCreatorLevel(points) { - for (let i = this.creatorLevels.length - 1; i >= 0; i--) { - if (points >= this.creatorLevels[i].minPoints) { - return this.creatorLevels[i]; - } + async recordSync(userId, hadConflict) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.cloudSyncs++; + analytics.lastSyncAt = new Date(); + if (hadConflict) { + analytics.syncConflicts++; } - return this.creatorLevels[0]; + await this.analyticsRepo.save(analytics); } - async addPointsToCreator(userId, points) { - this.logger.log(`Added ${points} points to creator ${userId}`); + async recordConflictResolved(userId) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.conflictsResolved++; + await this.analyticsRepo.save(analytics); } - async getTotalPoints(userId) { - const submissions = await this.submissionRepository.find({ - where: { userId }, - }); - return this.calculatePointsFromStats({ - totalPlays: submissions.reduce((sum, s) => sum + s.playCount, 0), - avgRating: submissions.reduce((sum, s) => sum + s.averageRating, 0) / submissions.length || 0, - puzzleCount: submissions.filter(s => s.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED).length, - featuredCount: submissions.filter(s => s.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED).length, - }); + async recordCorruption(userId) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.corruptionEvents++; + await this.analyticsRepo.save(analytics); } - async checkLevelUp(userId, currentStats) { - const currentLevel = this.getCreatorLevel(currentStats.totalPoints); - if (currentStats.currentLevel < currentLevel.level) { - await this.processRewardEvent({ - type: 'milestone_reached', - userId, - points: currentLevel.minPoints - this.creatorLevels[currentStats.currentLevel - 1]?.minPoints || 0, - metadata: { - milestone: 'level_up', - newLevel: currentLevel.level, - newTitle: currentLevel.title, - }, - }); - this.logger.log(`Creator ${userId} leveled up to ${currentLevel.title} (Level ${currentLevel.level})`); - } - } - async checkAchievements(userId, event) { - const achievements = []; - if (event.type === 'puzzle_play') { - const totalPlays = await this.getTotalPlays(userId); - if (totalPlays >= 1000) - achievements.push('Puzzle Master - 1000 Plays'); - if (totalPlays >= 5000) - achievements.push('Puzzle Legend - 5000 Plays'); - } - if (event.type === 'puzzle_featured') { - const featuredCount = await this.getFeaturedCount(userId); - if (featuredCount >= 1) - achievements.push('Featured Creator'); - if (featuredCount >= 5) - achievements.push('Star Creator'); - if (featuredCount >= 10) - achievements.push('Superstar Creator'); - } - for (const achievement of achievements) { - await this.processRewardEvent({ - type: 'milestone_reached', - userId, - points: 25, - metadata: { - milestone: 'achievement', - achievement, - }, - }); + async recordRecoveryAttempt(userId, success) { + const analytics = await this.getOrCreateAnalytics(userId); + analytics.recoveryAttempts++; + if (success) { + analytics.successfulRecoveries++; } + await this.analyticsRepo.save(analytics); } - async updateMonthlyEarnings(userId, points) { - const currentMonth = new Date().toISOString().slice(0, 7); - this.logger.log(`Updated monthly earnings for ${userId}: +${points} points for ${currentMonth}`); - } - async getMonthlyEarnings(userId) { - return {}; - } - async getCreatorAchievements(userId) { - return []; - } - async getTotalPlays(userId) { - const submissions = await this.submissionRepository.find({ - where: { userId, status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED }, - }); - return submissions.reduce((sum, s) => sum + s.playCount, 0); + 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 getFeaturedCount(userId) { - const submissions = await this.submissionRepository.find({ - where: { userId, status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED }, - }); - return submissions.length; + 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.CreatorRewardsService = CreatorRewardsService; -__decorate([ - (0, schedule_1.Cron)('0 0 1 * *'), - __metadata("design:type", Function), - __metadata("design:paramtypes", []), - __metadata("design:returntype", typeof (_b = typeof Promise !== "undefined" && Promise) === "function" ? _b : Object) -], CreatorRewardsService.prototype, "processMonthlyRewards", null); -exports.CreatorRewardsService = CreatorRewardsService = CreatorRewardsService_1 = __decorate([ +exports.SaveAnalyticsService = SaveAnalyticsService; +exports.SaveAnalyticsService = SaveAnalyticsService = SaveAnalyticsService_1 = __decorate([ (0, common_1.Injectable)(), - __param(0, (0, typeorm_1.InjectRepository)(user_puzzle_submission_entity_1.UserPuzzleSubmission)), + __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]) -], CreatorRewardsService); +], SaveAnalyticsService); /***/ }), -/***/ "./src/puzzles/services/featured-puzzles.service.ts": -/*!**********************************************************!*\ - !*** ./src/puzzles/services/featured-puzzles.service.ts ***! - \**********************************************************/ +/***/ "./src/save-game/services/save-backup.service.ts": +/*!*******************************************************!*\ + !*** ./src/save-game/services/save-backup.service.ts ***! + \*******************************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -7890,593 +10047,430 @@ var __metadata = (this && this.__metadata) || function (k, v) { var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; -var FeaturedPuzzlesService_1; -var _a, _b, _c; +var SaveBackupService_1; +var _a, _b, _c, _d, _e; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.FeaturedPuzzlesService = void 0; +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 user_puzzle_submission_entity_1 = __webpack_require__(/*! ../entities/user-puzzle-submission.entity */ "./src/puzzles/entities/user-puzzle-submission.entity.ts"); -let FeaturedPuzzlesService = FeaturedPuzzlesService_1 = class FeaturedPuzzlesService { - constructor(submissionRepository) { - this.submissionRepository = submissionRepository; - this.logger = new common_1.Logger(FeaturedPuzzlesService_1.name); - } - async rotateFeaturedPuzzles() { - this.logger.log('Starting daily featured puzzle rotation'); - try { - await this.unfeatureExpiredPuzzles(); - await this.selectNewFeaturedPuzzles(); - this.logger.log('Completed daily featured puzzle rotation'); - } - catch (error) { - this.logger.error('Error during featured puzzle rotation:', error); +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 weeklyFeatureSelection() { - this.logger.log('Starting weekly featured puzzle selection'); - try { - await this.selectWeeklyFeaturedPuzzles(); - this.logger.log('Completed weekly featured puzzle selection'); - } - catch (error) { - this.logger.error('Error during weekly featured selection:', error); + async getBackups(userId, slotId) { + const where = { userId }; + if (slotId !== undefined) { + where.slotId = slotId; } - } - async getFeaturedPuzzles(limit = 10) { - return await this.submissionRepository.find({ - where: { - status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED, - isPublic: true, - }, - order: { featuredAt: 'DESC' }, - take: limit, - relations: ['user'], - }); - } - async getFeaturedPuzzlesByCategory(category, limit = 5) { - return await this.submissionRepository.find({ - where: { - status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED, - isPublic: true, - category, - }, - order: { featuredAt: 'DESC' }, - take: limit, - relations: ['user'], + return this.backupRepo.find({ + where, + order: { createdAt: 'DESC' }, + take: 50, }); } - async manuallyFeaturePuzzle(submissionId, adminId) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId }, - }); - if (!submission) { - throw new Error('Puzzle submission not found'); - } - if (submission.status !== user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED) { - throw new Error('Only published puzzles can be featured'); - } - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED; - submission.featuredAt = new Date(); - submission.moderationData = { - ...submission.moderationData, - reviewedBy: adminId, - reviewedAt: new Date(), - reviewNotes: 'Manually featured by admin', - }; - await this.submissionRepository.save(submission); - await this.updateCreatorRewards(submission.userId, 'featured'); - this.logger.log(`Puzzle ${submissionId} manually featured by admin ${adminId}`); - return submission; - } - async unfeaturePuzzle(submissionId, adminId) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId }, + async restoreFromBackup(backupId, userId) { + const backup = await this.backupRepo.findOne({ + where: { id: backupId, userId }, }); - if (!submission) { - throw new Error('Puzzle submission not found'); - } - if (submission.status !== user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED) { - throw new Error('Puzzle is not currently featured'); - } - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED; - submission.featuredAt = null; - await this.submissionRepository.save(submission); - this.logger.log(`Puzzle ${submissionId} unfeatured by admin ${adminId}`); - return submission; - } - async unfeatureExpiredPuzzles() { - const thirtyDaysAgo = new Date(); - thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); - const expiredFeatured = await this.submissionRepository.find({ - where: { - status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED, - featuredAt: (0, typeorm_2.LessThan)(thirtyDaysAgo), - }, + 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 }, }); - for (const puzzle of expiredFeatured) { - puzzle.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED; - puzzle.featuredAt = null; - await this.submissionRepository.save(puzzle); - } - this.logger.log(`Unfeatured ${expiredFeatured.length} expired puzzles`); - } - async selectNewFeaturedPuzzles() { - const criteria = { - minRating: 4.0, - minPlays: 50, - minAge: 7, - maxAge: 90, - maxFromSameCreator: 2, - diversityWeight: 0.3, - }; - const candidates = await this.findFeaturedCandidates(criteria); - const selected = await this.selectDiversePuzzles(candidates, criteria, 5); - for (const puzzle of selected) { - puzzle.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED; - puzzle.featuredAt = new Date(); - await this.submissionRepository.save(puzzle); - } - this.logger.log(`Selected ${selected.length} new featured puzzles`); - } - async selectWeeklyFeaturedPuzzles() { - const oneWeekAgo = new Date(); - oneWeekAgo.setDate(oneWeekAgo.getDate() - 7); - const topPerformers = await this.submissionRepository - .createQueryBuilder('puzzle') - .where('puzzle.status = :status', { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED }) - .andWhere('puzzle.isPublic = :isPublic', { isPublic: true }) - .andWhere('puzzle.publishedAt >= :oneWeekAgo', { oneWeekAgo }) - .andWhere('puzzle.averageRating >= :minRating', { minRating: 4.5 }) - .andWhere('puzzle.playCount >= :minPlays', { minPlays: 100 }) - .orderBy('puzzle.communityScore', 'DESC') - .addOrderBy('puzzle.averageRating', 'DESC') - .addOrderBy('puzzle.playCount', 'DESC') - .take(3) - .getMany(); - for (const puzzle of topPerformers) { - if (puzzle.status !== user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED) { - puzzle.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED; - puzzle.featuredAt = new Date(); - await this.submissionRepository.save(puzzle); - } + 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; } - this.logger.log(`Featured ${topPerformers.length} top weekly performers`); - } - async findFeaturedCandidates(criteria) { - const minDate = new Date(); - minDate.setDate(minDate.getDate() - criteria.maxAge); - const maxDate = new Date(); - maxDate.setDate(maxDate.getDate() - criteria.minAge); - let query = this.submissionRepository - .createQueryBuilder('puzzle') - .where('puzzle.status = :status', { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED }) - .andWhere('puzzle.isPublic = :isPublic', { isPublic: true }) - .andWhere('puzzle.averageRating >= :minRating', { minRating: criteria.minRating }) - .andWhere('puzzle.playCount >= :minPlays', { minPlays: criteria.minPlays }) - .andWhere('puzzle.publishedAt BETWEEN :minDate AND :maxDate', { minDate, maxDate }); - if (criteria.categories && criteria.categories.length > 0) { - query = query.andWhere('puzzle.category IN (:...categories)', { categories: criteria.categories }); - } - if (criteria.excludeCreators && criteria.excludeCreators.length > 0) { - query = query.andWhere('puzzle.userId NOT IN (:...excludeCreators)', { excludeCreators: criteria.excludeCreators }); - } - return await query - .orderBy('puzzle.communityScore', 'DESC') - .addOrderBy('puzzle.averageRating', 'DESC') - .addOrderBy('puzzle.playCount', 'DESC') - .getMany(); + 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 selectDiversePuzzles(candidates, criteria, maxSelections) { - const selected = []; - const creatorCounts = {}; - const categoryCounts = {}; - const sortedCandidates = candidates.sort((a, b) => { - const scoreA = this.calculateFeaturedScore(a, criteria); - const scoreB = this.calculateFeaturedScore(b, criteria); - return scoreB - scoreA; - }); - for (const candidate of sortedCandidates) { - if (selected.length >= maxSelections) - break; - const creatorCount = creatorCounts[candidate.userId] || 0; - if (creatorCount >= criteria.maxFromSameCreator) - continue; - if (criteria.diversityWeight > 0.5) { - const categoryCount = categoryCounts[candidate.category] || 0; - const maxCategoryCount = Math.ceil(maxSelections / 5); - if (categoryCount >= maxCategoryCount) - continue; - } - selected.push(candidate); - creatorCounts[candidate.userId] = creatorCount + 1; - categoryCounts[candidate.category] = (categoryCounts[candidate.category] || 0) + 1; + async deleteBackup(backupId, userId) { + const result = await this.backupRepo.delete({ id: backupId, userId }); + if (result.affected === 0) { + throw new Error('Backup not found'); } - return selected; } - calculateFeaturedScore(puzzle, criteria) { - let score = 0; - score += puzzle.averageRating * 25; - score += Math.min(puzzle.playCount / 100, 10) * 15; - score += puzzle.communityScore * 20; - const daysSincePublication = Math.floor((Date.now() - puzzle.publishedAt.getTime()) / (1000 * 60 * 60 * 24)); - const recencyBonus = Math.max(0, 10 - (daysSincePublication / 10)); - score += recencyBonus * 10; - if (puzzle.ratingCount >= 10) - score += 5; - if (puzzle.ratingCount >= 50) - score += 5; - if (puzzle.averageCompletionRate && puzzle.averageCompletionRate > 0.7) - score += 5; - const categoryBonus = this.getCategoryDiversityBonus(puzzle.category); - score += categoryBonus * criteria.diversityWeight * 10; - return score; - } - getCategoryDiversityBonus(category) { - const commonCategories = ['logic', 'math', 'pattern']; - return commonCategories.includes(category) ? 0 : 5; - } - async updateCreatorRewards(userId, rewardType) { - this.logger.log(`Updating rewards for user ${userId}: ${rewardType}`); - } - async getFeaturedPuzzleStats() { - const totalFeatured = await this.submissionRepository.count({ - where: { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED }, - }); - const currentlyFeatured = await this.submissionRepository.count({ - where: { - status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED, - isPublic: true, - }, + async cleanupOldBackups(userId, slotId) { + const backups = await this.backupRepo.find({ + where: { userId, slotId }, + order: { createdAt: 'DESC' }, }); - const featuredByCategory = await this.submissionRepository - .createQueryBuilder('puzzle') - .select('puzzle.category', 'category') - .addSelect('COUNT(*)', 'count') - .where('puzzle.status = :status', { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED }) - .groupBy('puzzle.category') - .getRawMany(); - const categoryStats = {}; - featuredByCategory.forEach((row) => { - categoryStats[row.category] = parseInt(row.count); + 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()), }); - const averageRatingResult = await this.submissionRepository - .createQueryBuilder('puzzle') - .select('AVG(puzzle.averageRating)', 'avgRating') - .where('puzzle.status = :status', { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED }) - .getRawOne(); - const averageFeaturedRating = parseFloat(averageRatingResult.avgRating) || 0; - const ageDistribution = await this.getFeaturedAgeDistribution(); - return { - totalFeatured, - currentlyFeatured, - featuredByCategory: categoryStats, - averageFeaturedRating, - featuredAgeDistribution: ageDistribution, - }; + this.logger.log(`Cleaned up ${result.affected} expired backups`); } - async getFeaturedAgeDistribution() { - const now = new Date(); - const distributions = { - '0-7 days': 0, - '8-14 days': 0, - '15-30 days': 0, - '30+ days': 0, +}; +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__) { + + +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; }; - const featuredPuzzles = await this.submissionRepository.find({ - where: { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED }, - select: ['featuredAt'], - }); - featuredPuzzles.forEach(puzzle => { - if (!puzzle.featuredAt) - return; - const daysFeatured = Math.floor((now.getTime() - puzzle.featuredAt.getTime()) / (1000 * 60 * 60 * 24)); - if (daysFeatured <= 7) - distributions['0-7 days']++; - else if (daysFeatured <= 14) - distributions['8-14 days']++; - else if (daysFeatured <= 30) - distributions['15-30 days']++; - else - distributions['30+ days']++; - }); - return distributions; + 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 getFeaturedSchedule() { - return { - daily: 5, - weekly: 3, - monthly: 10, - }; + 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}`); + } } - async updateFeaturedSchedule(schedule) { - this.logger.log('Updated featured puzzle rotation schedule:', schedule); + estimateCompressedSize(data) { + const jsonSize = JSON.stringify(data).length; + return Math.ceil(jsonSize * 0.35); } }; -exports.FeaturedPuzzlesService = FeaturedPuzzlesService; -__decorate([ - (0, schedule_1.Cron)(schedule_1.CronExpression.EVERY_DAY_AT_MIDNIGHT), - __metadata("design:type", Function), - __metadata("design:paramtypes", []), - __metadata("design:returntype", typeof (_b = typeof Promise !== "undefined" && Promise) === "function" ? _b : Object) -], FeaturedPuzzlesService.prototype, "rotateFeaturedPuzzles", null); -__decorate([ - (0, schedule_1.Cron)('0 2 * * 0'), - __metadata("design:type", Function), - __metadata("design:paramtypes", []), - __metadata("design:returntype", typeof (_c = typeof Promise !== "undefined" && Promise) === "function" ? _c : Object) -], FeaturedPuzzlesService.prototype, "weeklyFeatureSelection", null); -exports.FeaturedPuzzlesService = FeaturedPuzzlesService = FeaturedPuzzlesService_1 = __decorate([ - (0, common_1.Injectable)(), - __param(0, (0, typeorm_1.InjectRepository)(user_puzzle_submission_entity_1.UserPuzzleSubmission)), - __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object]) -], FeaturedPuzzlesService); +exports.SaveCompressionService = SaveCompressionService; +exports.SaveCompressionService = SaveCompressionService = SaveCompressionService_1 = __decorate([ + (0, common_1.Injectable)() +], SaveCompressionService); /***/ }), -/***/ "./src/puzzles/services/puzzle-moderation.service.ts": +/***/ "./src/save-game/services/save-encryption.service.ts": /*!***********************************************************!*\ - !*** ./src/puzzles/services/puzzle-moderation.service.ts ***! + !*** ./src/save-game/services/save-encryption.service.ts ***! \***********************************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { +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 __param = (this && this.__param) || function (paramIndex, decorator) { - return function (target, key) { decorator(target, key, paramIndex); } -}; -var PuzzleModerationService_1; -var _a, _b; +var SaveEncryptionService_1; +var _a; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.PuzzleModerationService = void 0; +exports.SaveEncryptionService = 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_puzzle_submission_entity_1 = __webpack_require__(/*! ../entities/user-puzzle-submission.entity */ "./src/puzzles/entities/user-puzzle-submission.entity.ts"); -const puzzle_validation_service_1 = __webpack_require__(/*! ./puzzle-validation.service */ "./src/puzzles/services/puzzle-validation.service.ts"); -let PuzzleModerationService = PuzzleModerationService_1 = class PuzzleModerationService { - constructor(submissionRepository, validationService) { - this.submissionRepository = submissionRepository; - this.validationService = validationService; - this.logger = new common_1.Logger(PuzzleModerationService_1.name); - } - async submitForReview(submissionId, userId, reviewData) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId, userId }, - }); - if (!submission) { - throw new Error('Puzzle submission not found'); - } - if (submission.status !== user_puzzle_submission_entity_1.PuzzleSubmissionStatus.DRAFT) { - throw new Error('Only draft submissions can be submitted for review'); - } - const validationResults = await this.validationService.validatePuzzle(submission); - const duplicateCheck = await this.validationService.checkForDuplicates(submission); - submission.validationResults = validationResults; - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.SUBMITTED; - submission.submittedAt = new Date(); - if (validationResults.isValid && !duplicateCheck.isDuplicate && validationResults.score >= 85) { - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.APPROVED; - submission.moderationData = { - action: user_puzzle_submission_entity_1.ModerationAction.AUTO_APPROVED, - autoApprovalScore: validationResults.score, - qualityScore: validationResults.automatedChecks.contentQuality, - }; - } - else if (duplicateCheck.isDuplicate) { - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.REJECTED; - submission.moderationData = { - action: user_puzzle_submission_entity_1.ModerationAction.REJECTED_DUPLICATE, - reviewNotes: `Duplicate of: ${duplicateCheck.similarPuzzles.map(p => p.title).join(', ')}`, - }; +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 { - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.UNDER_REVIEW; - submission.moderationData = { - action: user_puzzle_submission_entity_1.ModerationAction.PENDING_REVIEW, - autoApprovalScore: validationResults.score, - qualityScore: validationResults.automatedChecks.contentQuality, - requiredChanges: validationResults.errors.length > 0 ? validationResults.errors : undefined, - }; + this.logger.warn('SAVE_ENCRYPTION_KEY not configured. Using random key. Save data will not persist across restarts.'); + this.encryptionKey = crypto.randomBytes(this.keyLength); } - await this.submissionRepository.save(submission); - this.logger.log(`Puzzle ${submissionId} submitted for review with status: ${submission.status}`); - return submission; } - async getModerationQueue(status, page = 1, limit = 20) { - const where = status ? { status } : {}; - const [submissions, total] = await this.submissionRepository.findAndCount({ - where, - order: { submittedAt: 'DESC' }, - skip: (page - 1) * limit, - take: limit, - relations: ['user'], + 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 { - submissions, - total, - page, - totalPages: Math.ceil(total / limit), + encryptedData: encrypted, + encryptionInfo: { + algorithm: 'aes-256-gcm', + iv: iv.toString('base64'), + tag: authTag.toString('base64'), + }, }; } - async moderatePuzzle(submissionId, moderatorId, decision) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId }, - relations: ['user'], - }); - if (!submission) { - throw new Error('Puzzle submission not found'); - } - if (submission.status !== user_puzzle_submission_entity_1.PuzzleSubmissionStatus.UNDER_REVIEW) { - throw new Error('Only submissions under review can be moderated'); - } - submission.moderationData = { - ...submission.moderationData, - action: decision.action, - reviewedBy: moderatorId, - reviewedAt: new Date(), - reviewNotes: decision.reviewNotes, - qualityScore: decision.qualityScore, - requiredChanges: decision.requiredChanges, - }; - switch (decision.action) { - case user_puzzle_submission_entity_1.ModerationAction.MANUALLY_APPROVED: - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.APPROVED; - break; - case user_puzzle_submission_entity_1.ModerationAction.REJECTED_CONTENT: - case user_puzzle_submission_entity_1.ModerationAction.REJECTED_QUALITY: - case user_puzzle_submission_entity_1.ModerationAction.REJECTED_DUPLICATE: - case user_puzzle_submission_entity_1.ModerationAction.REJECTED_INAPPROPRIATE: - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.REJECTED; - break; - case user_puzzle_submission_entity_1.ModerationAction.REQUIRES_CHANGES: - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.DRAFT; - break; - default: - throw new Error(`Invalid moderation action: ${decision.action}`); + async decrypt(encryptedData, encryptionInfo) { + if (encryptionInfo.algorithm !== 'aes-256-gcm') { + throw new Error(`Unsupported encryption algorithm: ${encryptionInfo.algorithm}`); } - await this.submissionRepository.save(submission); - this.logger.log(`Puzzle ${submissionId} moderated by ${moderatorId} with action: ${decision.action}`); - return submission; - } - async publishPuzzle(submissionId, userId) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId, userId }, + 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, }); - if (!submission) { - throw new Error('Puzzle submission not found'); - } - if (submission.status !== user_puzzle_submission_entity_1.PuzzleSubmissionStatus.APPROVED) { - throw new Error('Only approved puzzles can be published'); - } - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED; - submission.publishedAt = new Date(); - submission.isPublic = true; - await this.submissionRepository.save(submission); - this.logger.log(`Puzzle ${submissionId} published by user ${userId}`); - return submission; - } - async getPendingModerationCount() { - return await this.submissionRepository.count({ - where: { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.UNDER_REVIEW }, - }); - } - async getModerationStats(timeframe = 'week') { - const now = new Date(); - let startDate; - switch (timeframe) { - case 'day': - startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000); - break; - case 'week': - startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); - break; - case 'month': - startDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); - break; + decipher.setAuthTag(authTag); + try { + const decrypted = NodeBuffer.concat([decipher.update(encryptedData), decipher.final()]); + return decrypted; } - const submissions = await this.submissionRepository.find({ - where: { - submittedAt: (0, typeorm_2.Between)(startDate, now), - status: (0, typeorm_2.In)([user_puzzle_submission_entity_1.PuzzleSubmissionStatus.APPROVED, user_puzzle_submission_entity_1.PuzzleSubmissionStatus.REJECTED]), - }, - }); - const stats = { - total: submissions.length, - approved: submissions.filter(s => s.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.APPROVED).length, - rejected: submissions.filter(s => s.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.REJECTED).length, - autoApproved: submissions.filter(s => s.moderationData?.action === user_puzzle_submission_entity_1.ModerationAction.AUTO_APPROVED).length, - averageQualityScore: 0, - averageProcessingTime: 0, - }; - if (submissions.length > 0) { - const qualityScores = submissions - .map(s => s.moderationData?.qualityScore || 0) - .filter(score => score > 0); - stats.averageQualityScore = qualityScores.length > 0 - ? qualityScores.reduce((a, b) => a + b, 0) / qualityScores.length - : 0; - const processingTimes = submissions - .map(s => { - if (s.submittedAt && s.moderationData?.reviewedAt) { - return s.moderationData.reviewedAt.getTime() - s.submittedAt.getTime(); - } - return 0; - }) - .filter(time => time > 0); - stats.averageProcessingTime = processingTimes.length > 0 - ? processingTimes.reduce((a, b) => a + b, 0) / processingTimes.length - : 0; - } - return stats; - } - async flagInappropriateContent(submissionId, reporterId, reason) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId }, - }); - if (!submission) { - throw new Error('Puzzle submission not found'); - } - if (submission.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED) { - submission.status = user_puzzle_submission_entity_1.PuzzleSubmissionStatus.UNDER_REVIEW; - submission.moderationData = { - ...submission.moderationData, - action: user_puzzle_submission_entity_1.ModerationAction.PENDING_REVIEW, - flaggedContent: [...(submission.moderationData?.flaggedContent || []), reason], - }; + 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'); } - await this.submissionRepository.save(submission); - this.logger.log(`Puzzle ${submissionId} flagged by user ${reporterId}: ${reason}`); - return submission; } - async getCreatorStats(userId) { - const submissions = await this.submissionRepository.find({ - where: { userId }, - }); - const published = submissions.filter(s => s.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED); - const featured = submissions.filter(s => s.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED); - const averageRating = published.length > 0 - ? published.reduce((sum, s) => sum + s.averageRating, 0) / published.length - : 0; - const totalPlays = published.reduce((sum, s) => sum + s.playCount, 0); - const acceptanceRate = submissions.length > 0 - ? (published.length / submissions.length) * 100 - : 0; - return { - totalSubmissions: submissions.length, - publishedPuzzles: published.length, - averageRating, - totalPlays, - featuredCount: featured.length, - acceptanceRate, - }; + 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.PuzzleModerationService = PuzzleModerationService; -exports.PuzzleModerationService = PuzzleModerationService = PuzzleModerationService_1 = __decorate([ +exports.SaveEncryptionService = SaveEncryptionService; +exports.SaveEncryptionService = SaveEncryptionService = SaveEncryptionService_1 = __decorate([ (0, common_1.Injectable)(), - __param(0, (0, typeorm_1.InjectRepository)(user_puzzle_submission_entity_1.UserPuzzleSubmission)), - __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof puzzle_validation_service_1.PuzzleValidationService !== "undefined" && puzzle_validation_service_1.PuzzleValidationService) === "function" ? _b : Object]) -], PuzzleModerationService); + __metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object]) +], SaveEncryptionService); /***/ }), -/***/ "./src/puzzles/services/puzzle-validation.service.ts": -/*!***********************************************************!*\ - !*** ./src/puzzles/services/puzzle-validation.service.ts ***! - \***********************************************************/ +/***/ "./src/save-game/services/save-game.service.ts": +/*!*****************************************************!*\ + !*** ./src/save-game/services/save-game.service.ts ***! + \*****************************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -8492,225 +10486,237 @@ var __metadata = (this && this.__metadata) || function (k, v) { var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; -var PuzzleValidationService_1; -var _a; +var SaveGameService_1; +var _a, _b, _c, _d, _e, _f; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.PuzzleValidationService = void 0; +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 user_puzzle_submission_entity_1 = __webpack_require__(/*! ../entities/user-puzzle-submission.entity */ "./src/puzzles/entities/user-puzzle-submission.entity.ts"); -let PuzzleValidationService = PuzzleValidationService_1 = class PuzzleValidationService { - constructor(submissionRepository) { - this.submissionRepository = submissionRepository; - this.logger = new common_1.Logger(PuzzleValidationService_1.name); - } - async validatePuzzle(submission) { - const errors = []; - const warnings = []; - let score = 0; - const automatedChecks = { - hasValidAnswer: this.validateAnswer(submission.content), - hasExplanation: this.validateExplanation(submission.content), - appropriateDifficulty: this.validateDifficulty(submission), - contentQuality: this.assessContentQuality(submission), - mediaValidation: this.validateMedia(submission.content), +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), }; - score = this.calculateValidationScore(automatedChecks); - if (!automatedChecks.hasValidAnswer) { - errors.push('Puzzle must have a valid correct answer'); - } - if (!submission.title || submission.title.length < 3) { - errors.push('Title must be at least 3 characters long'); + 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`); } - if (!submission.description || submission.description.length < 10) { - errors.push('Description must be at least 10 characters long'); + 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 (submission.hints.length > submission.maxHints) { - errors.push('Number of hints exceeds maximum allowed'); + if (dto.playtime !== undefined) { + saveGame.metadata.playtime = dto.playtime; } - if (!automatedChecks.hasExplanation) { - warnings.push('Adding an explanation will improve puzzle quality'); + if (dto.customMetadata) { + saveGame.metadata.customData = { + ...saveGame.metadata.customData, + ...dto.customMetadata, + }; } - if (submission.tags.length < 2) { - warnings.push('Add more tags to improve discoverability'); + 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; + } } - if (submission.timeLimit < 60) { - warnings.push('Time limit seems very short for this difficulty level'); + 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`); } - const isValid = errors.length === 0 && score >= 70; - return { - isValid, - errors, - warnings, - score, - automatedChecks, - }; + return saveGame; } - validateAnswer(content) { - if (!content.correctAnswer) - return false; - switch (content.type) { - case 'multiple-choice': - return Array.isArray(content.options) && - content.options.length >= 2 && - content.options.includes(content.correctAnswer); - case 'fill-blank': - return typeof content.correctAnswer === 'string' && - content.correctAnswer.trim().length > 0; - case 'drag-drop': - return typeof content.correctAnswer === 'object' && - content.correctAnswer !== null; - default: - return content.correctAnswer !== null && - content.correctAnswer !== undefined; - } - } - validateExplanation(content) { - return content.explanation && - typeof content.explanation === 'string' && - content.explanation.trim().length >= 10; - } - validateDifficulty(submission) { - const { difficulty, difficultyRating, timeLimit, basePoints } = submission; - const difficultyRanges = { - easy: { rating: [1, 3], time: [60, 300], points: [10, 100] }, - medium: { rating: [3, 6], time: [180, 600], points: [50, 200] }, - hard: { rating: [6, 8], time: [300, 1200], points: [100, 400] }, - expert: { rating: [8, 10], time: [600, 3600], points: [200, 1000] }, - }; - const range = difficultyRanges[difficulty]; - return range && - difficultyRating >= range.rating[0] && - difficultyRating <= range.rating[1] && - timeLimit >= range.time[0] && - timeLimit <= range.time[1] && - basePoints >= range.points[0] && - basePoints <= range.points[1]; - } - assessContentQuality(submission) { - let qualityScore = 0; - const maxScore = 100; - if (submission.title && submission.title.length >= 10) - qualityScore += 10; - if (submission.title && submission.title.length >= 20) - qualityScore += 10; - if (submission.description && submission.description.length >= 50) - qualityScore += 10; - if (submission.description && submission.description.length >= 100) - qualityScore += 10; - if (submission.content.question) - qualityScore += 10; - if (submission.content.explanation) - qualityScore += 10; - if (submission.hints.length > 0) - qualityScore += 5; - if (submission.hints.length >= 2) - qualityScore += 5; - if (submission.hints.every(hint => hint.text.length >= 20)) - qualityScore += 5; - if (submission.tags.length >= 3) - qualityScore += 10; - if (submission.tags.length >= 5) - qualityScore += 5; - if (submission.creatorNotes && Object.keys(submission.creatorNotes).length > 0) { - qualityScore += 10; - } - return Math.min(qualityScore, maxScore); - } - validateMedia(content) { - if (!content.media) - return true; - const { images, videos, audio } = content.media; - if (images && Array.isArray(images)) { - return images.every(url => typeof url === 'string' && url.length > 0); + 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.`); } - if (videos && Array.isArray(videos)) { - return videos.every(url => typeof url === 'string' && url.length > 0); + 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; } - if (audio && Array.isArray(audio)) { - return audio.every(url => typeof url === 'string' && url.length > 0); + 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; } - return true; } - calculateValidationScore(checks) { - let score = 0; - const weights = { - hasValidAnswer: 30, - hasExplanation: 20, - appropriateDifficulty: 25, - contentQuality: 20, - mediaValidation: 5, - }; - if (checks.hasValidAnswer) - score += weights.hasValidAnswer; - if (checks.hasExplanation) - score += weights.hasExplanation; - if (checks.appropriateDifficulty) - score += weights.appropriateDifficulty; - score += (checks.contentQuality / 100) * weights.contentQuality; - if (checks.mediaValidation) - score += weights.mediaValidation; - return Math.round(score); - } - async checkForDuplicates(submission) { - const similarPuzzles = await this.submissionRepository - .createQueryBuilder('submission') - .where('submission.title ILIKE :title', { title: `%${submission.title}%` }) - .orWhere('submission.description ILIKE :description', { description: `%${submission.description}%` }) - .andWhere('submission.status != :rejected', { rejected: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.REJECTED }) - .andWhere('submission.id != :id', { id: submission.id }) - .select(['submission.id', 'submission.title']) - .limit(5) - .getMany(); - const similarityThreshold = 0.8; - const duplicates = similarPuzzles.map(puzzle => ({ - id: puzzle.id, - title: puzzle.title, - similarity: this.calculateSimilarity(submission.title, puzzle.title), - })).filter(result => result.similarity >= similarityThreshold); - return { - isDuplicate: duplicates.length > 0, - similarPuzzles: duplicates, - }; + 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}`); } - calculateSimilarity(str1, str2) { - const longer = str1.length > str2.length ? str1 : str2; - const shorter = str1.length > str2.length ? str2 : str1; - if (longer.length === 0) - return 1.0; - const distance = this.levenshteinDistance(longer, shorter); - return (longer.length - distance) / longer.length; - } - levenshteinDistance(str1, str2) { - const matrix = Array(str2.length + 1).fill(null).map(() => Array(str1.length + 1).fill(null)); - for (let i = 0; i <= str1.length; i++) - matrix[0][i] = i; - for (let j = 0; j <= str2.length; j++) - matrix[j][0] = j; - for (let j = 1; j <= str2.length; j++) { - for (let i = 1; i <= str1.length; i++) { - const indicator = str1[i - 1] === str2[j - 1] ? 0 : 1; - matrix[j][i] = Math.min(matrix[j][i - 1] + 1, matrix[j - 1][i] + 1, matrix[j - 1][i - 1] + indicator); + 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 matrix[str2.length][str1.length]; + 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.PuzzleValidationService = PuzzleValidationService; -exports.PuzzleValidationService = PuzzleValidationService = PuzzleValidationService_1 = __decorate([ +exports.SaveGameService = SaveGameService; +exports.SaveGameService = SaveGameService = SaveGameService_1 = __decorate([ (0, common_1.Injectable)(), - __param(0, (0, typeorm_1.InjectRepository)(user_puzzle_submission_entity_1.UserPuzzleSubmission)), - __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object]) -], PuzzleValidationService); + __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/puzzles/services/user-puzzle-submission.service.ts": -/*!****************************************************************!*\ - !*** ./src/puzzles/services/user-puzzle-submission.service.ts ***! - \****************************************************************/ +/***/ "./src/save-game/services/save-versioning.service.ts": +/*!***********************************************************!*\ + !*** ./src/save-game/services/save-versioning.service.ts ***! + \***********************************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -8720,232 +10726,121 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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 UserPuzzleSubmissionService_1; -var _a, _b, _c; +var SaveVersioningService_1; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.UserPuzzleSubmissionService = void 0; +exports.SaveVersioningService = 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_puzzle_submission_entity_1 = __webpack_require__(/*! ../entities/user-puzzle-submission.entity */ "./src/puzzles/entities/user-puzzle-submission.entity.ts"); -const puzzle_validation_service_1 = __webpack_require__(/*! ./puzzle-validation.service */ "./src/puzzles/services/puzzle-validation.service.ts"); -const puzzle_moderation_service_1 = __webpack_require__(/*! ./puzzle-moderation.service */ "./src/puzzles/services/puzzle-moderation.service.ts"); -let UserPuzzleSubmissionService = UserPuzzleSubmissionService_1 = class UserPuzzleSubmissionService { - constructor(submissionRepository, validationService, moderationService) { - this.submissionRepository = submissionRepository; - this.validationService = validationService; - this.moderationService = moderationService; - this.logger = new common_1.Logger(UserPuzzleSubmissionService_1.name); - } - async createSubmission(userId, createDto) { - const submission = this.submissionRepository.create({ - userId, - ...createDto, - status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.DRAFT, - sharingSettings: { - allowShare: true, - embeddable: false, - downloadAllowed: false, - attributionRequired: true, - ...createDto.sharingSettings, - }, - }); - if (createDto.isPublic) { - submission.sharingSettings.shareableLink = await this.generateShareableLink(); - } - const savedSubmission = await this.submissionRepository.save(submission); - this.logger.log(`Created puzzle submission ${savedSubmission.id} for user ${userId}`); - return savedSubmission; - } - async getUserSubmissions(userId, status, page = 1, limit = 20) { - const where = status ? { userId, status } : { userId }; - const [submissions, total] = await this.submissionRepository.findAndCount({ - where, - order: { createdAt: 'DESC' }, - skip: (page - 1) * limit, - take: limit, - }); - return { - submissions, - total, - page, - totalPages: Math.ceil(total / limit), - }; - } - async getSubmissionById(submissionId, userId) { - const where = userId ? { id: submissionId, userId } : { id: submissionId }; - const submission = await this.submissionRepository.findOne({ where }); - if (!submission) { - throw new Error('Puzzle submission not found'); - } - if (submission.isPublic && submission.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED) { - await this.submissionRepository.increment({ id: submissionId }, 'views', 1); - } - return submission; +let SaveVersioningService = SaveVersioningService_1 = class SaveVersioningService { + constructor() { + this.logger = new common_1.Logger(SaveVersioningService_1.name); + this.CURRENT_VERSION = 1; + this.migrations = []; } - async updateSubmission(submissionId, userId, updateDto) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId, userId }, - }); - if (!submission) { - throw new Error('Puzzle submission not found'); - } - if (submission.status !== user_puzzle_submission_entity_1.PuzzleSubmissionStatus.DRAFT) { - throw new Error('Only draft submissions can be updated'); + isCompatible(version) { + if (version === this.CURRENT_VERSION) { + return true; } - Object.assign(submission, updateDto); - submission.updatedAt = new Date(); - const savedSubmission = await this.submissionRepository.save(submission); - this.logger.log(`Updated puzzle submission ${submissionId} by user ${userId}`); - return savedSubmission; + return this.canMigrate(version, this.CURRENT_VERSION); } - async deleteSubmission(submissionId, userId) { - const submission = await this.submissionRepository.findOne({ - where: { id: submissionId, userId }, - }); - if (!submission) { - throw new Error('Puzzle submission not found'); + canMigrate(fromVersion, toVersion) { + if (fromVersion >= toVersion) { + return fromVersion === toVersion; } - if (submission.status === user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED) { - throw new Error('Published puzzles cannot be deleted'); + 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; } - await this.submissionRepository.remove(submission); - this.logger.log(`Deleted puzzle submission ${submissionId} by user ${userId}`); - } - async submitForReview(submissionId, userId, reviewData) { - return await this.moderationService.submitForReview(submissionId, userId, reviewData); + return migratedData; } - async publishPuzzle(submissionId, userId) { - return await this.moderationService.publishPuzzle(submissionId, userId); - } - async searchCommunityPuzzles(searchDto) { - const { query, categories, difficulties, tags, sortBy = 'newest', page = 1, limit = 20, isPublic = true, } = searchDto; - const queryBuilder = this.submissionRepository - .createQueryBuilder('submission') - .where('submission.isPublic = :isPublic', { isPublic }) - .andWhere('submission.status = :status', { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED }); - if (query) { - queryBuilder.andWhere('(submission.title ILIKE :query OR submission.description ILIKE :query)', { query: `%${query}%` }); + validateDataStructure(data) { + const errors = []; + if (!data || typeof data !== 'object') { + return { valid: false, errors: ['Data must be an object'] }; } - if (categories && categories.length > 0) { - queryBuilder.andWhere('submission.category IN (:...categories)', { categories }); + const saveData = data; + if (typeof saveData.version !== 'number') { + errors.push('Missing or invalid version field'); } - if (difficulties && difficulties.length > 0) { - queryBuilder.andWhere('submission.difficulty IN (:...difficulties)', { difficulties }); + if (!saveData.gameState || typeof saveData.gameState !== 'object') { + errors.push('Missing or invalid gameState field'); } - if (tags && tags.length > 0) { - queryBuilder.andWhere('submission.tags && :tags', { tags }); + if (!saveData.playerState || typeof saveData.playerState !== 'object') { + errors.push('Missing or invalid playerState field'); } - switch (sortBy) { - case 'newest': - queryBuilder.orderBy('submission.publishedAt', 'DESC'); - break; - case 'oldest': - queryBuilder.orderBy('submission.publishedAt', 'ASC'); - break; - case 'popular': - queryBuilder.orderBy('submission.views', 'DESC'); - break; - case 'highest_rated': - queryBuilder.orderBy('submission.averageRating', 'DESC'); - break; - case 'most_played': - queryBuilder.orderBy('submission.playCount', 'DESC'); - break; - case 'trending': - const sevenDaysAgo = new Date(); - sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); - queryBuilder - .orderBy('submission.lastActivityAt', 'DESC') - .andWhere('submission.lastActivityAt >= :sevenDaysAgo', { sevenDaysAgo }); - break; + if (!saveData.progressState || typeof saveData.progressState !== 'object') { + errors.push('Missing or invalid progressState field'); } - const [submissions, total] = await queryBuilder - .skip((page - 1) * limit) - .take(limit) - .getManyAndCount(); return { - submissions, - total, - page, - totalPages: Math.ceil(total / limit), + valid: errors.length === 0, + errors, }; } - async getFeaturedPuzzles(limit = 10) { - return await this.submissionRepository.find({ - where: { - status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.FEATURED, - isPublic: true, + createDefaultSaveData() { + return { + version: this.CURRENT_VERSION, + gameState: {}, + playerState: { + position: { x: 0, y: 0 }, + health: 100, + inventory: [], + stats: {}, }, - order: { featuredAt: 'DESC' }, - take: limit, - }); - } - async getTrendingPuzzles(limit = 10) { - const sevenDaysAgo = new Date(); - sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); - return await this.submissionRepository - .createQueryBuilder('submission') - .where('submission.isPublic = :isPublic', { isPublic: true }) - .andWhere('submission.status = :status', { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED }) - .andWhere('submission.lastActivityAt >= :sevenDaysAgo', { sevenDaysAgo }) - .orderBy('submission.playCount', 'DESC') - .addOrderBy('submission.averageRating', 'DESC') - .take(limit) - .getMany(); - } - async getRecommendedPuzzles(userId, limit = 10) { - return await this.submissionRepository - .createQueryBuilder('submission') - .where('submission.isPublic = :isPublic', { isPublic: true }) - .andWhere('submission.status = :status', { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED }) - .andWhere('submission.userId != :userId', { userId }) - .orderBy('submission.communityScore', 'DESC') - .addOrderBy('submission.averageRating', 'DESC') - .take(limit) - .getMany(); - } - async incrementPlayCount(submissionId) { - await this.submissionRepository.increment({ id: submissionId }, 'playCount', 1); - await this.submissionRepository.update({ id: submissionId }, { lastActivityAt: new Date() }); - } - async generateShareableLink() { - const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - let result = ''; - for (let i = 0; i < 12; i++) { - result += characters.charAt(Math.floor(Math.random() * characters.length)); - } - return result; - } - async getSubmissionByShareableLink(shareableLink) { - const submission = await this.submissionRepository - .createQueryBuilder('submission') - .where("submission.sharingSettings->>'shareableLink' = :shareableLink", { shareableLink }) - .andWhere('submission.isPublic = :isPublic', { isPublic: true }) - .andWhere('submission.status = :status', { status: user_puzzle_submission_entity_1.PuzzleSubmissionStatus.PUBLISHED }) - .getOne(); - if (!submission) { - throw new Error('Puzzle not found or not accessible'); - } - await this.submissionRepository.increment({ id: submission.id }, 'views', 1); - return submission; + progressState: { + completedLevels: [], + unlockedAchievements: [], + collectibles: [], + }, + settings: {}, + }; } - async getCreatorStats(userId) { - return await this.moderationService.getCreatorStats(userId); + mergeWithDefaults(partialData) { + const defaults = this.createDefaultSaveData(); + return { + ...defaults, + ...partialData, + version: this.CURRENT_VERSION, + playerState: { + ...defaults.playerState, + ...partialData.playerState, + }, + progressState: { + ...defaults.progressState, + ...partialData.progressState, + }, + }; } }; -exports.UserPuzzleSubmissionService = UserPuzzleSubmissionService; -exports.UserPuzzleSubmissionService = UserPuzzleSubmissionService = UserPuzzleSubmissionService_1 = __decorate([ - (0, common_1.Injectable)(), - __param(0, (0, typeorm_1.InjectRepository)(user_puzzle_submission_entity_1.UserPuzzleSubmission)), - __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof puzzle_validation_service_1.PuzzleValidationService !== "undefined" && puzzle_validation_service_1.PuzzleValidationService) === "function" ? _b : Object, typeof (_c = typeof puzzle_moderation_service_1.PuzzleModerationService !== "undefined" && puzzle_moderation_service_1.PuzzleModerationService) === "function" ? _c : Object]) -], UserPuzzleSubmissionService); +exports.SaveVersioningService = SaveVersioningService; +exports.SaveVersioningService = SaveVersioningService = SaveVersioningService_1 = __decorate([ + (0, common_1.Injectable)() +], SaveVersioningService); /***/ }), @@ -10896,15 +12791,83 @@ let TournamentsService = TournamentsService_1 = class TournamentsService { }; } }; -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); +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/user-progress/entities/user-collection-progress.entity.ts": +/*!***********************************************************************!*\ + !*** ./src/user-progress/entities/user-collection-progress.entity.ts ***! + \***********************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +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); /***/ }), @@ -10973,6 +12936,58 @@ class UpdateUserDto extends (0, mapped_types_1.PartialType)(create_user_dto_1.Cr 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__) { + + +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": @@ -11031,96 +13046,475 @@ __decorate([ __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); + (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__) { + + +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__) { + + +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: 'int', default: 0 }), - __metadata("design:type", Number) -], UserStats.prototype, "currentStreak", void 0); + (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) -], UserStats.prototype, "longestStreak", void 0); +], User.prototype, "totalScore", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'decimal', precision: 5, scale: 2, default: 0 }), - (0, typeorm_1.Index)(), + (0, typeorm_1.Column)({ type: 'int', default: 1 }), __metadata("design:type", Number) -], UserStats.prototype, "overallAccuracy", void 0); +], User.prototype, "level", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'decimal', precision: 10, scale: 2, default: 0 }), + (0, typeorm_1.Column)({ type: 'int', default: 0 }), __metadata("design:type", Number) -], UserStats.prototype, "averageCompletionTime", void 0); +], User.prototype, "experience", void 0); __decorate([ (0, typeorm_1.Column)({ type: 'int', default: 0 }), __metadata("design:type", Number) -], UserStats.prototype, "totalAchievements", void 0); +], User.prototype, "puzzlesSolved", void 0); __decorate([ (0, typeorm_1.Column)({ type: 'int', default: 0 }), __metadata("design:type", Number) -], UserStats.prototype, "totalGameSessions", void 0); +], User.prototype, "achievementsCount", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], UserStats.prototype, "difficultyStats", void 0); + (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: 'jsonb', default: {} }), - __metadata("design:type", typeof (_a = typeof Record !== "undefined" && Record) === "function" ? _a : Object) -], UserStats.prototype, "categoryStats", void 0); + (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) -], UserStats.prototype, "timeStats", void 0); +], User.prototype, "preferences", void 0); __decorate([ (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), __metadata("design:type", Object) -], UserStats.prototype, "trends", void 0); +], User.prototype, "profile", void 0); __decorate([ (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), __metadata("design:type", Object) -], UserStats.prototype, "milestones", void 0); +], User.prototype, "metadata", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'jsonb', default: {} }), - __metadata("design:type", Object) -], UserStats.prototype, "rankings", void 0); + (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.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); + (0, typeorm_1.OneToMany)('PuzzleProgress', 'user'), + __metadata("design:type", Array) +], User.prototype, "puzzleProgress", 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); + (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.CreateDateColumn)(), - (0, typeorm_1.Index)(), - __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) -], UserStats.prototype, "createdAt", void 0); + (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.UpdateDateColumn)(), - (0, typeorm_1.Index)(), - __metadata("design:type", typeof (_e = typeof Date !== "undefined" && Date) === "function" ? _e : Object) -], UserStats.prototype, "updatedAt", void 0); + (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__) { + + +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, 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); + (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__) { + + +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__) { + + +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/users/entities/user.entity.ts": -/*!*******************************************!*\ - !*** ./src/users/entities/user.entity.ts ***! - \*******************************************/ +/***/ "./src/wallet/dto/connect-wallet.dto.ts": +/*!**********************************************!*\ + !*** ./src/wallet/dto/connect-wallet.dto.ts ***! + \**********************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -11133,143 +13527,303 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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.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"); -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); +exports.ConnectWalletDto = void 0; +const class_validator_1 = __webpack_require__(/*! class-validator */ "class-validator"); +class ConnectWalletDto { +} +exports.ConnectWalletDto = ConnectWalletDto; __decorate([ - (0, typeorm_1.Column)({ type: 'varchar', length: 100 }), + (0, class_validator_1.IsString)(), __metadata("design:type", String) -], User.prototype, "firstName", void 0); +], ConnectWalletDto.prototype, "publicKey", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'varchar', length: 100 }), + (0, class_validator_1.IsString)(), __metadata("design:type", String) -], User.prototype, "lastName", void 0); +], ConnectWalletDto.prototype, "network", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'varchar', length: 255, unique: true }), - (0, typeorm_1.Index)(), + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), __metadata("design:type", String) -], User.prototype, "email", void 0); +], ConnectWalletDto.prototype, "signature", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'varchar', length: 255 }), + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), __metadata("design:type", String) -], User.prototype, "password", void 0); +], 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__) { + + +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, typeorm_1.Column)({ type: 'varchar', length: 255, nullable: true }), + (0, class_validator_1.IsString)(), __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); +], RecordTransactionDto.prototype, "assetCode", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'varchar', length: 50, nullable: true }), + (0, class_validator_1.IsOptional)(), + (0, class_validator_1.IsString)(), __metadata("design:type", String) -], User.prototype, "country", void 0); +], RecordTransactionDto.prototype, "issuer", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'active' }), - (0, typeorm_1.Index)(), + (0, class_validator_1.IsString)(), __metadata("design:type", String) -], User.prototype, "status", void 0); +], RecordTransactionDto.prototype, "amount", void 0); __decorate([ - (0, typeorm_1.Column)({ type: 'varchar', length: 20, default: 'player' }), - (0, typeorm_1.Index)(), + (0, class_validator_1.IsString)(), __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.CreateDateColumn)(), - (0, typeorm_1.Index)(), - __metadata("design:type", typeof (_d = typeof Date !== "undefined" && Date) === "function" ? _d : Object) -], User.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) -], User.prototype, "updatedAt", void 0); -__decorate([ - (0, typeorm_1.DeleteDateColumn)(), - __metadata("design:type", typeof (_f = typeof Date !== "undefined" && Date) === "function" ? _f : Object) -], User.prototype, "deletedAt", 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); -exports.User = User = __decorate([ - (0, typeorm_1.Entity)('users'), - (0, typeorm_1.Index)(['email'], { unique: true }), - (0, typeorm_1.Index)(['username'], { unique: true }) -], User); +], RecordTransactionDto.prototype, "transactionHash", void 0); /***/ }), -/***/ "./src/users/users.controller.ts": -/*!***************************************!*\ - !*** ./src/users/users.controller.ts ***! - \***************************************/ +/***/ "./src/wallet/guards/wallet-session.guard.ts": +/*!***************************************************!*\ + !*** ./src/wallet/guards/wallet-session.guard.ts ***! + \***************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +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__) => { + + +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__) { @@ -11285,97 +13839,140 @@ var __metadata = (this && this.__metadata) || function (k, v) { var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; -var _a, _b, _c, _d, _e; +var _a, _b, _c, _d; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.UsersController = void 0; +exports.WalletController = 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; +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); } - create(createUserDto) { - return this.usersService.create(createUserDto); + getSession(req) { + const session = req.walletSession; + return { + publicKey: session.publicKey, + network: session.network, + expiresAt: session.expiresAt.toISOString(), + }; } - findAll() { - return this.usersService.findAll(); + disconnect(req) { + const session = req.walletSession; + return this.walletService.disconnect(session.sessionToken); } - findOne(id) { - return this.usersService.findOne(id); + getBalances(req) { + return this.walletService.getBalances(req.walletSession); } - update(id, updateUserDto) { - return this.usersService.update(id, updateUserDto); + 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); } - remove(id) { - return this.usersService.remove(id); + recordPurchase(req, body) { + return this.walletService.recordPurchase(req.walletSession, body); } - uploadAvatar(file) { - return { message: 'Avatar uploaded successfully', filename: file.originalname }; + recordSpend(req, body) { + return this.walletService.recordSpend(req.walletSession, body); } }; -exports.UsersController = UsersController; +exports.WalletController = WalletController; __decorate([ - (0, common_1.Post)(), + (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 create_user_dto_1.CreateUserDto !== "undefined" && create_user_dto_1.CreateUserDto) === "function" ? _b : Object]), + __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) -], UsersController.prototype, "create", null); +], WalletController.prototype, "connect", null); __decorate([ - (0, common_1.Get)(), + (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", []), + __metadata("design:paramtypes", [Object]), __metadata("design:returntype", void 0) -], UsersController.prototype, "findAll", null); +], WalletController.prototype, "getSession", null); __decorate([ - (0, common_1.Get)(':id'), - __param(0, (0, common_1.Param)('id')), + (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", [String]), + __metadata("design:paramtypes", [Object]), __metadata("design:returntype", void 0) -], UsersController.prototype, "findOne", null); +], WalletController.prototype, "disconnect", null); __decorate([ - (0, common_1.Patch)(':id'), - __param(0, (0, common_1.Param)('id')), - __param(1, (0, common_1.Body)()), + (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", [String, typeof (_c = typeof update_user_dto_1.UpdateUserDto !== "undefined" && update_user_dto_1.UpdateUserDto) === "function" ? _c : Object]), + __metadata("design:paramtypes", [Object]), __metadata("design:returntype", void 0) -], UsersController.prototype, "update", null); +], WalletController.prototype, "getBalances", null); __decorate([ - (0, common_1.Delete)(':id'), - __param(0, (0, common_1.Param)('id')), + (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", [String]), + __metadata("design:paramtypes", [Object, String, String]), __metadata("design:returntype", void 0) -], UsersController.prototype, "remove", null); +], WalletController.prototype, "getTransactions", 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)()), + (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", [typeof (_e = typeof Express !== "undefined" && (_d = Express.Multer) !== void 0 && _d.File) === "function" ? _e : Object]), + __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) -], 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); +], 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/users/users.module.ts": -/*!***********************************!*\ - !*** ./src/users/users.module.ts ***! - \***********************************/ +/***/ "./src/wallet/wallet.module.ts": +/*!*************************************!*\ + !*** ./src/wallet/wallet.module.ts ***! + \*************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -11386,27 +13983,31 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, return c > 3 && r && Object.defineProperty(target, key, r), r; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.UsersModule = void 0; +exports.WalletModule = 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 { +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.UsersModule = UsersModule; -exports.UsersModule = UsersModule = __decorate([ +exports.WalletModule = WalletModule; +exports.WalletModule = WalletModule = __decorate([ (0, common_1.Module)({ - controllers: [users_controller_1.UsersController], - providers: [users_service_1.UsersService], + imports: [config_1.ConfigModule], + controllers: [wallet_controller_1.WalletController], + providers: [wallet_service_1.WalletService, wallet_session_guard_1.WalletSessionGuard], + exports: [wallet_service_1.WalletService], }) -], UsersModule); +], WalletModule); /***/ }), -/***/ "./src/users/users.service.ts": -/*!************************************!*\ - !*** ./src/users/users.service.ts ***! - \************************************/ +/***/ "./src/wallet/wallet.service.ts": +/*!**************************************!*\ + !*** ./src/wallet/wallet.service.ts ***! + \**************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { @@ -11416,30 +14017,473 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, 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.UsersService = void 0; +exports.WalletService = void 0; const common_1 = __webpack_require__(/*! @nestjs/common */ "@nestjs/common"); -let UsersService = class UsersService { - create(createUserDto) { - return 'This action adds a new user'; +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(), + }; } - findAll() { - return `This action returns all users`; + 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(), + }; } - findOne(id) { - return `This action returns a user with id #${id}`; + 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; } - update(id, updateUserDto) { - return `This action updates a user with id #${id}`; + disconnect(sessionToken) { + if (!this.sessions.has(sessionToken)) { + throw new common_1.UnauthorizedException('Wallet session not found'); + } + this.sessions.delete(sessionToken); + return { status: 'disconnected' }; } - remove(id) { - return `This action removes a user with id #${id}`; + 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.UsersService = UsersService; -exports.UsersService = UsersService = __decorate([ - (0, common_1.Injectable)() -], UsersService); +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); /***/ }), @@ -11484,6 +14528,16 @@ module.exports = require("@nestjs/mapped-types"); /***/ }), +/***/ "@nestjs/microservices": +/*!****************************************!*\ + !*** external "@nestjs/microservices" ***! + \****************************************/ +/***/ ((module) => { + +module.exports = require("@nestjs/microservices"); + +/***/ }), + /***/ "@nestjs/passport": /*!***********************************!*\ !*** external "@nestjs/passport" ***! @@ -11514,6 +14568,16 @@ module.exports = require("@nestjs/schedule"); /***/ }), +/***/ "@nestjs/swagger": +/*!**********************************!*\ + !*** external "@nestjs/swagger" ***! + \**********************************/ +/***/ ((module) => { + +module.exports = require("@nestjs/swagger"); + +/***/ }), + /***/ "@nestjs/terminus": /*!***********************************!*\ !*** external "@nestjs/terminus" ***! @@ -11554,6 +14618,16 @@ module.exports = require("@sentry/node"); /***/ }), +/***/ "buffer": +/*!*************************!*\ + !*** external "buffer" ***! + \*************************/ +/***/ ((module) => { + +module.exports = require("buffer"); + +/***/ }), + /***/ "class-transformer": /*!************************************!*\ !*** external "class-transformer" ***! @@ -11654,6 +14728,16 @@ module.exports = require("xss"); /***/ }), +/***/ "crypto": +/*!*************************!*\ + !*** external "crypto" ***! + \*************************/ +/***/ ((module) => { + +module.exports = require("crypto"); + +/***/ }), + /***/ "path": /*!***********************!*\ !*** external "path" ***! @@ -11662,6 +14746,26 @@ module.exports = require("xss"); module.exports = require("path"); +/***/ }), + +/***/ "util": +/*!***********************!*\ + !*** external "util" ***! + \***********************/ +/***/ ((module) => { + +module.exports = require("util"); + +/***/ }), + +/***/ "zlib": +/*!***********************!*\ + !*** external "zlib" ***! + \***********************/ +/***/ ((module) => { + +module.exports = require("zlib"); + /***/ }) /******/ }); diff --git a/package-lock.json b/package-lock.json index 82dbbb9..3e5fdf0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,16 +26,17 @@ "amqplib": "^0.10.9", "cache-manager": "^7.1.1", "class-transformer": "^0.5.1", - "class-validator": "^0.14.1", + "class-validator": "^0.14.3", "date-fns": "^4.1.0", "helmet": "^7.2.0", "nest-winston": "^1.9.7", "nodemailer": "^7.0.5", - "pg": "^8.16.3", + "passport": "^0.7.0", + "pg": "^8.17.2", "prom-client": "^15.1.3", "reflect-metadata": "^0.1.14", "rxjs": "^7.8.1", - "typeorm": "^0.3.25", + "typeorm": "^0.3.28", "winston": "^3.11.0", "winston-daily-rotate-file": "^5.0.0", "winston-elasticsearch": "^0.19.0", @@ -43,7 +44,7 @@ }, "devDependencies": { "@nestjs/cli": "^10.4.5", - "@nestjs/jwt": "^11.0.0", + "@nestjs/jwt": "^11.0.2", "@nestjs/passport": "^11.0.5", "@nestjs/schematics": "^10.1.4", "@nestjs/swagger": "^7.4.2", @@ -1904,13 +1905,14 @@ } }, "node_modules/@nestjs/jwt": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-11.0.0.tgz", - "integrity": "sha512-v7YRsW3Xi8HNTsO+jeHSEEqelX37TVWgwt+BcxtkG/OfXJEOs6GZdbdza200d6KqId1pJQZ6UPj1F0M6E+mxaA==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-11.0.2.tgz", + "integrity": "sha512-rK8aE/3/Ma45gAWfCksAXUNbOoSOUudU0Kn3rT39htPF7wsYXtKfjALKeKKJbFrIWbLjsbqfXX5bIJNvgBugGA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/jsonwebtoken": "9.0.7", - "jsonwebtoken": "9.0.2" + "@types/jsonwebtoken": "9.0.10", + "jsonwebtoken": "9.0.3" }, "peerDependencies": { "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" @@ -2005,6 +2007,7 @@ "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-11.0.5.tgz", "integrity": "sha512-ulQX6mbjlws92PIM15Naes4F4p2JoxGnIJuUsdXQPT+Oo2sqQmENEZXM7eYuimocfHnKlcfZOuyzbA33LwUlOQ==", "dev": true, + "license": "MIT", "peerDependencies": { "@nestjs/common": "^10.0.0 || ^11.0.0", "passport": "^0.5.0 || ^0.6.0 || ^0.7.0" @@ -3417,11 +3420,13 @@ "license": "MIT" }, "node_modules/@types/jsonwebtoken": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz", - "integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==", + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", "dev": true, + "license": "MIT", "dependencies": { + "@types/ms": "*", "@types/node": "*" } }, @@ -3445,6 +3450,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/multer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", @@ -3612,9 +3624,9 @@ "license": "MIT" }, "node_modules/@types/validator": { - "version": "13.15.2", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.2.tgz", - "integrity": "sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==", + "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": { @@ -4311,9 +4323,9 @@ } }, "node_modules/ansis": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", - "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "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" @@ -4685,6 +4697,7 @@ "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "node-addon-api": "^8.3.0", "node-gyp-build": "^4.8.4" @@ -4938,7 +4951,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/buffer-from": { "version": "1.1.2", @@ -5199,14 +5213,14 @@ "license": "MIT" }, "node_modules/class-validator": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.2.tgz", - "integrity": "sha512-3kMVRF2io8N8pY1IFIXlho9r8IPUUIfHe2hYVtiebvAzU2XeQFXTv+XI4WX+TnXmtwXMDcjngcpkiPM0O9PvLw==", + "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.11.8", + "@types/validator": "^13.15.3", "libphonenumber-js": "^1.11.1", - "validator": "^13.9.0" + "validator": "^13.15.20" } }, "node_modules/cli-boxes": { @@ -5766,15 +5780,15 @@ } }, "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "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.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "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" @@ -5789,9 +5803,9 @@ } }, "node_modules/dedent": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", - "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "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" @@ -5996,6 +6010,7 @@ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" } @@ -7431,6 +7446,7 @@ "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", @@ -9003,12 +9019,13 @@ } }, "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", "dev": true, + "license": "MIT", "dependencies": { - "jws": "^3.2.2", + "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", @@ -9025,10 +9042,11 @@ } }, "node_modules/jwa": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "dev": true, + "license": "MIT", "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -9036,12 +9054,13 @@ } }, "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", "dev": true, + "license": "MIT", "dependencies": { - "jwa": "^1.4.1", + "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, @@ -10559,11 +10578,9 @@ }, "node_modules/passport": { "version": "0.7.0", - "resolved": "https://registry.npmmirror.com/passport/-/passport-0.7.0.tgz", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "passport-strategy": "1.x.x", "pause": "0.0.1", @@ -10582,6 +10599,7 @@ "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", "dev": true, + "license": "MIT", "dependencies": { "jsonwebtoken": "^9.0.0", "passport-strategy": "^1.0.0" @@ -10591,7 +10609,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", - "dev": true, "engines": { "node": ">= 0.4.0" } @@ -10672,19 +10689,17 @@ "node_modules/pause": { "version": "0.0.1", "resolved": "https://registry.npmmirror.com/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==", - "dev": true, - "peer": true + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, "node_modules/pg": { - "version": "8.16.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", - "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==", + "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.9.1", - "pg-pool": "^3.10.1", - "pg-protocol": "^1.10.3", + "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" }, @@ -10692,7 +10707,7 @@ "node": ">= 16.0.0" }, "optionalDependencies": { - "pg-cloudflare": "^1.2.7" + "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" @@ -10704,16 +10719,16 @@ } }, "node_modules/pg-cloudflare": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz", - "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==", + "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.9.1", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz", - "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==", + "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": { @@ -10726,18 +10741,18 @@ } }, "node_modules/pg-pool": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz", - "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==", + "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.10.3", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", - "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==", + "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": { @@ -12947,22 +12962,23 @@ "license": "MIT" }, "node_modules/typeorm": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.25.tgz", - "integrity": "sha512-fTKDFzWXKwAaBdEMU4k661seZewbNYET4r1J/z3Jwf+eAvlzMVpTLKAVcAzg75WwQk7GDmtsmkZ5MfkmXCiFWg==", + "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": "^3.17.0", + "ansis": "^4.2.0", "app-root-path": "^3.1.0", "buffer": "^6.0.3", - "dayjs": "^1.11.13", - "debug": "^4.4.0", - "dedent": "^1.6.0", - "dotenv": "^16.4.7", - "glob": "^10.4.5", - "sha.js": "^2.4.11", - "sql-highlight": "^6.0.0", + "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" @@ -12979,20 +12995,18 @@ "url": "https://opencollective.com/typeorm" }, "peerDependencies": { - "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", - "@sap/hana-client": "^2.12.25", - "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", - "hdb-pool": "^0.1.6", + "@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.1 || ^11.0.1", + "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", - "reflect-metadata": "^0.1.14 || ^0.2.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", @@ -13008,9 +13022,6 @@ "better-sqlite3": { "optional": true }, - "hdb-pool": { - "optional": true - }, "ioredis": { "optional": true }, @@ -13088,6 +13099,32 @@ "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.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -13289,9 +13326,9 @@ } }, "node_modules/validator": { - "version": "13.15.15", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", - "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", + "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" diff --git a/package.json b/package.json index 3154635..ffa0715 100644 --- a/package.json +++ b/package.json @@ -55,16 +55,17 @@ "amqplib": "^0.10.9", "cache-manager": "^7.1.1", "class-transformer": "^0.5.1", - "class-validator": "^0.14.1", + "class-validator": "^0.14.3", "date-fns": "^4.1.0", "helmet": "^7.2.0", "nest-winston": "^1.9.7", "nodemailer": "^7.0.5", - "pg": "^8.16.3", + "passport": "^0.7.0", + "pg": "^8.17.2", "prom-client": "^15.1.3", "reflect-metadata": "^0.1.14", "rxjs": "^7.8.1", - "typeorm": "^0.3.25", + "typeorm": "^0.3.28", "winston": "^3.11.0", "winston-daily-rotate-file": "^5.0.0", "winston-elasticsearch": "^0.19.0", @@ -72,7 +73,7 @@ }, "devDependencies": { "@nestjs/cli": "^10.4.5", - "@nestjs/jwt": "^11.0.0", + "@nestjs/jwt": "^11.0.2", "@nestjs/passport": "^11.0.5", "@nestjs/schematics": "^10.1.4", "@nestjs/swagger": "^7.4.2", diff --git a/src/app.module.ts b/src/app.module.ts index 1921796..c15fde8 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -26,6 +26,9 @@ import { TournamentsModule } from './tournaments/tournaments.module'; import { RabbitMQModule } from './rabbitmq/rabbitmq.module'; import { ReferralsModule } from './referrals/referrals.module'; import { SaveGameModule } from './save-game/save-game.module'; +import { PlayerModule } from './player/player.module'; +import { ProfileModule } from './profile/profile.module'; +import { ProgressModule } from './progress/progress.module'; @Module({ imports: [ @@ -73,6 +76,9 @@ import { SaveGameModule } from './save-game/save-game.module'; TournamentsModule, ReferralsModule, SaveGameModule, + PlayerModule, + ProfileModule, + ProgressModule, ], controllers: [AppController], providers: [ diff --git a/src/player/dto/create-player.dto.ts b/src/player/dto/create-player.dto.ts new file mode 100644 index 0000000..fb33afa --- /dev/null +++ b/src/player/dto/create-player.dto.ts @@ -0,0 +1 @@ +export class CreatePlayerDto {} diff --git a/src/player/dto/update-player.dto.ts b/src/player/dto/update-player.dto.ts new file mode 100644 index 0000000..1ceb8fb --- /dev/null +++ b/src/player/dto/update-player.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreatePlayerDto } from './create-player.dto'; + +export class UpdatePlayerDto extends PartialType(CreatePlayerDto) {} diff --git a/src/player/entities/player.entity.ts b/src/player/entities/player.entity.ts new file mode 100644 index 0000000..68754f1 --- /dev/null +++ b/src/player/entities/player.entity.ts @@ -0,0 +1 @@ +export class Player {} diff --git a/src/player/player.controller.ts b/src/player/player.controller.ts new file mode 100644 index 0000000..27ce4c3 --- /dev/null +++ b/src/player/player.controller.ts @@ -0,0 +1,34 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { PlayerService } from './player.service'; +import { CreatePlayerDto } from './dto/create-player.dto'; +import { UpdatePlayerDto } from './dto/update-player.dto'; + +@Controller('player') +export class PlayerController { + constructor(private readonly playerService: PlayerService) {} + + @Post() + create(@Body() createPlayerDto: CreatePlayerDto) { + return this.playerService.create(createPlayerDto); + } + + @Get() + findAll() { + return this.playerService.findAll(); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.playerService.findOne(+id); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() updatePlayerDto: UpdatePlayerDto) { + return this.playerService.update(+id, updatePlayerDto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.playerService.remove(+id); + } +} diff --git a/src/player/player.module.ts b/src/player/player.module.ts new file mode 100644 index 0000000..3f402d4 --- /dev/null +++ b/src/player/player.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { PlayerService } from './player.service'; +import { PlayerController } from './player.controller'; + +@Module({ + controllers: [PlayerController], + providers: [PlayerService], +}) +export class PlayerModule {} diff --git a/src/player/player.service.ts b/src/player/player.service.ts new file mode 100644 index 0000000..9873aed --- /dev/null +++ b/src/player/player.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@nestjs/common'; +import { CreatePlayerDto } from './dto/create-player.dto'; +import { UpdatePlayerDto } from './dto/update-player.dto'; + +@Injectable() +export class PlayerService { + create(createPlayerDto: CreatePlayerDto) { + return 'This action adds a new player'; + } + + findAll() { + return `This action returns all player`; + } + + findOne(id: number) { + return `This action returns a #${id} player`; + } + + update(id: number, updatePlayerDto: UpdatePlayerDto) { + return `This action updates a #${id} player`; + } + + remove(id: number) { + return `This action removes a #${id} player`; + } +} diff --git a/src/profile/dto/create-profile.dto.ts b/src/profile/dto/create-profile.dto.ts new file mode 100644 index 0000000..2913518 --- /dev/null +++ b/src/profile/dto/create-profile.dto.ts @@ -0,0 +1 @@ +export class CreateProfileDto {} diff --git a/src/profile/dto/update-profile.dto.ts b/src/profile/dto/update-profile.dto.ts new file mode 100644 index 0000000..81abfb2 --- /dev/null +++ b/src/profile/dto/update-profile.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateProfileDto } from './create-profile.dto'; + +export class UpdateProfileDto extends PartialType(CreateProfileDto) {} diff --git a/src/profile/entities/profile.entity.ts b/src/profile/entities/profile.entity.ts new file mode 100644 index 0000000..b4a8829 --- /dev/null +++ b/src/profile/entities/profile.entity.ts @@ -0,0 +1 @@ +export class Profile {} diff --git a/src/profile/profile.controller.ts b/src/profile/profile.controller.ts new file mode 100644 index 0000000..2146cc5 --- /dev/null +++ b/src/profile/profile.controller.ts @@ -0,0 +1,34 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { ProfileService } from './profile.service'; +import { CreateProfileDto } from './dto/create-profile.dto'; +import { UpdateProfileDto } from './dto/update-profile.dto'; + +@Controller('profile') +export class ProfileController { + constructor(private readonly profileService: ProfileService) {} + + @Post() + create(@Body() createProfileDto: CreateProfileDto) { + return this.profileService.create(createProfileDto); + } + + @Get() + findAll() { + return this.profileService.findAll(); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.profileService.findOne(+id); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() updateProfileDto: UpdateProfileDto) { + return this.profileService.update(+id, updateProfileDto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.profileService.remove(+id); + } +} diff --git a/src/profile/profile.module.ts b/src/profile/profile.module.ts new file mode 100644 index 0000000..c9d59f7 --- /dev/null +++ b/src/profile/profile.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { ProfileService } from './profile.service'; +import { ProfileController } from './profile.controller'; + +@Module({ + controllers: [ProfileController], + providers: [ProfileService], +}) +export class ProfileModule {} diff --git a/src/profile/profile.service.ts b/src/profile/profile.service.ts new file mode 100644 index 0000000..ecfbf60 --- /dev/null +++ b/src/profile/profile.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@nestjs/common'; +import { CreateProfileDto } from './dto/create-profile.dto'; +import { UpdateProfileDto } from './dto/update-profile.dto'; + +@Injectable() +export class ProfileService { + create(createProfileDto: CreateProfileDto) { + return 'This action adds a new profile'; + } + + findAll() { + return `This action returns all profile`; + } + + findOne(id: number) { + return `This action returns a #${id} profile`; + } + + update(id: number, updateProfileDto: UpdateProfileDto) { + return `This action updates a #${id} profile`; + } + + remove(id: number) { + return `This action removes a #${id} profile`; + } +} diff --git a/src/progress/dto/create-progress.dto.ts b/src/progress/dto/create-progress.dto.ts new file mode 100644 index 0000000..53914d4 --- /dev/null +++ b/src/progress/dto/create-progress.dto.ts @@ -0,0 +1 @@ +export class CreateProgressDto {} diff --git a/src/progress/dto/update-progress.dto.ts b/src/progress/dto/update-progress.dto.ts new file mode 100644 index 0000000..c337087 --- /dev/null +++ b/src/progress/dto/update-progress.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateProgressDto } from './create-progress.dto'; + +export class UpdateProgressDto extends PartialType(CreateProgressDto) {} diff --git a/src/progress/entities/progress.entity.ts b/src/progress/entities/progress.entity.ts new file mode 100644 index 0000000..c3db02e --- /dev/null +++ b/src/progress/entities/progress.entity.ts @@ -0,0 +1 @@ +export class Progress {} diff --git a/src/progress/progress.controller.ts b/src/progress/progress.controller.ts new file mode 100644 index 0000000..db2fd9e --- /dev/null +++ b/src/progress/progress.controller.ts @@ -0,0 +1,34 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { ProgressService } from './progress.service'; +import { CreateProgressDto } from './dto/create-progress.dto'; +import { UpdateProgressDto } from './dto/update-progress.dto'; + +@Controller('progress') +export class ProgressController { + constructor(private readonly progressService: ProgressService) {} + + @Post() + create(@Body() createProgressDto: CreateProgressDto) { + return this.progressService.create(createProgressDto); + } + + @Get() + findAll() { + return this.progressService.findAll(); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.progressService.findOne(+id); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() updateProgressDto: UpdateProgressDto) { + return this.progressService.update(+id, updateProgressDto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.progressService.remove(+id); + } +} diff --git a/src/progress/progress.module.ts b/src/progress/progress.module.ts new file mode 100644 index 0000000..a399434 --- /dev/null +++ b/src/progress/progress.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { ProgressService } from './progress.service'; +import { ProgressController } from './progress.controller'; + +@Module({ + controllers: [ProgressController], + providers: [ProgressService], +}) +export class ProgressModule {} diff --git a/src/progress/progress.service.ts b/src/progress/progress.service.ts new file mode 100644 index 0000000..e5dab62 --- /dev/null +++ b/src/progress/progress.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@nestjs/common'; +import { CreateProgressDto } from './dto/create-progress.dto'; +import { UpdateProgressDto } from './dto/update-progress.dto'; + +@Injectable() +export class ProgressService { + create(createProgressDto: CreateProgressDto) { + return 'This action adds a new progress'; + } + + findAll() { + return `This action returns all progress`; + } + + findOne(id: number) { + return `This action returns a #${id} progress`; + } + + update(id: number, updateProgressDto: UpdateProgressDto) { + return `This action updates a #${id} progress`; + } + + remove(id: number) { + return `This action removes a #${id} progress`; + } +}