diff --git a/data/calorie_tracker.db b/data/calorie_tracker.db index 29fc8cf..8603add 100644 Binary files a/data/calorie_tracker.db and b/data/calorie_tracker.db differ diff --git a/data/sessions.db b/data/sessions.db index fa797e9..a1af66a 100644 Binary files a/data/sessions.db and b/data/sessions.db differ diff --git a/dist/app.controller.d.ts b/dist/app.controller.d.ts new file mode 100644 index 0000000..428a1d4 --- /dev/null +++ b/dist/app.controller.d.ts @@ -0,0 +1,12 @@ +import { Response } from 'express'; +import { UsersService } from './users/users.service'; +export declare class AppController { + private usersService; + constructor(usersService: UsersService); + root(req: any, res: Response): void; + login(): {}; + loginPost(res: Response): void; + register(): {}; + registerPost(body: any, res: Response, req: any): Promise; + logout(req: any, res: Response): void; +} diff --git a/dist/app.controller.js b/dist/app.controller.js new file mode 100644 index 0000000..fa01f20 --- /dev/null +++ b/dist/app.controller.js @@ -0,0 +1,120 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AppController = void 0; +const common_1 = require("@nestjs/common"); +const local_auth_guard_1 = require("./auth/guards/local-auth.guard"); +const users_service_1 = require("./users/users.service"); +let AppController = class AppController { + constructor(usersService) { + this.usersService = usersService; + } + root(req, res) { + if (req.isAuthenticated()) { + return res.redirect('/dashboard'); + } + else { + return res.redirect('/login'); + } + } + login() { + return {}; + } + loginPost(res) { + res.redirect('/dashboard'); + } + register() { + return {}; + } + async registerPost(body, res, req) { + const { username, password, name } = body; + try { + const existingUser = await this.usersService.findOne(username); + if (existingUser) { + req.flash('error', 'Username already exists'); + return res.redirect('/register'); + } + await this.usersService.create({ username, password, name }); + req.flash('success_msg', 'You are now registered and can log in'); + res.redirect('/login'); + } + catch (err) { + console.error(err); + req.flash('error', 'Error registering user'); + res.redirect('/register'); + } + } + logout(req, res) { + req.logout((err) => { + if (err) { + console.error(err); + } + req.flash('success_msg', 'You are logged out'); + res.redirect('/login'); + }); + } +}; +exports.AppController = AppController; +__decorate([ + (0, common_1.Get)(), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Res)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object]), + __metadata("design:returntype", void 0) +], AppController.prototype, "root", null); +__decorate([ + (0, common_1.Get)('login'), + (0, common_1.Render)('login'), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", void 0) +], AppController.prototype, "login", null); +__decorate([ + (0, common_1.UseGuards)(local_auth_guard_1.LocalAuthGuard), + (0, common_1.Post)('login'), + __param(0, (0, common_1.Res)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", void 0) +], AppController.prototype, "loginPost", null); +__decorate([ + (0, common_1.Get)('register'), + (0, common_1.Render)('register'), + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", void 0) +], AppController.prototype, "register", null); +__decorate([ + (0, common_1.Post)('register'), + __param(0, (0, common_1.Body)()), + __param(1, (0, common_1.Res)()), + __param(2, (0, common_1.Req)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object, Object]), + __metadata("design:returntype", Promise) +], AppController.prototype, "registerPost", null); +__decorate([ + (0, common_1.Get)('logout'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Res)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object]), + __metadata("design:returntype", void 0) +], AppController.prototype, "logout", null); +exports.AppController = AppController = __decorate([ + (0, common_1.Controller)(), + __metadata("design:paramtypes", [users_service_1.UsersService]) +], AppController); +//# sourceMappingURL=app.controller.js.map \ No newline at end of file diff --git a/dist/app.controller.js.map b/dist/app.controller.js.map new file mode 100644 index 0000000..110e1ad --- /dev/null +++ b/dist/app.controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.controller.js","sourceRoot":"","sources":["../src/app.controller.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/app.module.d.ts b/dist/app.module.d.ts new file mode 100644 index 0000000..d3492c3 --- /dev/null +++ b/dist/app.module.d.ts @@ -0,0 +1,4 @@ +import { MiddlewareConsumer } from '@nestjs/common'; +export declare class AppModule { + configure(consumer: MiddlewareConsumer): void; +} diff --git a/dist/app.module.js b/dist/app.module.js new file mode 100644 index 0000000..74dbf9e --- /dev/null +++ b/dist/app.module.js @@ -0,0 +1,52 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AppModule = void 0; +const common_1 = require("@nestjs/common"); +const config_1 = require("@nestjs/config"); +const database_module_1 = require("./database/database.module"); +const auth_module_1 = require("./auth/auth.module"); +const users_module_1 = require("./users/users.module"); +const app_controller_1 = require("./app.controller"); +const utils_module_1 = require("./utils/utils.module"); +const dashboard_module_1 = require("./dashboard/dashboard.module"); +const meals_module_1 = require("./meals/meals.module"); +const goals_module_1 = require("./goals/goals.module"); +const foods_module_1 = require("./foods/foods.module"); +const meal_planner_module_1 = require("./meal-planner/meal-planner.module"); +const locals_middleware_1 = require("./common/middleware/locals.middleware"); +let AppModule = class AppModule { + configure(consumer) { + consumer + .apply(locals_middleware_1.LocalsMiddleware) + .forRoutes({ path: '*', method: common_1.RequestMethod.ALL }); + } +}; +exports.AppModule = AppModule; +exports.AppModule = AppModule = __decorate([ + (0, common_1.Module)({ + imports: [ + config_1.ConfigModule.forRoot({ + isGlobal: true, + envFilePath: '.env', + }), + database_module_1.DatabaseModule, + auth_module_1.AuthModule, + users_module_1.UsersModule, + utils_module_1.UtilsModule, + dashboard_module_1.DashboardModule, + meals_module_1.MealsModule, + goals_module_1.GoalsModule, + foods_module_1.FoodsModule, + meal_planner_module_1.MealPlannerModule, + ], + controllers: [app_controller_1.AppController], + providers: [], + }) +], AppModule); +//# sourceMappingURL=app.module.js.map \ No newline at end of file diff --git a/dist/app.module.js.map b/dist/app.module.js.map new file mode 100644 index 0000000..7798ccf --- /dev/null +++ b/dist/app.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA2E;AAC3E,2CAA8C;AAC9C,gEAA4D;AAC5D,oDAAgD;AAChD,uDAAmD;AACnD,qDAAiD;AACjD,uDAAmD;AACnD,mEAA+D;AAC/D,uDAAmD;AACnD,uDAAmD;AACnD,uDAAmD;AACnD,4EAAuE;AACvE,6EAAyE;AAqBlE,IAAM,SAAS,GAAf,MAAM,SAAS;IACpB,SAAS,CAAC,QAA4B;QACpC,QAAQ;aACL,KAAK,CAAC,oCAAgB,CAAC;aACvB,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,sBAAa,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;CACF,CAAA;AANY,8BAAS;oBAAT,SAAS;IAnBrB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,qBAAY,CAAC,OAAO,CAAC;gBACnB,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,MAAM;aACpB,CAAC;YACF,gCAAc;YACd,wBAAU;YACV,0BAAW;YACX,0BAAW;YACX,kCAAe;YACf,0BAAW;YACX,0BAAW;YACX,0BAAW;YACX,uCAAiB;SAClB;QACD,WAAW,EAAE,CAAC,8BAAa,CAAC;QAC5B,SAAS,EAAE,EAAE;KACd,CAAC;GACW,SAAS,CAMrB"} \ No newline at end of file diff --git a/dist/auth/auth.module.d.ts b/dist/auth/auth.module.d.ts new file mode 100644 index 0000000..3f7dba9 --- /dev/null +++ b/dist/auth/auth.module.d.ts @@ -0,0 +1,2 @@ +export declare class AuthModule { +} diff --git a/dist/auth/auth.module.js b/dist/auth/auth.module.js new file mode 100644 index 0000000..fb471b0 --- /dev/null +++ b/dist/auth/auth.module.js @@ -0,0 +1,26 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AuthModule = void 0; +const common_1 = require("@nestjs/common"); +const auth_service_1 = require("./auth.service"); +const users_module_1 = require("../users/users.module"); +const passport_1 = require("@nestjs/passport"); +const local_strategy_1 = require("./local.strategy"); +const session_serializer_1 = require("./session.serializer"); +let AuthModule = class AuthModule { +}; +exports.AuthModule = AuthModule; +exports.AuthModule = AuthModule = __decorate([ + (0, common_1.Module)({ + imports: [users_module_1.UsersModule, passport_1.PassportModule.register({ session: true })], + providers: [auth_service_1.AuthService, local_strategy_1.LocalStrategy, session_serializer_1.SessionSerializer], + exports: [auth_service_1.AuthService], + }) +], AuthModule); +//# sourceMappingURL=auth.module.js.map \ No newline at end of file diff --git a/dist/auth/auth.module.js.map b/dist/auth/auth.module.js.map new file mode 100644 index 0000000..baef79e --- /dev/null +++ b/dist/auth/auth.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,iDAA6C;AAC7C,wDAAoD;AACpD,+CAAkD;AAClD,qDAAiD;AACjD,6DAAyD;AAOlD,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IALtB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,0BAAW,EAAE,yBAAc,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,SAAS,EAAE,CAAC,0BAAW,EAAE,8BAAa,EAAE,sCAAiB,CAAC;QAC1D,OAAO,EAAE,CAAC,0BAAW,CAAC;KACvB,CAAC;GACW,UAAU,CAAG"} \ No newline at end of file diff --git a/dist/auth/auth.service.d.ts b/dist/auth/auth.service.d.ts new file mode 100644 index 0000000..94653b7 --- /dev/null +++ b/dist/auth/auth.service.d.ts @@ -0,0 +1,6 @@ +import { UsersService } from '../users/users.service'; +export declare class AuthService { + private usersService; + constructor(usersService: UsersService); + validateUser(username: string, pass: string): Promise; +} diff --git a/dist/auth/auth.service.js b/dist/auth/auth.service.js new file mode 100644 index 0000000..b1ecdbe --- /dev/null +++ b/dist/auth/auth.service.js @@ -0,0 +1,32 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AuthService = void 0; +const common_1 = require("@nestjs/common"); +const users_service_1 = require("../users/users.service"); +let AuthService = class AuthService { + constructor(usersService) { + this.usersService = usersService; + } + async validateUser(username, pass) { + const user = await this.usersService.findOne(username); + if (user && user.validPassword(pass)) { + return user; + } + return null; + } +}; +exports.AuthService = AuthService; +exports.AuthService = AuthService = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [users_service_1.UsersService]) +], AuthService); +//# sourceMappingURL=auth.service.js.map \ No newline at end of file diff --git a/dist/auth/auth.service.js.map b/dist/auth/auth.service.js.map new file mode 100644 index 0000000..03d8fe6 --- /dev/null +++ b/dist/auth/auth.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/auth/auth.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,0DAAsD;AAG/C,IAAM,WAAW,GAAjB,MAAM,WAAW;IACtB,YAAoB,YAA0B;QAA1B,iBAAY,GAAZ,YAAY,CAAc;IAAG,CAAC;IAElD,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE,IAAY;QAC/C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YAGrC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAZY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAEuB,4BAAY;GADnC,WAAW,CAYvB"} \ No newline at end of file diff --git a/dist/auth/guards/authenticated.guard.d.ts b/dist/auth/guards/authenticated.guard.d.ts new file mode 100644 index 0000000..66eb8dc --- /dev/null +++ b/dist/auth/guards/authenticated.guard.d.ts @@ -0,0 +1,4 @@ +import { CanActivate, ExecutionContext } from '@nestjs/common'; +export declare class AuthenticatedGuard implements CanActivate { + canActivate(context: ExecutionContext): Promise; +} diff --git a/dist/auth/guards/authenticated.guard.js b/dist/auth/guards/authenticated.guard.js new file mode 100644 index 0000000..d19481c --- /dev/null +++ b/dist/auth/guards/authenticated.guard.js @@ -0,0 +1,21 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AuthenticatedGuard = void 0; +const common_1 = require("@nestjs/common"); +let AuthenticatedGuard = class AuthenticatedGuard { + async canActivate(context) { + const request = context.switchToHttp().getRequest(); + return request.isAuthenticated(); + } +}; +exports.AuthenticatedGuard = AuthenticatedGuard; +exports.AuthenticatedGuard = AuthenticatedGuard = __decorate([ + (0, common_1.Injectable)() +], AuthenticatedGuard); +//# sourceMappingURL=authenticated.guard.js.map \ No newline at end of file diff --git a/dist/auth/guards/authenticated.guard.js.map b/dist/auth/guards/authenticated.guard.js.map new file mode 100644 index 0000000..d1d2d69 --- /dev/null +++ b/dist/auth/guards/authenticated.guard.js.map @@ -0,0 +1 @@ +{"version":3,"file":"authenticated.guard.js","sourceRoot":"","sources":["../../../src/auth/guards/authenticated.guard.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA2E;AAGpE,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC7B,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QACpD,OAAO,OAAO,CAAC,eAAe,EAAE,CAAC;IACnC,CAAC;CACF,CAAA;AALY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,mBAAU,GAAE;GACA,kBAAkB,CAK9B"} \ No newline at end of file diff --git a/dist/auth/guards/local-auth.guard.d.ts b/dist/auth/guards/local-auth.guard.d.ts new file mode 100644 index 0000000..d2bab5a --- /dev/null +++ b/dist/auth/guards/local-auth.guard.d.ts @@ -0,0 +1,6 @@ +import { ExecutionContext } from '@nestjs/common'; +declare const LocalAuthGuard_base: import("@nestjs/passport").Type; +export declare class LocalAuthGuard extends LocalAuthGuard_base { + canActivate(context: ExecutionContext): Promise; +} +export {}; diff --git a/dist/auth/guards/local-auth.guard.js b/dist/auth/guards/local-auth.guard.js new file mode 100644 index 0000000..6e593e1 --- /dev/null +++ b/dist/auth/guards/local-auth.guard.js @@ -0,0 +1,24 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LocalAuthGuard = void 0; +const common_1 = require("@nestjs/common"); +const passport_1 = require("@nestjs/passport"); +let LocalAuthGuard = class LocalAuthGuard extends (0, passport_1.AuthGuard)('local') { + async canActivate(context) { + const result = (await super.canActivate(context)); + const request = context.switchToHttp().getRequest(); + await super.logIn(request); + return result; + } +}; +exports.LocalAuthGuard = LocalAuthGuard; +exports.LocalAuthGuard = LocalAuthGuard = __decorate([ + (0, common_1.Injectable)() +], LocalAuthGuard); +//# sourceMappingURL=local-auth.guard.js.map \ No newline at end of file diff --git a/dist/auth/guards/local-auth.guard.js.map b/dist/auth/guards/local-auth.guard.js.map new file mode 100644 index 0000000..b500a3c --- /dev/null +++ b/dist/auth/guards/local-auth.guard.js.map @@ -0,0 +1 @@ +{"version":3,"file":"local-auth.guard.js","sourceRoot":"","sources":["../../../src/auth/guards/local-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA8D;AAC9D,+CAA6C;AAGtC,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,IAAA,oBAAS,EAAC,OAAO,CAAC;IACpD,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,MAAM,GAAG,CAAC,MAAM,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAY,CAAC;QAC7D,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QACpD,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAA;AAPY,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAU,GAAE;GACA,cAAc,CAO1B"} \ No newline at end of file diff --git a/dist/auth/local.strategy.d.ts b/dist/auth/local.strategy.d.ts new file mode 100644 index 0000000..655bbfc --- /dev/null +++ b/dist/auth/local.strategy.d.ts @@ -0,0 +1,11 @@ +import { Strategy } from 'passport-local'; +import { AuthService } from './auth.service'; +declare const LocalStrategy_base: new (...args: [] | [options: import("passport-local").IStrategyOptionsWithRequest] | [options: import("passport-local").IStrategyOptions]) => Strategy & { + validate(...args: any[]): unknown; +}; +export declare class LocalStrategy extends LocalStrategy_base { + private authService; + constructor(authService: AuthService); + validate(username: string, pass: string): Promise; +} +export {}; diff --git a/dist/auth/local.strategy.js b/dist/auth/local.strategy.js new file mode 100644 index 0000000..96d8e54 --- /dev/null +++ b/dist/auth/local.strategy.js @@ -0,0 +1,35 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LocalStrategy = void 0; +const passport_local_1 = require("passport-local"); +const passport_1 = require("@nestjs/passport"); +const common_1 = require("@nestjs/common"); +const auth_service_1 = require("./auth.service"); +let LocalStrategy = class LocalStrategy extends (0, passport_1.PassportStrategy)(passport_local_1.Strategy) { + constructor(authService) { + super(); + this.authService = authService; + } + async validate(username, pass) { + const user = await this.authService.validateUser(username, pass); + if (!user) { + throw new common_1.UnauthorizedException(); + } + return user; + } +}; +exports.LocalStrategy = LocalStrategy; +exports.LocalStrategy = LocalStrategy = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [auth_service_1.AuthService]) +], LocalStrategy); +//# sourceMappingURL=local.strategy.js.map \ No newline at end of file diff --git a/dist/auth/local.strategy.js.map b/dist/auth/local.strategy.js.map new file mode 100644 index 0000000..74df467 --- /dev/null +++ b/dist/auth/local.strategy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"local.strategy.js","sourceRoot":"","sources":["../../src/auth/local.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,mDAA0C;AAC1C,+CAAoD;AACpD,2CAAmE;AACnE,iDAA6C;AAGtC,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,IAAA,2BAAgB,EAAC,yBAAQ,CAAC;IAC3D,YAAoB,WAAwB;QAC1C,KAAK,EAAE,CAAC;QADU,gBAAW,GAAX,WAAW,CAAa;IAE5C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,IAAY;QAC3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,8BAAqB,EAAE,CAAC;QACpC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAZY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAEsB,0BAAW;GADjC,aAAa,CAYzB"} \ No newline at end of file diff --git a/dist/auth/session.serializer.d.ts b/dist/auth/session.serializer.d.ts new file mode 100644 index 0000000..5e50ab1 --- /dev/null +++ b/dist/auth/session.serializer.d.ts @@ -0,0 +1,8 @@ +import { PassportSerializer } from '@nestjs/passport'; +import { UsersService } from '../users/users.service'; +export declare class SessionSerializer extends PassportSerializer { + private readonly usersService; + constructor(usersService: UsersService); + serializeUser(user: any, done: Function): void; + deserializeUser(userId: any, done: Function): Promise; +} diff --git a/dist/auth/session.serializer.js b/dist/auth/session.serializer.js new file mode 100644 index 0000000..42e0ed0 --- /dev/null +++ b/dist/auth/session.serializer.js @@ -0,0 +1,34 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SessionSerializer = void 0; +const passport_1 = require("@nestjs/passport"); +const common_1 = require("@nestjs/common"); +const users_service_1 = require("../users/users.service"); +let SessionSerializer = class SessionSerializer extends passport_1.PassportSerializer { + constructor(usersService) { + super(); + this.usersService = usersService; + } + serializeUser(user, done) { + done(null, user.id); + } + async deserializeUser(userId, done) { + const user = await this.usersService.findById(userId); + done(null, user); + } +}; +exports.SessionSerializer = SessionSerializer; +exports.SessionSerializer = SessionSerializer = __decorate([ + (0, common_1.Injectable)(), + __metadata("design:paramtypes", [users_service_1.UsersService]) +], SessionSerializer); +//# sourceMappingURL=session.serializer.js.map \ No newline at end of file diff --git a/dist/auth/session.serializer.js.map b/dist/auth/session.serializer.js.map new file mode 100644 index 0000000..d1e3ca7 --- /dev/null +++ b/dist/auth/session.serializer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"session.serializer.js","sourceRoot":"","sources":["../../src/auth/session.serializer.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+CAAsD;AACtD,2CAA4C;AAC5C,0DAAsD;AAG/C,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,6BAAkB;IACvD,YAA6B,YAA0B;QACrD,KAAK,EAAE,CAAC;QADmB,iBAAY,GAAZ,YAAY,CAAc;IAEvD,CAAC;IAED,aAAa,CAAC,IAAS,EAAE,IAAc;QACrC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,MAAW,EAAE,IAAc;QAC/C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnB,CAAC;CACF,CAAA;AAbY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;qCAEgC,4BAAY;GAD5C,iBAAiB,CAa7B"} \ No newline at end of file diff --git a/dist/common/middleware/locals.middleware.d.ts b/dist/common/middleware/locals.middleware.d.ts new file mode 100644 index 0000000..966461c --- /dev/null +++ b/dist/common/middleware/locals.middleware.d.ts @@ -0,0 +1,5 @@ +import { NestMiddleware } from '@nestjs/common'; +import { Request, Response, NextFunction } from 'express'; +export declare class LocalsMiddleware implements NestMiddleware { + use(req: Request, res: Response, next: NextFunction): void; +} diff --git a/dist/common/middleware/locals.middleware.js b/dist/common/middleware/locals.middleware.js new file mode 100644 index 0000000..af6a601 --- /dev/null +++ b/dist/common/middleware/locals.middleware.js @@ -0,0 +1,26 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LocalsMiddleware = void 0; +const common_1 = require("@nestjs/common"); +let LocalsMiddleware = class LocalsMiddleware { + use(req, res, next) { + const reqAny = req; + res.locals.current_user = reqAny.user; + res.locals.success_msg = reqAny.flash('success_msg'); + res.locals.error_msg = reqAny.flash('error_msg'); + res.locals.error = reqAny.flash('error'); + res.locals.path = req.path; + next(); + } +}; +exports.LocalsMiddleware = LocalsMiddleware; +exports.LocalsMiddleware = LocalsMiddleware = __decorate([ + (0, common_1.Injectable)() +], LocalsMiddleware); +//# sourceMappingURL=locals.middleware.js.map \ No newline at end of file diff --git a/dist/common/middleware/locals.middleware.js.map b/dist/common/middleware/locals.middleware.js.map new file mode 100644 index 0000000..d9f1389 --- /dev/null +++ b/dist/common/middleware/locals.middleware.js.map @@ -0,0 +1 @@ +{"version":3,"file":"locals.middleware.js","sourceRoot":"","sources":["../../../src/common/middleware/locals.middleware.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4D;AAIrD,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B,GAAG,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;QACjD,MAAM,MAAM,GAAG,GAAU,CAAC;QAC1B,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC;QACtC,GAAG,CAAC,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACrD,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACjD,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QAC3B,IAAI,EAAE,CAAC;IACT,CAAC;CACF,CAAA;AAVY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;GACA,gBAAgB,CAU5B"} \ No newline at end of file diff --git a/dist/dashboard/dashboard.controller.d.ts b/dist/dashboard/dashboard.controller.d.ts new file mode 100644 index 0000000..3c76129 --- /dev/null +++ b/dist/dashboard/dashboard.controller.d.ts @@ -0,0 +1,52 @@ +import { UtilsService } from '../utils/utils.service'; +import { UserGoal } from '../models/user-goal.model'; +import { WeightLog } from '../models/weight-log.model'; +import { Response } from 'express'; +export declare class DashboardController { + private utilsService; + private userGoalModel; + private weightLogModel; + constructor(utilsService: UtilsService, userGoalModel: typeof UserGoal, weightLogModel: typeof WeightLog); + getDashboard(req: any, res: Response): Promise<{ + user: any; + nutrition: { + calories: number; + protein: number; + carbs: number; + fat: number; + meals: any[]; + }; + water: { + total_ml: number; + logs: { + id: any; + amount_ml: number; + time: string; + }[]; + }; + goals: UserGoal; + weightLogToday: WeightLog; + weightChange: any; + remaining: { + calories: number; + protein: number; + carbs: number; + fat: number; + water: number; + }; + macroPercentages: { + protein: number; + carbs: number; + fat: number; + }; + } | { + user?: undefined; + nutrition?: undefined; + water?: undefined; + goals?: undefined; + weightLogToday?: undefined; + weightChange?: undefined; + remaining?: undefined; + macroPercentages?: undefined; + }>; +} diff --git a/dist/dashboard/dashboard.controller.js b/dist/dashboard/dashboard.controller.js new file mode 100644 index 0000000..0d7d29e --- /dev/null +++ b/dist/dashboard/dashboard.controller.js @@ -0,0 +1,100 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DashboardController = void 0; +const common_1 = require("@nestjs/common"); +const authenticated_guard_1 = require("../auth/guards/authenticated.guard"); +const utils_service_1 = require("../utils/utils.service"); +const user_goal_model_1 = require("../models/user-goal.model"); +const weight_log_model_1 = require("../models/weight-log.model"); +const sequelize_1 = require("@nestjs/sequelize"); +let DashboardController = class DashboardController { + constructor(utilsService, userGoalModel, weightLogModel) { + this.utilsService = utilsService; + this.userGoalModel = userGoalModel; + this.weightLogModel = weightLogModel; + } + async getDashboard(req, res) { + try { + const today = new Date(); + const dateStr = today.toISOString().split('T')[0]; + const nutrition = await this.utilsService.calculateDailyTotals(req.user.id, dateStr); + const water = await this.utilsService.calculateWaterTotal(req.user.id, dateStr); + let goals = await this.userGoalModel.findOne({ where: { UserId: req.user.id } }); + if (!goals) { + goals = await this.userGoalModel.create({ + UserId: req.user.id, + target_protein_g: 150, + target_carbs_g: 200, + target_fat_g: 60, + target_water_ml: 2000, + }); + } + const weightLogToday = await this.weightLogModel.findOne({ + where: { UserId: req.user.id, date: dateStr }, + }); + const yesterday = new Date(today); + yesterday.setDate(yesterday.getDate() - 1); + const yesterdayStr = yesterday.toISOString().split('T')[0]; + const weightLogYesterday = await this.weightLogModel.findOne({ + where: { UserId: req.user.id, date: yesterdayStr }, + }); + let weightChange = null; + if (weightLogToday && weightLogYesterday) { + weightChange = weightLogToday.weight_kg - weightLogYesterday.weight_kg; + } + const remaining = { + calories: req.user.target_daily_calories - nutrition.calories, + protein: goals.target_protein_g - nutrition.protein, + carbs: goals.target_carbs_g - nutrition.carbs, + fat: goals.target_fat_g - nutrition.fat, + water: goals.target_water_ml - water.total_ml, + }; + const macroPercentages = this.utilsService.getMacroPercentages(nutrition.protein, nutrition.carbs, nutrition.fat); + return { + user: req.user, + nutrition, + water, + goals, + weightLogToday, + weightChange, + remaining, + macroPercentages, + }; + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error loading dashboard'); + return {}; + } + } +}; +exports.DashboardController = DashboardController; +__decorate([ + (0, common_1.Get)(), + (0, common_1.Render)('dashboard'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Res)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object]), + __metadata("design:returntype", Promise) +], DashboardController.prototype, "getDashboard", null); +exports.DashboardController = DashboardController = __decorate([ + (0, common_1.Controller)('dashboard'), + (0, common_1.UseGuards)(authenticated_guard_1.AuthenticatedGuard), + __param(1, (0, sequelize_1.InjectModel)(user_goal_model_1.UserGoal)), + __param(2, (0, sequelize_1.InjectModel)(weight_log_model_1.WeightLog)), + __metadata("design:paramtypes", [utils_service_1.UtilsService, Object, Object]) +], DashboardController); +//# sourceMappingURL=dashboard.controller.js.map \ No newline at end of file diff --git a/dist/dashboard/dashboard.controller.js.map b/dist/dashboard/dashboard.controller.js.map new file mode 100644 index 0000000..36110ed --- /dev/null +++ b/dist/dashboard/dashboard.controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dashboard.controller.js","sourceRoot":"","sources":["../../src/dashboard/dashboard.controller.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/dashboard/dashboard.module.d.ts b/dist/dashboard/dashboard.module.d.ts new file mode 100644 index 0000000..6054687 --- /dev/null +++ b/dist/dashboard/dashboard.module.d.ts @@ -0,0 +1,2 @@ +export declare class DashboardModule { +} diff --git a/dist/dashboard/dashboard.module.js b/dist/dashboard/dashboard.module.js new file mode 100644 index 0000000..1152b85 --- /dev/null +++ b/dist/dashboard/dashboard.module.js @@ -0,0 +1,29 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DashboardModule = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const dashboard_controller_1 = require("./dashboard.controller"); +const progress_controller_1 = require("./progress.controller"); +const user_goal_model_1 = require("../models/user-goal.model"); +const weight_log_model_1 = require("../models/weight-log.model"); +const utils_module_1 = require("../utils/utils.module"); +let DashboardModule = class DashboardModule { +}; +exports.DashboardModule = DashboardModule; +exports.DashboardModule = DashboardModule = __decorate([ + (0, common_1.Module)({ + imports: [ + sequelize_1.SequelizeModule.forFeature([user_goal_model_1.UserGoal, weight_log_model_1.WeightLog]), + utils_module_1.UtilsModule, + ], + controllers: [dashboard_controller_1.DashboardController, progress_controller_1.ProgressController], + }) +], DashboardModule); +//# sourceMappingURL=dashboard.module.js.map \ No newline at end of file diff --git a/dist/dashboard/dashboard.module.js.map b/dist/dashboard/dashboard.module.js.map new file mode 100644 index 0000000..9c04d4c --- /dev/null +++ b/dist/dashboard/dashboard.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dashboard.module.js","sourceRoot":"","sources":["../../src/dashboard/dashboard.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,iDAAoD;AACpD,iEAA6D;AAC7D,+DAA2D;AAC3D,+DAAqD;AACrD,iEAAuD;AACvD,wDAAoD;AAS7C,IAAM,eAAe,GAArB,MAAM,eAAe;CAAG,CAAA;AAAlB,0CAAe;0BAAf,eAAe;IAP3B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,2BAAe,CAAC,UAAU,CAAC,CAAC,0BAAQ,EAAE,4BAAS,CAAC,CAAC;YACjD,0BAAW;SACZ;QACD,WAAW,EAAE,CAAC,0CAAmB,EAAE,wCAAkB,CAAC;KACvD,CAAC;GACW,eAAe,CAAG"} \ No newline at end of file diff --git a/dist/dashboard/progress.controller.d.ts b/dist/dashboard/progress.controller.d.ts new file mode 100644 index 0000000..8670b8b --- /dev/null +++ b/dist/dashboard/progress.controller.d.ts @@ -0,0 +1,19 @@ +import { UtilsService } from '../utils/utils.service'; +export declare class ProgressController { + private utilsService; + constructor(utilsService: UtilsService); + getProgress(req: any, daysQuery: string): Promise<{ + user: any; + weight_trend: { + date: Date; + weight_kg: number; + }[]; + calorie_trend: any[]; + avg_calories: number; + avg_protein: number; + avg_carbs: number; + avg_fat: number; + weight_change: any; + days: number; + }>; +} diff --git a/dist/dashboard/progress.controller.js b/dist/dashboard/progress.controller.js new file mode 100644 index 0000000..3a285ab --- /dev/null +++ b/dist/dashboard/progress.controller.js @@ -0,0 +1,83 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ProgressController = void 0; +const common_1 = require("@nestjs/common"); +const authenticated_guard_1 = require("../auth/guards/authenticated.guard"); +const utils_service_1 = require("../utils/utils.service"); +let ProgressController = class ProgressController { + constructor(utilsService) { + this.utilsService = utilsService; + } + async getProgress(req, daysQuery) { + try { + const days = parseInt(daysQuery) || 30; + const weightTrend = await this.utilsService.getWeightTrend(req.user.id, days); + const calorieTrend = await this.utilsService.getCalorieTrend(req.user.id, days); + let avgCalories = 0, avgProtein = 0, avgCarbs = 0, avgFat = 0; + if (calorieTrend.length > 0) { + avgCalories = calorieTrend.reduce((sum, d) => sum + d.calories, 0) / calorieTrend.length; + avgProtein = calorieTrend.reduce((sum, d) => sum + d.protein, 0) / calorieTrend.length; + avgCarbs = calorieTrend.reduce((sum, d) => sum + d.carbs, 0) / calorieTrend.length; + avgFat = calorieTrend.reduce((sum, d) => sum + d.fat, 0) / calorieTrend.length; + } + let weightChange = null; + if (weightTrend.length >= 2) { + weightChange = weightTrend[weightTrend.length - 1].weight_kg - weightTrend[0].weight_kg; + } + return { + user: req.user, + weight_trend: weightTrend, + calorie_trend: calorieTrend, + avg_calories: Math.round(avgCalories), + avg_protein: Math.round(avgProtein), + avg_carbs: Math.round(avgCarbs), + avg_fat: Math.round(avgFat), + weight_change: weightChange, + days, + }; + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error loading progress'); + return { + user: req.user, + weight_trend: [], + calorie_trend: [], + avg_calories: 0, + avg_protein: 0, + avg_carbs: 0, + avg_fat: 0, + weight_change: null, + days: 30, + }; + } + } +}; +exports.ProgressController = ProgressController; +__decorate([ + (0, common_1.Get)(), + (0, common_1.Render)('progress'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Query)('days')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, String]), + __metadata("design:returntype", Promise) +], ProgressController.prototype, "getProgress", null); +exports.ProgressController = ProgressController = __decorate([ + (0, common_1.Controller)('progress'), + (0, common_1.UseGuards)(authenticated_guard_1.AuthenticatedGuard), + __metadata("design:paramtypes", [utils_service_1.UtilsService]) +], ProgressController); +//# sourceMappingURL=progress.controller.js.map \ No newline at end of file diff --git a/dist/dashboard/progress.controller.js.map b/dist/dashboard/progress.controller.js.map new file mode 100644 index 0000000..332f066 --- /dev/null +++ b/dist/dashboard/progress.controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"progress.controller.js","sourceRoot":"","sources":["../../src/dashboard/progress.controller.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/database/database.module.d.ts b/dist/database/database.module.d.ts new file mode 100644 index 0000000..d6fdcd7 --- /dev/null +++ b/dist/database/database.module.d.ts @@ -0,0 +1,2 @@ +export declare class DatabaseModule { +} diff --git a/dist/database/database.module.js b/dist/database/database.module.js new file mode 100644 index 0000000..caf6789 --- /dev/null +++ b/dist/database/database.module.js @@ -0,0 +1,57 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DatabaseModule = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const config_1 = require("@nestjs/config"); +const user_model_1 = require("../models/user.model"); +const food_item_model_1 = require("../models/food-item.model"); +const meal_model_1 = require("../models/meal.model"); +const meal_food_model_1 = require("../models/meal-food.model"); +const water_log_model_1 = require("../models/water-log.model"); +const weight_log_model_1 = require("../models/weight-log.model"); +const meal_plan_model_1 = require("../models/meal-plan.model"); +const planned_food_model_1 = require("../models/planned-food.model"); +const user_goal_model_1 = require("../models/user-goal.model"); +const daily_summary_model_1 = require("../models/daily-summary.model"); +const api_cache_model_1 = require("../models/api-cache.model"); +let DatabaseModule = class DatabaseModule { +}; +exports.DatabaseModule = DatabaseModule; +exports.DatabaseModule = DatabaseModule = __decorate([ + (0, common_1.Module)({ + imports: [ + sequelize_1.SequelizeModule.forRootAsync({ + imports: [config_1.ConfigModule], + useFactory: (configService) => ({ + dialect: 'sqlite', + storage: configService.get('DATABASE_URL') ? configService.get('DATABASE_URL').replace('sqlite://', '') : 'data/calorie_tracker.db', + models: [ + user_model_1.User, + food_item_model_1.FoodItem, + meal_model_1.Meal, + meal_food_model_1.MealFood, + water_log_model_1.WaterLog, + weight_log_model_1.WeightLog, + meal_plan_model_1.MealPlan, + planned_food_model_1.PlannedFood, + user_goal_model_1.UserGoal, + daily_summary_model_1.DailySummary, + api_cache_model_1.APICache, + ], + autoLoadModels: true, + synchronize: true, + logging: false, + }), + inject: [config_1.ConfigService], + }), + ], + }) +], DatabaseModule); +//# sourceMappingURL=database.module.js.map \ No newline at end of file diff --git a/dist/database/database.module.js.map b/dist/database/database.module.js.map new file mode 100644 index 0000000..2a262f1 --- /dev/null +++ b/dist/database/database.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"database.module.js","sourceRoot":"","sources":["../../src/database/database.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,iDAAoD;AACpD,2CAA6D;AAC7D,qDAA4C;AAC5C,+DAAqD;AACrD,qDAA4C;AAC5C,+DAAqD;AACrD,+DAAqD;AACrD,iEAAuD;AACvD,+DAAqD;AACrD,qEAA2D;AAC3D,+DAAqD;AACrD,uEAA6D;AAC7D,+DAAqD;AA8B9C,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,wCAAc;yBAAd,cAAc;IA5B1B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,2BAAe,CAAC,YAAY,CAAC;gBAC3B,OAAO,EAAE,CAAC,qBAAY,CAAC;gBACvB,UAAU,EAAE,CAAC,aAA4B,EAAE,EAAE,CAAC,CAAC;oBAC7C,OAAO,EAAE,QAAQ;oBACjB,OAAO,EAAE,aAAa,CAAC,GAAG,CAAS,cAAc,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAS,cAAc,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,yBAAyB;oBACnJ,MAAM,EAAE;wBACN,iBAAI;wBACJ,0BAAQ;wBACR,iBAAI;wBACJ,0BAAQ;wBACR,0BAAQ;wBACR,4BAAS;wBACT,0BAAQ;wBACR,gCAAW;wBACX,0BAAQ;wBACR,kCAAY;wBACZ,0BAAQ;qBACT;oBACD,cAAc,EAAE,IAAI;oBACpB,WAAW,EAAE,IAAI;oBACjB,OAAO,EAAE,KAAK;iBACf,CAAC;gBACF,MAAM,EAAE,CAAC,sBAAa,CAAC;aACxB,CAAC;SACH;KACF,CAAC;GACW,cAAc,CAAG"} \ No newline at end of file diff --git a/dist/foods/foods.controller.d.ts b/dist/foods/foods.controller.d.ts new file mode 100644 index 0000000..063027b --- /dev/null +++ b/dist/foods/foods.controller.d.ts @@ -0,0 +1,13 @@ +import { FoodsService } from './foods.service'; +export declare class FoodsController { + private foodsService; + constructor(foodsService: FoodsService); + getFoods(req: any, category: string, q: string): Promise<{ + filipino_foods: import("../models/food-item.model").FoodItem[]; + other_foods: import("../models/food-item.model").FoodItem[]; + categories: string[]; + current_category: string; + search_query: string; + user: any; + }>; +} diff --git a/dist/foods/foods.controller.js b/dist/foods/foods.controller.js new file mode 100644 index 0000000..7f0e3a7 --- /dev/null +++ b/dist/foods/foods.controller.js @@ -0,0 +1,58 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FoodsController = void 0; +const common_1 = require("@nestjs/common"); +const authenticated_guard_1 = require("../auth/guards/authenticated.guard"); +const foods_service_1 = require("./foods.service"); +let FoodsController = class FoodsController { + constructor(foodsService) { + this.foodsService = foodsService; + } + async getFoods(req, category, q) { + try { + const data = await this.foodsService.getFoods(category, q); + return Object.assign({ user: req.user }, data); + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error loading foods'); + return { + user: req.user, + filipino_foods: [], + other_foods: [], + categories: [], + current_category: 'all', + search_query: '', + }; + } + } +}; +exports.FoodsController = FoodsController; +__decorate([ + (0, common_1.Get)(), + (0, common_1.Render)('foods'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Query)('category')), + __param(2, (0, common_1.Query)('q')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, String, String]), + __metadata("design:returntype", Promise) +], FoodsController.prototype, "getFoods", null); +exports.FoodsController = FoodsController = __decorate([ + (0, common_1.Controller)('foods'), + (0, common_1.UseGuards)(authenticated_guard_1.AuthenticatedGuard), + __metadata("design:paramtypes", [foods_service_1.FoodsService]) +], FoodsController); +//# sourceMappingURL=foods.controller.js.map \ No newline at end of file diff --git a/dist/foods/foods.controller.js.map b/dist/foods/foods.controller.js.map new file mode 100644 index 0000000..8029bd4 --- /dev/null +++ b/dist/foods/foods.controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"foods.controller.js","sourceRoot":"","sources":["../../src/foods/foods.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAgF;AAChF,4EAAwE;AACxE,mDAA+C;AAIxC,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B,YAAoB,YAA0B;QAA1B,iBAAY,GAAZ,YAAY,CAAc;IAAG,CAAC;IAI5C,AAAN,KAAK,CAAC,QAAQ,CAAQ,GAAG,EAAqB,QAAgB,EAAc,CAAS;QACnF,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAC3D,uBACE,IAAI,EAAE,GAAG,CAAC,IAAI,IACX,IAAI,EACP;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;YAC9C,OAAO;gBACL,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,cAAc,EAAE,EAAE;gBAClB,WAAW,EAAE,EAAE;gBACf,UAAU,EAAE,EAAE;gBACd,gBAAgB,EAAE,KAAK;gBACvB,YAAY,EAAE,EAAE;aACjB,CAAC;QACJ,CAAC;IACH,CAAC;CACF,CAAA;AAzBY,0CAAe;AAKpB;IAFL,IAAA,YAAG,GAAE;IACL,IAAA,eAAM,EAAC,OAAO,CAAC;IACA,WAAA,IAAA,YAAG,GAAE,CAAA;IAAO,WAAA,IAAA,cAAK,EAAC,UAAU,CAAC,CAAA;IAAoB,WAAA,IAAA,cAAK,EAAC,GAAG,CAAC,CAAA;;;;+CAmB1E;0BAxBU,eAAe;IAF3B,IAAA,mBAAU,EAAC,OAAO,CAAC;IACnB,IAAA,kBAAS,EAAC,wCAAkB,CAAC;qCAEM,4BAAY;GADnC,eAAe,CAyB3B"} \ No newline at end of file diff --git a/dist/foods/foods.module.d.ts b/dist/foods/foods.module.d.ts new file mode 100644 index 0000000..46f0cb0 --- /dev/null +++ b/dist/foods/foods.module.d.ts @@ -0,0 +1,2 @@ +export declare class FoodsModule { +} diff --git a/dist/foods/foods.module.js b/dist/foods/foods.module.js new file mode 100644 index 0000000..38dcd2d --- /dev/null +++ b/dist/foods/foods.module.js @@ -0,0 +1,25 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FoodsModule = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const foods_controller_1 = require("./foods.controller"); +const foods_service_1 = require("./foods.service"); +const food_item_model_1 = require("../models/food-item.model"); +let FoodsModule = class FoodsModule { +}; +exports.FoodsModule = FoodsModule; +exports.FoodsModule = FoodsModule = __decorate([ + (0, common_1.Module)({ + imports: [sequelize_1.SequelizeModule.forFeature([food_item_model_1.FoodItem])], + controllers: [foods_controller_1.FoodsController], + providers: [foods_service_1.FoodsService], + }) +], FoodsModule); +//# sourceMappingURL=foods.module.js.map \ No newline at end of file diff --git a/dist/foods/foods.module.js.map b/dist/foods/foods.module.js.map new file mode 100644 index 0000000..e20e80a --- /dev/null +++ b/dist/foods/foods.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"foods.module.js","sourceRoot":"","sources":["../../src/foods/foods.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,iDAAoD;AACpD,yDAAqD;AACrD,mDAA+C;AAC/C,+DAAqD;AAO9C,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IALvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,2BAAe,CAAC,UAAU,CAAC,CAAC,0BAAQ,CAAC,CAAC,CAAC;QACjD,WAAW,EAAE,CAAC,kCAAe,CAAC;QAC9B,SAAS,EAAE,CAAC,4BAAY,CAAC;KAC1B,CAAC;GACW,WAAW,CAAG"} \ No newline at end of file diff --git a/dist/foods/foods.service.d.ts b/dist/foods/foods.service.d.ts new file mode 100644 index 0000000..10d4814 --- /dev/null +++ b/dist/foods/foods.service.d.ts @@ -0,0 +1,12 @@ +import { FoodItem } from '../models/food-item.model'; +export declare class FoodsService { + private foodItemModel; + constructor(foodItemModel: typeof FoodItem); + getFoods(category?: string, searchQuery?: string): Promise<{ + filipino_foods: FoodItem[]; + other_foods: FoodItem[]; + categories: string[]; + current_category: string; + search_query: string; + }>; +} diff --git a/dist/foods/foods.service.js b/dist/foods/foods.service.js new file mode 100644 index 0000000..b0c990b --- /dev/null +++ b/dist/foods/foods.service.js @@ -0,0 +1,62 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FoodsService = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const sequelize_2 = require("sequelize"); +const food_item_model_1 = require("../models/food-item.model"); +let FoodsService = class FoodsService { + constructor(foodItemModel) { + this.foodItemModel = foodItemModel; + } + async getFoods(category = 'all', searchQuery = '') { + const whereClause = {}; + if (category !== 'all') { + whereClause.category = category; + } + if (searchQuery) { + whereClause[sequelize_2.Op.or] = [ + { name: { [sequelize_2.Op.like]: `%${searchQuery}%` } }, + { name_tagalog: { [sequelize_2.Op.like]: `%${searchQuery}%` } }, + ]; + } + const filipinoWhere = Object.assign(Object.assign({}, whereClause), { is_filipino: true }); + const otherWhere = Object.assign(Object.assign({}, whereClause), { is_filipino: false }); + const filipinoFoods = await this.foodItemModel.findAll({ + where: filipinoWhere, + order: [['name', 'ASC']], + }); + const otherFoods = await this.foodItemModel.findAll({ + where: otherWhere, + limit: 20, + order: [['name', 'ASC']], + }); + const categories = ['all', 'kanin', 'ulam', 'sabaw', 'gulay', 'meryenda', 'almusal']; + return { + filipino_foods: filipinoFoods, + other_foods: otherFoods, + categories, + current_category: category, + search_query: searchQuery, + }; + } +}; +exports.FoodsService = FoodsService; +exports.FoodsService = FoodsService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, sequelize_1.InjectModel)(food_item_model_1.FoodItem)), + __metadata("design:paramtypes", [Object]) +], FoodsService); +//# sourceMappingURL=foods.service.js.map \ No newline at end of file diff --git a/dist/foods/foods.service.js.map b/dist/foods/foods.service.js.map new file mode 100644 index 0000000..a994d79 --- /dev/null +++ b/dist/foods/foods.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"foods.service.js","sourceRoot":"","sources":["../../src/foods/foods.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,iDAAgD;AAChD,yCAA+B;AAC/B,+DAAqD;AAG9C,IAAM,YAAY,GAAlB,MAAM,YAAY;IACvB,YACiC,aAA8B;QAA9B,kBAAa,GAAb,aAAa,CAAiB;IAC5D,CAAC;IAEJ,KAAK,CAAC,QAAQ,CAAC,WAAmB,KAAK,EAAE,cAAsB,EAAE;QAC/D,MAAM,WAAW,GAAQ,EAAE,CAAC;QAE5B,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;YACvB,WAAW,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAClC,CAAC;QAED,IAAI,WAAW,EAAE,CAAC;YAChB,WAAW,CAAC,cAAE,CAAC,EAAE,CAAC,GAAG;gBACnB,EAAE,IAAI,EAAE,EAAE,CAAC,cAAE,CAAC,IAAI,CAAC,EAAE,IAAI,WAAW,GAAG,EAAE,EAAE;gBAC3C,EAAE,YAAY,EAAE,EAAE,CAAC,cAAE,CAAC,IAAI,CAAC,EAAE,IAAI,WAAW,GAAG,EAAE,EAAE;aACpD,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,mCAAQ,WAAW,KAAE,WAAW,EAAE,IAAI,GAAE,CAAC;QAC5D,MAAM,UAAU,mCAAQ,WAAW,KAAE,WAAW,EAAE,KAAK,GAAE,CAAC;QAE1D,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YACrD,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;SACzB,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YAClD,KAAK,EAAE,UAAU;YACjB,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;SACzB,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QAErF,OAAO;YACL,cAAc,EAAE,aAAa;YAC7B,WAAW,EAAE,UAAU;YACvB,UAAU;YACV,gBAAgB,EAAE,QAAQ;YAC1B,YAAY,EAAE,WAAW;SAC1B,CAAC;IACJ,CAAC;CACF,CAAA;AA3CY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,uBAAW,EAAC,0BAAQ,CAAC,CAAA;;GAFb,YAAY,CA2CxB"} \ No newline at end of file diff --git a/dist/goals/goals.controller.d.ts b/dist/goals/goals.controller.d.ts new file mode 100644 index 0000000..d1affc9 --- /dev/null +++ b/dist/goals/goals.controller.d.ts @@ -0,0 +1,13 @@ +import { Response } from 'express'; +import { GoalsService } from './goals.service'; +export declare class GoalsController { + private goalsService; + constructor(goalsService: GoalsService); + getGoals(req: any): Promise<{ + user: any; + goals: import("../models/user-goal.model").UserGoal; + bmr: any; + tdee: any; + }>; + updateGoals(req: any, body: any, res: Response): Promise; +} diff --git a/dist/goals/goals.controller.js b/dist/goals/goals.controller.js new file mode 100644 index 0000000..4a59b14 --- /dev/null +++ b/dist/goals/goals.controller.js @@ -0,0 +1,80 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GoalsController = void 0; +const common_1 = require("@nestjs/common"); +const authenticated_guard_1 = require("../auth/guards/authenticated.guard"); +const goals_service_1 = require("./goals.service"); +let GoalsController = class GoalsController { + constructor(goalsService) { + this.goalsService = goalsService; + } + async getGoals(req) { + try { + const data = await this.goalsService.getGoals(req.user.id); + return { + user: req.user, + goals: data.goals, + bmr: data.bmr, + tdee: data.tdee, + }; + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error loading goals'); + return { + user: req.user, + goals: null, + bmr: null, + tdee: null, + }; + } + } + async updateGoals(req, body, res) { + try { + await this.goalsService.updateGoals(req.user.id, body); + req.flash('success_msg', 'Goals updated successfully!'); + res.redirect('/goals'); + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error updating goals'); + res.redirect('/goals'); + } + } +}; +exports.GoalsController = GoalsController; +__decorate([ + (0, common_1.Get)(), + (0, common_1.Render)('goals'), + __param(0, (0, common_1.Req)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], GoalsController.prototype, "getGoals", null); +__decorate([ + (0, common_1.Post)(), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Body)()), + __param(2, (0, common_1.Res)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object, Object]), + __metadata("design:returntype", Promise) +], GoalsController.prototype, "updateGoals", null); +exports.GoalsController = GoalsController = __decorate([ + (0, common_1.Controller)('goals'), + (0, common_1.UseGuards)(authenticated_guard_1.AuthenticatedGuard), + __metadata("design:paramtypes", [goals_service_1.GoalsService]) +], GoalsController); +//# sourceMappingURL=goals.controller.js.map \ No newline at end of file diff --git a/dist/goals/goals.controller.js.map b/dist/goals/goals.controller.js.map new file mode 100644 index 0000000..c879a56 --- /dev/null +++ b/dist/goals/goals.controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"goals.controller.js","sourceRoot":"","sources":["../../src/goals/goals.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA0F;AAE1F,4EAAwE;AACxE,mDAA+C;AAIxC,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B,YAAoB,YAA0B;QAA1B,iBAAY,GAAZ,YAAY,CAAc;IAAG,CAAC;IAI5C,AAAN,KAAK,CAAC,QAAQ,CAAQ,GAAG;QACvB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC3D,OAAO;gBACL,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;YAC9C,OAAO;gBACL,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,KAAK,EAAE,IAAI;gBACX,GAAG,EAAE,IAAI;gBACT,IAAI,EAAE,IAAI;aACX,CAAC;QACJ,CAAC;IACH,CAAC;IAGK,AAAN,KAAK,CAAC,WAAW,CAAQ,GAAG,EAAU,IAAI,EAAS,GAAa;QAC9D,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACvD,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,6BAA6B,CAAC,CAAC;YACxD,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAC;YAC/C,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;CACF,CAAA;AAtCY,0CAAe;AAKpB;IAFL,IAAA,YAAG,GAAE;IACL,IAAA,eAAM,EAAC,OAAO,CAAC;IACA,WAAA,IAAA,YAAG,GAAE,CAAA;;;;+CAmBpB;AAGK;IADL,IAAA,aAAI,GAAE;IACY,WAAA,IAAA,YAAG,GAAE,CAAA;IAAO,WAAA,IAAA,aAAI,GAAE,CAAA;IAAQ,WAAA,IAAA,YAAG,GAAE,CAAA;;;;kDAUjD;0BArCU,eAAe;IAF3B,IAAA,mBAAU,EAAC,OAAO,CAAC;IACnB,IAAA,kBAAS,EAAC,wCAAkB,CAAC;qCAEM,4BAAY;GADnC,eAAe,CAsC3B"} \ No newline at end of file diff --git a/dist/goals/goals.module.d.ts b/dist/goals/goals.module.d.ts new file mode 100644 index 0000000..1ae91b8 --- /dev/null +++ b/dist/goals/goals.module.d.ts @@ -0,0 +1,2 @@ +export declare class GoalsModule { +} diff --git a/dist/goals/goals.module.js b/dist/goals/goals.module.js new file mode 100644 index 0000000..fcfc37f --- /dev/null +++ b/dist/goals/goals.module.js @@ -0,0 +1,30 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GoalsModule = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const goals_controller_1 = require("./goals.controller"); +const goals_service_1 = require("./goals.service"); +const user_model_1 = require("../models/user.model"); +const user_goal_model_1 = require("../models/user-goal.model"); +const utils_module_1 = require("../utils/utils.module"); +let GoalsModule = class GoalsModule { +}; +exports.GoalsModule = GoalsModule; +exports.GoalsModule = GoalsModule = __decorate([ + (0, common_1.Module)({ + imports: [ + sequelize_1.SequelizeModule.forFeature([user_model_1.User, user_goal_model_1.UserGoal]), + utils_module_1.UtilsModule, + ], + controllers: [goals_controller_1.GoalsController], + providers: [goals_service_1.GoalsService], + }) +], GoalsModule); +//# sourceMappingURL=goals.module.js.map \ No newline at end of file diff --git a/dist/goals/goals.module.js.map b/dist/goals/goals.module.js.map new file mode 100644 index 0000000..8e3731b --- /dev/null +++ b/dist/goals/goals.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"goals.module.js","sourceRoot":"","sources":["../../src/goals/goals.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,iDAAoD;AACpD,yDAAqD;AACrD,mDAA+C;AAC/C,qDAA4C;AAC5C,+DAAqD;AACrD,wDAAoD;AAU7C,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IARvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,2BAAe,CAAC,UAAU,CAAC,CAAC,iBAAI,EAAE,0BAAQ,CAAC,CAAC;YAC5C,0BAAW;SACZ;QACD,WAAW,EAAE,CAAC,kCAAe,CAAC;QAC9B,SAAS,EAAE,CAAC,4BAAY,CAAC;KAC1B,CAAC;GACW,WAAW,CAAG"} \ No newline at end of file diff --git a/dist/goals/goals.service.d.ts b/dist/goals/goals.service.d.ts new file mode 100644 index 0000000..2dcf410 --- /dev/null +++ b/dist/goals/goals.service.d.ts @@ -0,0 +1,20 @@ +import { User } from '../models/user.model'; +import { UserGoal } from '../models/user-goal.model'; +import { UtilsService } from '../utils/utils.service'; +export declare class GoalsService { + private userModel; + private userGoalModel; + private utilsService; + constructor(userModel: typeof User, userGoalModel: typeof UserGoal, utilsService: UtilsService); + getGoals(userId: number): Promise<{ + goals: UserGoal; + bmr: any; + tdee: any; + user: User; + }>; + updateGoals(userId: number, data: any): Promise<{ + success: boolean; + user: User; + goals: UserGoal; + }>; +} diff --git a/dist/goals/goals.service.js b/dist/goals/goals.service.js new file mode 100644 index 0000000..65ae722 --- /dev/null +++ b/dist/goals/goals.service.js @@ -0,0 +1,94 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GoalsService = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const user_model_1 = require("../models/user.model"); +const user_goal_model_1 = require("../models/user-goal.model"); +const utils_service_1 = require("../utils/utils.service"); +let GoalsService = class GoalsService { + constructor(userModel, userGoalModel, utilsService) { + this.userModel = userModel; + this.userGoalModel = userGoalModel; + this.utilsService = utilsService; + } + async getGoals(userId) { + const user = await this.userModel.findByPk(userId); + const userGoals = await this.userGoalModel.findOne({ where: { UserId: userId } }); + let bmr = null; + let tdee = null; + if (user && user.weight_kg && user.height_cm && user.age) { + bmr = this.utilsService.calculateBMR(user.weight_kg, user.height_cm, user.age, user.gender || 'male'); + tdee = this.utilsService.calculateTDEE(bmr, user.activity_level || 'moderate'); + } + return { + goals: userGoals, + bmr, + tdee, + user, + }; + } + async updateGoals(userId, data) { + const user = await this.userModel.findByPk(userId); + if (!user) { + throw new Error('User not found'); + } + user.age = parseInt(data.age) || 25; + user.gender = data.gender || 'male'; + user.height_cm = parseFloat(data.height_cm) || 170; + user.weight_kg = parseFloat(data.weight_kg) || 70; + user.activity_level = data.activity_level || 'moderate'; + const bmr = this.utilsService.calculateBMR(user.weight_kg, user.height_cm, user.age, user.gender); + const tdee = this.utilsService.calculateTDEE(bmr, user.activity_level); + const goalType = data.goal_type || 'recomp'; + let targetCalories; + if (goalType === 'weight_loss') { + targetCalories = tdee - 500; + } + else if (goalType === 'muscle_gain') { + targetCalories = tdee + 300; + } + else { + targetCalories = tdee; + } + user.target_daily_calories = Math.round(targetCalories); + await user.save(); + let userGoals = await this.userGoalModel.findOne({ where: { UserId: userId } }); + if (!userGoals) { + userGoals = await this.userGoalModel.create({ UserId: userId }); + } + userGoals.goal_type = goalType; + userGoals.target_weight_kg = parseFloat(data.target_weight_kg) || 70; + const macros = this.utilsService.calculateMacroTargets(user.weight_kg, goalType); + userGoals.target_protein_g = macros.protein_g; + userGoals.target_carbs_g = macros.carbs_g; + userGoals.target_fat_g = macros.fat_g; + userGoals.target_water_ml = parseInt(data.target_water_ml) || 2000; + await userGoals.save(); + return { + success: true, + user, + goals: userGoals, + }; + } +}; +exports.GoalsService = GoalsService; +exports.GoalsService = GoalsService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, sequelize_1.InjectModel)(user_model_1.User)), + __param(1, (0, sequelize_1.InjectModel)(user_goal_model_1.UserGoal)), + __metadata("design:paramtypes", [Object, Object, utils_service_1.UtilsService]) +], GoalsService); +//# sourceMappingURL=goals.service.js.map \ No newline at end of file diff --git a/dist/goals/goals.service.js.map b/dist/goals/goals.service.js.map new file mode 100644 index 0000000..48d69c9 --- /dev/null +++ b/dist/goals/goals.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"goals.service.js","sourceRoot":"","sources":["../../src/goals/goals.service.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/main.d.ts b/dist/main.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/main.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/main.js b/dist/main.js new file mode 100644 index 0000000..9c5447e --- /dev/null +++ b/dist/main.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const core_1 = require("@nestjs/core"); +const app_module_1 = require("./app.module"); +const session = require("express-session"); +const passport = require("passport"); +const flash = require("express-flash"); +const expressLayouts = require("express-ejs-layouts"); +const methodOverride = require("method-override"); +const path = require("path"); +const SQLiteStore = require('connect-sqlite3')(session); +async function bootstrap() { + const app = await core_1.NestFactory.create(app_module_1.AppModule); + app.useStaticAssets(path.join(__dirname, '..', 'public')); + app.setBaseViewsDir(path.join(__dirname, '..', 'views')); + app.setViewEngine('ejs'); + app.use(expressLayouts); + app.set('layout', 'layout'); + app.use(methodOverride('_method')); + app.useBodyParser('urlencoded', { extended: true }); + app.use(session({ + store: new SQLiteStore({ db: 'sessions.db', dir: './data' }), + secret: process.env.SECRET_KEY || 'secret', + resave: false, + saveUninitialized: false, + cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 }, + })); + app.use(passport.initialize()); + app.use(passport.session()); + app.use(flash()); + const expressApp = app.getHttpAdapter().getInstance(); + expressApp.locals.round = Math.round; + const PORT = process.env.PORT || 3000; + await app.listen(PORT); + console.log(`Application is running on: ${await app.getUrl()}`); +} +bootstrap(); +//# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/dist/main.js.map b/dist/main.js.map new file mode 100644 index 0000000..55c0b42 --- /dev/null +++ b/dist/main.js.map @@ -0,0 +1 @@ +{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAE3C,6CAAyC;AACzC,2CAA2C;AAC3C,qCAAqC;AACrC,uCAAuC;AACvC,sDAAsD;AACtD,kDAAkD;AAClD,6BAA6B;AAG7B,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC;AAExD,KAAK,UAAU,SAAS;IACtB,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAyB,sBAAS,CAAC,CAAC;IAGxE,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAG1D,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACzD,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAGzB,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACxB,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAG5B,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC;IAGnC,GAAG,CAAC,aAAa,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAGpD,GAAG,CAAC,GAAG,CACL,OAAO,CAAC;QACN,KAAK,EAAE,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;QAC5D,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,QAAQ;QAC1C,MAAM,EAAE,KAAK;QACb,iBAAiB,EAAE,KAAK;QACxB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE;KAC7C,CAAC,CACH,CAAC;IAGF,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAC/B,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IAG5B,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;IAGjB,MAAM,UAAU,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC,WAAW,EAAE,CAAC;IACtD,UAAU,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAErC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;IACtC,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC,8BAA8B,MAAM,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAClE,CAAC;AACD,SAAS,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/meal-planner/meal-planner.controller.d.ts b/dist/meal-planner/meal-planner.controller.d.ts new file mode 100644 index 0000000..5d85c69 --- /dev/null +++ b/dist/meal-planner/meal-planner.controller.d.ts @@ -0,0 +1,15 @@ +import { Response } from 'express'; +import { MealPlannerService } from './meal-planner.service'; +export declare class MealPlannerController { + private mealPlannerService; + constructor(mealPlannerService: MealPlannerService); + getMealPlanner(req: any): Promise<{ + user: any; + dates: any[]; + meal_plans: {}; + today: string; + }>; + autoGenerate(req: any, body: any, res: Response): Promise; + addMealPlan(req: any, body: any, res: Response): Promise; + toggleComplete(req: any, id: number, res: Response): Promise; +} diff --git a/dist/meal-planner/meal-planner.controller.js b/dist/meal-planner/meal-planner.controller.js new file mode 100644 index 0000000..e9641d5 --- /dev/null +++ b/dist/meal-planner/meal-planner.controller.js @@ -0,0 +1,125 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MealPlannerController = void 0; +const common_1 = require("@nestjs/common"); +const authenticated_guard_1 = require("../auth/guards/authenticated.guard"); +const meal_planner_service_1 = require("./meal-planner.service"); +let MealPlannerController = class MealPlannerController { + constructor(mealPlannerService) { + this.mealPlannerService = mealPlannerService; + } + async getMealPlanner(req) { + try { + const data = await this.mealPlannerService.getWeeklyMealPlans(req.user.id); + return { + user: req.user, + dates: data.dates, + meal_plans: data.mealPlans, + today: data.today, + }; + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error loading meal planner'); + return { + user: req.user, + dates: [], + meal_plans: {}, + today: new Date().toISOString().split('T')[0], + }; + } + } + async autoGenerate(req, body, res) { + try { + const { date } = body; + if (!date) { + req.flash('error_msg', 'Please select a date'); + return res.redirect('/meal-planner'); + } + await this.mealPlannerService.autoGenerate(req.user.id, date); + req.flash('success_msg', 'Meal plan generated successfully!'); + res.redirect('/meal-planner'); + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error generating meal plan'); + res.redirect('/meal-planner'); + } + } + async addMealPlan(req, body, res) { + try { + await this.mealPlannerService.addMealPlan(req.user.id, body); + req.flash('success_msg', 'Meal plan updated!'); + res.redirect('/meal-planner'); + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error adding meal plan'); + res.redirect('/meal-planner'); + } + } + async toggleComplete(req, id, res) { + try { + await this.mealPlannerService.toggleComplete(req.user.id, id); + res.json({ success: true }); + } + catch (err) { + console.error(err); + res.status(500).json({ success: false }); + } + } +}; +exports.MealPlannerController = MealPlannerController; +__decorate([ + (0, common_1.Get)(), + (0, common_1.Render)('meal_planner'), + __param(0, (0, common_1.Req)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], MealPlannerController.prototype, "getMealPlanner", null); +__decorate([ + (0, common_1.Post)('auto-generate'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Body)()), + __param(2, (0, common_1.Res)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object, Object]), + __metadata("design:returntype", Promise) +], MealPlannerController.prototype, "autoGenerate", null); +__decorate([ + (0, common_1.Post)('add'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Body)()), + __param(2, (0, common_1.Res)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object, Object]), + __metadata("design:returntype", Promise) +], MealPlannerController.prototype, "addMealPlan", null); +__decorate([ + (0, common_1.Post)('complete/:id'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Param)('id')), + __param(2, (0, common_1.Res)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Number, Object]), + __metadata("design:returntype", Promise) +], MealPlannerController.prototype, "toggleComplete", null); +exports.MealPlannerController = MealPlannerController = __decorate([ + (0, common_1.Controller)('meal-planner'), + (0, common_1.UseGuards)(authenticated_guard_1.AuthenticatedGuard), + __metadata("design:paramtypes", [meal_planner_service_1.MealPlannerService]) +], MealPlannerController); +//# sourceMappingURL=meal-planner.controller.js.map \ No newline at end of file diff --git a/dist/meal-planner/meal-planner.controller.js.map b/dist/meal-planner/meal-planner.controller.js.map new file mode 100644 index 0000000..c315a84 --- /dev/null +++ b/dist/meal-planner/meal-planner.controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"meal-planner.controller.js","sourceRoot":"","sources":["../../src/meal-planner/meal-planner.controller.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/meal-planner/meal-planner.module.d.ts b/dist/meal-planner/meal-planner.module.d.ts new file mode 100644 index 0000000..27c08e8 --- /dev/null +++ b/dist/meal-planner/meal-planner.module.d.ts @@ -0,0 +1,2 @@ +export declare class MealPlannerModule { +} diff --git a/dist/meal-planner/meal-planner.module.js b/dist/meal-planner/meal-planner.module.js new file mode 100644 index 0000000..a65ebe1 --- /dev/null +++ b/dist/meal-planner/meal-planner.module.js @@ -0,0 +1,31 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MealPlannerModule = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const meal_planner_controller_1 = require("./meal-planner.controller"); +const meal_planner_service_1 = require("./meal-planner.service"); +const meal_plan_model_1 = require("../models/meal-plan.model"); +const planned_food_model_1 = require("../models/planned-food.model"); +const food_item_model_1 = require("../models/food-item.model"); +const utils_module_1 = require("../utils/utils.module"); +let MealPlannerModule = class MealPlannerModule { +}; +exports.MealPlannerModule = MealPlannerModule; +exports.MealPlannerModule = MealPlannerModule = __decorate([ + (0, common_1.Module)({ + imports: [ + sequelize_1.SequelizeModule.forFeature([meal_plan_model_1.MealPlan, planned_food_model_1.PlannedFood, food_item_model_1.FoodItem]), + utils_module_1.UtilsModule, + ], + controllers: [meal_planner_controller_1.MealPlannerController], + providers: [meal_planner_service_1.MealPlannerService], + }) +], MealPlannerModule); +//# sourceMappingURL=meal-planner.module.js.map \ No newline at end of file diff --git a/dist/meal-planner/meal-planner.module.js.map b/dist/meal-planner/meal-planner.module.js.map new file mode 100644 index 0000000..771aad0 --- /dev/null +++ b/dist/meal-planner/meal-planner.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"meal-planner.module.js","sourceRoot":"","sources":["../../src/meal-planner/meal-planner.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,iDAAoD;AACpD,uEAAkE;AAClE,iEAA4D;AAC5D,+DAAqD;AACrD,qEAA2D;AAC3D,+DAAqD;AACrD,wDAAoD;AAU7C,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;CAAG,CAAA;AAApB,8CAAiB;4BAAjB,iBAAiB;IAR7B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,2BAAe,CAAC,UAAU,CAAC,CAAC,0BAAQ,EAAE,gCAAW,EAAE,0BAAQ,CAAC,CAAC;YAC7D,0BAAW;SACZ;QACD,WAAW,EAAE,CAAC,+CAAqB,CAAC;QACpC,SAAS,EAAE,CAAC,yCAAkB,CAAC;KAChC,CAAC;GACW,iBAAiB,CAAG"} \ No newline at end of file diff --git a/dist/meal-planner/meal-planner.service.d.ts b/dist/meal-planner/meal-planner.service.d.ts new file mode 100644 index 0000000..6ff41b0 --- /dev/null +++ b/dist/meal-planner/meal-planner.service.d.ts @@ -0,0 +1,19 @@ +import { MealPlan } from '../models/meal-plan.model'; +import { PlannedFood } from '../models/planned-food.model'; +import { FoodItem } from '../models/food-item.model'; +import { UtilsService } from '../utils/utils.service'; +export declare class MealPlannerService { + private mealPlanModel; + private plannedFoodModel; + private foodItemModel; + private utilsService; + constructor(mealPlanModel: typeof MealPlan, plannedFoodModel: typeof PlannedFood, foodItemModel: typeof FoodItem, utilsService: UtilsService); + getWeeklyMealPlans(userId: number): Promise<{ + dates: any[]; + mealPlans: {}; + today: string; + }>; + autoGenerate(userId: number, date: string): Promise; + addMealPlan(userId: number, data: any): Promise; + toggleComplete(userId: number, planId: number): Promise; +} diff --git a/dist/meal-planner/meal-planner.service.js b/dist/meal-planner/meal-planner.service.js new file mode 100644 index 0000000..fb3dd5e --- /dev/null +++ b/dist/meal-planner/meal-planner.service.js @@ -0,0 +1,150 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MealPlannerService = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const meal_plan_model_1 = require("../models/meal-plan.model"); +const planned_food_model_1 = require("../models/planned-food.model"); +const food_item_model_1 = require("../models/food-item.model"); +const utils_service_1 = require("../utils/utils.service"); +let MealPlannerService = class MealPlannerService { + constructor(mealPlanModel, plannedFoodModel, foodItemModel, utilsService) { + this.mealPlanModel = mealPlanModel; + this.plannedFoodModel = plannedFoodModel; + this.foodItemModel = foodItemModel; + this.utilsService = utilsService; + } + async getWeeklyMealPlans(userId) { + const today = new Date(); + const day = today.getDay(); + const diff = today.getDate() - day + (day === 0 ? -6 : 1); + const startDate = new Date(today); + startDate.setDate(diff); + const dates = []; + for (let i = 0; i < 7; i++) { + const d = new Date(startDate); + d.setDate(startDate.getDate() + i); + dates.push(d); + } + const mealPlans = {}; + for (const d of dates) { + const dateStr = d.toISOString().split('T')[0]; + const plans = await this.mealPlanModel.findAll({ + where: { UserId: userId, date: dateStr }, + include: [ + { + model: planned_food_model_1.PlannedFood, + include: [food_item_model_1.FoodItem], + }, + ], + }); + mealPlans[dateStr] = plans.map((p) => { + let calories = 0, protein = 0, carbs = 0, fat = 0; + const foods = []; + if (p.plannedFoods) { + p.plannedFoods.forEach((pf) => { + if (pf.foodItem) { + const q = pf.quantity || 1; + calories += pf.foodItem.calories * q; + protein += pf.foodItem.protein_g * q; + carbs += pf.foodItem.carbs_g * q; + fat += pf.foodItem.fat_g * q; + foods.push({ + name: pf.foodItem.name, + quantity: q, + }); + } + }); + } + return { + id: p.id, + meal_type: p.meal_type, + is_completed: p.is_completed, + foods: foods, + totals: { + calories, + protein, + carbs, + fat, + }, + }; + }); + } + return { + dates: dates.map((d) => d.toISOString().split('T')[0]), + mealPlans, + today: new Date().toISOString().split('T')[0], + }; + } + async autoGenerate(userId, date) { + return this.utilsService.generateDailyMealPlan(userId, date); + } + async addMealPlan(userId, data) { + let { date, meal_type, 'food_id[]': foodIds, 'quantity[]': quantities } = data; + if (!foodIds) { + throw new Error('Please add at least one food item'); + } + if (!Array.isArray(foodIds)) { + foodIds = [foodIds]; + quantities = [quantities]; + } + let mealPlan = await this.mealPlanModel.findOne({ + where: { + UserId: userId, + date: date, + meal_type: meal_type, + }, + }); + if (!mealPlan) { + mealPlan = await this.mealPlanModel.create({ + UserId: userId, + date: date, + meal_type: meal_type, + }); + } + for (let i = 0; i < foodIds.length; i++) { + const foodId = foodIds[i]; + const quantity = quantities[i]; + if (foodId && quantity) { + await this.plannedFoodModel.create({ + MealPlanId: mealPlan.id, + FoodItemId: foodId, + quantity: quantity, + }); + } + } + return mealPlan; + } + async toggleComplete(userId, planId) { + const plan = await this.mealPlanModel.findOne({ + where: { id: planId, UserId: userId }, + }); + if (plan) { + plan.is_completed = !plan.is_completed; + await plan.save(); + return plan; + } + return null; + } +}; +exports.MealPlannerService = MealPlannerService; +exports.MealPlannerService = MealPlannerService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, sequelize_1.InjectModel)(meal_plan_model_1.MealPlan)), + __param(1, (0, sequelize_1.InjectModel)(planned_food_model_1.PlannedFood)), + __param(2, (0, sequelize_1.InjectModel)(food_item_model_1.FoodItem)), + __metadata("design:paramtypes", [Object, Object, Object, utils_service_1.UtilsService]) +], MealPlannerService); +//# sourceMappingURL=meal-planner.service.js.map \ No newline at end of file diff --git a/dist/meal-planner/meal-planner.service.js.map b/dist/meal-planner/meal-planner.service.js.map new file mode 100644 index 0000000..584a498 --- /dev/null +++ b/dist/meal-planner/meal-planner.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"meal-planner.service.js","sourceRoot":"","sources":["../../src/meal-planner/meal-planner.service.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/meals/meals.controller.d.ts b/dist/meals/meals.controller.d.ts new file mode 100644 index 0000000..2ee2f3a --- /dev/null +++ b/dist/meals/meals.controller.d.ts @@ -0,0 +1,32 @@ +import { Response } from 'express'; +import { UtilsService } from '../utils/utils.service'; +import { NutritionService } from './nutrition.service'; +import { Meal } from '../models/meal.model'; +import { MealFood } from '../models/meal-food.model'; +import { FoodItem } from '../models/food-item.model'; +import { WaterLog } from '../models/water-log.model'; +import { WeightLog } from '../models/weight-log.model'; +export declare class MealsController { + private utilsService; + private nutritionService; + private mealModel; + private mealFoodModel; + private foodItemModel; + private waterLogModel; + private weightLogModel; + constructor(utilsService: UtilsService, nutritionService: NutritionService, mealModel: typeof Meal, mealFoodModel: typeof MealFood, foodItemModel: typeof FoodItem, waterLogModel: typeof WaterLog, weightLogModel: typeof WeightLog); + addMealPage(req: any, res: Response): void; + addMeal(req: any, res: Response, body: any): Promise; + searchFood(query: string): Promise; + addFood(body: any): Promise<{ + success: boolean; + food_id: any; + name: string; + } | { + success: boolean; + food_id?: undefined; + name?: undefined; + }>; + addWater(req: any, res: Response, body: any): Promise; + addWeight(req: any, res: Response, body: any): Promise; +} diff --git a/dist/meals/meals.controller.js b/dist/meals/meals.controller.js new file mode 100644 index 0000000..6c8a44a --- /dev/null +++ b/dist/meals/meals.controller.js @@ -0,0 +1,220 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MealsController = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const authenticated_guard_1 = require("../auth/guards/authenticated.guard"); +const utils_service_1 = require("../utils/utils.service"); +const nutrition_service_1 = require("./nutrition.service"); +const meal_model_1 = require("../models/meal.model"); +const meal_food_model_1 = require("../models/meal-food.model"); +const food_item_model_1 = require("../models/food-item.model"); +const water_log_model_1 = require("../models/water-log.model"); +const weight_log_model_1 = require("../models/weight-log.model"); +let MealsController = class MealsController { + constructor(utilsService, nutritionService, mealModel, mealFoodModel, foodItemModel, waterLogModel, weightLogModel) { + this.utilsService = utilsService; + this.nutritionService = nutritionService; + this.mealModel = mealModel; + this.mealFoodModel = mealFoodModel; + this.foodItemModel = foodItemModel; + this.waterLogModel = waterLogModel; + this.weightLogModel = weightLogModel; + } + addMealPage(req, res) { + res.render('add_meal', { today: new Date().toISOString().split('T')[0] }); + } + async addMeal(req, res, body) { + try { + let { date, meal_type, time, 'food_id[]': foodIds, 'quantity[]': quantities } = body; + if (!foodIds) { + req.flash('error_msg', 'Please add at least one food item'); + return res.redirect('/add-meal'); + } + if (!Array.isArray(foodIds)) { + foodIds = [foodIds]; + quantities = [quantities]; + } + const meal = await this.mealModel.create({ + UserId: req.user.id, + date: date || new Date(), + meal_type, + time: time || null, + }); + for (let i = 0; i < foodIds.length; i++) { + const foodId = foodIds[i]; + const quantity = quantities[i]; + if (foodId && quantity) { + const food = await this.foodItemModel.findByPk(foodId); + if (food) { + await this.mealFoodModel.create({ + MealId: meal.id, + FoodItemId: foodId, + quantity: quantity, + calories_consumed: food.calories * quantity, + protein_consumed: food.protein_g * quantity, + carbs_consumed: food.carbs_g * quantity, + fat_consumed: food.fat_g * quantity, + }); + } + } + } + await this.utilsService.updateDailySummary(req.user.id, date); + req.flash('success_msg', 'Meal added successfully!'); + res.redirect('/dashboard'); + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error adding meal'); + res.redirect('/add-meal'); + } + } + async searchFood(query) { + if (!query || query.length < 2) { + return []; + } + return this.nutritionService.searchAllSources(query); + } + async addFood(body) { + try { + const food = await this.nutritionService.saveFoodToDb(body); + if (food) { + return { + success: true, + food_id: food.id, + name: food.name, + }; + } + else { + return { success: false }; + } + } + catch (err) { + console.error(err); + return { success: false }; + } + } + async addWater(req, res, body) { + try { + const amountMl = parseInt(body.amount_ml) || 250; + const date = body.date || new Date().toISOString().split('T')[0]; + await this.waterLogModel.create({ + UserId: req.user.id, + date: date, + amount_ml: amountMl, + time: new Date().toISOString(), + }); + await this.utilsService.updateDailySummary(req.user.id, date); + req.flash('success_msg', `Added ${amountMl}ml of water!`); + res.redirect('/dashboard'); + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error adding water'); + res.redirect('/dashboard'); + } + } + async addWeight(req, res, body) { + try { + const weightKg = parseFloat(body.weight_kg); + const date = body.date || new Date().toISOString().split('T')[0]; + const weightLog = await this.weightLogModel.findOne({ + where: { UserId: req.user.id, date: date }, + }); + if (weightLog) { + weightLog.weight_kg = weightKg; + weightLog.time = new Date().toISOString(); + await weightLog.save(); + } + else { + await this.weightLogModel.create({ + UserId: req.user.id, + date: date, + weight_kg: weightKg, + time: new Date().toISOString(), + }); + } + await this.utilsService.updateDailySummary(req.user.id, date); + res.redirect('/dashboard'); + } + catch (err) { + console.error(err); + req.flash('error_msg', 'Error adding weight'); + res.redirect('/dashboard'); + } + } +}; +exports.MealsController = MealsController; +__decorate([ + (0, common_1.Get)('add-meal'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Res)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object]), + __metadata("design:returntype", void 0) +], MealsController.prototype, "addMealPage", null); +__decorate([ + (0, common_1.Post)('add-meal'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Res)()), + __param(2, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object, Object]), + __metadata("design:returntype", Promise) +], MealsController.prototype, "addMeal", null); +__decorate([ + (0, common_1.Get)('api/search-food'), + __param(0, (0, common_1.Query)('q')), + __metadata("design:type", Function), + __metadata("design:paramtypes", [String]), + __metadata("design:returntype", Promise) +], MealsController.prototype, "searchFood", null); +__decorate([ + (0, common_1.Post)('api/add-food'), + __param(0, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], MealsController.prototype, "addFood", null); +__decorate([ + (0, common_1.Post)('add-water'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Res)()), + __param(2, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object, Object]), + __metadata("design:returntype", Promise) +], MealsController.prototype, "addWater", null); +__decorate([ + (0, common_1.Post)('add-weight'), + __param(0, (0, common_1.Req)()), + __param(1, (0, common_1.Res)()), + __param(2, (0, common_1.Body)()), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, Object, Object]), + __metadata("design:returntype", Promise) +], MealsController.prototype, "addWeight", null); +exports.MealsController = MealsController = __decorate([ + (0, common_1.Controller)(), + (0, common_1.UseGuards)(authenticated_guard_1.AuthenticatedGuard), + __param(2, (0, sequelize_1.InjectModel)(meal_model_1.Meal)), + __param(3, (0, sequelize_1.InjectModel)(meal_food_model_1.MealFood)), + __param(4, (0, sequelize_1.InjectModel)(food_item_model_1.FoodItem)), + __param(5, (0, sequelize_1.InjectModel)(water_log_model_1.WaterLog)), + __param(6, (0, sequelize_1.InjectModel)(weight_log_model_1.WeightLog)), + __metadata("design:paramtypes", [utils_service_1.UtilsService, + nutrition_service_1.NutritionService, Object, Object, Object, Object, Object]) +], MealsController); +//# sourceMappingURL=meals.controller.js.map \ No newline at end of file diff --git a/dist/meals/meals.controller.js.map b/dist/meals/meals.controller.js.map new file mode 100644 index 0000000..ea44b05 --- /dev/null +++ b/dist/meals/meals.controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"meals.controller.js","sourceRoot":"","sources":["../../src/meals/meals.controller.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/meals/meals.module.d.ts b/dist/meals/meals.module.d.ts new file mode 100644 index 0000000..de93d10 --- /dev/null +++ b/dist/meals/meals.module.d.ts @@ -0,0 +1,2 @@ +export declare class MealsModule { +} diff --git a/dist/meals/meals.module.js b/dist/meals/meals.module.js new file mode 100644 index 0000000..6472909 --- /dev/null +++ b/dist/meals/meals.module.js @@ -0,0 +1,39 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MealsModule = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const meals_controller_1 = require("./meals.controller"); +const nutrition_service_1 = require("./nutrition.service"); +const meal_model_1 = require("../models/meal.model"); +const meal_food_model_1 = require("../models/meal-food.model"); +const food_item_model_1 = require("../models/food-item.model"); +const water_log_model_1 = require("../models/water-log.model"); +const weight_log_model_1 = require("../models/weight-log.model"); +const api_cache_model_1 = require("../models/api-cache.model"); +let MealsModule = class MealsModule { +}; +exports.MealsModule = MealsModule; +exports.MealsModule = MealsModule = __decorate([ + (0, common_1.Module)({ + imports: [ + sequelize_1.SequelizeModule.forFeature([ + meal_model_1.Meal, + meal_food_model_1.MealFood, + food_item_model_1.FoodItem, + water_log_model_1.WaterLog, + weight_log_model_1.WeightLog, + api_cache_model_1.APICache, + ]), + ], + controllers: [meals_controller_1.MealsController], + providers: [nutrition_service_1.NutritionService], + }) +], MealsModule); +//# sourceMappingURL=meals.module.js.map \ No newline at end of file diff --git a/dist/meals/meals.module.js.map b/dist/meals/meals.module.js.map new file mode 100644 index 0000000..55ee7fa --- /dev/null +++ b/dist/meals/meals.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"meals.module.js","sourceRoot":"","sources":["../../src/meals/meals.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,iDAAoD;AACpD,yDAAqD;AACrD,2DAAuD;AACvD,qDAA4C;AAC5C,+DAAqD;AACrD,+DAAqD;AACrD,+DAAqD;AACrD,iEAAuD;AACvD,+DAAqD;AAgB9C,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IAdvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,2BAAe,CAAC,UAAU,CAAC;gBACzB,iBAAI;gBACJ,0BAAQ;gBACR,0BAAQ;gBACR,0BAAQ;gBACR,4BAAS;gBACT,0BAAQ;aACT,CAAC;SACH;QACD,WAAW,EAAE,CAAC,kCAAe,CAAC;QAC9B,SAAS,EAAE,CAAC,oCAAgB,CAAC;KAC9B,CAAC;GACW,WAAW,CAAG"} \ No newline at end of file diff --git a/dist/meals/nutrition.service.d.ts b/dist/meals/nutrition.service.d.ts new file mode 100644 index 0000000..93aab1f --- /dev/null +++ b/dist/meals/nutrition.service.d.ts @@ -0,0 +1,52 @@ +import { ConfigService } from '@nestjs/config'; +import { FoodItem } from '../models/food-item.model'; +import { APICache } from '../models/api-cache.model'; +export declare class NutritionService { + private configService; + private foodItemModel; + private apiCacheModel; + private apiKey; + private baseUrl; + private headers; + private cacheDurationDays; + constructor(configService: ConfigService, foodItemModel: typeof FoodItem, apiCacheModel: typeof APICache); + searchFood(query: string): Promise<{ + name: any; + calories: any; + protein_g: any; + carbs_g: any; + fat_g: any; + fiber_g: any; + sugar_g: any; + sodium_mg: any; + serving_size_g: any; + source: string; + }[]>; + _getFromCache(query: string): Promise<{ + name: any; + calories: any; + protein_g: any; + carbs_g: any; + fat_g: any; + fiber_g: any; + sugar_g: any; + sodium_mg: any; + serving_size_g: any; + source: string; + }[]>; + _saveToCache(query: string, source: string, data: any): Promise; + _parseApiResponse(data: any[]): { + name: any; + calories: any; + protein_g: any; + carbs_g: any; + fat_g: any; + fiber_g: any; + sugar_g: any; + sodium_mg: any; + serving_size_g: any; + source: string; + }[]; + saveFoodToDb(foodData: any): Promise; + searchAllSources(query: string): Promise; +} diff --git a/dist/meals/nutrition.service.js b/dist/meals/nutrition.service.js new file mode 100644 index 0000000..52e677e --- /dev/null +++ b/dist/meals/nutrition.service.js @@ -0,0 +1,215 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NutritionService = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const config_1 = require("@nestjs/config"); +const sequelize_2 = require("sequelize"); +const axios_1 = require("axios"); +const food_item_model_1 = require("../models/food-item.model"); +const api_cache_model_1 = require("../models/api-cache.model"); +let NutritionService = class NutritionService { + constructor(configService, foodItemModel, apiCacheModel) { + this.configService = configService; + this.foodItemModel = foodItemModel; + this.apiCacheModel = apiCacheModel; + this.apiKey = this.configService.get('API_NINJAS_KEY'); + this.baseUrl = 'https://api.api-ninjas.com/v1/nutrition'; + this.headers = { 'X-Api-Key': this.apiKey }; + this.cacheDurationDays = 30; + } + async searchFood(query) { + const cached = await this._getFromCache(query); + if (cached) { + return cached; + } + try { + if (!this.apiKey) { + console.warn('API_NINJAS_KEY is not set'); + return []; + } + const response = await axios_1.default.get(this.baseUrl, { + headers: this.headers, + params: { query: query }, + timeout: 10000, + }); + if (response.status === 200) { + const data = response.data; + await this._saveToCache(query, 'api_ninjas', data); + return this._parseApiResponse(data); + } + else { + console.error(`API Error: ${response.status}`); + return []; + } + } + catch (error) { + console.error(`API Request failed: ${error.message}`); + return []; + } + } + async _getFromCache(query) { + const cacheEntry = await this.apiCacheModel.findOne({ + where: { query: query.toLowerCase() }, + }); + if (cacheEntry) { + const age = (new Date().getTime() - new Date(cacheEntry.cached_at).getTime()) / (1000 * 60 * 60 * 24); + if (age < this.cacheDurationDays) { + const data = JSON.parse(cacheEntry.response_json); + return this._parseApiResponse(data); + } + } + return null; + } + async _saveToCache(query, source, data) { + try { + let cacheEntry = await this.apiCacheModel.findOne({ + where: { query: query.toLowerCase() }, + }); + if (cacheEntry) { + cacheEntry.response_json = JSON.stringify(data); + cacheEntry.cached_at = new Date(); + await cacheEntry.save(); + } + else { + await this.apiCacheModel.create({ + query: query.toLowerCase(), + api_source: source, + response_json: JSON.stringify(data), + cached_at: new Date(), + }); + } + } + catch (error) { + console.error(`Cache save failed: ${error.message}`); + } + } + _parseApiResponse(data) { + return data.map((item) => ({ + name: (item.name || '').replace(/\b\w/g, (l) => l.toUpperCase()), + calories: item.calories || 0, + protein_g: item.protein_g || 0, + carbs_g: item.carbohydrates_total_g || 0, + fat_g: item.fat_total_g || 0, + fiber_g: item.fiber_g || 0, + sugar_g: item.sugar_g || 0, + sodium_mg: item.sodium_mg || 0, + serving_size_g: item.serving_size_g || 100, + source: 'api_ninjas', + })); + } + async saveFoodToDb(foodData) { + try { + const existing = await this.foodItemModel.findOne({ + where: { + name: foodData.name, + source: foodData.source || 'api', + }, + }); + if (existing) { + return existing; + } + const food = await this.foodItemModel.create({ + name: foodData.name, + calories: foodData.calories, + protein_g: foodData.protein_g || 0, + carbs_g: foodData.carbs_g || 0, + fat_g: foodData.fat_g || 0, + fiber_g: foodData.fiber_g || 0, + sugar_g: foodData.sugar_g || 0, + sodium_mg: foodData.sodium_mg || 0, + serving_size_g: foodData.serving_size_g || 100, + serving_description: foodData.serving_description || '1 serving', + source: foodData.source || 'api', + api_data: JSON.stringify(foodData), + }); + return food; + } + catch (error) { + console.error(`Error saving food to DB: ${error.message}`); + return null; + } + } + async searchAllSources(query) { + const results = []; + const filipinoFoods = await this.foodItemModel.findAll({ + where: { + is_filipino: true, + [sequelize_2.Op.or]: [ + { name: { [sequelize_2.Op.like]: `%${query}%` } }, + { name_tagalog: { [sequelize_2.Op.like]: `%${query}%` } }, + ], + }, + limit: 5, + }); + for (const food of filipinoFoods) { + results.push({ + id: food.id, + name: food.name, + name_tagalog: food.name_tagalog, + calories: food.calories, + protein_g: food.protein_g, + carbs_g: food.carbs_g, + fat_g: food.fat_g, + serving_description: food.serving_description, + source: 'filipino', + category: food.category, + }); + } + const otherFoods = await this.foodItemModel.findAll({ + where: { + is_filipino: false, + name: { [sequelize_2.Op.like]: `%${query}%` }, + }, + limit: 5, + }); + for (const food of otherFoods) { + results.push({ + id: food.id, + name: food.name, + calories: food.calories, + protein_g: food.protein_g, + carbs_g: food.carbs_g, + fat_g: food.fat_g, + serving_description: food.serving_description, + source: food.source, + }); + } + if (results.length < 3 && this.apiKey) { + const apiResults = await this.searchFood(query); + for (const foodData of apiResults.slice(0, 5)) { + results.push({ + name: foodData.name, + calories: foodData.calories, + protein_g: foodData.protein_g, + carbs_g: foodData.carbs_g || 0, + fat_g: foodData.fat_g || 0, + serving_description: '100g', + source: 'api_ninjas', + raw_data: foodData, + }); + } + } + return results; + } +}; +exports.NutritionService = NutritionService; +exports.NutritionService = NutritionService = __decorate([ + (0, common_1.Injectable)(), + __param(1, (0, sequelize_1.InjectModel)(food_item_model_1.FoodItem)), + __param(2, (0, sequelize_1.InjectModel)(api_cache_model_1.APICache)), + __metadata("design:paramtypes", [config_1.ConfigService, Object, Object]) +], NutritionService); +//# sourceMappingURL=nutrition.service.js.map \ No newline at end of file diff --git a/dist/meals/nutrition.service.js.map b/dist/meals/nutrition.service.js.map new file mode 100644 index 0000000..b0f9a7f --- /dev/null +++ b/dist/meals/nutrition.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nutrition.service.js","sourceRoot":"","sources":["../../src/meals/nutrition.service.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/models/api-cache.model.d.ts b/dist/models/api-cache.model.d.ts new file mode 100644 index 0000000..c46b6c5 --- /dev/null +++ b/dist/models/api-cache.model.d.ts @@ -0,0 +1,7 @@ +import { Model } from 'sequelize-typescript'; +export declare class APICache extends Model { + query: string; + api_source: string; + response_json: string; + cached_at: Date; +} diff --git a/dist/models/api-cache.model.js b/dist/models/api-cache.model.js new file mode 100644 index 0000000..79d21f2 --- /dev/null +++ b/dist/models/api-cache.model.js @@ -0,0 +1,36 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.APICache = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +let APICache = class APICache extends sequelize_typescript_1.Model { +}; +exports.APICache = APICache; +__decorate([ + (0, sequelize_typescript_1.Column)({ unique: true, allowNull: false }), + __metadata("design:type", String) +], APICache.prototype, "query", void 0); +__decorate([ + sequelize_typescript_1.Column, + __metadata("design:type", String) +], APICache.prototype, "api_source", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.TEXT), + __metadata("design:type", String) +], APICache.prototype, "response_json", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: sequelize_typescript_1.DataType.NOW }), + __metadata("design:type", Date) +], APICache.prototype, "cached_at", void 0); +exports.APICache = APICache = __decorate([ + sequelize_typescript_1.Table +], APICache); +//# sourceMappingURL=api-cache.model.js.map \ No newline at end of file diff --git a/dist/models/api-cache.model.js.map b/dist/models/api-cache.model.js.map new file mode 100644 index 0000000..8d78b2d --- /dev/null +++ b/dist/models/api-cache.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"api-cache.model.js","sourceRoot":"","sources":["../../src/models/api-cache.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAAsE;AAG/D,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,4BAAK;CAYlC,CAAA;AAZY,4BAAQ;AAEnB;IADC,IAAA,6BAAM,EAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;uCAC7B;AAGd;IADC,6BAAM;;4CACY;AAGnB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,IAAI,CAAC;;+CACA;AAGtB;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,+BAAQ,CAAC,GAAG,EAAE,CAAC;8BAC5B,IAAI;2CAAC;mBAXL,QAAQ;IADpB,4BAAK;GACO,QAAQ,CAYpB"} \ No newline at end of file diff --git a/dist/models/daily-summary.model.d.ts b/dist/models/daily-summary.model.d.ts new file mode 100644 index 0000000..66385f8 --- /dev/null +++ b/dist/models/daily-summary.model.d.ts @@ -0,0 +1,15 @@ +import { Model } from 'sequelize-typescript'; +import { User } from './user.model'; +export declare class DailySummary extends Model { + UserId: number; + user: User; + date: Date; + total_calories: number; + total_protein_g: number; + total_carbs_g: number; + total_fat_g: number; + total_water_ml: number; + calories_remaining: number; + weight_kg: number; + notes: string; +} diff --git a/dist/models/daily-summary.model.js b/dist/models/daily-summary.model.js new file mode 100644 index 0000000..5bd2051 --- /dev/null +++ b/dist/models/daily-summary.model.js @@ -0,0 +1,66 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DailySummary = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +const user_model_1 = require("./user.model"); +let DailySummary = class DailySummary extends sequelize_typescript_1.Model { +}; +exports.DailySummary = DailySummary; +__decorate([ + (0, sequelize_typescript_1.ForeignKey)(() => user_model_1.User), + sequelize_typescript_1.Column, + __metadata("design:type", Number) +], DailySummary.prototype, "UserId", void 0); +__decorate([ + (0, sequelize_typescript_1.BelongsTo)(() => user_model_1.User), + __metadata("design:type", user_model_1.User) +], DailySummary.prototype, "user", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.DATEONLY, allowNull: false }), + __metadata("design:type", Date) +], DailySummary.prototype, "date", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0 }), + __metadata("design:type", Number) +], DailySummary.prototype, "total_calories", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0 }), + __metadata("design:type", Number) +], DailySummary.prototype, "total_protein_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0 }), + __metadata("design:type", Number) +], DailySummary.prototype, "total_carbs_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0 }), + __metadata("design:type", Number) +], DailySummary.prototype, "total_fat_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: 0 }), + __metadata("design:type", Number) +], DailySummary.prototype, "total_water_ml", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], DailySummary.prototype, "calories_remaining", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], DailySummary.prototype, "weight_kg", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.TEXT), + __metadata("design:type", String) +], DailySummary.prototype, "notes", void 0); +exports.DailySummary = DailySummary = __decorate([ + sequelize_typescript_1.Table +], DailySummary); +//# sourceMappingURL=daily-summary.model.js.map \ No newline at end of file diff --git a/dist/models/daily-summary.model.js.map b/dist/models/daily-summary.model.js.map new file mode 100644 index 0000000..96df149 --- /dev/null +++ b/dist/models/daily-summary.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"daily-summary.model.js","sourceRoot":"","sources":["../../src/models/daily-summary.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAA6F;AAC7F,6CAAoC;AAG7B,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,4BAAK;CAkCtC,CAAA;AAlCY,oCAAY;AAGvB;IAFC,IAAA,iCAAU,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;IACtB,6BAAM;;4CACQ;AAGf;IADC,IAAA,gCAAS,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;8BAChB,iBAAI;0CAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;8BAChD,IAAI;0CAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;oDAC3B;AAGvB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;qDAC1B;AAGxB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;mDAC5B;AAGtB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;iDAC9B;AAGpB;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;oDACL;AAGvB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;wDACI;AAG3B;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;+CACL;AAGlB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,IAAI,CAAC;;2CACR;uBAjCH,YAAY;IADxB,4BAAK;GACO,YAAY,CAkCxB"} \ No newline at end of file diff --git a/dist/models/food-item.model.d.ts b/dist/models/food-item.model.d.ts new file mode 100644 index 0000000..2c7baec --- /dev/null +++ b/dist/models/food-item.model.d.ts @@ -0,0 +1,24 @@ +import { Model } from 'sequelize-typescript'; +import { MealFood } from './meal-food.model'; +import { PlannedFood } from './planned-food.model'; +export declare class FoodItem extends Model { + name: string; + name_tagalog: string; + category: string; + calories: number; + protein_g: number; + carbs_g: number; + fat_g: number; + fiber_g: number; + sugar_g: number; + sodium_mg: number; + serving_size_g: number; + serving_description: string; + source: string; + is_filipino: boolean; + is_favorite: boolean; + api_data: string; + last_updated: Date; + mealFoods: MealFood[]; + plannedFoods: PlannedFood[]; +} diff --git a/dist/models/food-item.model.js b/dist/models/food-item.model.js new file mode 100644 index 0000000..f7eb74a --- /dev/null +++ b/dist/models/food-item.model.js @@ -0,0 +1,98 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FoodItem = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +const meal_food_model_1 = require("./meal-food.model"); +const planned_food_model_1 = require("./planned-food.model"); +let FoodItem = class FoodItem extends sequelize_typescript_1.Model { +}; +exports.FoodItem = FoodItem; +__decorate([ + (0, sequelize_typescript_1.Column)({ allowNull: false }), + __metadata("design:type", String) +], FoodItem.prototype, "name", void 0); +__decorate([ + sequelize_typescript_1.Column, + __metadata("design:type", String) +], FoodItem.prototype, "name_tagalog", void 0); +__decorate([ + sequelize_typescript_1.Column, + __metadata("design:type", String) +], FoodItem.prototype, "category", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, allowNull: false }), + __metadata("design:type", Number) +], FoodItem.prototype, "calories", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0 }), + __metadata("design:type", Number) +], FoodItem.prototype, "protein_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0 }), + __metadata("design:type", Number) +], FoodItem.prototype, "carbs_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0 }), + __metadata("design:type", Number) +], FoodItem.prototype, "fat_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0 }), + __metadata("design:type", Number) +], FoodItem.prototype, "fiber_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0 }), + __metadata("design:type", Number) +], FoodItem.prototype, "sugar_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0 }), + __metadata("design:type", Number) +], FoodItem.prototype, "sodium_mg", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 100 }), + __metadata("design:type", Number) +], FoodItem.prototype, "serving_size_g", void 0); +__decorate([ + sequelize_typescript_1.Column, + __metadata("design:type", String) +], FoodItem.prototype, "serving_description", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: 'manual' }), + __metadata("design:type", String) +], FoodItem.prototype, "source", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: false }), + __metadata("design:type", Boolean) +], FoodItem.prototype, "is_filipino", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: false }), + __metadata("design:type", Boolean) +], FoodItem.prototype, "is_favorite", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.TEXT), + __metadata("design:type", String) +], FoodItem.prototype, "api_data", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: sequelize_typescript_1.DataType.NOW }), + __metadata("design:type", Date) +], FoodItem.prototype, "last_updated", void 0); +__decorate([ + (0, sequelize_typescript_1.HasMany)(() => meal_food_model_1.MealFood), + __metadata("design:type", Array) +], FoodItem.prototype, "mealFoods", void 0); +__decorate([ + (0, sequelize_typescript_1.HasMany)(() => planned_food_model_1.PlannedFood), + __metadata("design:type", Array) +], FoodItem.prototype, "plannedFoods", void 0); +exports.FoodItem = FoodItem = __decorate([ + sequelize_typescript_1.Table +], FoodItem); +//# sourceMappingURL=food-item.model.js.map \ No newline at end of file diff --git a/dist/models/food-item.model.js.map b/dist/models/food-item.model.js.map new file mode 100644 index 0000000..62047ad --- /dev/null +++ b/dist/models/food-item.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"food-item.model.js","sourceRoot":"","sources":["../../src/models/food-item.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAA+E;AAC/E,uDAA6C;AAC7C,6DAAmD;AAG5C,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,4BAAK;CAyDlC,CAAA;AAzDY,4BAAQ;AAEnB;IADC,IAAA,6BAAM,EAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;sCAChB;AAGb;IADC,6BAAM;;8CACc;AAGrB;IADC,6BAAM;;0CACU;AAGjB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;0CAClC;AAGjB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;2CAChC;AAGlB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;yCAClC;AAGhB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;uCACpC;AAGd;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;yCAClC;AAGhB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;yCAClC;AAGhB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;;2CAChC;AAGlB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;;gDAC7B;AAGvB;IADC,6BAAM;;qDACqB;AAG5B;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;;wCACpB;AAGf;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;;6CACX;AAGrB;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;;6CACX;AAGrB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,IAAI,CAAC;;0CACL;AAGjB;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,+BAAQ,CAAC,GAAG,EAAE,CAAC;8BACzB,IAAI;8CAAC;AAGnB;IADC,IAAA,8BAAO,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;;2CACF;AAGtB;IADC,IAAA,8BAAO,EAAC,GAAG,EAAE,CAAC,gCAAW,CAAC;;8CACC;mBAxDjB,QAAQ;IADpB,4BAAK;GACO,QAAQ,CAyDpB"} \ No newline at end of file diff --git a/dist/models/meal-food.model.d.ts b/dist/models/meal-food.model.d.ts new file mode 100644 index 0000000..f138e22 --- /dev/null +++ b/dist/models/meal-food.model.d.ts @@ -0,0 +1,15 @@ +import { Model } from 'sequelize-typescript'; +import { Meal } from './meal.model'; +import { FoodItem } from './food-item.model'; +export declare class MealFood extends Model { + MealId: number; + meal: Meal; + FoodItemId: number; + foodItem: FoodItem; + quantity: number; + quantity_grams: number; + calories_consumed: number; + protein_consumed: number; + carbs_consumed: number; + fat_consumed: number; +} diff --git a/dist/models/meal-food.model.js b/dist/models/meal-food.model.js new file mode 100644 index 0000000..93a1a13 --- /dev/null +++ b/dist/models/meal-food.model.js @@ -0,0 +1,64 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MealFood = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +const meal_model_1 = require("./meal.model"); +const food_item_model_1 = require("./food-item.model"); +let MealFood = class MealFood extends sequelize_typescript_1.Model { +}; +exports.MealFood = MealFood; +__decorate([ + (0, sequelize_typescript_1.ForeignKey)(() => meal_model_1.Meal), + sequelize_typescript_1.Column, + __metadata("design:type", Number) +], MealFood.prototype, "MealId", void 0); +__decorate([ + (0, sequelize_typescript_1.BelongsTo)(() => meal_model_1.Meal), + __metadata("design:type", meal_model_1.Meal) +], MealFood.prototype, "meal", void 0); +__decorate([ + (0, sequelize_typescript_1.ForeignKey)(() => food_item_model_1.FoodItem), + sequelize_typescript_1.Column, + __metadata("design:type", Number) +], MealFood.prototype, "FoodItemId", void 0); +__decorate([ + (0, sequelize_typescript_1.BelongsTo)(() => food_item_model_1.FoodItem), + __metadata("design:type", food_item_model_1.FoodItem) +], MealFood.prototype, "foodItem", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, allowNull: false, defaultValue: 1.0 }), + __metadata("design:type", Number) +], MealFood.prototype, "quantity", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], MealFood.prototype, "quantity_grams", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], MealFood.prototype, "calories_consumed", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], MealFood.prototype, "protein_consumed", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], MealFood.prototype, "carbs_consumed", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], MealFood.prototype, "fat_consumed", void 0); +exports.MealFood = MealFood = __decorate([ + sequelize_typescript_1.Table +], MealFood); +//# sourceMappingURL=meal-food.model.js.map \ No newline at end of file diff --git a/dist/models/meal-food.model.js.map b/dist/models/meal-food.model.js.map new file mode 100644 index 0000000..1780ae7 --- /dev/null +++ b/dist/models/meal-food.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"meal-food.model.js","sourceRoot":"","sources":["../../src/models/meal-food.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAA6F;AAC7F,6CAAoC;AACpC,uDAA6C;AAGtC,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,4BAAK;CAgClC,CAAA;AAhCY,4BAAQ;AAGnB;IAFC,IAAA,iCAAU,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;IACtB,6BAAM;;wCACQ;AAGf;IADC,IAAA,gCAAS,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;8BAChB,iBAAI;sCAAC;AAIX;IAFC,IAAA,iCAAU,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;IAC1B,6BAAM;;4CACY;AAGnB;IADC,IAAA,gCAAS,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;8BAChB,0BAAQ;0CAAC;AAGnB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;;0CACrD;AAGjB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;gDACA;AAGvB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;mDACG;AAG1B;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;kDACE;AAGzB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;gDACA;AAGvB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;8CACF;mBA/BV,QAAQ;IADpB,4BAAK;GACO,QAAQ,CAgCpB"} \ No newline at end of file diff --git a/dist/models/meal-plan.model.d.ts b/dist/models/meal-plan.model.d.ts new file mode 100644 index 0000000..a6aa3f0 --- /dev/null +++ b/dist/models/meal-plan.model.d.ts @@ -0,0 +1,12 @@ +import { Model } from 'sequelize-typescript'; +import { User } from './user.model'; +import { PlannedFood } from './planned-food.model'; +export declare class MealPlan extends Model { + UserId: number; + user: User; + date: Date; + meal_type: string; + is_completed: boolean; + notes: string; + plannedFoods: PlannedFood[]; +} diff --git a/dist/models/meal-plan.model.js b/dist/models/meal-plan.model.js new file mode 100644 index 0000000..0f13bcd --- /dev/null +++ b/dist/models/meal-plan.model.js @@ -0,0 +1,51 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MealPlan = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +const user_model_1 = require("./user.model"); +const planned_food_model_1 = require("./planned-food.model"); +let MealPlan = class MealPlan extends sequelize_typescript_1.Model { +}; +exports.MealPlan = MealPlan; +__decorate([ + (0, sequelize_typescript_1.ForeignKey)(() => user_model_1.User), + sequelize_typescript_1.Column, + __metadata("design:type", Number) +], MealPlan.prototype, "UserId", void 0); +__decorate([ + (0, sequelize_typescript_1.BelongsTo)(() => user_model_1.User), + __metadata("design:type", user_model_1.User) +], MealPlan.prototype, "user", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.DATEONLY, allowNull: false }), + __metadata("design:type", Date) +], MealPlan.prototype, "date", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ allowNull: false }), + __metadata("design:type", String) +], MealPlan.prototype, "meal_type", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: false }), + __metadata("design:type", Boolean) +], MealPlan.prototype, "is_completed", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.TEXT), + __metadata("design:type", String) +], MealPlan.prototype, "notes", void 0); +__decorate([ + (0, sequelize_typescript_1.HasMany)(() => planned_food_model_1.PlannedFood), + __metadata("design:type", Array) +], MealPlan.prototype, "plannedFoods", void 0); +exports.MealPlan = MealPlan = __decorate([ + sequelize_typescript_1.Table +], MealPlan); +//# sourceMappingURL=meal-plan.model.js.map \ No newline at end of file diff --git a/dist/models/meal-plan.model.js.map b/dist/models/meal-plan.model.js.map new file mode 100644 index 0000000..2ec1020 --- /dev/null +++ b/dist/models/meal-plan.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"meal-plan.model.js","sourceRoot":"","sources":["../../src/models/meal-plan.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAAsG;AACtG,6CAAoC;AACpC,6DAAmD;AAG5C,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,4BAAK;CAsBlC,CAAA;AAtBY,4BAAQ;AAGnB;IAFC,IAAA,iCAAU,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;IACtB,6BAAM;;wCACQ;AAGf;IADC,IAAA,gCAAS,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;8BAChB,iBAAI;sCAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;8BAChD,IAAI;sCAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;2CACX;AAGlB;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;;8CACV;AAGtB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,IAAI,CAAC;;uCACR;AAGd;IADC,IAAA,8BAAO,EAAC,GAAG,EAAE,CAAC,gCAAW,CAAC;;8CACC;mBArBjB,QAAQ;IADpB,4BAAK;GACO,QAAQ,CAsBpB"} \ No newline at end of file diff --git a/dist/models/meal.model.d.ts b/dist/models/meal.model.d.ts new file mode 100644 index 0000000..f0824ad --- /dev/null +++ b/dist/models/meal.model.d.ts @@ -0,0 +1,12 @@ +import { Model } from 'sequelize-typescript'; +import { User } from './user.model'; +import { MealFood } from './meal-food.model'; +export declare class Meal extends Model { + UserId: number; + user: User; + date: Date; + meal_type: string; + time: string; + notes: string; + mealFoods: MealFood[]; +} diff --git a/dist/models/meal.model.js b/dist/models/meal.model.js new file mode 100644 index 0000000..c6b9fa4 --- /dev/null +++ b/dist/models/meal.model.js @@ -0,0 +1,51 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Meal = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +const user_model_1 = require("./user.model"); +const meal_food_model_1 = require("./meal-food.model"); +let Meal = class Meal extends sequelize_typescript_1.Model { +}; +exports.Meal = Meal; +__decorate([ + (0, sequelize_typescript_1.ForeignKey)(() => user_model_1.User), + sequelize_typescript_1.Column, + __metadata("design:type", Number) +], Meal.prototype, "UserId", void 0); +__decorate([ + (0, sequelize_typescript_1.BelongsTo)(() => user_model_1.User), + __metadata("design:type", user_model_1.User) +], Meal.prototype, "user", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.DATEONLY, allowNull: false, defaultValue: sequelize_typescript_1.DataType.NOW }), + __metadata("design:type", Date) +], Meal.prototype, "date", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ allowNull: false }), + __metadata("design:type", String) +], Meal.prototype, "meal_type", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.TIME), + __metadata("design:type", String) +], Meal.prototype, "time", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.TEXT), + __metadata("design:type", String) +], Meal.prototype, "notes", void 0); +__decorate([ + (0, sequelize_typescript_1.HasMany)(() => meal_food_model_1.MealFood), + __metadata("design:type", Array) +], Meal.prototype, "mealFoods", void 0); +exports.Meal = Meal = __decorate([ + sequelize_typescript_1.Table +], Meal); +//# sourceMappingURL=meal.model.js.map \ No newline at end of file diff --git a/dist/models/meal.model.js.map b/dist/models/meal.model.js.map new file mode 100644 index 0000000..d7b14fa --- /dev/null +++ b/dist/models/meal.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"meal.model.js","sourceRoot":"","sources":["../../src/models/meal.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAAsG;AACtG,6CAAoC;AACpC,uDAA6C;AAGtC,IAAM,IAAI,GAAV,MAAM,IAAK,SAAQ,4BAAK;CAsB9B,CAAA;AAtBY,oBAAI;AAGf;IAFC,IAAA,iCAAU,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;IACtB,6BAAM;;oCACQ;AAGf;IADC,IAAA,gCAAS,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;8BAChB,iBAAI;kCAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,+BAAQ,CAAC,GAAG,EAAE,CAAC;8BAC5E,IAAI;kCAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;uCACX;AAGlB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,IAAI,CAAC;;kCACT;AAGb;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,IAAI,CAAC;;mCACR;AAGd;IADC,IAAA,8BAAO,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;;uCACF;eArBX,IAAI;IADhB,4BAAK;GACO,IAAI,CAsBhB"} \ No newline at end of file diff --git a/dist/models/planned-food.model.d.ts b/dist/models/planned-food.model.d.ts new file mode 100644 index 0000000..d7edfed --- /dev/null +++ b/dist/models/planned-food.model.d.ts @@ -0,0 +1,10 @@ +import { Model } from 'sequelize-typescript'; +import { MealPlan } from './meal-plan.model'; +import { FoodItem } from './food-item.model'; +export declare class PlannedFood extends Model { + MealPlanId: number; + mealPlan: MealPlan; + FoodItemId: number; + foodItem: FoodItem; + quantity: number; +} diff --git a/dist/models/planned-food.model.js b/dist/models/planned-food.model.js new file mode 100644 index 0000000..8a98f94 --- /dev/null +++ b/dist/models/planned-food.model.js @@ -0,0 +1,44 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PlannedFood = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +const meal_plan_model_1 = require("./meal-plan.model"); +const food_item_model_1 = require("./food-item.model"); +let PlannedFood = class PlannedFood extends sequelize_typescript_1.Model { +}; +exports.PlannedFood = PlannedFood; +__decorate([ + (0, sequelize_typescript_1.ForeignKey)(() => meal_plan_model_1.MealPlan), + sequelize_typescript_1.Column, + __metadata("design:type", Number) +], PlannedFood.prototype, "MealPlanId", void 0); +__decorate([ + (0, sequelize_typescript_1.BelongsTo)(() => meal_plan_model_1.MealPlan), + __metadata("design:type", meal_plan_model_1.MealPlan) +], PlannedFood.prototype, "mealPlan", void 0); +__decorate([ + (0, sequelize_typescript_1.ForeignKey)(() => food_item_model_1.FoodItem), + sequelize_typescript_1.Column, + __metadata("design:type", Number) +], PlannedFood.prototype, "FoodItemId", void 0); +__decorate([ + (0, sequelize_typescript_1.BelongsTo)(() => food_item_model_1.FoodItem), + __metadata("design:type", food_item_model_1.FoodItem) +], PlannedFood.prototype, "foodItem", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, allowNull: false, defaultValue: 1.0 }), + __metadata("design:type", Number) +], PlannedFood.prototype, "quantity", void 0); +exports.PlannedFood = PlannedFood = __decorate([ + sequelize_typescript_1.Table +], PlannedFood); +//# sourceMappingURL=planned-food.model.js.map \ No newline at end of file diff --git a/dist/models/planned-food.model.js.map b/dist/models/planned-food.model.js.map new file mode 100644 index 0000000..7fffc60 --- /dev/null +++ b/dist/models/planned-food.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"planned-food.model.js","sourceRoot":"","sources":["../../src/models/planned-food.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAA6F;AAC7F,uDAA6C;AAC7C,uDAA6C;AAGtC,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,4BAAK;CAiBrC,CAAA;AAjBY,kCAAW;AAGtB;IAFC,IAAA,iCAAU,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;IAC1B,6BAAM;;+CACY;AAGnB;IADC,IAAA,gCAAS,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;8BAChB,0BAAQ;6CAAC;AAInB;IAFC,IAAA,iCAAU,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;IAC1B,6BAAM;;+CACY;AAGnB;IADC,IAAA,gCAAS,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;8BAChB,0BAAQ;6CAAC;AAGnB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;;6CACrD;sBAhBN,WAAW;IADvB,4BAAK;GACO,WAAW,CAiBvB"} \ No newline at end of file diff --git a/dist/models/user-goal.model.d.ts b/dist/models/user-goal.model.d.ts new file mode 100644 index 0000000..6d9cf44 --- /dev/null +++ b/dist/models/user-goal.model.d.ts @@ -0,0 +1,13 @@ +import { Model } from 'sequelize-typescript'; +import { User } from './user.model'; +export declare class UserGoal extends Model { + UserId: number; + user: User; + goal_type: string; + target_weight_kg: number; + weekly_goal_kg: number; + target_protein_g: number; + target_carbs_g: number; + target_fat_g: number; + target_water_ml: number; +} diff --git a/dist/models/user-goal.model.js b/dist/models/user-goal.model.js new file mode 100644 index 0000000..0aa6d55 --- /dev/null +++ b/dist/models/user-goal.model.js @@ -0,0 +1,58 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UserGoal = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +const user_model_1 = require("./user.model"); +let UserGoal = class UserGoal extends sequelize_typescript_1.Model { +}; +exports.UserGoal = UserGoal; +__decorate([ + (0, sequelize_typescript_1.ForeignKey)(() => user_model_1.User), + sequelize_typescript_1.Column, + __metadata("design:type", Number) +], UserGoal.prototype, "UserId", void 0); +__decorate([ + (0, sequelize_typescript_1.BelongsTo)(() => user_model_1.User), + __metadata("design:type", user_model_1.User) +], UserGoal.prototype, "user", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: 'recomp' }), + __metadata("design:type", String) +], UserGoal.prototype, "goal_type", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], UserGoal.prototype, "target_weight_kg", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, defaultValue: 0.5 }), + __metadata("design:type", Number) +], UserGoal.prototype, "weekly_goal_kg", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: 150 }), + __metadata("design:type", Number) +], UserGoal.prototype, "target_protein_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: 200 }), + __metadata("design:type", Number) +], UserGoal.prototype, "target_carbs_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: 60 }), + __metadata("design:type", Number) +], UserGoal.prototype, "target_fat_g", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: 2000 }), + __metadata("design:type", Number) +], UserGoal.prototype, "target_water_ml", void 0); +exports.UserGoal = UserGoal = __decorate([ + sequelize_typescript_1.Table +], UserGoal); +//# sourceMappingURL=user-goal.model.js.map \ No newline at end of file diff --git a/dist/models/user-goal.model.js.map b/dist/models/user-goal.model.js.map new file mode 100644 index 0000000..874a4f7 --- /dev/null +++ b/dist/models/user-goal.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"user-goal.model.js","sourceRoot":"","sources":["../../src/models/user-goal.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAA6F;AAC7F,6CAAoC;AAG7B,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,4BAAK;CA4BlC,CAAA;AA5BY,4BAAQ;AAGnB;IAFC,IAAA,iCAAU,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;IACtB,6BAAM;;wCACQ;AAGf;IADC,IAAA,gCAAS,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;8BAChB,iBAAI;sCAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;;2CACjB;AAGlB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;kDACE;AAGzB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;;gDAC7B;AAGvB;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;;kDACL;AAGzB;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;;gDACP;AAGvB;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;;8CACR;AAGrB;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;;iDACP;mBA3Bb,QAAQ;IADpB,4BAAK;GACO,QAAQ,CA4BpB"} \ No newline at end of file diff --git a/dist/models/user.model.d.ts b/dist/models/user.model.d.ts new file mode 100644 index 0000000..b76a2cc --- /dev/null +++ b/dist/models/user.model.d.ts @@ -0,0 +1,26 @@ +import { Model } from 'sequelize-typescript'; +import { Meal } from './meal.model'; +import { WeightLog } from './weight-log.model'; +import { WaterLog } from './water-log.model'; +import { MealPlan } from './meal-plan.model'; +import { UserGoal } from './user-goal.model'; +import { DailySummary } from './daily-summary.model'; +export declare class User extends Model { + username: string; + password: string; + name: string; + age: number; + gender: string; + height_cm: number; + weight_kg: number; + activity_level: string; + target_daily_calories: number; + meals: Meal[]; + weightLogs: WeightLog[]; + waterLogs: WaterLog[]; + mealPlans: MealPlan[]; + goal: UserGoal; + dailySummaries: DailySummary[]; + validPassword(password: string): boolean; + static hashPassword(user: User): Promise; +} diff --git a/dist/models/user.model.js b/dist/models/user.model.js new file mode 100644 index 0000000..3b2a873 --- /dev/null +++ b/dist/models/user.model.js @@ -0,0 +1,101 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.User = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +const bcrypt = require("bcryptjs"); +const meal_model_1 = require("./meal.model"); +const weight_log_model_1 = require("./weight-log.model"); +const water_log_model_1 = require("./water-log.model"); +const meal_plan_model_1 = require("./meal-plan.model"); +const user_goal_model_1 = require("./user-goal.model"); +const daily_summary_model_1 = require("./daily-summary.model"); +let User = class User extends sequelize_typescript_1.Model { + validPassword(password) { + return bcrypt.compareSync(password, this.password); + } + static async hashPassword(user) { + if (user.password) { + user.password = await bcrypt.hash(user.password, 10); + } + } +}; +exports.User = User; +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.STRING(80), unique: true, allowNull: false }), + __metadata("design:type", String) +], User.prototype, "username", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.STRING(200), allowNull: false }), + __metadata("design:type", String) +], User.prototype, "password", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.STRING(100)), + __metadata("design:type", String) +], User.prototype, "name", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.INTEGER), + __metadata("design:type", Number) +], User.prototype, "age", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.STRING(10)), + __metadata("design:type", String) +], User.prototype, "gender", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], User.prototype, "height_cm", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], User.prototype, "weight_kg", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.STRING(20), defaultValue: 'moderate' }), + __metadata("design:type", String) +], User.prototype, "activity_level", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.INTEGER, defaultValue: 2000 }), + __metadata("design:type", Number) +], User.prototype, "target_daily_calories", void 0); +__decorate([ + (0, sequelize_typescript_1.HasMany)(() => meal_model_1.Meal), + __metadata("design:type", Array) +], User.prototype, "meals", void 0); +__decorate([ + (0, sequelize_typescript_1.HasMany)(() => weight_log_model_1.WeightLog), + __metadata("design:type", Array) +], User.prototype, "weightLogs", void 0); +__decorate([ + (0, sequelize_typescript_1.HasMany)(() => water_log_model_1.WaterLog), + __metadata("design:type", Array) +], User.prototype, "waterLogs", void 0); +__decorate([ + (0, sequelize_typescript_1.HasMany)(() => meal_plan_model_1.MealPlan), + __metadata("design:type", Array) +], User.prototype, "mealPlans", void 0); +__decorate([ + (0, sequelize_typescript_1.HasOne)(() => user_goal_model_1.UserGoal), + __metadata("design:type", user_goal_model_1.UserGoal) +], User.prototype, "goal", void 0); +__decorate([ + (0, sequelize_typescript_1.HasMany)(() => daily_summary_model_1.DailySummary), + __metadata("design:type", Array) +], User.prototype, "dailySummaries", void 0); +__decorate([ + sequelize_typescript_1.BeforeCreate, + __metadata("design:type", Function), + __metadata("design:paramtypes", [User]), + __metadata("design:returntype", Promise) +], User, "hashPassword", null); +exports.User = User = __decorate([ + sequelize_typescript_1.Table +], User); +//# sourceMappingURL=user.model.js.map \ No newline at end of file diff --git a/dist/models/user.model.js.map b/dist/models/user.model.js.map new file mode 100644 index 0000000..9d2aa62 --- /dev/null +++ b/dist/models/user.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"user.model.js","sourceRoot":"","sources":["../../src/models/user.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAAqG;AACrG,mCAAmC;AACnC,6CAAoC;AACpC,yDAA+C;AAC/C,uDAA6C;AAC7C,uDAA6C;AAC7C,uDAA6C;AAC7C,+DAAqD;AAG9C,IAAM,IAAI,GAAV,MAAM,IAAK,SAAQ,4BAAK;IA8C7B,aAAa,CAAC,QAAgB;QAC5B,OAAO,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC;IAGY,AAAb,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAU;QAClC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF,CAAA;AAxDY,oBAAI;AAEf;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;sCACrD;AAGjB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;sCACxC;AAGjB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;;kCAChB;AAGb;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,OAAO,CAAC;;iCACb;AAGZ;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;;oCACb;AAGf;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;uCACL;AAGlB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;uCACL;AAGlB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;;4CACzC;AAGvB;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;;mDACzB;AAG9B;IADC,IAAA,8BAAO,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;;mCACN;AAGd;IADC,IAAA,8BAAO,EAAC,GAAG,EAAE,CAAC,4BAAS,CAAC;;wCACD;AAGxB;IADC,IAAA,8BAAO,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;;uCACF;AAGtB;IADC,IAAA,8BAAO,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;;uCACF;AAGtB;IADC,IAAA,6BAAM,EAAC,GAAG,EAAE,CAAC,0BAAQ,CAAC;8BACjB,0BAAQ;kCAAC;AAGf;IADC,IAAA,8BAAO,EAAC,GAAG,EAAE,CAAC,kCAAY,CAAC;;4CACG;AAOlB;IADZ,mCAAY;;qCACmB,IAAI;;8BAInC;eAvDU,IAAI;IADhB,4BAAK;GACO,IAAI,CAwDhB"} \ No newline at end of file diff --git a/dist/models/water-log.model.d.ts b/dist/models/water-log.model.d.ts new file mode 100644 index 0000000..c9779f9 --- /dev/null +++ b/dist/models/water-log.model.d.ts @@ -0,0 +1,9 @@ +import { Model } from 'sequelize-typescript'; +import { User } from './user.model'; +export declare class WaterLog extends Model { + UserId: number; + user: User; + date: Date; + amount_ml: number; + time: string; +} diff --git a/dist/models/water-log.model.js b/dist/models/water-log.model.js new file mode 100644 index 0000000..4ef0857 --- /dev/null +++ b/dist/models/water-log.model.js @@ -0,0 +1,42 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WaterLog = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +const user_model_1 = require("./user.model"); +let WaterLog = class WaterLog extends sequelize_typescript_1.Model { +}; +exports.WaterLog = WaterLog; +__decorate([ + (0, sequelize_typescript_1.ForeignKey)(() => user_model_1.User), + sequelize_typescript_1.Column, + __metadata("design:type", Number) +], WaterLog.prototype, "UserId", void 0); +__decorate([ + (0, sequelize_typescript_1.BelongsTo)(() => user_model_1.User), + __metadata("design:type", user_model_1.User) +], WaterLog.prototype, "user", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.DATEONLY, allowNull: false, defaultValue: sequelize_typescript_1.DataType.NOW }), + __metadata("design:type", Date) +], WaterLog.prototype, "date", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ allowNull: false }), + __metadata("design:type", Number) +], WaterLog.prototype, "amount_ml", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: sequelize_typescript_1.DataType.NOW }), + __metadata("design:type", String) +], WaterLog.prototype, "time", void 0); +exports.WaterLog = WaterLog = __decorate([ + sequelize_typescript_1.Table +], WaterLog); +//# sourceMappingURL=water-log.model.js.map \ No newline at end of file diff --git a/dist/models/water-log.model.js.map b/dist/models/water-log.model.js.map new file mode 100644 index 0000000..ee746e9 --- /dev/null +++ b/dist/models/water-log.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"water-log.model.js","sourceRoot":"","sources":["../../src/models/water-log.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAA6F;AAC7F,6CAAoC;AAG7B,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,4BAAK;CAgBlC,CAAA;AAhBY,4BAAQ;AAGnB;IAFC,IAAA,iCAAU,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;IACtB,6BAAM;;wCACQ;AAGf;IADC,IAAA,gCAAS,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;8BAChB,iBAAI;sCAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,+BAAQ,CAAC,GAAG,EAAE,CAAC;8BAC5E,IAAI;sCAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;2CACX;AAGlB;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,+BAAQ,CAAC,GAAG,EAAE,CAAC;;sCAC1B;mBAfF,QAAQ;IADpB,4BAAK;GACO,QAAQ,CAgBpB"} \ No newline at end of file diff --git a/dist/models/weight-log.model.d.ts b/dist/models/weight-log.model.d.ts new file mode 100644 index 0000000..1c75597 --- /dev/null +++ b/dist/models/weight-log.model.d.ts @@ -0,0 +1,11 @@ +import { Model } from 'sequelize-typescript'; +import { User } from './user.model'; +export declare class WeightLog extends Model { + UserId: number; + user: User; + date: Date; + weight_kg: number; + body_fat_percentage: number; + notes: string; + time: string; +} diff --git a/dist/models/weight-log.model.js b/dist/models/weight-log.model.js new file mode 100644 index 0000000..aa0bcd4 --- /dev/null +++ b/dist/models/weight-log.model.js @@ -0,0 +1,50 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WeightLog = void 0; +const sequelize_typescript_1 = require("sequelize-typescript"); +const user_model_1 = require("./user.model"); +let WeightLog = class WeightLog extends sequelize_typescript_1.Model { +}; +exports.WeightLog = WeightLog; +__decorate([ + (0, sequelize_typescript_1.ForeignKey)(() => user_model_1.User), + sequelize_typescript_1.Column, + __metadata("design:type", Number) +], WeightLog.prototype, "UserId", void 0); +__decorate([ + (0, sequelize_typescript_1.BelongsTo)(() => user_model_1.User), + __metadata("design:type", user_model_1.User) +], WeightLog.prototype, "user", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.DATEONLY, allowNull: false, defaultValue: sequelize_typescript_1.DataType.NOW }), + __metadata("design:type", Date) +], WeightLog.prototype, "date", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ type: sequelize_typescript_1.DataType.FLOAT, allowNull: false }), + __metadata("design:type", Number) +], WeightLog.prototype, "weight_kg", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.FLOAT), + __metadata("design:type", Number) +], WeightLog.prototype, "body_fat_percentage", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.TEXT), + __metadata("design:type", String) +], WeightLog.prototype, "notes", void 0); +__decorate([ + (0, sequelize_typescript_1.Column)({ defaultValue: sequelize_typescript_1.DataType.NOW }), + __metadata("design:type", String) +], WeightLog.prototype, "time", void 0); +exports.WeightLog = WeightLog = __decorate([ + sequelize_typescript_1.Table +], WeightLog); +//# sourceMappingURL=weight-log.model.js.map \ No newline at end of file diff --git a/dist/models/weight-log.model.js.map b/dist/models/weight-log.model.js.map new file mode 100644 index 0000000..1d7f296 --- /dev/null +++ b/dist/models/weight-log.model.js.map @@ -0,0 +1 @@ +{"version":3,"file":"weight-log.model.js","sourceRoot":"","sources":["../../src/models/weight-log.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+DAA6F;AAC7F,6CAAoC;AAG7B,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,4BAAK;CAsBnC,CAAA;AAtBY,8BAAS;AAGpB;IAFC,IAAA,iCAAU,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;IACtB,6BAAM;;yCACQ;AAGf;IADC,IAAA,gCAAS,EAAC,GAAG,EAAE,CAAC,iBAAI,CAAC;8BAChB,iBAAI;uCAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,+BAAQ,CAAC,GAAG,EAAE,CAAC;8BAC5E,IAAI;uCAAC;AAGX;IADC,IAAA,6BAAM,EAAC,EAAE,IAAI,EAAE,+BAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;4CACjC;AAGlB;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,KAAK,CAAC;;sDACK;AAG5B;IADC,IAAA,6BAAM,EAAC,+BAAQ,CAAC,IAAI,CAAC;;wCACR;AAGd;IADC,IAAA,6BAAM,EAAC,EAAE,YAAY,EAAE,+BAAQ,CAAC,GAAG,EAAE,CAAC;;uCAC1B;oBArBF,SAAS;IADrB,4BAAK;GACO,SAAS,CAsBrB"} \ No newline at end of file diff --git a/dist/tsconfig.tsbuildinfo b/dist/tsconfig.tsbuildinfo new file mode 100644 index 0000000..ee8cf7c --- /dev/null +++ b/dist/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2016.d.ts","../node_modules/typescript/lib/lib.es2017.d.ts","../node_modules/typescript/lib/lib.es2018.d.ts","../node_modules/typescript/lib/lib.es2019.d.ts","../node_modules/typescript/lib/lib.es2020.d.ts","../node_modules/typescript/lib/lib.dom.d.ts","../node_modules/typescript/lib/lib.dom.iterable.d.ts","../node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../node_modules/typescript/lib/lib.scripthost.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../node_modules/typescript/lib/lib.es2016.intl.d.ts","../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../node_modules/typescript/lib/lib.es2017.date.d.ts","../node_modules/typescript/lib/lib.es2017.object.d.ts","../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2017.string.d.ts","../node_modules/typescript/lib/lib.es2017.intl.d.ts","../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../node_modules/typescript/lib/lib.es2018.intl.d.ts","../node_modules/typescript/lib/lib.es2018.promise.d.ts","../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../node_modules/typescript/lib/lib.es2019.array.d.ts","../node_modules/typescript/lib/lib.es2019.object.d.ts","../node_modules/typescript/lib/lib.es2019.string.d.ts","../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../node_modules/typescript/lib/lib.es2019.intl.d.ts","../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../node_modules/typescript/lib/lib.es2020.date.d.ts","../node_modules/typescript/lib/lib.es2020.promise.d.ts","../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2020.string.d.ts","../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2020.intl.d.ts","../node_modules/typescript/lib/lib.es2020.number.d.ts","../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../node_modules/typescript/lib/lib.esnext.float16.d.ts","../node_modules/typescript/lib/lib.decorators.d.ts","../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../node_modules/typescript/lib/lib.es2017.full.d.ts","../node_modules/reflect-metadata/index.d.ts","../node_modules/@nestjs/common/decorators/core/bind.decorator.d.ts","../node_modules/@nestjs/common/interfaces/abstract.interface.d.ts","../node_modules/@nestjs/common/interfaces/controllers/controller-metadata.interface.d.ts","../node_modules/@nestjs/common/interfaces/controllers/controller.interface.d.ts","../node_modules/@nestjs/common/interfaces/features/arguments-host.interface.d.ts","../node_modules/@nestjs/common/interfaces/exceptions/exception-filter.interface.d.ts","../node_modules/rxjs/dist/types/internal/subscription.d.ts","../node_modules/rxjs/dist/types/internal/subscriber.d.ts","../node_modules/rxjs/dist/types/internal/operator.d.ts","../node_modules/rxjs/dist/types/internal/observable.d.ts","../node_modules/rxjs/dist/types/internal/types.d.ts","../node_modules/rxjs/dist/types/internal/operators/audit.d.ts","../node_modules/rxjs/dist/types/internal/operators/audittime.d.ts","../node_modules/rxjs/dist/types/internal/operators/buffer.d.ts","../node_modules/rxjs/dist/types/internal/operators/buffercount.d.ts","../node_modules/rxjs/dist/types/internal/operators/buffertime.d.ts","../node_modules/rxjs/dist/types/internal/operators/buffertoggle.d.ts","../node_modules/rxjs/dist/types/internal/operators/bufferwhen.d.ts","../node_modules/rxjs/dist/types/internal/operators/catcherror.d.ts","../node_modules/rxjs/dist/types/internal/operators/combinelatestall.d.ts","../node_modules/rxjs/dist/types/internal/operators/combineall.d.ts","../node_modules/rxjs/dist/types/internal/operators/combinelatest.d.ts","../node_modules/rxjs/dist/types/internal/operators/combinelatestwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/concat.d.ts","../node_modules/rxjs/dist/types/internal/operators/concatall.d.ts","../node_modules/rxjs/dist/types/internal/operators/concatmap.d.ts","../node_modules/rxjs/dist/types/internal/operators/concatmapto.d.ts","../node_modules/rxjs/dist/types/internal/operators/concatwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/connect.d.ts","../node_modules/rxjs/dist/types/internal/operators/count.d.ts","../node_modules/rxjs/dist/types/internal/operators/debounce.d.ts","../node_modules/rxjs/dist/types/internal/operators/debouncetime.d.ts","../node_modules/rxjs/dist/types/internal/operators/defaultifempty.d.ts","../node_modules/rxjs/dist/types/internal/operators/delay.d.ts","../node_modules/rxjs/dist/types/internal/operators/delaywhen.d.ts","../node_modules/rxjs/dist/types/internal/operators/dematerialize.d.ts","../node_modules/rxjs/dist/types/internal/operators/distinct.d.ts","../node_modules/rxjs/dist/types/internal/operators/distinctuntilchanged.d.ts","../node_modules/rxjs/dist/types/internal/operators/distinctuntilkeychanged.d.ts","../node_modules/rxjs/dist/types/internal/operators/elementat.d.ts","../node_modules/rxjs/dist/types/internal/operators/endwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/every.d.ts","../node_modules/rxjs/dist/types/internal/operators/exhaustall.d.ts","../node_modules/rxjs/dist/types/internal/operators/exhaust.d.ts","../node_modules/rxjs/dist/types/internal/operators/exhaustmap.d.ts","../node_modules/rxjs/dist/types/internal/operators/expand.d.ts","../node_modules/rxjs/dist/types/internal/operators/filter.d.ts","../node_modules/rxjs/dist/types/internal/operators/finalize.d.ts","../node_modules/rxjs/dist/types/internal/operators/find.d.ts","../node_modules/rxjs/dist/types/internal/operators/findindex.d.ts","../node_modules/rxjs/dist/types/internal/operators/first.d.ts","../node_modules/rxjs/dist/types/internal/subject.d.ts","../node_modules/rxjs/dist/types/internal/operators/groupby.d.ts","../node_modules/rxjs/dist/types/internal/operators/ignoreelements.d.ts","../node_modules/rxjs/dist/types/internal/operators/isempty.d.ts","../node_modules/rxjs/dist/types/internal/operators/last.d.ts","../node_modules/rxjs/dist/types/internal/operators/map.d.ts","../node_modules/rxjs/dist/types/internal/operators/mapto.d.ts","../node_modules/rxjs/dist/types/internal/notification.d.ts","../node_modules/rxjs/dist/types/internal/operators/materialize.d.ts","../node_modules/rxjs/dist/types/internal/operators/max.d.ts","../node_modules/rxjs/dist/types/internal/operators/merge.d.ts","../node_modules/rxjs/dist/types/internal/operators/mergeall.d.ts","../node_modules/rxjs/dist/types/internal/operators/mergemap.d.ts","../node_modules/rxjs/dist/types/internal/operators/flatmap.d.ts","../node_modules/rxjs/dist/types/internal/operators/mergemapto.d.ts","../node_modules/rxjs/dist/types/internal/operators/mergescan.d.ts","../node_modules/rxjs/dist/types/internal/operators/mergewith.d.ts","../node_modules/rxjs/dist/types/internal/operators/min.d.ts","../node_modules/rxjs/dist/types/internal/observable/connectableobservable.d.ts","../node_modules/rxjs/dist/types/internal/operators/multicast.d.ts","../node_modules/rxjs/dist/types/internal/operators/observeon.d.ts","../node_modules/rxjs/dist/types/internal/operators/onerrorresumenextwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/pairwise.d.ts","../node_modules/rxjs/dist/types/internal/operators/partition.d.ts","../node_modules/rxjs/dist/types/internal/operators/pluck.d.ts","../node_modules/rxjs/dist/types/internal/operators/publish.d.ts","../node_modules/rxjs/dist/types/internal/operators/publishbehavior.d.ts","../node_modules/rxjs/dist/types/internal/operators/publishlast.d.ts","../node_modules/rxjs/dist/types/internal/operators/publishreplay.d.ts","../node_modules/rxjs/dist/types/internal/operators/race.d.ts","../node_modules/rxjs/dist/types/internal/operators/racewith.d.ts","../node_modules/rxjs/dist/types/internal/operators/reduce.d.ts","../node_modules/rxjs/dist/types/internal/operators/repeat.d.ts","../node_modules/rxjs/dist/types/internal/operators/repeatwhen.d.ts","../node_modules/rxjs/dist/types/internal/operators/retry.d.ts","../node_modules/rxjs/dist/types/internal/operators/retrywhen.d.ts","../node_modules/rxjs/dist/types/internal/operators/refcount.d.ts","../node_modules/rxjs/dist/types/internal/operators/sample.d.ts","../node_modules/rxjs/dist/types/internal/operators/sampletime.d.ts","../node_modules/rxjs/dist/types/internal/operators/scan.d.ts","../node_modules/rxjs/dist/types/internal/operators/sequenceequal.d.ts","../node_modules/rxjs/dist/types/internal/operators/share.d.ts","../node_modules/rxjs/dist/types/internal/operators/sharereplay.d.ts","../node_modules/rxjs/dist/types/internal/operators/single.d.ts","../node_modules/rxjs/dist/types/internal/operators/skip.d.ts","../node_modules/rxjs/dist/types/internal/operators/skiplast.d.ts","../node_modules/rxjs/dist/types/internal/operators/skipuntil.d.ts","../node_modules/rxjs/dist/types/internal/operators/skipwhile.d.ts","../node_modules/rxjs/dist/types/internal/operators/startwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/subscribeon.d.ts","../node_modules/rxjs/dist/types/internal/operators/switchall.d.ts","../node_modules/rxjs/dist/types/internal/operators/switchmap.d.ts","../node_modules/rxjs/dist/types/internal/operators/switchmapto.d.ts","../node_modules/rxjs/dist/types/internal/operators/switchscan.d.ts","../node_modules/rxjs/dist/types/internal/operators/take.d.ts","../node_modules/rxjs/dist/types/internal/operators/takelast.d.ts","../node_modules/rxjs/dist/types/internal/operators/takeuntil.d.ts","../node_modules/rxjs/dist/types/internal/operators/takewhile.d.ts","../node_modules/rxjs/dist/types/internal/operators/tap.d.ts","../node_modules/rxjs/dist/types/internal/operators/throttle.d.ts","../node_modules/rxjs/dist/types/internal/operators/throttletime.d.ts","../node_modules/rxjs/dist/types/internal/operators/throwifempty.d.ts","../node_modules/rxjs/dist/types/internal/operators/timeinterval.d.ts","../node_modules/rxjs/dist/types/internal/operators/timeout.d.ts","../node_modules/rxjs/dist/types/internal/operators/timeoutwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/timestamp.d.ts","../node_modules/rxjs/dist/types/internal/operators/toarray.d.ts","../node_modules/rxjs/dist/types/internal/operators/window.d.ts","../node_modules/rxjs/dist/types/internal/operators/windowcount.d.ts","../node_modules/rxjs/dist/types/internal/operators/windowtime.d.ts","../node_modules/rxjs/dist/types/internal/operators/windowtoggle.d.ts","../node_modules/rxjs/dist/types/internal/operators/windowwhen.d.ts","../node_modules/rxjs/dist/types/internal/operators/withlatestfrom.d.ts","../node_modules/rxjs/dist/types/internal/operators/zip.d.ts","../node_modules/rxjs/dist/types/internal/operators/zipall.d.ts","../node_modules/rxjs/dist/types/internal/operators/zipwith.d.ts","../node_modules/rxjs/dist/types/operators/index.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/action.d.ts","../node_modules/rxjs/dist/types/internal/scheduler.d.ts","../node_modules/rxjs/dist/types/internal/testing/testmessage.d.ts","../node_modules/rxjs/dist/types/internal/testing/subscriptionlog.d.ts","../node_modules/rxjs/dist/types/internal/testing/subscriptionloggable.d.ts","../node_modules/rxjs/dist/types/internal/testing/coldobservable.d.ts","../node_modules/rxjs/dist/types/internal/testing/hotobservable.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/asyncscheduler.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/timerhandle.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/asyncaction.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/virtualtimescheduler.d.ts","../node_modules/rxjs/dist/types/internal/testing/testscheduler.d.ts","../node_modules/rxjs/dist/types/testing/index.d.ts","../node_modules/rxjs/dist/types/internal/symbol/observable.d.ts","../node_modules/rxjs/dist/types/internal/observable/dom/animationframes.d.ts","../node_modules/rxjs/dist/types/internal/behaviorsubject.d.ts","../node_modules/rxjs/dist/types/internal/replaysubject.d.ts","../node_modules/rxjs/dist/types/internal/asyncsubject.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/asapscheduler.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/asap.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/async.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/queuescheduler.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/queue.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/animationframescheduler.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/animationframe.d.ts","../node_modules/rxjs/dist/types/internal/util/identity.d.ts","../node_modules/rxjs/dist/types/internal/util/pipe.d.ts","../node_modules/rxjs/dist/types/internal/util/noop.d.ts","../node_modules/rxjs/dist/types/internal/util/isobservable.d.ts","../node_modules/rxjs/dist/types/internal/lastvaluefrom.d.ts","../node_modules/rxjs/dist/types/internal/firstvaluefrom.d.ts","../node_modules/rxjs/dist/types/internal/util/argumentoutofrangeerror.d.ts","../node_modules/rxjs/dist/types/internal/util/emptyerror.d.ts","../node_modules/rxjs/dist/types/internal/util/notfounderror.d.ts","../node_modules/rxjs/dist/types/internal/util/objectunsubscribederror.d.ts","../node_modules/rxjs/dist/types/internal/util/sequenceerror.d.ts","../node_modules/rxjs/dist/types/internal/util/unsubscriptionerror.d.ts","../node_modules/rxjs/dist/types/internal/observable/bindcallback.d.ts","../node_modules/rxjs/dist/types/internal/observable/bindnodecallback.d.ts","../node_modules/rxjs/dist/types/internal/anycatcher.d.ts","../node_modules/rxjs/dist/types/internal/observable/combinelatest.d.ts","../node_modules/rxjs/dist/types/internal/observable/concat.d.ts","../node_modules/rxjs/dist/types/internal/observable/connectable.d.ts","../node_modules/rxjs/dist/types/internal/observable/defer.d.ts","../node_modules/rxjs/dist/types/internal/observable/empty.d.ts","../node_modules/rxjs/dist/types/internal/observable/forkjoin.d.ts","../node_modules/rxjs/dist/types/internal/observable/from.d.ts","../node_modules/rxjs/dist/types/internal/observable/fromevent.d.ts","../node_modules/rxjs/dist/types/internal/observable/fromeventpattern.d.ts","../node_modules/rxjs/dist/types/internal/observable/generate.d.ts","../node_modules/rxjs/dist/types/internal/observable/iif.d.ts","../node_modules/rxjs/dist/types/internal/observable/interval.d.ts","../node_modules/rxjs/dist/types/internal/observable/merge.d.ts","../node_modules/rxjs/dist/types/internal/observable/never.d.ts","../node_modules/rxjs/dist/types/internal/observable/of.d.ts","../node_modules/rxjs/dist/types/internal/observable/onerrorresumenext.d.ts","../node_modules/rxjs/dist/types/internal/observable/pairs.d.ts","../node_modules/rxjs/dist/types/internal/observable/partition.d.ts","../node_modules/rxjs/dist/types/internal/observable/race.d.ts","../node_modules/rxjs/dist/types/internal/observable/range.d.ts","../node_modules/rxjs/dist/types/internal/observable/throwerror.d.ts","../node_modules/rxjs/dist/types/internal/observable/timer.d.ts","../node_modules/rxjs/dist/types/internal/observable/using.d.ts","../node_modules/rxjs/dist/types/internal/observable/zip.d.ts","../node_modules/rxjs/dist/types/internal/scheduled/scheduled.d.ts","../node_modules/rxjs/dist/types/internal/config.d.ts","../node_modules/rxjs/dist/types/index.d.ts","../node_modules/@nestjs/common/interfaces/exceptions/rpc-exception-filter.interface.d.ts","../node_modules/@nestjs/common/interfaces/exceptions/ws-exception-filter.interface.d.ts","../node_modules/@nestjs/common/interfaces/external/validation-error.interface.d.ts","../node_modules/@nestjs/common/interfaces/features/execution-context.interface.d.ts","../node_modules/@nestjs/common/interfaces/features/can-activate.interface.d.ts","../node_modules/@nestjs/common/interfaces/features/custom-route-param-factory.interface.d.ts","../node_modules/@nestjs/common/interfaces/features/nest-interceptor.interface.d.ts","../node_modules/@nestjs/common/interfaces/features/paramtype.interface.d.ts","../node_modules/@nestjs/common/interfaces/type.interface.d.ts","../node_modules/@nestjs/common/interfaces/features/pipe-transform.interface.d.ts","../node_modules/@nestjs/common/enums/request-method.enum.d.ts","../node_modules/@nestjs/common/enums/http-status.enum.d.ts","../node_modules/@nestjs/common/enums/shutdown-signal.enum.d.ts","../node_modules/@nestjs/common/enums/version-type.enum.d.ts","../node_modules/@nestjs/common/enums/index.d.ts","../node_modules/@nestjs/common/interfaces/version-options.interface.d.ts","../node_modules/@nestjs/common/interfaces/middleware/middleware-configuration.interface.d.ts","../node_modules/@nestjs/common/interfaces/middleware/middleware-consumer.interface.d.ts","../node_modules/@nestjs/common/interfaces/middleware/middleware-config-proxy.interface.d.ts","../node_modules/@nestjs/common/interfaces/middleware/nest-middleware.interface.d.ts","../node_modules/@nestjs/common/interfaces/middleware/index.d.ts","../node_modules/@nestjs/common/interfaces/global-prefix-options.interface.d.ts","../node_modules/@nestjs/common/interfaces/hooks/before-application-shutdown.interface.d.ts","../node_modules/@nestjs/common/interfaces/hooks/on-application-bootstrap.interface.d.ts","../node_modules/@nestjs/common/interfaces/hooks/on-application-shutdown.interface.d.ts","../node_modules/@nestjs/common/interfaces/hooks/on-destroy.interface.d.ts","../node_modules/@nestjs/common/interfaces/hooks/on-init.interface.d.ts","../node_modules/@nestjs/common/interfaces/hooks/index.d.ts","../node_modules/@nestjs/common/interfaces/http/http-exception-body.interface.d.ts","../node_modules/@nestjs/common/interfaces/http/http-redirect-response.interface.d.ts","../node_modules/@nestjs/common/interfaces/external/cors-options.interface.d.ts","../node_modules/@nestjs/common/interfaces/external/https-options.interface.d.ts","../node_modules/@nestjs/common/services/logger.service.d.ts","../node_modules/@nestjs/common/interfaces/nest-application-context-options.interface.d.ts","../node_modules/@nestjs/common/interfaces/nest-application-options.interface.d.ts","../node_modules/@nestjs/common/interfaces/http/http-server.interface.d.ts","../node_modules/@nestjs/common/interfaces/http/message-event.interface.d.ts","../node_modules/@nestjs/common/interfaces/http/raw-body-request.interface.d.ts","../node_modules/@nestjs/common/interfaces/http/index.d.ts","../node_modules/@nestjs/common/interfaces/injectable.interface.d.ts","../node_modules/@nestjs/common/interfaces/microservices/nest-hybrid-application-options.interface.d.ts","../node_modules/@nestjs/common/interfaces/modules/forward-reference.interface.d.ts","../node_modules/@nestjs/common/interfaces/scope-options.interface.d.ts","../node_modules/@nestjs/common/interfaces/modules/injection-token.interface.d.ts","../node_modules/@nestjs/common/interfaces/modules/optional-factory-dependency.interface.d.ts","../node_modules/@nestjs/common/interfaces/modules/provider.interface.d.ts","../node_modules/@nestjs/common/interfaces/modules/module-metadata.interface.d.ts","../node_modules/@nestjs/common/interfaces/modules/dynamic-module.interface.d.ts","../node_modules/@nestjs/common/interfaces/modules/introspection-result.interface.d.ts","../node_modules/@nestjs/common/interfaces/modules/nest-module.interface.d.ts","../node_modules/@nestjs/common/interfaces/modules/index.d.ts","../node_modules/@nestjs/common/interfaces/shutdown-hooks-options.interface.d.ts","../node_modules/@nestjs/common/interfaces/nest-application-context.interface.d.ts","../node_modules/@nestjs/common/interfaces/websockets/web-socket-adapter.interface.d.ts","../node_modules/@nestjs/common/interfaces/nest-application.interface.d.ts","../node_modules/@nestjs/common/interfaces/nest-microservice.interface.d.ts","../node_modules/@nestjs/common/interfaces/index.d.ts","../node_modules/@nestjs/common/decorators/core/catch.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/controller.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/dependencies.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/exception-filters.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/inject.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/injectable.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/optional.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/set-metadata.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/use-guards.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/use-interceptors.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/use-pipes.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/apply-decorators.d.ts","../node_modules/@nestjs/common/decorators/core/version.decorator.d.ts","../node_modules/@nestjs/common/decorators/core/index.d.ts","../node_modules/@nestjs/common/decorators/modules/global.decorator.d.ts","../node_modules/@nestjs/common/decorators/modules/module.decorator.d.ts","../node_modules/@nestjs/common/decorators/modules/index.d.ts","../node_modules/@nestjs/common/decorators/http/request-mapping.decorator.d.ts","../node_modules/@nestjs/common/decorators/http/route-params.decorator.d.ts","../node_modules/@nestjs/common/decorators/http/http-code.decorator.d.ts","../node_modules/@nestjs/common/decorators/http/create-route-param-metadata.decorator.d.ts","../node_modules/@nestjs/common/decorators/http/render.decorator.d.ts","../node_modules/@nestjs/common/decorators/http/header.decorator.d.ts","../node_modules/@nestjs/common/decorators/http/redirect.decorator.d.ts","../node_modules/@nestjs/common/constants.d.ts","../node_modules/@nestjs/common/decorators/http/sse.decorator.d.ts","../node_modules/@nestjs/common/decorators/http/index.d.ts","../node_modules/@nestjs/common/decorators/index.d.ts","../node_modules/@nestjs/common/exceptions/intrinsic.exception.d.ts","../node_modules/@nestjs/common/exceptions/http.exception.d.ts","../node_modules/@nestjs/common/exceptions/bad-gateway.exception.d.ts","../node_modules/@nestjs/common/exceptions/bad-request.exception.d.ts","../node_modules/@nestjs/common/exceptions/conflict.exception.d.ts","../node_modules/@nestjs/common/exceptions/forbidden.exception.d.ts","../node_modules/@nestjs/common/exceptions/gateway-timeout.exception.d.ts","../node_modules/@nestjs/common/exceptions/gone.exception.d.ts","../node_modules/@nestjs/common/exceptions/http-version-not-supported.exception.d.ts","../node_modules/@nestjs/common/exceptions/im-a-teapot.exception.d.ts","../node_modules/@nestjs/common/exceptions/internal-server-error.exception.d.ts","../node_modules/@nestjs/common/exceptions/method-not-allowed.exception.d.ts","../node_modules/@nestjs/common/exceptions/misdirected.exception.d.ts","../node_modules/@nestjs/common/exceptions/not-acceptable.exception.d.ts","../node_modules/@nestjs/common/exceptions/not-found.exception.d.ts","../node_modules/@nestjs/common/exceptions/not-implemented.exception.d.ts","../node_modules/@nestjs/common/exceptions/payload-too-large.exception.d.ts","../node_modules/@nestjs/common/exceptions/precondition-failed.exception.d.ts","../node_modules/@nestjs/common/exceptions/request-timeout.exception.d.ts","../node_modules/@nestjs/common/exceptions/service-unavailable.exception.d.ts","../node_modules/@nestjs/common/exceptions/unauthorized.exception.d.ts","../node_modules/@nestjs/common/exceptions/unprocessable-entity.exception.d.ts","../node_modules/@nestjs/common/exceptions/unsupported-media-type.exception.d.ts","../node_modules/@nestjs/common/exceptions/index.d.ts","../node_modules/@nestjs/common/services/console-logger.service.d.ts","../node_modules/@nestjs/common/services/utils/filter-log-levels.util.d.ts","../node_modules/@nestjs/common/services/index.d.ts","../node_modules/@nestjs/common/file-stream/interfaces/streamable-options.interface.d.ts","../node_modules/@nestjs/common/file-stream/interfaces/streamable-handler-response.interface.d.ts","../node_modules/@nestjs/common/file-stream/interfaces/index.d.ts","../node_modules/@nestjs/common/file-stream/streamable-file.d.ts","../node_modules/@nestjs/common/file-stream/index.d.ts","../node_modules/@nestjs/common/module-utils/constants.d.ts","../node_modules/@nestjs/common/module-utils/interfaces/configurable-module-async-options.interface.d.ts","../node_modules/@nestjs/common/module-utils/interfaces/configurable-module-cls.interface.d.ts","../node_modules/@nestjs/common/module-utils/interfaces/configurable-module-host.interface.d.ts","../node_modules/@nestjs/common/module-utils/interfaces/index.d.ts","../node_modules/@nestjs/common/module-utils/configurable-module.builder.d.ts","../node_modules/@nestjs/common/module-utils/index.d.ts","../node_modules/@nestjs/common/pipes/default-value.pipe.d.ts","../node_modules/@nestjs/common/pipes/file/interfaces/file.interface.d.ts","../node_modules/@nestjs/common/pipes/file/interfaces/index.d.ts","../node_modules/@nestjs/common/pipes/file/file-validator-context.interface.d.ts","../node_modules/@nestjs/common/pipes/file/file-validator.interface.d.ts","../node_modules/@nestjs/common/pipes/file/file-type.validator.d.ts","../node_modules/@nestjs/common/pipes/file/max-file-size.validator.d.ts","../node_modules/@nestjs/common/utils/http-error-by-code.util.d.ts","../node_modules/@nestjs/common/pipes/file/parse-file-options.interface.d.ts","../node_modules/@nestjs/common/pipes/file/parse-file.pipe.d.ts","../node_modules/@nestjs/common/pipes/file/parse-file-pipe.builder.d.ts","../node_modules/@nestjs/common/pipes/file/index.d.ts","../node_modules/@nestjs/common/interfaces/external/class-transform-options.interface.d.ts","../node_modules/@nestjs/common/interfaces/external/transformer-package.interface.d.ts","../node_modules/@nestjs/common/interfaces/external/validator-options.interface.d.ts","../node_modules/@nestjs/common/interfaces/external/validator-package.interface.d.ts","../node_modules/@nestjs/common/pipes/validation.pipe.d.ts","../node_modules/@nestjs/common/pipes/parse-array.pipe.d.ts","../node_modules/@nestjs/common/pipes/parse-bool.pipe.d.ts","../node_modules/@nestjs/common/pipes/parse-date.pipe.d.ts","../node_modules/@nestjs/common/pipes/parse-enum.pipe.d.ts","../node_modules/@nestjs/common/pipes/parse-float.pipe.d.ts","../node_modules/@nestjs/common/pipes/parse-int.pipe.d.ts","../node_modules/@nestjs/common/pipes/parse-uuid.pipe.d.ts","../node_modules/@nestjs/common/pipes/index.d.ts","../node_modules/@nestjs/common/serializer/class-serializer.interfaces.d.ts","../node_modules/@nestjs/common/serializer/class-serializer.interceptor.d.ts","../node_modules/@nestjs/common/serializer/decorators/serialize-options.decorator.d.ts","../node_modules/@nestjs/common/serializer/decorators/index.d.ts","../node_modules/@nestjs/common/serializer/index.d.ts","../node_modules/@nestjs/common/utils/forward-ref.util.d.ts","../node_modules/@nestjs/common/utils/index.d.ts","../node_modules/@nestjs/common/index.d.ts","../node_modules/@types/node/compatibility/iterators.d.ts","../node_modules/@types/node/globals.typedarray.d.ts","../node_modules/@types/node/buffer.buffer.d.ts","../node_modules/@types/node/globals.d.ts","../node_modules/@types/node/web-globals/abortcontroller.d.ts","../node_modules/@types/node/web-globals/blob.d.ts","../node_modules/@types/node/web-globals/console.d.ts","../node_modules/@types/node/web-globals/crypto.d.ts","../node_modules/@types/node/web-globals/domexception.d.ts","../node_modules/@types/node/web-globals/encoding.d.ts","../node_modules/@types/node/web-globals/events.d.ts","../node_modules/buffer/index.d.ts","../node_modules/undici-types/utility.d.ts","../node_modules/undici-types/header.d.ts","../node_modules/undici-types/readable.d.ts","../node_modules/undici-types/fetch.d.ts","../node_modules/undici-types/formdata.d.ts","../node_modules/undici-types/connector.d.ts","../node_modules/undici-types/client-stats.d.ts","../node_modules/undici-types/client.d.ts","../node_modules/undici-types/errors.d.ts","../node_modules/undici-types/dispatcher.d.ts","../node_modules/undici-types/global-dispatcher.d.ts","../node_modules/undici-types/global-origin.d.ts","../node_modules/undici-types/pool-stats.d.ts","../node_modules/undici-types/pool.d.ts","../node_modules/undici-types/handlers.d.ts","../node_modules/undici-types/balanced-pool.d.ts","../node_modules/undici-types/h2c-client.d.ts","../node_modules/undici-types/agent.d.ts","../node_modules/undici-types/mock-interceptor.d.ts","../node_modules/undici-types/mock-call-history.d.ts","../node_modules/undici-types/mock-agent.d.ts","../node_modules/undici-types/mock-client.d.ts","../node_modules/undici-types/mock-pool.d.ts","../node_modules/undici-types/snapshot-agent.d.ts","../node_modules/undici-types/mock-errors.d.ts","../node_modules/undici-types/proxy-agent.d.ts","../node_modules/undici-types/env-http-proxy-agent.d.ts","../node_modules/undici-types/retry-handler.d.ts","../node_modules/undici-types/retry-agent.d.ts","../node_modules/undici-types/api.d.ts","../node_modules/undici-types/cache-interceptor.d.ts","../node_modules/undici-types/interceptors.d.ts","../node_modules/undici-types/util.d.ts","../node_modules/undici-types/cookies.d.ts","../node_modules/undici-types/patch.d.ts","../node_modules/undici-types/websocket.d.ts","../node_modules/undici-types/eventsource.d.ts","../node_modules/undici-types/diagnostics-channel.d.ts","../node_modules/undici-types/content-type.d.ts","../node_modules/undici-types/cache.d.ts","../node_modules/undici-types/index.d.ts","../node_modules/@types/node/web-globals/fetch.d.ts","../node_modules/@types/node/web-globals/importmeta.d.ts","../node_modules/@types/node/web-globals/messaging.d.ts","../node_modules/@types/node/web-globals/navigator.d.ts","../node_modules/@types/node/web-globals/performance.d.ts","../node_modules/@types/node/web-globals/storage.d.ts","../node_modules/@types/node/web-globals/streams.d.ts","../node_modules/@types/node/web-globals/timers.d.ts","../node_modules/@types/node/web-globals/url.d.ts","../node_modules/@types/node/assert.d.ts","../node_modules/@types/node/assert/strict.d.ts","../node_modules/@types/node/async_hooks.d.ts","../node_modules/@types/node/buffer.d.ts","../node_modules/@types/node/child_process.d.ts","../node_modules/@types/node/cluster.d.ts","../node_modules/@types/node/console.d.ts","../node_modules/@types/node/constants.d.ts","../node_modules/@types/node/crypto.d.ts","../node_modules/@types/node/dgram.d.ts","../node_modules/@types/node/diagnostics_channel.d.ts","../node_modules/@types/node/dns.d.ts","../node_modules/@types/node/dns/promises.d.ts","../node_modules/@types/node/domain.d.ts","../node_modules/@types/node/events.d.ts","../node_modules/@types/node/fs.d.ts","../node_modules/@types/node/fs/promises.d.ts","../node_modules/@types/node/http.d.ts","../node_modules/@types/node/http2.d.ts","../node_modules/@types/node/https.d.ts","../node_modules/@types/node/inspector.d.ts","../node_modules/@types/node/inspector.generated.d.ts","../node_modules/@types/node/inspector/promises.d.ts","../node_modules/@types/node/module.d.ts","../node_modules/@types/node/net.d.ts","../node_modules/@types/node/os.d.ts","../node_modules/@types/node/path.d.ts","../node_modules/@types/node/path/posix.d.ts","../node_modules/@types/node/path/win32.d.ts","../node_modules/@types/node/perf_hooks.d.ts","../node_modules/@types/node/process.d.ts","../node_modules/@types/node/punycode.d.ts","../node_modules/@types/node/querystring.d.ts","../node_modules/@types/node/quic.d.ts","../node_modules/@types/node/readline.d.ts","../node_modules/@types/node/readline/promises.d.ts","../node_modules/@types/node/repl.d.ts","../node_modules/@types/node/sea.d.ts","../node_modules/@types/node/sqlite.d.ts","../node_modules/@types/node/stream.d.ts","../node_modules/@types/node/stream/consumers.d.ts","../node_modules/@types/node/stream/promises.d.ts","../node_modules/@types/node/stream/web.d.ts","../node_modules/@types/node/string_decoder.d.ts","../node_modules/@types/node/test.d.ts","../node_modules/@types/node/test/reporters.d.ts","../node_modules/@types/node/timers.d.ts","../node_modules/@types/node/timers/promises.d.ts","../node_modules/@types/node/tls.d.ts","../node_modules/@types/node/trace_events.d.ts","../node_modules/@types/node/tty.d.ts","../node_modules/@types/node/url.d.ts","../node_modules/@types/node/util.d.ts","../node_modules/@types/node/util/types.d.ts","../node_modules/@types/node/v8.d.ts","../node_modules/@types/node/vm.d.ts","../node_modules/@types/node/wasi.d.ts","../node_modules/@types/node/worker_threads.d.ts","../node_modules/@types/node/zlib.d.ts","../node_modules/@types/node/index.d.ts","../node_modules/@types/send/index.d.ts","../node_modules/@types/qs/index.d.ts","../node_modules/@types/range-parser/index.d.ts","../node_modules/@types/express-serve-static-core/index.d.ts","../node_modules/@types/http-errors/index.d.ts","../node_modules/@types/serve-static/index.d.ts","../node_modules/@types/connect/index.d.ts","../node_modules/@types/body-parser/index.d.ts","../node_modules/@types/express/index.d.ts","../node_modules/@nestjs/passport/dist/abstract.strategy.d.ts","../node_modules/@nestjs/passport/dist/interfaces/auth-module.options.d.ts","../node_modules/@nestjs/passport/dist/interfaces/type.interface.d.ts","../node_modules/@nestjs/passport/dist/interfaces/index.d.ts","../node_modules/@nestjs/passport/dist/auth.guard.d.ts","../node_modules/@nestjs/passport/dist/passport.module.d.ts","../node_modules/@types/passport/index.d.ts","../node_modules/@nestjs/passport/dist/passport/passport.serializer.d.ts","../node_modules/@nestjs/passport/dist/passport/passport.strategy.d.ts","../node_modules/@nestjs/passport/dist/index.d.ts","../node_modules/@nestjs/passport/index.d.ts","../src/auth/guards/local-auth.guard.ts","../node_modules/sequelize/types/data-types.d.ts","../node_modules/sequelize/types/deferrable.d.ts","../node_modules/sequelize/types/operators.d.ts","../node_modules/sequelize/types/query-types.d.ts","../node_modules/sequelize/types/table-hints.d.ts","../node_modules/sequelize/types/index-hints.d.ts","../node_modules/sequelize/types/associations/base.d.ts","../node_modules/sequelize/types/associations/belongs-to.d.ts","../node_modules/sequelize/types/associations/has-one.d.ts","../node_modules/sequelize/types/associations/has-many.d.ts","../node_modules/sequelize/types/associations/belongs-to-many.d.ts","../node_modules/sequelize/types/associations/index.d.ts","../node_modules/sequelize/types/instance-validator.d.ts","../node_modules/sequelize/types/dialects/abstract/connection-manager.d.ts","../node_modules/retry-as-promised/dist/index.d.ts","../node_modules/sequelize/types/model-manager.d.ts","../node_modules/sequelize/types/transaction.d.ts","../node_modules/sequelize/types/utils/set-required.d.ts","../node_modules/sequelize/types/dialects/abstract/query-interface.d.ts","../node_modules/sequelize/types/sequelize.d.ts","../node_modules/sequelize/types/dialects/abstract/query.d.ts","../node_modules/sequelize/types/hooks.d.ts","../node_modules/sequelize/types/model.d.ts","../node_modules/sequelize/types/utils.d.ts","../node_modules/sequelize/types/errors/base-error.d.ts","../node_modules/sequelize/types/errors/database-error.d.ts","../node_modules/sequelize/types/errors/aggregate-error.d.ts","../node_modules/sequelize/types/errors/association-error.d.ts","../node_modules/sequelize/types/errors/bulk-record-error.d.ts","../node_modules/sequelize/types/errors/connection-error.d.ts","../node_modules/sequelize/types/errors/eager-loading-error.d.ts","../node_modules/sequelize/types/errors/empty-result-error.d.ts","../node_modules/sequelize/types/errors/instance-error.d.ts","../node_modules/sequelize/types/errors/optimistic-lock-error.d.ts","../node_modules/sequelize/types/errors/query-error.d.ts","../node_modules/sequelize/types/errors/sequelize-scope-error.d.ts","../node_modules/sequelize/types/errors/validation-error.d.ts","../node_modules/sequelize/types/errors/connection/access-denied-error.d.ts","../node_modules/sequelize/types/errors/connection/connection-acquire-timeout-error.d.ts","../node_modules/sequelize/types/errors/connection/connection-refused-error.d.ts","../node_modules/sequelize/types/errors/connection/connection-timed-out-error.d.ts","../node_modules/sequelize/types/errors/connection/host-not-found-error.d.ts","../node_modules/sequelize/types/errors/connection/host-not-reachable-error.d.ts","../node_modules/sequelize/types/errors/connection/invalid-connection-error.d.ts","../node_modules/sequelize/types/errors/database/exclusion-constraint-error.d.ts","../node_modules/sequelize/types/errors/database/foreign-key-constraint-error.d.ts","../node_modules/sequelize/types/errors/database/timeout-error.d.ts","../node_modules/sequelize/types/errors/database/unknown-constraint-error.d.ts","../node_modules/sequelize/types/errors/validation/unique-constraint-error.d.ts","../node_modules/sequelize/types/dialects/mssql/async-queue.d.ts","../node_modules/sequelize/types/errors/index.d.ts","../node_modules/@types/validator/lib/isboolean.d.ts","../node_modules/@types/validator/lib/isemail.d.ts","../node_modules/@types/validator/lib/isfqdn.d.ts","../node_modules/@types/validator/lib/isiban.d.ts","../node_modules/@types/validator/lib/isiso31661alpha2.d.ts","../node_modules/@types/validator/lib/isiso4217.d.ts","../node_modules/@types/validator/lib/isiso6391.d.ts","../node_modules/@types/validator/lib/istaxid.d.ts","../node_modules/@types/validator/lib/isurl.d.ts","../node_modules/@types/validator/index.d.ts","../node_modules/sequelize/types/utils/validator-extras.d.ts","../node_modules/sequelize/types/index.d.ts","../node_modules/sequelize-typescript/dist/model/model/association/association-get-options.d.ts","../node_modules/sequelize-typescript/dist/model/model/association/association-count-options.d.ts","../node_modules/sequelize-typescript/dist/model/model/association/association-action-options.d.ts","../node_modules/sequelize-typescript/dist/model/model/association/association-create-options.d.ts","../node_modules/sequelize-typescript/dist/shared/types.d.ts","../node_modules/sequelize-typescript/dist/sequelize/repository/repository.d.ts","../node_modules/sequelize-typescript/dist/model/model/model.d.ts","../node_modules/sequelize-typescript/dist/model/shared/model-class-getter.d.ts","../node_modules/sequelize-typescript/dist/associations/belongs-to/belongs-to.d.ts","../node_modules/sequelize-typescript/dist/associations/shared/union-association-options.d.ts","../node_modules/sequelize-typescript/dist/associations/shared/association.d.ts","../node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize-options.d.ts","../node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize.d.ts","../node_modules/sequelize-typescript/dist/associations/shared/base-association.d.ts","../node_modules/sequelize-typescript/dist/associations/belongs-to/belongs-to-association.d.ts","../node_modules/sequelize-typescript/dist/associations/through/through-options.d.ts","../node_modules/sequelize-typescript/dist/associations/belongs-to-many/belongs-to-many-options.d.ts","../node_modules/sequelize-typescript/dist/associations/belongs-to-many/belongs-to-many.d.ts","../node_modules/sequelize-typescript/dist/associations/belongs-to-many/belongs-to-many-association.d.ts","../node_modules/sequelize-typescript/dist/associations/foreign-key/foreign-key.d.ts","../node_modules/sequelize-typescript/dist/associations/has/has-association.d.ts","../node_modules/sequelize-typescript/dist/associations/has/has-one.d.ts","../node_modules/sequelize-typescript/dist/associations/has/has-many.d.ts","../node_modules/sequelize-typescript/dist/associations/shared/association-service.d.ts","../node_modules/sequelize-typescript/dist/hooks/shared/hook-options.d.ts","../node_modules/sequelize-typescript/dist/hooks/bulk/after/after-bulk-create.d.ts","../node_modules/sequelize-typescript/dist/hooks/bulk/after/after-bulk-destroy.d.ts","../node_modules/sequelize-typescript/dist/hooks/bulk/after/after-bulk-restore.d.ts","../node_modules/sequelize-typescript/dist/hooks/bulk/after/after-bulk-sync.d.ts","../node_modules/sequelize-typescript/dist/hooks/bulk/after/after-bulk-update.d.ts","../node_modules/sequelize-typescript/dist/hooks/bulk/before/before-bulk-create.d.ts","../node_modules/sequelize-typescript/dist/hooks/bulk/before/before-bulk-destroy.d.ts","../node_modules/sequelize-typescript/dist/hooks/bulk/before/before-bulk-restore.d.ts","../node_modules/sequelize-typescript/dist/hooks/bulk/before/before-bulk-sync.d.ts","../node_modules/sequelize-typescript/dist/hooks/bulk/before/before-bulk-update.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-connect.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-create.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-define.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-destroy.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-find.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-init.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-restore.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-save.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-sync.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-update.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-upsert.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/after/after-validate.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-connect.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-count.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-create.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-define.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-destroy.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-find.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-find-after-expand-include-all.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-find-after-options.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-init.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-restore.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-save.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-sync.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-update.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-upsert.d.ts","../node_modules/sequelize-typescript/dist/hooks/single/before/before-validate.d.ts","../node_modules/sequelize-typescript/dist/hooks/shared/hook-meta.d.ts","../node_modules/sequelize-typescript/dist/hooks/shared/hooks-service.d.ts","../node_modules/sequelize-typescript/dist/hooks/shared/validation-failed.d.ts","../node_modules/sequelize-typescript/dist/model/column/column-options/allow-null.d.ts","../node_modules/sequelize-typescript/dist/model/column/column-options/comment.d.ts","../node_modules/sequelize-typescript/dist/model/column/column-options/default.d.ts","../node_modules/sequelize-typescript/dist/model/column/column-options/unique.d.ts","../node_modules/sequelize-typescript/dist/model/column/primary-key/auto-increment.d.ts","../node_modules/sequelize-typescript/dist/model/column/primary-key/primary-key.d.ts","../node_modules/sequelize-typescript/dist/model/column/timestamps/created-at.d.ts","../node_modules/sequelize-typescript/dist/model/column/timestamps/deleted-at.d.ts","../node_modules/sequelize-typescript/dist/model/column/timestamps/updated-at.d.ts","../node_modules/sequelize-typescript/dist/model/column/attribute-service.d.ts","../node_modules/sequelize-typescript/dist/model/column/column.d.ts","../node_modules/sequelize-typescript/dist/model/shared/model-service.d.ts","../node_modules/sequelize-typescript/dist/model/table/table-options.d.ts","../node_modules/sequelize-typescript/dist/model/table/table.d.ts","../node_modules/sequelize-typescript/dist/model/index/index-service.d.ts","../node_modules/sequelize-typescript/dist/model/index/create-index-decorator.d.ts","../node_modules/sequelize-typescript/dist/model/index/index-decorator.d.ts","../node_modules/sequelize-typescript/dist/scopes/scope-find-options.d.ts","../node_modules/sequelize-typescript/dist/scopes/scope-table-options.d.ts","../node_modules/sequelize-typescript/dist/scopes/scope-options.d.ts","../node_modules/sequelize-typescript/dist/scopes/default-scope.d.ts","../node_modules/sequelize-typescript/dist/scopes/scope-service.d.ts","../node_modules/sequelize-typescript/dist/scopes/scopes.d.ts","../node_modules/sequelize-typescript/dist/sequelize/data-type/data-type.d.ts","../node_modules/sequelize-typescript/dist/sequelize/data-type/data-type-service.d.ts","../node_modules/sequelize-typescript/dist/sequelize/validation-only/db-dialect-dummy.d.ts","../node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize-service.d.ts","../node_modules/sequelize-typescript/dist/validation/contains.d.ts","../node_modules/sequelize-typescript/dist/validation/equals.d.ts","../node_modules/sequelize-typescript/dist/validation/is.d.ts","../node_modules/sequelize-typescript/dist/validation/is-after.d.ts","../node_modules/sequelize-typescript/dist/validation/is-alpha.d.ts","../node_modules/sequelize-typescript/dist/validation/is-alphanumeric.d.ts","../node_modules/sequelize-typescript/dist/validation/is-before.d.ts","../node_modules/sequelize-typescript/dist/validation/is-credit-card.d.ts","../node_modules/sequelize-typescript/dist/validation/is-date.d.ts","../node_modules/sequelize-typescript/dist/validation/is-decimal.d.ts","../node_modules/sequelize-typescript/dist/validation/is-email.d.ts","../node_modules/sequelize-typescript/dist/validation/is-float.d.ts","../node_modules/sequelize-typescript/dist/validation/is-in.d.ts","../node_modules/sequelize-typescript/dist/validation/is-int.d.ts","../node_modules/sequelize-typescript/dist/validation/is-ip.d.ts","../node_modules/sequelize-typescript/dist/validation/is-ip-v4.d.ts","../node_modules/sequelize-typescript/dist/validation/is-array.d.ts","../node_modules/sequelize-typescript/dist/validation/is-ip-v6.d.ts","../node_modules/sequelize-typescript/dist/validation/is-lowercase.d.ts","../node_modules/sequelize-typescript/dist/validation/is-null.d.ts","../node_modules/sequelize-typescript/dist/validation/is-numeric.d.ts","../node_modules/sequelize-typescript/dist/validation/is-uppercase.d.ts","../node_modules/sequelize-typescript/dist/validation/is-url.d.ts","../node_modules/sequelize-typescript/dist/validation/is-uuid.d.ts","../node_modules/sequelize-typescript/dist/validation/length.d.ts","../node_modules/sequelize-typescript/dist/validation/max.d.ts","../node_modules/sequelize-typescript/dist/validation/min.d.ts","../node_modules/sequelize-typescript/dist/validation/not.d.ts","../node_modules/sequelize-typescript/dist/validation/not-contains.d.ts","../node_modules/sequelize-typescript/dist/validation/not-empty.d.ts","../node_modules/sequelize-typescript/dist/validation/not-in.d.ts","../node_modules/sequelize-typescript/dist/validation/not-null.d.ts","../node_modules/sequelize-typescript/dist/validation/validate.d.ts","../node_modules/sequelize-typescript/dist/validation/validator.d.ts","../node_modules/sequelize-typescript/dist/index.d.ts","../node_modules/@nestjs/sequelize/dist/interfaces/sequelize-options.interface.d.ts","../node_modules/@nestjs/sequelize/dist/common/sequelize.decorators.d.ts","../node_modules/@nestjs/sequelize/dist/interfaces/index.d.ts","../node_modules/@nestjs/sequelize/dist/common/sequelize.utils.d.ts","../node_modules/@nestjs/sequelize/dist/common/index.d.ts","../node_modules/@nestjs/sequelize/dist/sequelize.module.d.ts","../node_modules/@nestjs/sequelize/dist/index.d.ts","../node_modules/@nestjs/sequelize/index.d.ts","../src/models/meal-plan.model.ts","../src/models/planned-food.model.ts","../src/models/food-item.model.ts","../src/models/meal-food.model.ts","../src/models/meal.model.ts","../src/models/weight-log.model.ts","../src/models/water-log.model.ts","../src/models/user-goal.model.ts","../src/models/daily-summary.model.ts","../src/models/user.model.ts","../src/users/users.service.ts","../src/auth/guards/authenticated.guard.ts","../src/app.controller.ts","../node_modules/@nestjs/config/dist/conditional.module.d.ts","../node_modules/@nestjs/config/dist/interfaces/config-change-event.interface.d.ts","../node_modules/@nestjs/config/dist/types/config-object.type.d.ts","../node_modules/@nestjs/config/dist/types/config.type.d.ts","../node_modules/@nestjs/config/dist/types/no-infer.type.d.ts","../node_modules/@nestjs/config/dist/types/path-value.type.d.ts","../node_modules/@nestjs/config/dist/types/index.d.ts","../node_modules/@nestjs/config/dist/interfaces/config-factory.interface.d.ts","../node_modules/dotenv-expand/lib/main.d.ts","../node_modules/@nestjs/config/dist/interfaces/config-module-options.interface.d.ts","../node_modules/@nestjs/config/dist/interfaces/index.d.ts","../node_modules/@nestjs/config/dist/config.module.d.ts","../node_modules/@nestjs/config/dist/config.service.d.ts","../node_modules/@nestjs/config/dist/utils/register-as.util.d.ts","../node_modules/@nestjs/config/dist/utils/get-config-token.util.d.ts","../node_modules/@nestjs/config/dist/utils/index.d.ts","../node_modules/@nestjs/config/dist/index.d.ts","../node_modules/@nestjs/config/index.d.ts","../src/models/api-cache.model.ts","../src/database/database.module.ts","../src/auth/auth.service.ts","../src/users/users.module.ts","../node_modules/@types/passport-strategy/index.d.ts","../node_modules/@types/passport-local/index.d.ts","../src/auth/local.strategy.ts","../src/auth/session.serializer.ts","../src/auth/auth.module.ts","../src/utils/utils.service.ts","../src/utils/utils.module.ts","../src/dashboard/dashboard.controller.ts","../src/dashboard/progress.controller.ts","../src/dashboard/dashboard.module.ts","../node_modules/axios/index.d.ts","../src/meals/nutrition.service.ts","../src/meals/meals.controller.ts","../src/meals/meals.module.ts","../src/goals/goals.service.ts","../src/goals/goals.controller.ts","../src/goals/goals.module.ts","../src/foods/foods.service.ts","../src/foods/foods.controller.ts","../src/foods/foods.module.ts","../src/meal-planner/meal-planner.service.ts","../src/meal-planner/meal-planner.controller.ts","../src/meal-planner/meal-planner.module.ts","../src/common/middleware/locals.middleware.ts","../src/app.module.ts","../node_modules/@nestjs/core/adapters/http-adapter.d.ts","../node_modules/@nestjs/core/adapters/index.d.ts","../node_modules/@nestjs/core/inspector/interfaces/edge.interface.d.ts","../node_modules/@nestjs/core/inspector/interfaces/entrypoint.interface.d.ts","../node_modules/@nestjs/core/inspector/interfaces/extras.interface.d.ts","../node_modules/@nestjs/core/inspector/interfaces/node.interface.d.ts","../node_modules/@nestjs/core/injector/settlement-signal.d.ts","../node_modules/@nestjs/core/injector/injector.d.ts","../node_modules/@nestjs/core/inspector/interfaces/serialized-graph-metadata.interface.d.ts","../node_modules/@nestjs/core/inspector/interfaces/serialized-graph-json.interface.d.ts","../node_modules/@nestjs/core/inspector/serialized-graph.d.ts","../node_modules/@nestjs/core/injector/opaque-key-factory/interfaces/module-opaque-key-factory.interface.d.ts","../node_modules/@nestjs/core/injector/compiler.d.ts","../node_modules/@nestjs/core/injector/modules-container.d.ts","../node_modules/@nestjs/core/injector/container.d.ts","../node_modules/@nestjs/core/injector/instance-links-host.d.ts","../node_modules/@nestjs/core/injector/abstract-instance-resolver.d.ts","../node_modules/@nestjs/core/injector/module-ref.d.ts","../node_modules/@nestjs/core/injector/module.d.ts","../node_modules/@nestjs/core/injector/instance-wrapper.d.ts","../node_modules/@nestjs/core/router/interfaces/exclude-route-metadata.interface.d.ts","../node_modules/@nestjs/core/application-config.d.ts","../node_modules/@nestjs/core/constants.d.ts","../node_modules/@nestjs/core/discovery/discovery-module.d.ts","../node_modules/@nestjs/core/discovery/discovery-service.d.ts","../node_modules/@nestjs/core/discovery/index.d.ts","../node_modules/@nestjs/core/helpers/http-adapter-host.d.ts","../node_modules/@nestjs/core/exceptions/base-exception-filter.d.ts","../node_modules/@nestjs/core/exceptions/index.d.ts","../node_modules/@nestjs/core/helpers/context-id-factory.d.ts","../node_modules/@nestjs/common/interfaces/exceptions/exception-filter-metadata.interface.d.ts","../node_modules/@nestjs/core/exceptions/exceptions-handler.d.ts","../node_modules/@nestjs/core/router/router-proxy.d.ts","../node_modules/@nestjs/core/helpers/context-creator.d.ts","../node_modules/@nestjs/core/exceptions/base-exception-filter-context.d.ts","../node_modules/@nestjs/common/interfaces/exceptions/rpc-exception-filter-metadata.interface.d.ts","../node_modules/@nestjs/common/interfaces/exceptions/index.d.ts","../node_modules/@nestjs/core/exceptions/external-exception-filter.d.ts","../node_modules/@nestjs/core/exceptions/external-exceptions-handler.d.ts","../node_modules/@nestjs/core/exceptions/external-exception-filter-context.d.ts","../node_modules/@nestjs/core/guards/constants.d.ts","../node_modules/@nestjs/core/helpers/execution-context-host.d.ts","../node_modules/@nestjs/core/guards/guards-consumer.d.ts","../node_modules/@nestjs/core/guards/guards-context-creator.d.ts","../node_modules/@nestjs/core/guards/index.d.ts","../node_modules/@nestjs/core/interceptors/interceptors-consumer.d.ts","../node_modules/@nestjs/core/interceptors/interceptors-context-creator.d.ts","../node_modules/@nestjs/core/interceptors/index.d.ts","../node_modules/@nestjs/common/enums/route-paramtypes.enum.d.ts","../node_modules/@nestjs/core/pipes/params-token-factory.d.ts","../node_modules/@nestjs/core/pipes/pipes-consumer.d.ts","../node_modules/@nestjs/core/pipes/pipes-context-creator.d.ts","../node_modules/@nestjs/core/pipes/index.d.ts","../node_modules/@nestjs/core/helpers/context-utils.d.ts","../node_modules/@nestjs/core/injector/inquirer/inquirer-constants.d.ts","../node_modules/@nestjs/core/injector/inquirer/index.d.ts","../node_modules/@nestjs/core/interfaces/module-definition.interface.d.ts","../node_modules/@nestjs/core/interfaces/module-override.interface.d.ts","../node_modules/@nestjs/core/inspector/interfaces/enhancer-metadata-cache-entry.interface.d.ts","../node_modules/@nestjs/core/inspector/graph-inspector.d.ts","../node_modules/@nestjs/core/metadata-scanner.d.ts","../node_modules/@nestjs/core/scanner.d.ts","../node_modules/@nestjs/core/injector/instance-loader.d.ts","../node_modules/@nestjs/core/injector/lazy-module-loader/lazy-module-loader-options.interface.d.ts","../node_modules/@nestjs/core/injector/lazy-module-loader/lazy-module-loader.d.ts","../node_modules/@nestjs/core/injector/index.d.ts","../node_modules/@nestjs/core/helpers/interfaces/external-handler-metadata.interface.d.ts","../node_modules/@nestjs/core/helpers/interfaces/params-metadata.interface.d.ts","../node_modules/@nestjs/core/helpers/external-context-creator.d.ts","../node_modules/@nestjs/core/helpers/index.d.ts","../node_modules/@nestjs/core/inspector/initialize-on-preview.allowlist.d.ts","../node_modules/@nestjs/core/inspector/partial-graph.host.d.ts","../node_modules/@nestjs/core/inspector/index.d.ts","../node_modules/@nestjs/core/middleware/route-info-path-extractor.d.ts","../node_modules/@nestjs/core/middleware/routes-mapper.d.ts","../node_modules/@nestjs/core/middleware/builder.d.ts","../node_modules/@nestjs/core/middleware/index.d.ts","../node_modules/@nestjs/core/nest-application-context.d.ts","../node_modules/@nestjs/core/nest-application.d.ts","../node_modules/@nestjs/common/interfaces/microservices/nest-microservice-options.interface.d.ts","../node_modules/@nestjs/core/nest-factory.d.ts","../node_modules/@nestjs/core/repl/repl.d.ts","../node_modules/@nestjs/core/repl/index.d.ts","../node_modules/@nestjs/core/router/interfaces/routes.interface.d.ts","../node_modules/@nestjs/core/router/interfaces/index.d.ts","../node_modules/@nestjs/core/router/request/request-constants.d.ts","../node_modules/@nestjs/core/router/request/index.d.ts","../node_modules/@nestjs/core/router/router-module.d.ts","../node_modules/@nestjs/core/router/index.d.ts","../node_modules/@nestjs/core/services/reflector.service.d.ts","../node_modules/@nestjs/core/services/index.d.ts","../node_modules/@nestjs/core/index.d.ts","../node_modules/@nestjs/platform-express/interfaces/nest-express-body-parser-options.interface.d.ts","../node_modules/@nestjs/platform-express/interfaces/nest-express-body-parser.interface.d.ts","../node_modules/@nestjs/platform-express/interfaces/serve-static-options.interface.d.ts","../node_modules/@nestjs/platform-express/adapters/express-adapter.d.ts","../node_modules/@nestjs/platform-express/adapters/index.d.ts","../node_modules/@nestjs/platform-express/interfaces/nest-express-application.interface.d.ts","../node_modules/@nestjs/platform-express/interfaces/index.d.ts","../node_modules/@nestjs/platform-express/multer/interfaces/multer-options.interface.d.ts","../node_modules/@nestjs/platform-express/multer/interceptors/any-files.interceptor.d.ts","../node_modules/@nestjs/platform-express/multer/interceptors/file-fields.interceptor.d.ts","../node_modules/@nestjs/platform-express/multer/interceptors/file.interceptor.d.ts","../node_modules/@nestjs/platform-express/multer/interceptors/files.interceptor.d.ts","../node_modules/@nestjs/platform-express/multer/interceptors/no-files.interceptor.d.ts","../node_modules/@nestjs/platform-express/multer/interceptors/index.d.ts","../node_modules/@nestjs/platform-express/multer/interfaces/files-upload-module.interface.d.ts","../node_modules/@nestjs/platform-express/multer/interfaces/index.d.ts","../node_modules/@nestjs/platform-express/multer/multer.module.d.ts","../node_modules/@nestjs/platform-express/multer/index.d.ts","../node_modules/@nestjs/platform-express/index.d.ts","../node_modules/@types/express-session/index.d.ts","../src/main.ts","../node_modules/@types/ms/index.d.ts","../node_modules/@types/debug/index.d.ts"],"fileIdsList":[[408,471,479,483,486,488,489,490,502],[305,408,471,479,483,486,488,489,490,502],[405,408,471,479,483,486,488,489,490,502],[54,306,307,308,309,310,311,312,313,314,315,316,317,318,408,471,479,483,486,488,489,490,502],[257,291,408,471,479,483,486,488,489,490,502],[264,408,471,479,483,486,488,489,490,502],[254,305,405,408,471,479,483,486,488,489,490,502],[323,324,325,326,327,328,329,331,408,471,479,483,486,488,489,490,502],[259,408,471,479,483,486,488,489,490,502],[305,405,408,471,479,483,486,488,489,490,502],[259,330,408,471,479,483,486,488,489,490,502],[319,322,332,408,471,479,483,486,488,489,490,502],[320,321,408,471,479,483,486,488,489,490,502],[295,408,471,479,483,486,488,489,490,502],[259,260,261,262,408,471,479,483,486,488,489,490,502],[335,408,471,479,483,486,488,489,490,502],[277,334,408,471,479,483,486,488,489,490,502],[334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,408,471,479,483,486,488,489,490,502],[364,408,471,479,483,486,488,489,490,502],[361,362,408,471,479,483,486,488,489,490,502],[360,363,408,471,479,483,486,488,489,490,502,507],[53,263,305,333,357,360,365,372,397,402,404,408,471,479,483,486,488,489,490,502],[59,257,408,471,479,483,486,488,489,490,502],[58,408,471,479,483,486,488,489,490,502],[59,249,250,408,471,479,483,486,488,489,490,502,837,842],[249,257,408,471,479,483,486,488,489,490,502],[58,248,408,471,479,483,486,488,489,490,502],[257,385,408,471,479,483,486,488,489,490,502],[251,387,408,471,479,483,486,488,489,490,502],[248,252,408,471,479,483,486,488,489,490,502],[252,408,471,479,483,486,488,489,490,502],[58,305,408,471,479,483,486,488,489,490,502],[256,257,408,471,479,483,486,488,489,490,502],[269,408,471,479,483,486,488,489,490,502],[271,272,273,274,275,408,471,479,483,486,488,489,490,502],[263,408,471,479,483,486,488,489,490,502],[263,264,283,408,471,479,483,486,488,489,490,502],[277,278,284,285,286,408,471,479,483,486,488,489,490,502],[55,56,57,58,59,249,250,251,252,253,254,255,256,257,258,264,269,270,276,283,287,288,289,291,299,300,301,302,303,304,408,471,479,483,486,488,489,490,502],[282,408,471,479,483,486,488,489,490,502],[265,266,267,268,408,471,479,483,486,488,489,490,502],[257,265,266,408,471,479,483,486,488,489,490,502],[257,263,264,408,471,479,483,486,488,489,490,502],[257,267,408,471,479,483,486,488,489,490,502],[257,295,408,471,479,483,486,488,489,490,502],[290,292,293,294,295,296,297,298,408,471,479,483,486,488,489,490,502],[55,257,408,471,479,483,486,488,489,490,502],[291,408,471,479,483,486,488,489,490,502],[55,257,290,294,296,408,471,479,483,486,488,489,490,502],[266,408,471,479,483,486,488,489,490,502],[292,408,471,479,483,486,488,489,490,502],[257,291,292,293,408,471,479,483,486,488,489,490,502],[281,408,471,479,483,486,488,489,490,502],[257,261,281,282,299,300,408,471,479,483,486,488,489,490,502],[279,280,282,408,471,479,483,486,488,489,490,502],[253,255,264,270,284,301,302,305,408,471,479,483,486,488,489,490,502],[59,248,253,255,258,301,302,408,471,479,483,486,488,489,490,502],[262,408,471,479,483,486,488,489,490,502],[248,408,471,479,483,486,488,489,490,502],[281,305,366,370,408,471,479,483,486,488,489,490,502],[370,371,408,471,479,483,486,488,489,490,502],[305,366,408,471,479,483,486,488,489,490,502],[305,366,367,408,471,479,483,486,488,489,490,502],[367,368,408,471,479,483,486,488,489,490,502],[367,368,369,408,471,479,483,486,488,489,490,502],[258,408,471,479,483,486,488,489,490,502],[375,376,377,408,471,479,483,486,488,489,490,502],[375,408,471,479,483,486,488,489,490,502],[377,378,379,381,382,383,408,471,479,483,486,488,489,490,502],[374,408,471,479,483,486,488,489,490,502],[377,380,408,471,479,483,486,488,489,490,502],[377,378,379,381,382,408,471,479,483,486,488,489,490,502],[258,375,377,381,408,471,479,483,486,488,489,490,502],[373,384,389,390,391,392,393,394,395,396,408,471,479,483,486,488,489,490,502],[258,305,389,408,471,479,483,486,488,489,490,502],[258,380,408,471,479,483,486,488,489,490,502],[258,380,405,408,471,479,483,486,488,489,490,502],[251,257,258,380,385,386,387,388,408,471,479,483,486,488,489,490,502],[248,305,385,386,398,408,471,479,483,486,488,489,490,502],[305,385,408,471,479,483,486,488,489,490,502],[400,408,471,479,483,486,488,489,490,502],[333,398,408,471,479,483,486,488,489,490,502],[398,399,401,408,471,479,483,486,488,489,490,502],[281,408,471,479,483,486,488,489,490,502,520],[281,358,359,408,471,479,483,486,488,489,490,502],[290,408,471,479,483,486,488,489,490,502],[263,305,408,471,479,483,486,488,489,490,502],[403,408,471,479,483,486,488,489,490,502],[405,408,471,479,483,486,488,489,490,502,770],[248,408,471,479,483,486,488,489,490,502,761,766],[408,471,479,483,486,488,489,490,502,760,766,770,771,772,775],[408,471,479,483,486,488,489,490,502,766],[408,471,479,483,486,488,489,490,502,767,768],[408,471,479,483,486,488,489,490,502,761,767,769],[408,471,479,483,486,488,489,490,502,762,763,764,765],[408,471,479,483,486,488,489,490,502,773,774],[408,471,479,483,486,488,489,490,502,766,770,776],[408,471,479,483,486,488,489,490,502,776],[283,305,405,408,471,479,483,486,488,489,490,502],[408,471,479,483,486,488,489,490,502,807],[305,405,408,471,479,483,486,488,489,490,502,826,827],[330,408,471,479,483,486,488,489,490,502],[405,408,471,479,483,486,488,489,490,502,820,825,826],[408,471,479,483,486,488,489,490,502,830,831],[59,305,408,471,479,483,486,488,489,490,502,821,826,840],[405,408,471,479,483,486,488,489,490,502,808,833],[58,405,408,471,479,483,486,488,489,490,502,834,837],[305,408,471,479,483,486,488,489,490,502,821,826,828,839,841,845],[58,408,471,479,483,486,488,489,490,502,843,844],[408,471,479,483,486,488,489,490,502,834],[248,305,405,408,471,479,483,486,488,489,490,502,848],[305,405,408,471,479,483,486,488,489,490,502,821,826,828,840],[408,471,479,483,486,488,489,490,502,847,849,850],[305,408,471,479,483,486,488,489,490,502,826],[408,471,479,483,486,488,489,490,502,826],[305,405,408,471,479,483,486,488,489,490,502,848],[58,305,405,408,471,479,483,486,488,489,490,502],[305,405,408,471,479,483,486,488,489,490,502,820,821,826,846,848,851,854,859,860,873,874],[248,408,471,479,483,486,488,489,490,502,807],[408,471,479,483,486,488,489,490,502,833,836,875],[408,471,479,483,486,488,489,490,502,860,872],[53,408,471,479,483,486,488,489,490,502,808,828,829,832,835,867,872,876,879,883,884,885,887,889,895,897],[305,405,408,471,479,483,486,488,489,490,502,814,822,825,826],[305,408,471,479,483,486,488,489,490,502,818],[282,305,330,405,408,471,479,483,486,488,489,490,502,817,818,819,820,825,826,828,898],[408,471,479,483,486,488,489,490,502,820,821,824,826,862,871],[305,405,408,471,479,483,486,488,489,490,502,813,825,826],[408,471,479,483,486,488,489,490,502,861],[405,408,471,479,483,486,488,489,490,502,821,826],[405,408,471,479,483,486,488,489,490,502,814,821,825,866],[305,330,405,408,471,479,483,486,488,489,490,502,813,825],[405,408,471,479,483,486,488,489,490,502,819,820,824,864,868,869,870],[405,408,471,479,483,486,488,489,490,502,814,821,822,823,825,826],[305,330,408,471,479,483,486,488,489,490,502,821,824,826],[248,408,471,479,483,486,488,489,490,502,825],[257,290,296,408,471,479,483,486,488,489,490,502],[408,471,479,483,486,488,489,490,502,810,811,812,821,825,826,865],[408,471,479,483,486,488,489,490,502,817,866,877,878],[330,405,408,471,479,483,486,488,489,490,502,826],[330,405,408,471,479,483,486,488,489,490,502],[408,471,479,483,486,488,489,490,502,809,810,811,812,815,817],[408,471,479,483,486,488,489,490,502,814],[408,471,479,483,486,488,489,490,502,816,817],[405,408,471,479,483,486,488,489,490,502,809,810,811,812,815,816],[408,471,479,483,486,488,489,490,502,852,853],[305,408,471,479,483,486,488,489,490,502,821,826,828,840],[408,471,479,483,486,488,489,490,502,863],[288,408,471,479,483,486,488,489,490,502],[269,305,408,471,479,483,486,488,489,490,502,880,881],[408,471,479,483,486,488,489,490,502,882],[305,408,471,479,483,486,488,489,490,502,828],[305,408,471,479,483,486,488,489,490,502,821,828],[282,305,405,408,471,479,483,486,488,489,490,502,814,821,822,823,825,826],[281,305,405,408,471,479,483,486,488,489,490,502,808,821,828,866,884],[282,283,405,408,471,479,483,486,488,489,490,502,807,886],[408,471,479,483,486,488,489,490,502,856,857,858],[405,408,471,479,483,486,488,489,490,502,855],[408,471,479,483,486,488,489,490,502,888],[405,408,471,479,483,486,488,489,490,502,504],[408,471,479,483,486,488,489,490,502,891,893,894],[408,471,479,483,486,488,489,490,502,890],[408,471,479,483,486,488,489,490,502,892],[405,408,471,479,483,486,488,489,490,502,820,825,891],[408,471,479,483,486,488,489,490,502,838],[305,330,405,408,471,479,483,486,488,489,490,502,821,825,826,828,863,864,866,867],[408,471,479,483,486,488,489,490,502,896],[405,408,471,479,483,486,488,489,490,502,538,540],[408,471,479,483,486,488,489,490,502,537,540,541,542,544,545],[408,471,479,483,486,488,489,490,502,538,539],[405,408,471,479,483,486,488,489,490,502,538],[408,471,479,483,486,488,489,490,502,543],[408,471,479,483,486,488,489,490,502,540],[408,471,479,483,486,488,489,490,502,546],[279,283,305,405,408,471,479,483,485,486,487,488,489,490,502,536,807,899,900,901],[408,471,479,483,486,488,489,490,502,902],[408,471,479,483,486,488,489,490,502,903,905,916],[408,471,479,483,486,488,489,490,502,899,900,904],[279,405,408,471,479,483,485,486,487,488,489,490,502,536,899,900,901],[408,471,479,483,485,486,488,489,490,502],[408,471,479,483,486,488,489,490,502,912,914,915],[405,408,471,479,483,486,488,489,490,502,906],[408,471,479,483,486,488,489,490,502,907,908,909,910,911],[305,408,471,479,483,486,488,489,490,502,906],[408,471,479,483,486,488,489,490,502,913],[405,408,471,479,483,486,488,489,490,502,913],[408,471,479,483,486,488,489,490,502,740,742],[408,471,479,483,486,488,489,490,502,739],[248,405,408,471,479,483,486,488,489,490,502,738,741],[408,471,479,483,486,488,489,490,502,741,743,744],[305,405,408,471,479,483,486,488,489,490,502,738],[405,408,471,479,483,486,488,489,490,502,738,739],[408,471,479,483,486,488,489,490,502,745],[408,471,479,483,485,486,488,489,490,502,527,534],[408,471,479,483,485,486,488,489,490,502,527],[408,471,479,483,486,488,489,490,502,920],[408,471,479,482,483,485,486,488,489,490,502,527,528,529,530],[408,471,476,479,482,483,486,488,489,490,502,536],[408,471,479,483,486,488,489,490,502,531,533,535],[408,468,469,471,479,483,486,488,489,490,502],[408,470,471,479,483,486,488,489,490,502],[471,479,483,486,488,489,490,502],[408,471,479,483,486,488,489,490,502,510],[408,471,472,477,479,482,483,486,488,489,490,492,502,507,519],[408,471,472,473,479,482,483,486,488,489,490,502],[408,471,474,479,483,486,488,489,490,502,520],[408,471,475,476,479,483,486,488,489,490,493,502],[408,471,476,479,483,486,488,489,490,502,507,516],[408,471,477,479,482,483,486,488,489,490,492,502],[408,470,471,478,479,483,486,488,489,490,502],[408,471,479,480,483,486,488,489,490,502],[408,471,479,481,482,483,486,488,489,490,502],[408,470,471,479,482,483,486,488,489,490,502],[408,471,479,482,483,484,486,488,489,490,502,507,519],[408,471,479,482,483,484,486,488,489,490,502,507,510],[408,458,471,479,482,483,485,486,488,489,490,492,502,507,519],[408,471,479,482,483,485,486,488,489,490,492,502,507,516,519],[408,471,479,483,485,486,487,488,489,490,502,507,516,519],[406,407,408,409,410,411,412,413,414,415,416,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526],[408,471,479,482,483,486,488,489,490,502],[408,471,479,483,486,488,490,502],[408,471,479,483,486,488,489,490,491,502,519],[408,471,479,482,483,486,488,489,490,492,502,507],[408,471,479,483,486,488,489,490,493,502],[408,471,479,483,486,488,489,490,494,502],[408,471,479,482,483,486,488,489,490,497,502],[408,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526],[408,471,479,483,486,488,489,490,499,502],[408,471,479,483,486,488,489,490,500,502],[408,471,476,479,483,486,488,489,490,492,502,510],[408,471,479,482,483,486,488,489,490,502,503],[408,471,479,483,486,488,489,490,502,504,520,523],[408,471,479,482,483,486,488,489,490,502,507,509,510],[408,471,479,483,486,488,489,490,502,508,510],[408,471,479,483,486,488,489,490,502,510,520],[408,471,479,483,486,488,489,490,502,511],[408,468,471,479,483,486,488,489,490,502,507,513],[408,471,479,483,486,488,489,490,502,507,512],[408,471,479,482,483,486,488,489,490,502,514,515],[408,471,479,483,486,488,489,490,502,514,515],[408,471,476,479,483,486,488,489,490,492,502,507,516],[408,471,479,483,486,488,489,490,502,517],[408,471,479,483,486,488,489,490,492,502,518],[408,471,479,483,485,486,488,489,490,500,502,519],[408,471,479,483,486,488,489,490,502,520,521],[408,471,476,479,483,486,488,489,490,502,521],[408,471,479,483,486,488,489,490,502,507,522],[408,471,479,483,486,488,489,490,491,502,523],[408,471,479,483,486,488,489,490,502,524],[408,471,474,479,483,486,488,489,490,502],[408,471,476,479,483,486,488,489,490,502],[408,471,479,483,486,488,489,490,502,520],[408,458,471,479,483,486,488,489,490,502],[408,471,479,483,486,488,489,490,502,519],[408,471,479,483,486,488,489,490,502,525],[408,471,479,483,486,488,489,490,497,502],[408,471,479,483,486,488,489,490,502,515],[408,458,471,479,482,483,484,486,488,489,490,497,502,507,510,519,522,523,525],[408,471,479,483,486,488,489,490,502,507,526],[408,471,479,483,486,488,489,490,502,536,543,782],[408,471,479,483,486,488,489,490,502,536,543],[408,471,479,483,485,486,488,489,490,502,536],[408,471,479,483,486,488,489,490,502,507,527],[408,471,479,483,485,486,488,489,490,502,527,532],[408,471,479,483,486,488,489,490,502,600,601,602,603,604,605,606,607,608],[408,471,479,483,486,488,489,490,502,527],[60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,76,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,129,130,131,132,133,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,179,180,181,183,192,194,195,196,197,198,199,201,202,204,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,408,471,479,483,486,488,489,490,502],[105,408,471,479,483,486,488,489,490,502],[61,64,408,471,479,483,486,488,489,490,502],[63,408,471,479,483,486,488,489,490,502],[63,64,408,471,479,483,486,488,489,490,502],[60,61,62,64,408,471,479,483,486,488,489,490,502],[61,63,64,221,408,471,479,483,486,488,489,490,502],[64,408,471,479,483,486,488,489,490,502],[60,63,105,408,471,479,483,486,488,489,490,502],[63,64,221,408,471,479,483,486,488,489,490,502],[63,229,408,471,479,483,486,488,489,490,502],[61,63,64,408,471,479,483,486,488,489,490,502],[73,408,471,479,483,486,488,489,490,502],[96,408,471,479,483,486,488,489,490,502],[117,408,471,479,483,486,488,489,490,502],[63,64,105,408,471,479,483,486,488,489,490,502],[64,112,408,471,479,483,486,488,489,490,502],[63,64,105,123,408,471,479,483,486,488,489,490,502],[63,64,123,408,471,479,483,486,488,489,490,502],[64,164,408,471,479,483,486,488,489,490,502],[64,105,408,471,479,483,486,488,489,490,502],[60,64,182,408,471,479,483,486,488,489,490,502],[60,64,183,408,471,479,483,486,488,489,490,502],[205,408,471,479,483,486,488,489,490,502],[189,191,408,471,479,483,486,488,489,490,502],[200,408,471,479,483,486,488,489,490,502],[189,408,471,479,483,486,488,489,490,502],[60,64,182,189,190,408,471,479,483,486,488,489,490,502],[182,183,191,408,471,479,483,486,488,489,490,502],[203,408,471,479,483,486,488,489,490,502],[60,64,189,190,191,408,471,479,483,486,488,489,490,502],[62,63,64,408,471,479,483,486,488,489,490,502],[60,64,408,471,479,483,486,488,489,490,502],[61,63,183,184,185,186,408,471,479,483,486,488,489,490,502],[105,183,184,185,186,408,471,479,483,486,488,489,490,502],[183,185,408,471,479,483,486,488,489,490,502],[63,184,185,187,188,192,408,471,479,483,486,488,489,490,502],[60,63,408,471,479,483,486,488,489,490,502],[64,207,408,471,479,483,486,488,489,490,502],[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,106,107,108,109,110,111,113,114,115,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,408,471,479,483,486,488,489,490,502],[193,408,471,479,483,486,488,489,490,502],[408,471,479,483,486,488,489,490,502,618,619,621,622,624,625,628],[408,471,479,483,486,488,489,490,502,611,619,627],[408,471,479,483,486,488,489,490,502,619,628],[408,471,479,483,486,488,489,490,502,611,618,619,621,622,625],[408,471,479,483,486,488,489,490,502,611,619],[408,471,479,483,486,488,489,490,502,619],[53,408,471,479,483,486,488,489,490,502,611,625],[408,471,479,483,486,488,489,490,502,618,619,621,622,624],[408,471,479,483,486,488,489,490,502,611],[408,471,479,483,486,488,489,490,502,636],[408,471,479,483,486,488,489,490,502,570,636],[53,408,471,479,483,486,488,489,490,502,570,618,636,674],[408,471,479,483,486,488,489,490,502,612,613,614,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737],[408,471,479,483,486,488,489,490,502,691],[53,408,471,479,483,486,488,489,490,502,611],[408,471,479,483,486,488,489,490,502,611,612,613,614,615,617],[408,471,479,483,486,488,489,490,502,618],[408,471,479,483,486,488,489,490,502,618,689],[408,471,479,483,486,488,489,490,502,694,696],[408,471,479,483,486,488,489,490,502,611,694,695],[408,471,479,483,486,488,489,490,502,618,696],[408,471,479,483,486,488,489,490,502,694],[408,471,479,483,486,488,489,490,502,695,696],[408,471,479,483,486,488,489,490,502,616,738],[408,471,479,483,486,488,489,490,502,611,618],[408,471,479,483,486,488,489,490,502,618,623],[408,471,479,483,486,488,489,490,502,611,618,623,738],[408,471,479,483,486,488,489,490,502,571],[408,471,479,483,486,488,489,490,502,555,571],[408,471,479,483,486,488,489,490,502,549,555,571],[408,471,479,483,486,488,489,490,502,555,556,557,558,559],[408,471,479,483,486,488,489,490,502,549,550,552,565,566,568,571,572],[408,471,479,483,486,488,489,490,502,552,562,568,571],[408,471,479,483,486,488,489,490,502,573],[408,471,479,483,486,488,489,490,502,573,611],[408,471,479,483,486,488,489,490,502,578],[408,471,479,483,486,488,489,490,502,574],[408,471,479,483,486,488,489,490,502,573,574],[408,471,479,483,486,488,489,490,502,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598],[408,471,479,483,486,488,489,490,502,573,585],[408,471,479,483,486,488,489,490,502,561,562,567,568,569,571,572],[408,471,479,483,486,488,489,490,502,549,550,551,552,553,554,560,565,567,568,571,572,599,610],[408,471,479,483,486,488,489,490,502,568,571],[408,471,479,483,486,488,489,490,502,549,550,554,560,561,566,567,568,570,572,611],[408,471,479,483,486,488,489,490,502,552,561,562,563,564,565,567,570,571,572,611],[408,471,479,483,486,488,489,490,502,550,568,571],[408,471,479,483,486,488,489,490,502,549,571,611],[408,471,479,483,486,488,489,490,502,609],[408,424,427,430,431,471,479,483,486,488,489,490,502,519],[408,427,471,479,483,486,488,489,490,502,507,519],[408,427,431,471,479,483,486,488,489,490,502,519],[408,471,479,483,486,488,489,490,502,507],[408,421,471,479,483,486,488,489,490,502],[408,425,471,479,483,486,488,489,490,502],[408,423,424,427,471,479,483,486,488,489,490,502,519],[408,471,479,483,486,488,489,490,492,502,516],[408,421,471,479,483,486,488,489,490,502,527],[408,423,427,471,479,483,486,488,489,490,492,502,519],[408,418,419,420,422,426,471,479,482,483,486,488,489,490,502,507,519],[408,427,435,443,471,479,483,486,488,489,490,502],[408,419,425,471,479,483,486,488,489,490,502],[408,427,452,453,471,479,483,486,488,489,490,502],[408,419,422,427,471,479,483,486,488,489,490,502,510,519,527],[408,427,471,479,483,486,488,489,490,502],[408,423,427,471,479,483,486,488,489,490,502,519],[408,418,471,479,483,486,488,489,490,502],[408,421,422,423,425,426,427,428,429,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,453,454,455,456,457,471,479,483,486,488,489,490,502],[408,427,445,448,471,479,483,486,488,489,490,502],[408,427,435,436,437,471,479,483,486,488,489,490,502],[408,425,427,436,438,471,479,483,486,488,489,490,502],[408,426,471,479,483,486,488,489,490,502],[408,419,421,427,471,479,483,486,488,489,490,502],[408,427,431,436,438,471,479,483,486,488,489,490,502],[408,431,471,479,483,486,488,489,490,502],[408,425,427,430,471,479,483,486,488,489,490,502,519],[408,419,423,427,435,471,479,483,486,488,489,490,502],[408,427,445,471,479,483,486,488,489,490,502],[408,438,471,479,483,486,488,489,490,502],[408,421,427,452,471,479,483,486,488,489,490,502,510,525,527],[405,408,471,479,483,486,488,489,490,502,536,548,757,758],[405,408,471,479,483,486,488,489,490,502,759,777,779,781,786,788,791,795,798,801,804,805],[405,408,471,479,483,486,488,489,490,502,547,780,781,784,785],[405,408,471,479,483,486,488,489,490,502,757],[405,408,471,479,483,486,488,489,490,502,547],[405,408,471,479,483,486,488,489,490,502,547,780,783],[405,408,471,479,483,486,488,489,490,502,547,757],[405,408,471,479,483,486,488,489,490,502,536],[405,408,471,479,483,486,488,489,490,502,536,746,752,754,758,787],[405,408,471,479,483,486,488,489,490,502,746,752,754,788,789,790],[405,408,471,479,483,486,488,489,490,502,758,787],[405,408,471,479,483,486,488,489,490,502,746,747,748,749,750,751,752,753,754,755,756,777,778],[405,408,471,479,483,486,488,489,490,502,758,799],[405,408,471,479,483,486,488,489,490,502,746,749,799,800],[405,408,471,479,483,486,488,489,490,502,611,746,749],[405,408,471,479,483,486,488,489,490,502,536,758,796],[405,408,471,479,483,486,488,489,490,502,746,754,756,788,796,797],[405,408,471,479,483,486,488,489,490,502,746,754,756,787],[408,471,479,483,486,488,489,490,494,502,543,806,898,917,918],[405,408,471,479,483,486,488,489,490,502,536,758,802],[405,408,471,479,483,486,488,489,490,502,746,747,748,749,788,802,803],[405,408,471,479,483,486,488,489,490,502,746,747,748,749,787],[405,408,471,479,483,486,488,489,490,502,536,746,749,750,751,752,753,758,787,793],[405,408,471,479,483,486,488,489,490,502,746,749,750,751,752,753,778,793,794],[405,408,471,479,483,486,488,489,490,502,611,746,749,777,778,792],[408,471,479,483,486,488,489,490,502,738],[408,471,479,483,486,488,489,490,502,738,756],[408,471,479,483,486,488,489,490,502,738,748,750],[408,471,479,483,486,488,489,490,502,738,749,751],[408,471,479,483,486,488,489,490,502,738,748,756],[408,471,479,483,486,488,489,490,502,738,750,756],[408,471,479,483,486,488,489,490,502,738,747,749],[408,471,479,483,486,488,489,490,502,738,747,751,752,753,754,755],[405,408,471,479,483,486,488,489,490,502,746,756,757],[405,408,471,479,483,486,488,489,490,502,746,756],[405,408,471,479,483,486,488,489,490,502,746,747,748,749,750,751,752,753,755,756,787],[405,408,471,479,483,486,488,489,490,502,611,746,747,748,749,750,751,752,753,755,756]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"196cb558a13d4533a5163286f30b0509ce0210e4b316c56c38d4c0fd2fb38405","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"1d242d5c24cf285c88bc4fb93c5ff903de8319064e282986edeb6247ba028d5e","impliedFormat":1},{"version":"8d6d51a5118d000ed3bfe6e1dd1335bebfff3fef23cd2af2f84a24d30f90cc90","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d8dedbec739bc79642c1e96e9bfc0b83b25b104a0486aebf016fc7b85b39f48","impliedFormat":1},{"version":"e89535c3ec439608bcd0f68af555d0e5ddf121c54abe69343549718bd7506b9c","impliedFormat":1},{"version":"622a984b60c294ffb2f9152cf1d4d12e91d2b733d820eec949cf54d63a3c1025","impliedFormat":1},{"version":"81aae92abdeaccd9c1723cef39232c90c1aed9d9cf199e6e2a523b7d8e058a11","impliedFormat":1},{"version":"a63a6c6806a1e519688ef7bd8ca57be912fc0764485119dbd923021eb4e79665","impliedFormat":1},{"version":"75b57b109d774acca1e151df21cf5cb54c7a1df33a273f0457b9aee4ebd36fb9","impliedFormat":1},{"version":"073ca26c96184db9941b5ec0ddea6981c9b816156d9095747809e524fdd90e35","impliedFormat":1},{"version":"e41d17a2ec23306d953cda34e573ed62954ca6ea9b8c8b74e013d07a6886ce47","impliedFormat":1},{"version":"241bd4add06f06f0699dcd58f3b334718d85e3045d9e9d4fa556f11f4d1569c1","impliedFormat":1},{"version":"2ae3787e1498b20aad1b9c2ee9ea517ec30e89b70d242d8e3e52d1e091039695","impliedFormat":1},{"version":"c7c72c4cffb1bc83617eefed71ed68cc89df73cab9e19507ccdecb3e72b4967e","affectsGlobalScope":true,"impliedFormat":1},{"version":"b8bff8a60af0173430b18d9c3e5c443eaa3c515617210c0c7b3d2e1743c19ecb","impliedFormat":1},{"version":"38b38db08e7121828294dec10957a7a9ff263e33e2a904b346516d4a4acca482","impliedFormat":1},{"version":"a76ebdf2579e68e4cfe618269c47e5a12a4e045c2805ed7f7ab37af8daa6b091","impliedFormat":1},{"version":"8a2aaea564939c22be05d665cc955996721bad6d43148f8fa21ae8f64afecd37","impliedFormat":1},{"version":"e59d36b7b6e8ba2dd36d032a5f5c279d2460968c8b4e691ca384f118fb09b52a","impliedFormat":1},{"version":"e96885c0684c9042ec72a9a43ef977f6b4b4a2728f4b9e737edcbaa0c74e5bf6","impliedFormat":1},{"version":"95950a187596e206d32d5d9c7b932901088c65ed8f9040e614aa8e321e0225ef","impliedFormat":1},{"version":"89e061244da3fc21b7330f4bd32f47c1813dd4d7f1dc3d0883d88943f035b993","impliedFormat":1},{"version":"e46558c2e04d06207b080138678020448e7fc201f3d69c2601b0d1456105f29a","impliedFormat":1},{"version":"71549375db52b1163411dba383b5f4618bdf35dc57fa327a1c7d135cf9bf67d1","impliedFormat":1},{"version":"7e6b2d61d6215a4e82ea75bc31a80ebb8ad0c2b37a60c10c70dd671e8d9d6d5d","impliedFormat":1},{"version":"78bea05df2896083cca28ed75784dde46d4b194984e8fc559123b56873580a23","impliedFormat":1},{"version":"5dd04ced37b7ea09f29d277db11f160df7fd73ba8b9dba86cb25552e0653a637","impliedFormat":1},{"version":"f74b81712e06605677ae1f061600201c425430151f95b5ef4d04387ad7617e6a","impliedFormat":1},{"version":"9a72847fcf4ac937e352d40810f7b7aec7422d9178451148296cf1aa19467620","impliedFormat":1},{"version":"3ae18f60e0b96fa1e025059b7d25b3247ba4dcb5f4372f6d6e67ce2adac74eac","impliedFormat":1},{"version":"2b9260f44a2e071450ae82c110f5dc8f330c9e5c3e85567ed97248330f2bf639","impliedFormat":1},{"version":"4f196e13684186bda6f5115fc4677a87cf84a0c9c4fc17b8f51e0984f3697b6d","impliedFormat":1},{"version":"61419f2c5822b28c1ea483258437c1faab87d00c6f84481aa22afb3380d8e9a4","impliedFormat":1},{"version":"64479aee03812264e421c0bf5104a953ca7b02740ba80090aead1330d0effe91","impliedFormat":1},{"version":"0521108c9f8ddb17654a0a54dae6ba9667c99eddccfd6af5748113e022d1c37a","impliedFormat":1},{"version":"c5570e504be103e255d80c60b56c367bf45d502ca52ee35c55dec882f6563b5c","impliedFormat":1},{"version":"ee764e6e9a7f2b987cc1a2c0a9afd7a8f4d5ebc4fdb66ad557a7f14a8c2bd320","impliedFormat":1},{"version":"0520b5093712c10c6ef23b5fea2f833bf5481771977112500045e5ea7e8e2b69","impliedFormat":1},{"version":"5c3cf26654cf762ac4d7fd7b83f09acfe08eef88d2d6983b9a5a423cb4004ca3","impliedFormat":1},{"version":"e60fa19cf7911c1623b891155d7eb6b7e844e9afdf5738e3b46f3b687730a2bd","impliedFormat":1},{"version":"b1fd72ff2bb0ba91bb588f3e5329f8fc884eb859794f1c4657a2bfa122ae54d0","impliedFormat":1},{"version":"6cf42a4f3cfec648545925d43afaa8bb364ac10a839ffed88249da109361b275","impliedFormat":1},{"version":"d7058e75920120b142a9d57be25562a3cd9a936269fd52908505f530105f2ec4","impliedFormat":1},{"version":"6df52b70d7f7702202f672541a5f4a424d478ee5be51a9d37b8ccbe1dbf3c0f2","impliedFormat":1},{"version":"0ca7f997e9a4d8985e842b7c882e521b6f63233c4086e9fe79dd7a9dc4742b5e","impliedFormat":1},{"version":"91046b5c6b55d3b194c81fd4df52f687736fad3095e9d103ead92bb64dc160ee","impliedFormat":1},{"version":"db5704fdad56c74dfc5941283c1182ed471bd17598209d3ac4a49faa72e43cfc","impliedFormat":1},{"version":"758e8e89559b02b81bc0f8fd395b17ad5aff75490c862cbe369bb1a3d1577c40","impliedFormat":1},{"version":"2ee64342c077b1868f1834c063f575063051edd6e2964257d34aad032d6b657c","impliedFormat":1},{"version":"6f6b4b3d670b6a5f0e24ea001c1b3d36453c539195e875687950a178f1730fa7","impliedFormat":1},{"version":"a472a1d3f25ce13a1d44911cd3983956ac040ce2018e155435ea34afb25f864c","impliedFormat":1},{"version":"b48b83a86dd9cfe36f8776b3ff52fcd45b0e043c0538dc4a4b149ba45fe367b9","impliedFormat":1},{"version":"792de5c062444bd2ee0413fb766e57e03cce7cdaebbfc52fc0c7c8e95069c96b","impliedFormat":1},{"version":"a79e3e81094c7a04a885bad9b049c519aace53300fb8a0fe4f26727cb5a746ce","impliedFormat":1},{"version":"93181bac0d90db185bb730c95214f6118ae997fe836a98a49664147fbcaf1988","impliedFormat":1},{"version":"8a4e89564d8ea66ad87ee3762e07540f9f0656a62043c910d819b4746fc429c5","impliedFormat":1},{"version":"b9011d99942889a0f95e120d06b698c628b0b6fdc3e6b7ecb459b97ed7d5bcc6","impliedFormat":1},{"version":"4d639cbbcc2f8f9ce6d55d5d503830d6c2556251df332dc5255d75af53c8a0e7","impliedFormat":1},{"version":"cdb48277f600ab5f429ecf1c5ea046683bc6b9f73f3deab9a100adac4b34969c","impliedFormat":1},{"version":"75be84956a29040a1afbe864c0a7a369dfdb739380072484eff153905ef867ee","impliedFormat":1},{"version":"b06b4adc2ae03331a92abd1b19af8eb91ec2bf8541747ee355887a167d53145e","impliedFormat":1},{"version":"c54166a85bd60f86d1ebb90ce0117c0ecb850b8a33b366691629fdf26f1bbbd8","impliedFormat":1},{"version":"0d417c15c5c635384d5f1819cc253a540fe786cc3fda32f6a2ae266671506a21","impliedFormat":1},{"version":"80f23f1d60fbed356f726b3b26f9d348dddbb34027926d10d59fad961e70a730","impliedFormat":1},{"version":"cb59317243a11379a101eb2f27b9df1022674c3df1df0727360a0a3f963f523b","impliedFormat":1},{"version":"cc20bb2227dd5de0aab0c8d697d1572f8000550e62c7bf5c92f212f657dd88c5","impliedFormat":1},{"version":"06b8a7d46195b6b3980e523ef59746702fd210b71681a83a5cf73799623621f9","impliedFormat":1},{"version":"860e4405959f646c101b8005a191298b2381af8f33716dc5f42097e4620608f8","impliedFormat":1},{"version":"f7e32adf714b8f25d3c1783473abec3f2e82d5724538d8dcf6f51baaaff1ca7a","impliedFormat":1},{"version":"d0da80c845999a16c24d0783033fb5366ada98df17867c98ad433ede05cd87fd","impliedFormat":1},{"version":"bfbf80f9cd4558af2d7b2006065340aaaced15947d590045253ded50aabb9bc5","impliedFormat":1},{"version":"fd9a991b51870325e46ebb0e6e18722d313f60cd8e596e645ec5ac15b96dbf4e","impliedFormat":1},{"version":"c3bd2b94e4298f81743d92945b80e9b56c1cdfb2bef43c149b7106a2491b1fc9","impliedFormat":1},{"version":"a246cce57f558f9ebaffd55c1e5673da44ea603b4da3b2b47eb88915d30a9181","impliedFormat":1},{"version":"d993eacc103c5a065227153c9aae8acea3a4322fe1a169ee7c70b77015bf0bb2","impliedFormat":1},{"version":"fc2b03d0c042aa1627406e753a26a1eaad01b3c496510a78016822ef8d456bb6","impliedFormat":1},{"version":"063c7ebbe756f0155a8b453f410ca6b76ffa1bbc1048735bcaf9c7c81a1ce35f","impliedFormat":1},{"version":"314e402cd481370d08f63051ae8b8c8e6370db5ee3b8820eeeaaf8d722a6dac6","impliedFormat":1},{"version":"9669075ac38ce36b638b290ba468233980d9f38bdc62f0519213b2fd3e2552ec","impliedFormat":1},{"version":"4d123de012c24e2f373925100be73d50517ac490f9ed3578ac82d0168bfbd303","impliedFormat":1},{"version":"656c9af789629aa36b39092bee3757034009620439d9a39912f587538033ce28","impliedFormat":1},{"version":"3ac3f4bdb8c0905d4c3035d6f7fb20118c21e8a17bee46d3735195b0c2a9f39f","impliedFormat":1},{"version":"1f453e6798ed29c86f703e9b41662640d4f2e61337007f27ac1c616f20093f69","impliedFormat":1},{"version":"af43b7871ff21c62bf1a54ec5c488e31a8d3408d5b51ff2e9f8581b6c55f2fc7","impliedFormat":1},{"version":"70550511d25cbb0b6a64dcac7fffc3c1397fd4cbeb6b23ccc7f9b794ab8a6954","impliedFormat":1},{"version":"af0fbf08386603a62f2a78c42d998c90353b1f1d22e05a384545f7accf881e0a","impliedFormat":1},{"version":"cefc20054d20b85b534206dbcedd509bb74f87f3d8bc45c58c7be3a76caa45e1","impliedFormat":1},{"version":"ad6eee4877d0f7e5244d34bc5026fd6e9cf8e66c5c79416b73f9f6ebf132f924","impliedFormat":1},{"version":"4888fd2bcfee9a0ce89d0df860d233e0cee8ee9c479b6bd5a5d5f9aae98342fe","impliedFormat":1},{"version":"f4749c102ced952aa6f40f0b579865429c4869f6d83df91000e98005476bee87","impliedFormat":1},{"version":"56654d2c5923598384e71cb808fac2818ca3f07dd23bb018988a39d5e64f268b","impliedFormat":1},{"version":"8b6719d3b9e65863da5390cb26994602c10a315aa16e7d70778a63fee6c4c079","impliedFormat":1},{"version":"05f56cd4b929977d18df8f3d08a4c929a2592ef5af083e79974b20a063f30940","impliedFormat":1},{"version":"547d3c406a21b30e2b78629ecc0b2ddaf652d9e0bdb2d59ceebce5612906df33","impliedFormat":1},{"version":"b3a4f9385279443c3a5568ec914a9492b59a723386161fd5ef0619d9f8982f97","impliedFormat":1},{"version":"3fe66aba4fbe0c3ba196a4f9ed2a776fe99dc4d1567a558fb11693e9fcc4e6ed","impliedFormat":1},{"version":"140eef237c7db06fc5adcb5df434ee21e81ee3a6fd57e1a75b8b3750aa2df2d8","impliedFormat":1},{"version":"0944ec553e4744efae790c68807a461720cff9f3977d4911ac0d918a17c9dd99","impliedFormat":1},{"version":"cb46b38d5e791acaa243bf342b8b5f8491639847463ac965b93896d4fb0af0d9","impliedFormat":1},{"version":"7c7d9e116fe51100ff766703e6b5e4424f51ad8977fe474ddd8d0959aa6de257","impliedFormat":1},{"version":"af70a2567e586be0083df3938b6a6792e6821363d8ef559ad8d721a33a5bcdaf","impliedFormat":1},{"version":"006cff3a8bcb92d77953f49a94cd7d5272fef4ab488b9052ef82b6a1260d870b","impliedFormat":1},{"version":"7d44bfdc8ee5e9af70738ff652c622ae3ad81815e63ab49bdc593d34cb3a68e5","impliedFormat":1},{"version":"339814517abd4dbc7b5f013dfd3b5e37ef0ea914a8bbe65413ecffd668792bc6","impliedFormat":1},{"version":"34d5bc0a6958967ec237c99f980155b5145b76e6eb927c9ffc57d8680326b5d8","impliedFormat":1},{"version":"9eae79b70c9d8288032cbe1b21d0941f6bd4f315e14786b2c1d10bccc634e897","impliedFormat":1},{"version":"18ce015ed308ea469b13b17f99ce53bbb97975855b2a09b86c052eefa4aa013a","impliedFormat":1},{"version":"5a931bc4106194e474be141e0bc1046629510dc95b9a0e4b02a3783847222965","impliedFormat":1},{"version":"5e5f371bf23d5ced2212a5ff56675aefbd0c9b3f4d4fdda1b6123ac6e28f058c","impliedFormat":1},{"version":"907c17ad5a05eecb29b42b36cc8fec6437be27cc4986bb3a218e4f74f606911c","impliedFormat":1},{"version":"ce60a562cd2a92f37a88f2ddd99a3abfbc5848d7baf38c48fb8d3243701fcb75","impliedFormat":1},{"version":"a726ad2d0a98bfffbe8bc1cd2d90b6d831638c0adc750ce73103a471eb9a891c","impliedFormat":1},{"version":"f44c0c8ce58d3dacac016607a1a90e5342d830ea84c48d2e571408087ae55894","impliedFormat":1},{"version":"75a315a098e630e734d9bc932d9841b64b30f7a349a20cf4717bf93044eff113","impliedFormat":1},{"version":"9131d95e32b3d4611d4046a613e022637348f6cebfe68230d4e81b691e4761a1","impliedFormat":1},{"version":"b03aa292cfdcd4edc3af00a7dbd71136dd067ec70a7536b655b82f4dd444e857","impliedFormat":1},{"version":"b6e2b0448ced813b8c207810d96551a26e7d7bb73255eea4b9701698f78846d6","impliedFormat":1},{"version":"8ae10cd85c1bd94d2f2d17c4cbd25c068a4b2471c70c2d96434239f97040747a","impliedFormat":1},{"version":"9ed5b799c50467b0c9f81ddf544b6bcda3e34d92076d6cab183c84511e45c39f","impliedFormat":1},{"version":"b4fa87cc1833839e51c49f20de71230e259c15b2c9c3e89e4814acc1d1ef10de","impliedFormat":1},{"version":"e90ac9e4ac0326faa1bc39f37af38ace0f9d4a655cd6d147713c653139cf4928","impliedFormat":1},{"version":"ea27110249d12e072956473a86fd1965df8e1be985f3b686b4e277afefdde584","impliedFormat":1},{"version":"8776a368617ce51129b74db7d55c3373dadcce5d0701e61d106e99998922a239","impliedFormat":1},{"version":"5666075052877fe2fdddd5b16de03168076cf0f03fbca5c1d4a3b8f43cba570c","impliedFormat":1},{"version":"9108ab5af05418f599ab48186193b1b07034c79a4a212a7f73535903ba4ca249","impliedFormat":1},{"version":"bb4e2cdcadf9c9e6ee2820af23cee6582d47c9c9c13b0dca1baaffe01fbbcb5f","impliedFormat":1},{"version":"6e30d0b5a1441d831d19fe02300ab3d83726abd5141cbcc0e2993fa0efd33db4","impliedFormat":1},{"version":"423f28126b2fc8d8d6fa558035309000a1297ed24473c595b7dec52e5c7ebae5","impliedFormat":1},{"version":"fb30734f82083d4790775dae393cd004924ebcbfde49849d9430bf0f0229dd16","impliedFormat":1},{"version":"2c92b04a7a4a1cd9501e1be338bf435738964130fb2ad5bd6c339ee41224ac4c","impliedFormat":1},{"version":"c5c5f0157b41833180419dacfbd2bcce78fb1a51c136bd4bcba5249864d8b9b5","impliedFormat":1},{"version":"02ae43d5bae42efcd5a00d3923e764895ce056bca005a9f4e623aa6b4797c8af","impliedFormat":1},{"version":"db6e01f17012a9d7b610ae764f94a1af850f5d98c9c826ad61747dca0fb800bd","impliedFormat":1},{"version":"8a44b424edee7bb17dc35a558cc15f92555f14a0441205613e0e50452ab3a602","impliedFormat":1},{"version":"24a00d0f98b799e6f628373249ece352b328089c3383b5606214357e9107e7d5","impliedFormat":1},{"version":"33637e3bc64edd2075d4071c55d60b32bdb0d243652977c66c964021b6fc8066","impliedFormat":1},{"version":"0f0ad9f14dedfdca37260931fac1edf0f6b951c629e84027255512f06a6ebc4c","impliedFormat":1},{"version":"16ad86c48bf950f5a480dc812b64225ca4a071827d3d18ffc5ec1ae176399e36","impliedFormat":1},{"version":"8cbf55a11ff59fd2b8e39a4aa08e25c5ddce46e3af0ed71fb51610607a13c505","impliedFormat":1},{"version":"d5bc4544938741f5daf8f3a339bfbf0d880da9e89e79f44a6383aaf056fe0159","impliedFormat":1},{"version":"97f9169882d393e6f303f570168ca86b5fe9aab556e9a43672dae7e6bb8e6495","impliedFormat":1},{"version":"7c9adb3fcd7851497818120b7e151465406e711d6a596a71b807f3a17853cb58","impliedFormat":1},{"version":"6752d402f9282dd6f6317c8c048aaaac27295739a166eed27e00391b358fed9a","impliedFormat":1},{"version":"9fd7466b77020847dbc9d2165829796bf7ea00895b2520ff3752ffdcff53564b","impliedFormat":1},{"version":"fbfc12d54a4488c2eb166ed63bab0fb34413e97069af273210cf39da5280c8d6","impliedFormat":1},{"version":"85a84240002b7cf577cec637167f0383409d086e3c4443852ca248fc6e16711e","impliedFormat":1},{"version":"84794e3abd045880e0fadcf062b648faf982aa80cfc56d28d80120e298178626","impliedFormat":1},{"version":"053d8b827286a16a669a36ffc8ccc8acdf8cc154c096610aa12348b8c493c7b8","impliedFormat":1},{"version":"3cce4ce031710970fe12d4f7834375f5fd455aa129af4c11eb787935923ff551","impliedFormat":1},{"version":"8f62cbd3afbd6a07bb8c934294b6bfbe437021b89e53a4da7de2648ecfc7af25","impliedFormat":1},{"version":"62c3621d34fb2567c17a2c4b89914ebefbfbd1b1b875b070391a7d4f722e55dc","impliedFormat":1},{"version":"c05ac811542e0b59cb9c2e8f60e983461f0b0e39cea93e320fad447ff8e474f3","impliedFormat":1},{"version":"8e7a5b8f867b99cc8763c0b024068fb58e09f7da2c4810c12833e1ca6eb11c4f","impliedFormat":1},{"version":"132351cbd8437a463757d3510258d0fa98fd3ebef336f56d6f359cf3e177a3ce","impliedFormat":1},{"version":"df877050b04c29b9f8409aa10278d586825f511f0841d1ec41b6554f8362092b","impliedFormat":1},{"version":"33d1888c3c27d3180b7fd20bac84e97ecad94b49830d5dd306f9e770213027d1","impliedFormat":1},{"version":"ee942c58036a0de88505ffd7c129f86125b783888288c2389330168677d6347f","impliedFormat":1},{"version":"a3f317d500c30ea56d41501632cdcc376dae6d24770563a5e59c039e1c2a08ec","impliedFormat":1},{"version":"eb21ddc3a8136a12e69176531197def71dc28ffaf357b74d4bf83407bd845991","impliedFormat":1},{"version":"0c1651a159995dfa784c57b4ea9944f16bdf8d924ed2d8b3db5c25d25749a343","impliedFormat":1},{"version":"aaa13958e03409d72e179b5d7f6ec5c6cc666b7be14773ae7b6b5ee4921e52db","impliedFormat":1},{"version":"0a86e049843ad02977a94bb9cdfec287a6c5a0a4b6b5391a6648b1a122072c5a","impliedFormat":1},{"version":"40f06693e2e3e58526b713c937895c02e113552dc8ba81ecd49cdd9596567ddb","impliedFormat":1},{"version":"4ed5e1992aedb174fb8f5aa8796aa6d4dcb8bd819b4af1b162a222b680a37fa0","impliedFormat":1},{"version":"d7f4bd46a8b97232ea6f8c28012b8d2b995e55e729d11405f159d3e00c51420a","impliedFormat":1},{"version":"d604d413aff031f4bfbdae1560e54ebf503d374464d76d50a2c6ded4df525712","impliedFormat":1},{"version":"e4f4f9cf1e3ac9fd91ada072e4d428ecbf0aa6dc57138fb797b8a0ca3a1d521c","impliedFormat":1},{"version":"12bfd290936824373edda13f48a4094adee93239b9a73432db603127881a300d","impliedFormat":1},{"version":"340ceb3ea308f8e98264988a663640e567c553b8d6dc7d5e43a8f3b64f780374","impliedFormat":1},{"version":"c5a769564e530fba3ec696d0a5cff1709b9095a0bdf5b0826d940d2fc9786413","impliedFormat":1},{"version":"7124ef724c3fc833a17896f2d994c368230a8d4b235baed39aa8037db31de54f","impliedFormat":1},{"version":"5de1c0759a76e7710f76899dcae601386424eab11fb2efaf190f2b0f09c3d3d3","impliedFormat":1},{"version":"9c5ee8f7e581f045b6be979f062a61bf076d362bf89c7f966b993a23424e8b0d","impliedFormat":1},{"version":"1a11df987948a86aa1ec4867907c59bdf431f13ed2270444bf47f788a5c7f92d","impliedFormat":1},{"version":"8018dd2e95e7ce6e613ddd81672a54532614dc745520a2f9e3860ff7fb1be0ca","impliedFormat":1},{"version":"b756781cd40d465da57d1fc6a442c34ae61fe8c802d752aace24f6a43fedacee","impliedFormat":1},{"version":"0fe76167c87289ea094e01616dcbab795c11b56bad23e1ef8aba9aa37e93432a","impliedFormat":1},{"version":"3a45029dba46b1f091e8dc4d784e7be970e209cd7d4ff02bd15270a98a9ba24b","impliedFormat":1},{"version":"032c1581f921f8874cf42966f27fd04afcabbb7878fa708a8251cac5415a2a06","impliedFormat":1},{"version":"69c68ed9652842ce4b8e495d63d2cd425862104c9fb7661f72e7aa8a9ef836f8","impliedFormat":1},{"version":"0e704ee6e9fd8b6a5a7167886f4d8915f4bc22ed79f19cb7b32bd28458f50643","impliedFormat":1},{"version":"06f62a14599a68bcde148d1efd60c2e52e8fa540cc7dcfa4477af132bb3de271","impliedFormat":1},{"version":"904a96f84b1bcee9a7f0f258d17f8692e6652a0390566515fe6741a5c6db8c1c","impliedFormat":1},{"version":"11f19ce32d21222419cecab448fa335017ebebf4f9e5457c4fa9df42fa2dcca7","impliedFormat":1},{"version":"2e8ee2cbb5e9159764e2189cf5547aebd0e6b0d9a64d479397bb051cd1991744","impliedFormat":1},{"version":"1b0471d75f5adb7f545c1a97c02a0f825851b95fe6e069ac6ecaa461b8bb321d","impliedFormat":1},{"version":"1d157c31a02b1e5cca9bc495b3d8d39f4b42b409da79f863fb953fbe3c7d4884","impliedFormat":1},{"version":"07baaceaec03d88a4b78cb0651b25f1ae0322ac1aa0b555ae3749a79a41cba86","impliedFormat":1},{"version":"619a132f634b4ebe5b4b4179ea5870f62f2cb09916a25957bff17b408de8b56d","impliedFormat":1},{"version":"f60fa446a397eb1aead9c4e568faf2df8068b4d0306ebc075fb4be16ed26b741","impliedFormat":1},{"version":"f3cb784be4d9e91f966a0b5052a098d9b53b0af0d341f690585b0cc05c6ca412","impliedFormat":1},{"version":"350f63439f8fe2e06c97368ddc7fb6d6c676d54f59520966f7dbbe6a4586014e","impliedFormat":1},{"version":"eba613b9b357ac8c50a925fa31dc7e65ff3b95a07efbaa684b624f143d8d34ba","impliedFormat":1},{"version":"45b74185005ed45bec3f07cac6e4d68eaf02ead9ff5a66721679fb28020e5e7c","impliedFormat":1},{"version":"0f6199602df09bdb12b95b5434f5d7474b1490d2cd8cc036364ab3ba6fd24263","impliedFormat":1},{"version":"c8ca7fd9ec7a3ec82185bfc8213e4a7f63ae748fd6fced931741d23ef4ea3c0f","impliedFormat":1},{"version":"5c6a8a3c2a8d059f0592d4eab59b062210a1c871117968b10797dee36d991ef7","impliedFormat":1},{"version":"ad77fd25ece8e09247040826a777dc181f974d28257c9cd5acb4921b51967bd8","impliedFormat":1},{"version":"795a08ae4e193f345073b49f68826ab6a9b280400b440906e4ec5c237ae777e6","impliedFormat":1},{"version":"8153df63cf65122809db17128e5918f59d6bb43a371b5218f4430c4585f64085","impliedFormat":1},{"version":"a8150bc382dd12ce58e00764d2366e1d59a590288ee3123af8a4a2cb4ef7f9df","impliedFormat":1},{"version":"5adfaf2f9f33957264ad199a186456a4676b2724ed700fc313ff945d03372169","impliedFormat":1},{"version":"d5c41a741cd408c34cb91f84468f70e9bda3dfeabf33251a61039b3cdb8b22d8","impliedFormat":1},{"version":"a20c3e0fe86a1d8fc500a0e9afec9a872ad3ab5b746ceb3dd7118c6d2bff4328","impliedFormat":1},{"version":"cbaf4a4aa8a8c02aa681c5870d5c69127974de29b7e01df570edec391a417959","impliedFormat":1},{"version":"c7135e329a18b0e712378d5c7bc2faec6f5ab0e955ea0002250f9e232af8b3e4","impliedFormat":1},{"version":"340a45cd77b41d8a6deda248167fa23d3dc67ec798d411bd282f7b3d555b1695","impliedFormat":1},{"version":"fae330f86bc10db6841b310f32367aaa6f553036a3afc426e0389ddc5566cd74","impliedFormat":1},{"version":"2bee1efe53481e93bb8b31736caba17353e7bb6fc04520bd312f4e344afd92f9","impliedFormat":1},{"version":"357b67529139e293a0814cb5b980c3487717c6fbf7c30934d67bc42dad316871","impliedFormat":1},{"version":"99d99a765426accf8133737843fb024a154dc6545fc0ffbba968a7c0b848959d","impliedFormat":1},{"version":"c782c5fd5fa5491c827ecade05c3af3351201dd1c7e77e06711c8029b7a9ee4d","impliedFormat":1},{"version":"883d2104e448bb351c49dd9689a7e8117b480b614b2622732655cef03021bf6d","impliedFormat":1},{"version":"d9b00ee2eca9b149663fdba1c1956331841ae296ee03eaaff6c5becbc0ff1ea8","impliedFormat":1},{"version":"09a7e04beb0547c43270b327c067c85a4e2154372417390731dfe092c4350998","impliedFormat":1},{"version":"eee530aaa93e9ec362e3941ee8355e2d073c7b21d88c2af4713e3d701dab8fef","impliedFormat":1},{"version":"28d47319b97dbeee9130b78eae03b2061d46dedbf92b0d9de13ed7ab8399ccd0","impliedFormat":1},{"version":"6559a36671052ca93cab9a289279a6cef6f9d1a72c34c34546a8848274a9c66c","impliedFormat":1},{"version":"7a0e4cd92545ad03910fd019ae9838718643bd4dde39881c745f236914901dfa","impliedFormat":1},{"version":"c99ebd20316217e349004ee1a0bc74d32d041fb6864093f10f31984c737b8cad","impliedFormat":1},{"version":"6f622e7f054f5ab86258362ac0a64a2d6a27f1e88732d6f5f052f422e08a70e7","impliedFormat":1},{"version":"d62d2ef93ceeb41cf9dfab25989a1e5f9ca5160741aac7f1453c69a6c14c69be","impliedFormat":1},{"version":"1491e80d72873fc586605283f2d9056ee59b166333a769e64378240df130d1c9","impliedFormat":1},{"version":"c32c073d389cfaa3b3e562423e16c2e6d26b8edebbb7d73ccffff4aa66f2171d","impliedFormat":1},{"version":"eca72bf229eecadb63e758613c62fab13815879053539a22477d83a48a21cd73","impliedFormat":1},{"version":"633db46fd1765736409a4767bfc670861468dde60dbb9a501fba4c1b72f8644d","impliedFormat":1},{"version":"f379412f2c0dddd193ff66dcdd9d9cc169162e441d86804c98c84423f993aa8a","impliedFormat":1},{"version":"f2ee748883723aa9325e5d7f30fce424f6a786706e1b91a5a55237c78ee89c4a","impliedFormat":1},{"version":"d928324d17146fce30b99a28d1d6b48648feac72bbd23641d3ce5ac34aefdfee","impliedFormat":1},{"version":"142f5190d730259339be1433931c0eb31ae7c7806f4e325f8a470bd9221b6533","impliedFormat":1},{"version":"cbd19f594f0ee7beffeb37dc0367af3908815acf4ce46d86b0515478718cfed8","impliedFormat":1},{"version":"3cdb96f128133efd129c798ac11f959e59d278ae439f69983224774d79ed11db","impliedFormat":1},{"version":"8776e64e6165838ac152fa949456732755b0976d1867ae5534ce248f0ccd7f41","impliedFormat":1},{"version":"896bbc7402b3a403cda96813c8ea595470ff76d31f32869d053317c00ca2589a","impliedFormat":1},{"version":"5c4c5b49bbb01828402bb04af1d71673b18852c11b7e95bfd5cf4c3d80d352c8","impliedFormat":1},{"version":"7030df3d920343df00324df59dc93a959a33e0f4940af3fefef8c07b7ee329bf","impliedFormat":1},{"version":"a96bc00e0c356e29e620eaec24a56d6dd7f4e304feefcc99066a1141c6fe05a7","impliedFormat":1},{"version":"d12cc0e5b09943c4cd0848f787eb9d07bf78b60798e4588c50582db9d4decc70","impliedFormat":1},{"version":"7333ee6354964fd396297958e52e5bf62179aa2c88ca0a35c6d3a668293b7e0e","impliedFormat":1},{"version":"19c3760af3cbc9da99d5b7763b9e33aaf8d018bc2ed843287b7ff4343adf4634","impliedFormat":1},{"version":"9d1e38aeb76084848d2fcd39b458ec88246de028c0f3f448b304b15d764b23d2","impliedFormat":1},{"version":"d406da1eccf18cec56fd29730c24af69758fe3ff49c4f94335e797119cbc0554","impliedFormat":1},{"version":"4898c93890a136da9156c75acd1a80a941a961b3032a0cf14e1fa09a764448b7","impliedFormat":1},{"version":"f5d7a845e3e1c6c27351ea5f358073d0b0681537a2da6201fab254aa434121d3","impliedFormat":1},{"version":"3a47d4582ef0697cccf1f3d03b620002f03fb0ff098f630e284433c417d6c61b","impliedFormat":1},{"version":"d7c30f0abfe9e197e376b016086cf66b2ffb84015139963f37301ed0da9d3d0d","impliedFormat":1},{"version":"ff75bba0148f07775bcb54bf4823421ed4ebdb751b3bf79cc003bd22e49d7d73","impliedFormat":1},{"version":"d40d20ac633703a7333770bfd60360126fc3302d5392d237bbb76e8c529a4f95","impliedFormat":1},{"version":"35a9867207c488061fb4f6fe4715802fbc164b4400018d2fa0149ad02db9a61c","impliedFormat":1},{"version":"b5fd805b7c578ca6a42c42bbfa6fda95a85d9e332106d810bb18116dc13a45f8","impliedFormat":1},{"version":"3abd9ab4fb3a035c865e6a68cb9f4260515354d5ebebacd5c681aee52c046d1f","impliedFormat":1},{"version":"13e82862532619a727cff9a9ba78df7ca66e8a9b69e4cbd18e9809257b6bf7ba","impliedFormat":1},{"version":"601fe4e366b99181cd0244d96418cffeaaa987a7e310c6f0ed0f06ce63dfe3e9","impliedFormat":1},{"version":"c66a4f2b1362abc4aeee0870c697691618b423c8c6e75624a40ef14a06f787b7","impliedFormat":1},{"version":"8808b1c4f84f2e43da98757a959fe7282cb1795737e16534a97b7d4d33e84dfc","impliedFormat":1},{"version":"cd0565ace87a2d7802bf4c20ea23a997c54e598b9eb89f9c75e69478c1f7a0b4","impliedFormat":1},{"version":"738020d2c8fc9df92d5dee4b682d35a776eaedfe2166d12bc8f186e1ea57cc52","impliedFormat":1},{"version":"86dd7c5657a0b0bc6bee8002edcfd544458d3d3c60974555746eb9b2583dc35e","impliedFormat":1},{"version":"d97b96b6ecd4ee03f9f1170722c825ef778430a6a0d7aab03b8929012bf773cd","impliedFormat":1},{"version":"e84e9b89251a57da26a339e75f4014f52e8ef59b77c2ee1e0171cde18d17b3b8","impliedFormat":1},{"version":"272dbfe04cfa965d6fff63fdaba415c1b5a515b1881ae265148f8a84ddeb318f","impliedFormat":1},{"version":"2035fb009b5fafa9a4f4e3b3fdb06d9225b89f2cbbf17a5b62413bf72cea721a","impliedFormat":1},{"version":"eefafec7c059f07b885b79b327d381c9a560e82b439793de597441a4e68d774a","impliedFormat":1},{"version":"72636f59b635c378dc9ea5246b9b3517b1214e340e468e54cb80126353053b2e","impliedFormat":1},{"version":"ebb79f267a3bf2de5f8edc1995c5d31777b539935fab8b7d863e8efb06c8e9ea","impliedFormat":1},{"version":"ada033e6a4c7f4e147e6d76bb881069dc66750619f8cc2472d65beeec1100145","impliedFormat":1},{"version":"0c04cc14a807a5dc0e3752d18a3b2655a135fefbf76ddcdabd0c5df037530d41","impliedFormat":1},{"version":"605d29d619180fbec287d1701e8b1f51f2d16747ec308d20aba3e9a0dac43a0f","impliedFormat":1},{"version":"67c19848b442d77c767414084fc571ce118b08301c4ddff904889d318f3a3363","impliedFormat":1},{"version":"c704ff0e0cb86d1b791767a88af21dadfee259180720a14c12baee668d0eb8fb","impliedFormat":1},{"version":"195c50e15d5b3ea034e01fbdca6f8ad4b35ad47463805bb0360bdffd6fce3009","impliedFormat":1},{"version":"da665f00b6877ae4adb39cd548257f487a76e3d99e006a702a4f38b4b39431cb","impliedFormat":1},{"version":"083aebdd7c96aee90b71ec970f81c48984d9c8ab863e7d30084f048ddcc9d6af","impliedFormat":1},{"version":"1c3bde1951add95d54a05e6628a814f2f43bf9d49902729eaf718dc9eb9f4e02","impliedFormat":1},{"version":"d7a4309673b06223537bc9544b1a5fe9425628e1c8ab5605f3c5ebc27ecb8074","impliedFormat":1},{"version":"0be3da88f06100e2291681bbda2592816dd804004f0972296b20725138ebcddf","impliedFormat":1},{"version":"3eadfd083d40777b403f4f4eecfa40f93876f2a01779157cc114b2565a7afb51","impliedFormat":1},{"version":"cb6789ce3eba018d5a7996ccbf50e27541d850e9b4ee97fdcb3cbd8c5093691f","impliedFormat":1},{"version":"a3684ea9719122f9477902acd08cd363a6f3cff6d493df89d4dc12fa58204e27","impliedFormat":1},{"version":"ff3c48a17bf10dfbb62448152042e4a48a56c9972059997ab9e7ed03b191809b","impliedFormat":1},{"version":"bc3561e460de5a2c19123f618fc1d5a96a484d168884d00666997d847f502bf9","impliedFormat":1},{"version":"c0c46113b4cd5ec9e7cf56e6dbfb3930ef6cbba914c0883eeced396988ae8320","impliedFormat":1},{"version":"118ea3f4e7b9c12e92551be0766706f57a411b4f18a1b4762cfde3cd6d4f0a96","impliedFormat":1},{"version":"01acd7f315e2493395292d9a02841f3b0300e77ccf42f84f4f11460e7623107d","impliedFormat":1},{"version":"656d1ce5b8fbed896bb803d849d6157242261030967b821d01e72264774cab55","impliedFormat":1},{"version":"da66c1b41d833858fe61947432130d39649f0b53d992dfd7d00f0bbe57191ef4","impliedFormat":1},{"version":"835739c6dcf0a9a1533d1e95b7d7cf8e44ca1341652856b897f4573078b23a31","impliedFormat":1},{"version":"774a3bcc0700036313c57a079e2e1161a506836d736203aa0463efa7b11a7e54","impliedFormat":1},{"version":"96577e3f8e0f9ea07ddf748d72dc1908581ef2aafd4ae7418a4574c26027cf02","impliedFormat":1},{"version":"f55971cb3ede99c17443b03788fe27b259dcd0f890ac31badcb74e3ffb4bb371","impliedFormat":1},{"version":"0ef0c246f8f255a5d798727c40d6d2231d2b0ebda5b1ec75e80eadb02022c548","impliedFormat":1},{"version":"ea127752a5ec75f2ac6ef7f1440634e6ae5bc8d09e6f98b61a8fb600def6a861","impliedFormat":1},{"version":"862320e775649dcca8915f8886865e9c6d8affc1e70ed4b97199f3b70a843b47","impliedFormat":1},{"version":"561764374e9f37cb895263d5c8380885972d75d09d0db64c12e0cb10ba90ae3e","impliedFormat":1},{"version":"ee889da857c29fa7375ad500926748ef2e029a6645d7c080e57769923d15dfef","impliedFormat":1},{"version":"56984ba2d781bd742b6bc0fa34c10df2eae59b42ec8b1b731d297f1590fa4071","impliedFormat":1},{"version":"7521de5e64e2dd022be87fce69d956a52d4425286fbc5697ecfec386da896d7e","impliedFormat":1},{"version":"f50b072ec1f4839b54fd1269a4fa7b03efbc9c59940224c7939632c0f70a39c3","impliedFormat":1},{"version":"a5b7ec6f1ff3f1d19a2547f7e1a50ab1284e6b4755d260a481ea01ed2c7cec60","impliedFormat":1},{"version":"1747f9eebf5beb8cfc46cf0303e300950b7bff20cff60b9c46818caced3226e3","impliedFormat":1},{"version":"9d969f36abb62139a90345ee5d03f1c2479831bd84c8f843d87ec304cad96ead","impliedFormat":1},{"version":"e972b52218fd5919aec6cd0e5e2a5fb75f5d2234cf05597a9441837a382b2b29","impliedFormat":1},{"version":"d1e292b0837d0ef5ede4f52363c9d8e93f5d5234086adc796e11eae390305b36","impliedFormat":1},{"version":"0a9e10028a96865d0f25aeca9e3b1ff0691b9b662aa186d9d490728434cf8261","impliedFormat":1},{"version":"1aed740b674839c89f427f48737bad435ee5a39d80b5929f9dc9cc9ac10a7700","impliedFormat":1},{"version":"6e9e3690dc3a6e99a845482e33ee78915893f2d0d579a55b6a0e9b4c44193371","impliedFormat":1},{"version":"4e7a76cce3b537b6cdb1c4b97e29cb4048ee8e7d829cf3a85f4527e92eb573f2","impliedFormat":1},{"version":"bedbf6e1e952560ff250828c494da56976ca88860f8ba3dfb17dc89eac2e3463","impliedFormat":1},{"version":"46f1fe93f199a419172d7480407d9572064b54712b69406efa97e0244008b24e","impliedFormat":1},{"version":"044e6aaa3f612833fb80e323c65e9d816c3148b397e93630663cda5c2d8f4de1","impliedFormat":1},{"version":"deaf8eb392c46ea2c88553d3cc38d46cfd5ee498238dbc466e3f5be63ae0f651","impliedFormat":1},{"version":"6a79b61f57699de0a381c8a13f4c4bcd120556bfab0b4576994b6917cb62948b","impliedFormat":1},{"version":"c5133d7bdec65f465df12f0b507fbc0d96c78bfa5a012b0eb322cf1ff654e733","impliedFormat":1},{"version":"7905c052681cbe9286797ec036942618e1e8d698dcc2e60f4fb7a0013d470442","impliedFormat":1},{"version":"89049878a456b5e0870bb50289ea8ece28a2abd0255301a261fa8ab6a3e9a07d","impliedFormat":1},{"version":"d0da4f4fd66f37c13deabc1a641edd629141c333ccf862733788bd27e89436ac","impliedFormat":1},{"version":"d4a4f10062a6d82ba60d3ffde9154ef24b1baf2ce28c6439f5bdfb97aa0d18fc","impliedFormat":1},{"version":"f13310c360ecffddb3858dcb33a7619665369d465f55e7386c31d45dfc3847bf","impliedFormat":1},{"version":"e7bde95a05a0564ee1450bc9a53797b0ac7944bf24d87d6f645baca3aa60df48","impliedFormat":1},{"version":"62e68ce120914431a7d34232d3eca643a7ddd67584387936a5202ae1c4dd9a1b","impliedFormat":1},{"version":"91d695bba902cc2eda7edc076cd17c5c9340f7bb254597deb6679e343effadbb","impliedFormat":1},{"version":"e1cb8168c7e0bd4857a66558fe7fe6c66d08432a0a943c51bacdac83773d5745","impliedFormat":1},{"version":"a464510505f31a356e9833963d89ce39f37a098715fc2863e533255af4410525","impliedFormat":1},{"version":"0612b149cabbc136cb25de9daf062659f306b67793edc5e39755c51c724e2949","impliedFormat":1},{"version":"2579b150b86b5f644d86a6d58f17e3b801772c78866c34d41f86f3fc9eb523fe","impliedFormat":1},{"version":"e4b3a3e1b21a194b29d35488ec880948fc2ef8e937288463ea2981ad62a7b106","impliedFormat":1},{"version":"0353e05b0d8475c10ddd88056e0483b191aa5cdea00a25e0505b96e023f1a2d9","impliedFormat":1},{"version":"6a312caabb43c284a4b0da60d5c24f285338096eb9e977af1faca38d32a34685","impliedFormat":1},{"version":"b6eda93163beb978dd0d3042b11c60373506400c94613c0b40d1c0a9a9f1020e","impliedFormat":1},{"version":"a8af4739274959d70f7da4bfdd64f71cfc08d825c2d5d3561bc7baed760b33ef","impliedFormat":1},{"version":"99193bafaa9ce112889698de25c4b8c80b1209bb7402189aea1c7ada708a8a54","impliedFormat":1},{"version":"70473538c6eb9494d53bf1539fe69df68d87c348743d8f7244dcb02ca3619484","impliedFormat":1},{"version":"c48932ab06a4e7531bdca7b0f739ace5fa273f9a1b9009bcd26902f8c0b851f0","impliedFormat":1},{"version":"df6c83e574308f6540c19e3409370482a7d8f448d56c65790b4ac0ab6f6fedd8","impliedFormat":1},{"version":"ebbe6765a836bfa7f03181bc433c8984ca29626270ca1e240c009851222cb8a7","impliedFormat":1},{"version":"20f630766b73752f9d74aab6f4367dba9664e8122ea2edcb00168e4f8b667627","impliedFormat":1},{"version":"468df9d24a6e2bc6b4351417e3b5b4c2ca08264d6d5045fe18eb42e7996e58b4","impliedFormat":1},{"version":"954523d1f4856180cbf79b35bd754e14d3b2aea06c7efd71b254c745976086e9","impliedFormat":1},{"version":"31a030f1225ab463dd0189a11706f0eb413429510a7490192a170114b2af8697","impliedFormat":1},{"version":"6f48f244cd4b5b7e9a0326c74f480b179432397580504726de7c3c65d6304b36","impliedFormat":1},{"version":"5520e6defac8e6cdced6dd28808fafe795cb2cd87407bb1012e13a2b061f50b7","impliedFormat":1},{"version":"c3451661fb058f4e15971bbed29061dd960d02d9f8db1038e08b90d294a05c68","impliedFormat":1},{"version":"1f21aefa51f03629582568f97c20ef138febe32391012828e2a0149c2c393f62","impliedFormat":1},{"version":"b18141cda681d82b2693aef045107a910b90a7409ecff0830e1283f0bb2a53e6","impliedFormat":1},{"version":"18eb53924f27af2a5e9734dce28cf5985df7b2828dade1239241e95b639e9bf1","impliedFormat":1},{"version":"a9f1c52f4e7c2a2c4988b5638bd3dbfe38e408b358d02dd2fb8c8920e877f088","impliedFormat":1},{"version":"a7e10a8ad6536dd0225029e46108b18cee0d3c15c2f6e49bd62798ad85bc57b6","impliedFormat":1},{"version":"8db1ed144dd2304b9bd6e41211e22bad5f4ab1d8006e6ac127b29599f4b36083","impliedFormat":1},{"version":"843a5e3737f2abbbbd43bf2014b70f1c69a80530814a27ae1f8be213ae9ec222","impliedFormat":1},{"version":"6fc1be224ad6b3f3ec11535820def2d21636a47205c2c9de32238ba1ac8d82e6","impliedFormat":1},{"version":"5a44788293f9165116c9c183be66cefef0dc5d718782a04847de53bf664f3cc1","impliedFormat":1},{"version":"afd653ae63ce07075b018ba5ce8f4e977b6055c81cc65998410b904b94003c0a","impliedFormat":1},{"version":"9172155acfeb17b9d75f65b84f36cb3eb0ff3cd763db3f0d1ad5f6d10d55662f","impliedFormat":1},{"version":"71807b208e5f15feffb3ff530bec5b46b1217af0d8cc96dde00d549353bcb864","impliedFormat":1},{"version":"1a6eca5c2bc446481046c01a54553c3ffb856f81607a074f9f0256c59dd0ab13","impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"0ccdaa19852d25ecd84eec365c3bfa16e7859cadecf6e9ca6d0dbbbee439743f","affectsGlobalScope":true,"impliedFormat":1},{"version":"438b41419b1df9f1fbe33b5e1b18f5853432be205991d1b19f5b7f351675541e","affectsGlobalScope":true,"impliedFormat":1},{"version":"096116f8fedc1765d5bd6ef360c257b4a9048e5415054b3bf3c41b07f8951b0b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5e01375c9e124a83b52ee4b3244ed1a4d214a6cfb54ac73e164a823a4a7860a","affectsGlobalScope":true,"impliedFormat":1},{"version":"f90ae2bbce1505e67f2f6502392e318f5714bae82d2d969185c4a6cecc8af2fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b58e207b93a8f1c88bbf2a95ddc686ac83962b13830fe8ad3f404ffc7051fb4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1fefabcb2b06736a66d2904074d56268753654805e829989a46a0161cd8412c5","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"c18a99f01eb788d849ad032b31cafd49de0b19e083fe775370834c5675d7df8e","affectsGlobalScope":true,"impliedFormat":1},{"version":"5247874c2a23b9a62d178ae84f2db6a1d54e6c9a2e7e057e178cc5eea13757fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"487b694c3de27ddf4ad107d4007ad304d29effccf9800c8ae23c2093638d906a","impliedFormat":1},{"version":"3a80bc85f38526ca3b08007ee80712e7bb0601df178b23fbf0bf87036fce40ce","impliedFormat":1},{"version":"ccf4552357ce3c159ef75f0f0114e80401702228f1898bdc9402214c9499e8c0","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"2931540c47ee0ff8a62860e61782eb17b155615db61e36986e54645ec67f67c2","impliedFormat":1},{"version":"ccab02f3920fc75c01174c47fcf67882a11daf16baf9e81701d0a94636e94556","impliedFormat":1},{"version":"f6faf5f74e4c4cc309a6c6a6c4da02dbb840be5d3e92905a23dcd7b2b0bd1986","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"33e981bf6376e939f99bd7f89abec757c64897d33c005036b9a10d9587d80187","impliedFormat":1},{"version":"7fd1b31fd35876b0aa650811c25ec2c97a3c6387e5473eb18004bed86cdd76b6","impliedFormat":1},{"version":"b41767d372275c154c7ea6c9d5449d9a741b8ce080f640155cc88ba1763e35b3","impliedFormat":1},{"version":"3bacf516d686d08682751a3bd2519ea3b8041a164bfb4f1d35728993e70a2426","impliedFormat":1},{"version":"7fb266686238369442bd1719bc0d7edd0199da4fb8540354e1ff7f16669b4323","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"54c3e2371e3d016469ad959697fd257e5621e16296fa67082c2575d0bf8eced0","impliedFormat":1},{"version":"beb8233b2c220cfa0feea31fbe9218d89fa02faa81ef744be8dce5acb89bb1fd","impliedFormat":1},{"version":"c183b931b68ad184bc8e8372bf663f3d33304772fb482f29fb91b3c391031f3e","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"48cc3ec153b50985fb95153258a710782b25975b10dd4ac8a4f3920632d10790","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"e1528ca65ac90f6fa0e4a247eb656b4263c470bb22d9033e466463e13395e599","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"866078923a56d026e39243b4392e282c1c63159723996fa89243140e1388a98d","impliedFormat":1},{"version":"dd0109710de4cd93e245121ab86d8c66d20f3ead80074b68e9c3e349c4f53342","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3275d55fac10b799c9546804126239baf020d220136163f763b55a74e50e750","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa68a0a3b7cb32c00e39ee3cd31f8f15b80cac97dce51b6ee7fc14a1e8deb30b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"6c36e755bced82df7fb6ce8169265d0a7bb046ab4e2cb6d0da0cb72b22033e89","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7a93de4ff8a63bafe62ba86b89af1df0ccb5e40bb85b0c67d6bbcfdcf96bf3d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"90e85f9bc549dfe2b5749b45fe734144e96cd5d04b38eae244028794e142a77e","affectsGlobalScope":true,"impliedFormat":1},{"version":"e0a5deeb610b2a50a6350bd23df6490036a1773a8a71d70f2f9549ab009e67ee","affectsGlobalScope":true,"impliedFormat":1},{"version":"435b3711465425770ed2ee2f1cf00ce071835265e0851a7dc4600ab4b007550e","impliedFormat":1},{"version":"7e49f52a159435fc8df4de9dc377ef5860732ca2dc9efec1640531d3cf5da7a3","impliedFormat":1},{"version":"dd4bde4bdc2e5394aed6855e98cf135dfdf5dd6468cad842e03116d31bbcc9bc","impliedFormat":1},{"version":"4d4e879009a84a47c05350b8dca823036ba3a29a3038efed1be76c9f81e45edf","affectsGlobalScope":true,"impliedFormat":1},{"version":"cf83d90d5faf27b994c2e79af02e32b555dbfe42cd9bd1571445f2168d1f4e2d","impliedFormat":1},{"version":"9ba13b47cb450a438e3076c4a3f6afb9dc85e17eae50f26d4b2d72c0688c9251","impliedFormat":1},{"version":"b64cd4401633ea4ecadfd700ddc8323a13b63b106ac7127c1d2726f32424622c","impliedFormat":1},{"version":"37c6e5fe5715814412b43cc9b50b24c67a63c4e04e753e0d1305970d65417a60","impliedFormat":1},{"version":"0e28335ac43f4d94dd2fe6d9e6fa6813570640839addd10d309d7985f33a6308","impliedFormat":1},{"version":"ee0e4946247f842c6dd483cbb60a5e6b484fee07996e3a7bc7343dfb68a04c5d","impliedFormat":1},{"version":"ef051f42b7e0ef5ca04552f54c4552eac84099d64b6c5ad0ef4033574b6035b8","impliedFormat":1},{"version":"853a43154f1d01b0173d9cbd74063507ece57170bad7a3b68f3fa1229ad0a92f","impliedFormat":1},{"version":"56231e3c39a031bfb0afb797690b20ed4537670c93c0318b72d5180833d98b72","impliedFormat":1},{"version":"5cc7c39031bfd8b00ad58f32143d59eb6ffc24f5d41a20931269011dccd36c5e","impliedFormat":1},{"version":"b0b69c61b0f0ec8ca15db4c8c41f6e77f4cacb784d42bca948f42dea33e8757e","affectsGlobalScope":true,"impliedFormat":1},{"version":"f96a48183254c00d24575401f1a761b4ce4927d927407e7862a83e06ce5d6964","impliedFormat":1},{"version":"cc25940cfb27aa538e60d465f98bb5068d4d7d33131861ace43f04fe6947d68f","impliedFormat":1},{"version":"e6f370b5c1d52edabb93ef055d0c0c396a98be77db8aa022fcc3670787b8b5f5","impliedFormat":1},{"version":"01ff95aa1443e3f7248974e5a771f513cb2ac158c8898f470a1792f817bee497","impliedFormat":1},{"version":"9d96a7ce809392ff2cb99691acf7c62e632fe56897356ba013b689277aca3619","impliedFormat":1},{"version":"42a05d8f239f74587d4926aba8cc54792eed8e8a442c7adc9b38b516642aadfe","impliedFormat":1},{"version":"5d21b58d60383cc6ab9ad3d3e265d7d25af24a2c9b506247e0e50b0a884920be","impliedFormat":1},{"version":"101f482fd48cb4c7c0468dcc6d62c843d842977aea6235644b1edd05e81fbf22","impliedFormat":1},{"version":"ae6757460f37078884b1571a3de3ebaf724d827d7e1d53626c02b3c2a408ac63","affectsGlobalScope":true,"impliedFormat":1},{"version":"27c0a08e343c6a0ae17bd13ba6d44a9758236dc904cd5e4b43456996cd51f520","impliedFormat":1},{"version":"3ef397f12387eff17f550bc484ea7c27d21d43816bbe609d495107f44b97e933","impliedFormat":1},{"version":"1023282e2ba810bc07905d3668349fbd37a26411f0c8f94a70ef3c05fe523fcf","impliedFormat":1},{"version":"b214ebcf76c51b115453f69729ee8aa7b7f8eccdae2a922b568a45c2d7ff52f7","impliedFormat":1},{"version":"429c9cdfa7d126255779efd7e6d9057ced2d69c81859bbab32073bad52e9ba76","impliedFormat":1},{"version":"6f80e51ba310608cd71bcdc09a171d7bbfb3b316048601c9ec215ce16a8dcfbc","impliedFormat":1},{"version":"10947bb49601aeec9ea1dddf61ef6e4f8442f949bd40a8008e12b129deb037be","affectsGlobalScope":true,"impliedFormat":1},{"version":"7f2c62938251b45715fd2a9887060ec4fbc8724727029d1cbce373747252bdd7","impliedFormat":1},{"version":"e3ace08b6bbd84655d41e244677b474fd995923ffef7149ddb68af8848b60b05","impliedFormat":1},{"version":"132580b0e86c48fab152bab850fc57a4b74fe915c8958d2ccb052b809a44b61c","impliedFormat":1},{"version":"af4ab0aa8908fc9a655bb833d3bc28e117c4f0e1038c5a891546158beb25accb","impliedFormat":1},{"version":"69c9a5a9392e8564bd81116e1ed93b13205201fb44cb35a7fde8c9f9e21c4b23","impliedFormat":1},{"version":"5f8fc37f8434691ffac1bfd8fc2634647da2c0e84253ab5d2dd19a7718915b35","impliedFormat":1},{"version":"5981c2340fd8b076cae8efbae818d42c11ffc615994cb060b1cd390795f1be2b","impliedFormat":1},{"version":"1641d32611fc7aa82cdd9fa38ff18349aac4eda9e032ced76b21943673887f9a","impliedFormat":1},{"version":"ed4f674fc8c0c993cc7e145069ac44129e03519b910c62be206a0cc777bdc60b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0250da3eb85c99624f974e77ef355cdf86f43980251bc371475c2b397ba55bcd","impliedFormat":1},{"version":"f1c93e046fb3d9b7f8249629f4b63dc068dd839b824dd0aa39a5e68476dc9420","impliedFormat":1},{"version":"3d3a5f27ffbc06c885dd4d5f9ee20de61faf877fe2c3a7051c4825903d9a7fdc","impliedFormat":1},{"version":"12806f9f085598ef930edaf2467a5fa1789a878fba077cd27e85dc5851e11834","impliedFormat":1},{"version":"17d06eb5709839c7ce719f0c38ada6f308fb433f2cd6d8c87b35856e07400950","impliedFormat":1},{"version":"a43fe41c33d0a192a0ecaf9b92e87bef3709c9972e6d53c42c49251ccb962d69","impliedFormat":1},{"version":"a177959203c017fad3ecc4f3d96c8757a840957a4959a3ae00dab9d35961ca6c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6fc727ccf9b36e257ff982ea0badeffbfc2c151802f741bddff00c6af3b784cf","impliedFormat":1},{"version":"2a00d005e3af99cd1cfa75220e60c61b04bfb6be7ca7453bfe2ef6cca37cc03c","impliedFormat":1},{"version":"4844a4c9b4b1e812b257676ed8a80b3f3be0e29bf05e742cc2ea9c3c6865e6c6","impliedFormat":1},{"version":"064878a60367e0407c42fb7ba02a2ea4d83257357dc20088e549bd4d89433e9c","impliedFormat":1},{"version":"14d4bd22d1b05824971b98f7e91b2484c90f1a684805c330476641417c3d9735","impliedFormat":1},{"version":"586eaf66bace2e731cee0ddfbfac326ad74a83c1acfeac4afb2db85ad23226c7","impliedFormat":1},{"version":"b484ec11ba00e3a2235562a41898d55372ccabe607986c6fa4f4aba72093749f","impliedFormat":1},{"version":"d1a14d87cedcf4f0b8173720d6eb29cc02878bf2b6dabf9c9d9cee742f275368","impliedFormat":1},{"version":"41ef7992c555671a8fe54db302788adefa191ded810a50329b79d20a6772d14c","impliedFormat":1},{"version":"041a7781b9127ab568d2cdcce62c58fdea7c7407f40b8c50045d7866a2727130","impliedFormat":1},{"version":"b37f83e7deea729aa9ce5593f78905afb45b7532fdff63041d374f60059e7852","impliedFormat":1},{"version":"e1cb68f3ef3a8dd7b2a9dfb3de482ed6c0f1586ba0db4e7d73c1d2147b6ffc51","impliedFormat":1},{"version":"55cdbeebe76a1fa18bbd7e7bf73350a2173926bd3085bb050cf5a5397025ee4e","impliedFormat":1},{"version":"d34aa8df2d0b18fb56b1d772ff9b3c7aea7256cf0d692f969be6e1d27b74d660","impliedFormat":1},{"version":"baac9896d29bcc55391d769e408ff400d61273d832dd500f21de766205255acb","impliedFormat":1},{"version":"2f5747b1508ccf83fad0c251ba1e5da2f5a30b78b09ffa1cfaf633045160afed","impliedFormat":1},{"version":"6823ccc7b5b77bbf898d878dbcad18aa45e0fa96bdd0abd0de98d514845d9ed9","affectsGlobalScope":true,"impliedFormat":1},{"version":"b71c603a539078a5e3a039b20f2b0a0d1708967530cf97dec8850a9ca45baa2b","impliedFormat":1},{"version":"168d88e14e0d81fe170e0dadd38ae9d217476c11435ea640ddb9b7382bdb6c1f","impliedFormat":1},{"version":"104c67f0da1bdf0d94865419247e20eded83ce7f9911a1aa75fc675c077ca66e","impliedFormat":1},{"version":"cc0d0b339f31ce0ab3b7a5b714d8e578ce698f1e13d7f8c60bfb766baeb1d35c","impliedFormat":1},{"version":"8e04cf0688e0d921111659c2b55851957017148fa7b977b02727477d155b3c47","impliedFormat":1},{"version":"ba63131c5e91f797736444933af16ffa42f9f8c150d859ec65f568f037a416ea","impliedFormat":1},{"version":"44372b8b42e8916b0ab379da38dcf4de11227bad4221aba3e2dbe718999bdfab","impliedFormat":1},{"version":"43ebfcc5a9e9a9306ea4de9fda3abdd9e018040e246434b48ad56d93b14d4a3d","impliedFormat":1},{"version":"0e9aa853b5eb2ca09e0e3e3eb94cbd1d5fb3d682ab69817d4d11fe225953fc57","impliedFormat":1},{"version":"179683df1e78572988152d598f44297da79ac302545770710bba87563ce53e06","impliedFormat":1},{"version":"793c353144f16601da994fa4e62c09b7525836ce999c44f69c28929072ca206a","impliedFormat":1},{"version":"ff155930718467b27e379e4a195e4607ce277f805cad9d2fa5f4fd5dec224df6","affectsGlobalScope":true,"impliedFormat":1},{"version":"599ac4a84b7aa6a298731179ec1663a623ff8ac324cdc1dabb9c73c1259dc854","impliedFormat":1},{"version":"95c2ab3597d7d38e990bf212231a6def6f6af7e3d12b3bb1b67c15fc8bfd4f4a","impliedFormat":1},{"version":"585bc61f439c027640754dd26e480afa202f33e51db41ee283311a59c12c62e7","impliedFormat":1},{"version":"8f1241f5d9f0d3d72117768b3c974e462840fbd85026fb66685078945404cf2f","impliedFormat":1},{"version":"b180acde3a28387924084971aded1a6db689e4c2344facbd4b7eb50fde77a54d","signature":"e97b0df9bc2de58796bd4bb9856b5d52ee7d4f3ef2bc64a26b0b7d7ee7b48ab9"},{"version":"621ed0cd60a214ddd22ed8bce16f6aad157e04ba495ee36edb83541492775a29","impliedFormat":1},{"version":"c0f575e9f7005738c3470854fa23817120457d870b1a58eadb3b3212d38aaa80","impliedFormat":1},{"version":"746915725cfeb343c98f0d08f082ac6c2b2e1460893b2d3dbf3ac30d3d283dc8","impliedFormat":1},{"version":"0c098f6d249616469e6d9e2c584145c8e9299297b472d77ca348d293fe3ffd80","impliedFormat":1},{"version":"fd7d0017b5f33a8a58e07d0c15a93387250ae1d627170ecec68f0a93960cc02b","impliedFormat":1},{"version":"334236475f89849f4373639c9053809ec3ee48f20f859f96e3cd3f0eff770921","impliedFormat":1},{"version":"63751196a413d53618aa3819ee39c957a4bd0c8b0b0cadf5201ae85c8c02ded3","impliedFormat":1},{"version":"017c6724837b29b0d237c0c7a721729644af6d27a21b269a534da9a830524155","impliedFormat":1},{"version":"62c0948cd8237411c00de10ddfb4c4fb75eb6b78dfcabc7eee77d7083bd8da1e","impliedFormat":1},{"version":"df6de24af77449f932dd9f4f293410ce22a6b34601b11ce585923db1ee55d9c7","impliedFormat":1},{"version":"24810c982585d364b4d1c3bca813cc0646f929017240daf4acae9f1ca5d04a31","impliedFormat":1},{"version":"47d01ed73d26a694589ea1e020f8edf31cb0640d82096203672bb603d82e7166","impliedFormat":1},{"version":"2501f0aaf3650774a9f7bf18340d2a04cbdc013c4ebac4572666c214411c4196","impliedFormat":1},{"version":"0281154c8da1c89230ac501f49b05bc0dca0bd11114050d04035a954d317a9de","impliedFormat":1},{"version":"6c65d4120ad672b3690c431b1363b70c39b20fda34ef0a956558d1c70995f887","impliedFormat":1},{"version":"263101a9f264ddc212803e7f021f1e476f7ff95646eb38d0aaa9f0f7fc2b129d","impliedFormat":1},{"version":"43a8d3537978e356eb9d3cb1ebf14808e3fd340cfb5a6d11614ccf278e688469","impliedFormat":1},{"version":"4aba836729ab68943658be14d4571133e75fb3816e24a36f3914727c6cd69a09","impliedFormat":1},{"version":"b7a072ba3cffacff7b8737f9674639fbdf42a795b543d527e0c57a7b40b35bbd","impliedFormat":1},{"version":"fcae0c7e37d693c5f0949a9288f0635e009d8de0e4a1dde224db1faaaea1f025","impliedFormat":1},{"version":"7b0c0a9c59518dfccf0f52bd3d52c6d5a4544a594b09f5aa3b237b4d7b11dc1a","impliedFormat":1},{"version":"0f41ce8d811d809df3c422829426013f00036bc04dfe6e751cabba59aef32300","impliedFormat":1},{"version":"70b1e8a81fca72e46cdcb341df1c33b6eb1c641f089f863c92676d186656a3b6","impliedFormat":1},{"version":"b57c5893640ad5ea144a2ab18fe85b3f7c09fc74b527462af5e08b2cac81e5a8","impliedFormat":1},{"version":"143417b2f2c8551a62a63c5dbf215695ad2144cdfaa3f64e272f0a0a1425302f","impliedFormat":1},{"version":"6b6d7b15c806f374f276d072e0abdc16c0fa75f8eb368153e2e31e77d7775b19","impliedFormat":1},{"version":"3729c8d87d152088bfe90e4de08a7ccf014c1c6c463f754412310e15ef7bdea3","impliedFormat":1},{"version":"eb84d92d0e8f30d97ff087d9dbc367b8d318799520be4a819a9d860b9d4c226f","impliedFormat":1},{"version":"02b5bfd1c5242bc46e81ca9103d3b794bf337c2e64ac7e0e0927909257c4e833","impliedFormat":1},{"version":"6baa4d11817ab1b073b53744ce172d66afe8b21f9aedad6150573ff5acc88bd2","impliedFormat":1},{"version":"b2bb7c01de5345890250273ba08c012a8d453c91a2e7c41bb1a1b1c4cc8c3383","impliedFormat":1},{"version":"c063b6e9f950b7ac9fb94099dae1c1477225404f45c6990644daa9e150e07c0a","impliedFormat":1},{"version":"2583bd81bf7f4bb2e613b9b28888f9a6cce653352533a697b67599a380b73bc1","impliedFormat":1},{"version":"06a5447a024892a2289a5d79bece392c37ce8dc335973389d478e0890d71b529","impliedFormat":1},{"version":"d38f58d9a6f0a0df70cf60d295949e21551f3ce35849a37a7f9522bd50c0c0c9","impliedFormat":1},{"version":"628a24ecf46ef0118f268a2585822f2530cf0141e508037ed52c9490e4440859","impliedFormat":1},{"version":"494c503966cd59f051c146e5efb88f3e4c66bc94e8338a4e3919a111bdedddf9","impliedFormat":1},{"version":"7ce2fe3f89937850648bdc460c59db1e35251758e00a8faacba16e6d56d3c501","impliedFormat":1},{"version":"60d3a7b2a54706a022acc3fca11164be6abf2352938b99f1a26660d697207da3","impliedFormat":1},{"version":"839719b09d4bffac4acb08d19ff63f9a6b29ccd6c348c871f211308eca6d5a04","impliedFormat":1},{"version":"e64afc9809626f0adfa47d88f5f584dc9c5308508c9ccbf2246d8b66da19b394","impliedFormat":1},{"version":"d243f93260abf87a61a5c82cecf5f3a673766ad7877a89f6ef7fc906d251426c","impliedFormat":1},{"version":"cba8fdd6780c61fcf3ab38bf5b91d5f58facbf4a6dcbe7e9351c952732429ade","impliedFormat":1},{"version":"5da6de323b6990287f8497f9e89245ac3be58153748e51e4c069ef0b57b9c6f7","impliedFormat":1},{"version":"3e5987fa94b9733fcb1a3eee5b909c83ce72380022f36838bd82aa9d53bc6869","impliedFormat":1},{"version":"4e19dc229635f5285bd411f095c4726f9a0a69b2957fdf85553782f5d411bc9b","impliedFormat":1},{"version":"667c4a7aaa7446bae6c96668921d337ae1b4cedce7a190de2e36ddd8421bfef5","impliedFormat":1},{"version":"9c4480a9d7e9f58d61045641e4f717f8ad48a584c08939a0d816b173a9ccec87","impliedFormat":1},{"version":"a4ded6b4c2f30f04aad97d8dfa213bc016339b06faab229a0c85f2ac1b5b025f","impliedFormat":1},{"version":"530f2c02b6da526dc0e0f104d4de1cb752c8580dcc394e0676966fced250edeb","impliedFormat":1},{"version":"41481a725ed2486e8f97d6b9202442d640ad7a76debf4acc03eb1917b39d3bfb","impliedFormat":1},{"version":"c6cdcd12d577032b84eed1de4d2de2ae343463701a25961b202cff93989439fb","impliedFormat":1},{"version":"3dc633586d48fcd04a4f8acdbf7631b8e4a334632f252d5707e04b299069721e","impliedFormat":1},{"version":"3322858f01c0349ee7968a5ce93a1ca0c154c4692aa8f1721dc5192a9191a168","impliedFormat":1},{"version":"6dde0a77adad4173a49e6de4edd6ef70f5598cbebb5c80d76c111943854636ca","impliedFormat":1},{"version":"09acacae732e3cc67a6415026cfae979ebe900905500147a629837b790a366b3","impliedFormat":1},{"version":"f7b622759e094a3c2e19640e0cb233b21810d2762b3e894ef7f415334125eb22","impliedFormat":1},{"version":"99236ea5c4c583082975823fd19bcce6a44963c5c894e20384bc72e7eccf9b03","impliedFormat":1},{"version":"f6688a02946a3f7490aa9e26d76d1c97a388e42e77388cbab010b69982c86e9e","impliedFormat":1},{"version":"9f642953aba68babd23de41de85d4e97f0c39ef074cb8ab8aa7d55237f62aff6","impliedFormat":1},{"version":"159d95163a0ed369175ae7838fa21a9e9e703de5fdb0f978721293dd403d9f4a","impliedFormat":1},{"version":"3b9e650cf228a1d63f90e018be93b4e77e2250c563006559a77a617a3d5bae2e","impliedFormat":1},{"version":"4310fad110acee6483f4099b89b1b4c5666d3350c6a7151201ae9cd4078437b4","impliedFormat":1},{"version":"db12ca4d561de7550c64544064b09d59a3a4560c372251cc8b743abc16330252","impliedFormat":1},{"version":"c0bbb1777313f7dbf9aaf2db9829c1d997ed89f612cb5fcc8947711aa88aa112","impliedFormat":1},{"version":"08eeedef29a6e4401989a1b306f391a18414b2e8599d49d9ac8022629e60dfda","impliedFormat":1},{"version":"b888cd224b3fae54aa11397c663b298ef2d8db98b9670fa399e04e03ac8b075a","impliedFormat":1},{"version":"1f9d34a0a3b92390221bcbd45f09cdebaad090c8ea31aa0353305754702ce79d","impliedFormat":1},{"version":"bf54a28e0726debb0343db62d93270528076ed8ec493abd7d9711c04ed2dc227","impliedFormat":1},{"version":"e5e936e3a5d64d1bb064807d2f9a8cd5a13e04e29d1ee09f2d864b3f5e92164f","impliedFormat":1},{"version":"74e0bdc9c9bb92a398b8bad9cb64e22990ea849781f4c5b7484e0f02ea627fce","impliedFormat":1},{"version":"1d997f97a64e823104ae2789c2bacfceef94b19fcfb7038735f835474ff0d229","impliedFormat":1},{"version":"a331a6263556bf5eca5516a8628e40e0e867c5617e9afabdd668dd9def7919ec","impliedFormat":1},{"version":"1394912ef3f2355f73fd037d59e7f7ff5ba6e20f4de3e315362c47965dd44cc2","impliedFormat":1},{"version":"43ad960f7d986eecaa5b08274c8e1e12829f371d38b7d7a6380f066f1107d126","impliedFormat":1},{"version":"2f56b25d1d0ffa78f6ba414a97f29ebb9530058e89d4f6389f58d64fbda927fa","impliedFormat":1},{"version":"3e4c74826ab85d72f17fe4d1ebf9c05c0cf1390ff6a50917f7bb51d8839b5b39","impliedFormat":1},{"version":"209a5b198410ece77bbad70dd43656028d333c5487a0c62fcef575e8bcc98ed6","impliedFormat":1},{"version":"816fa7fe4a11b81b84b4348560af7d765eacf1b436697a4718de723dcb533a21","impliedFormat":1},{"version":"d219cab4a681cc75c6978850260add3fdd991df012083171ec3ad196658327cc","impliedFormat":1},{"version":"ffa15676fdef641df3e11d1e44ef9716bf72a852577c84ed76db353aa5fdf21d","impliedFormat":1},{"version":"22e92d7805f499b7cf1b10cdba394849348d4d921a62060e8540b80f95536813","impliedFormat":1},{"version":"b624a6f15cd510036cbe88d6979a8ca850a29081a0f621f8d2f930e570fea1f0","impliedFormat":1},{"version":"2662060a00651b0179409690408ea51e67a871c784d7a7a7001c5992e29a15e4","impliedFormat":1},{"version":"6507d6daf0e43be301b37087277f4f7e63ef6db2ed0d50d13eb0efc690bfd479","impliedFormat":1},{"version":"6df67797e60bc4ae5ac8ffeb627d9193cb40aebeb594b1b3986efc77e09abc22","impliedFormat":1},{"version":"ff6ce828cf3f131ed0d723d1279bee376d645df03c4944d23d371c36d0a85119","impliedFormat":1},{"version":"d60c72243b056608064b85bc16bbcc7782cd26e367908992b2a9d2601ddbbf51","impliedFormat":1},{"version":"3a76c62c2b5aa5e432bc70a1dab6ad0ea4289233f99469855a57c24558f9fe9e","impliedFormat":1},{"version":"24bb05d1efe0891670f5b24c2de83f84c3dd180da2c8da95e9fe24d1754e3b3e","impliedFormat":1},{"version":"bd7e1e96947a16eb2d629803b9ce0d8b8236464a8d58e61a240f3b625fd61246","impliedFormat":1},{"version":"cd838b4aace3324a177305ac9665764d972bef8faef3ca90136326e6e31fffb0","impliedFormat":1},{"version":"b2d5c0c25b7be6f2284c3fcfe74a4bce9df40b2dab6e9a0d834f61139181d121","impliedFormat":1},{"version":"6af114bf1507dc2d4bc6de194c5ffd59f565fec3257ea03c765e71955f6328f0","impliedFormat":1},{"version":"3e6273e5873f88313ddf2e2143af4f81e821755090d3c9d680bd1faa6bb90685","impliedFormat":1},{"version":"868057f8250e93dc2d201a78ff034d750aec109a44938da343e96b2a65443e91","impliedFormat":1},{"version":"22085d3f0ed4b1f9f8a89273d5b1ee89c0c0a5b028355ff11b98ed20efe3fcc7","impliedFormat":1},{"version":"129ca99d8f24df36e9484cc64a18b61ce9796c0d5bb46a9cd55b199470954c68","impliedFormat":1},{"version":"77603f128a5c2e59d6c3a8a0ed22c00418348c72f7c3eccdbd72adc05373bfa0","impliedFormat":1},{"version":"3003977dd82eec5f4ecf9ffa5f5b2b6f8e6084d0d2327d4066bc58bdbf57eecb","impliedFormat":1},{"version":"74d31fda297aa93e98345a828659ed5f511c7d7bb2ebb04c45c94794aa13b603","impliedFormat":1},{"version":"701451e21c9f5c344cabeead95dc990f2a9796194f8a754c5598ee5dbcd82483","impliedFormat":1},{"version":"9abfd6b3728a47d500fa31f922a8c9304bb5e5324e1703dff1b47c580acb6240","impliedFormat":1},{"version":"767bd6dc7ac7630a08b1eed34055f6e6444fdd22feae228633d0e49bdcee3b2f","impliedFormat":1},{"version":"50a9c14927e406408649c212c7a1e458c0e40a0a1136d7cdc8643fcd1fb838ed","impliedFormat":1},{"version":"f4c0b3c76c196e2cd9dd9a105d6c5de8d92fa62d18a1b4870def3eb9c76824f4","impliedFormat":1},{"version":"daa833b86b2873eff82978d2cecd5da94654b3d913afa512a643209bdff91ee0","impliedFormat":1},{"version":"3b6fe3c942916b34e9bf8186636e624eefe04ef3a4deba7d10e02194751841be","impliedFormat":1},{"version":"fd89502024c8c66f303372ba21df1f5f4dd651698fe4a2b3b555e2d8f4ccc888","impliedFormat":1},{"version":"d355e5f8cad53f510823dee4e2b315f6b5266268f3c0adfeeb23d602fff031ae","impliedFormat":1},{"version":"f096f1e51147138799017271593e863d0f30634b040ba4d23929fa51af44a7c1","impliedFormat":1},{"version":"3bd33b9fc57d46d6110e72edaec699c52023de1a51fd3ce6be865b2dd354fe3a","impliedFormat":1},{"version":"6cb5de6bb76fbeb717730fc0c6184640b42333197bc189ea81550a754b5ae825","impliedFormat":1},{"version":"c407a174687059ea1602fa72d1b500158e31d922cea1a2e66be6d0fc0311574e","impliedFormat":1},{"version":"ba94986f84ec23c66f5776e17bf6565717d9334617ac2a919c3de875dec5ed43","impliedFormat":1},{"version":"cdcfa8049703d76c4a81677d6c5355122880cc2af724939ba1bd300dfaa13c6e","impliedFormat":1},{"version":"ad7bb2f58c7c5e5788c201c3e6860fdc5cc95c3521681616e141dccea70a7d73","impliedFormat":1},{"version":"ea606b2e640c64bb456db64548b60ee6a80077fbc0619099f40c60984f9bac97","impliedFormat":1},{"version":"e4934630771560d981c7ea39615287c52a565d88727bf57980614b4be36f9b23","impliedFormat":1},{"version":"719328f1bf7a2f54fd2fd0808afad47d5d410433f9cbc43f9cb5cade63c06235","impliedFormat":1},{"version":"44e816a150edc2e2323d85d8c6579c0acdfca8c227122afd2d1d0283890bc92e","impliedFormat":1},{"version":"be27f1a625ed2dcf18d9cfda6ad4158ad873890fd7ccd1a546952e547c454c21","impliedFormat":1},{"version":"cb84f91c48e0426032834a84f7e307285cbc4599e609d7e682a9ea8bf88897b3","impliedFormat":1},{"version":"6f9e53a12cc7a70d8c64ea0da0ca0fd44a7ba8b1e57a40e1da0662ce1aca838a","impliedFormat":1},{"version":"22ee946c191427c61835c301d03019ddd46338f3be5f42ba0708682b05acd128","impliedFormat":1},{"version":"2766597bd15be29202e42a7985e72213aa805023b16f10806d354aa0cf790216","impliedFormat":1},{"version":"963995cb3a928fdbadcb2dbdc583196d70a00b1db88a03c6f5cd75d1d76894bb","impliedFormat":1},{"version":"4b7136c8c228fb68827417072a2de1587fa9375ba318128c00f03618724b094c","impliedFormat":1},{"version":"03bf75a64f5863530593bddae9b3399944ea5900f9a02959eac08d38bc54f079","impliedFormat":1},{"version":"8563c7298a9eb9f5ac5bdafc361bdeade9f6a1082a9a774ce97876c6ea613eb4","impliedFormat":1},{"version":"d6eb3d0af3c9390cf7d701a83f8cce269757da436529d7dc34028d67a2cb8a9d","impliedFormat":1},{"version":"3170ad02d82944b74342cec2d370f9ab5e2f4ae4b0124cb45a6174489fccdeb1","impliedFormat":1},{"version":"942523f920e5a83c45ff32fa0294d7921309f5d7a52081c271183f70301729e6","impliedFormat":1},{"version":"6c17e64627b476dcb03ccabdb0322f22c0f536e72f9f72b9c13847b6abfceea9","impliedFormat":1},{"version":"c6f6550d9e0fc184cbea82c74dc812be0fc3248346446077021ffbbef93e0723","impliedFormat":1},{"version":"aaab817ea7aae249c25d44ae66c5b0ccb9ec7bd9a911c0baa8061f7539a894f8","impliedFormat":1},{"version":"5daf607cead28ea8a2da8e67d72525f524e3a225d24763dbfae9be5f40383f72","impliedFormat":1},{"version":"8fdc5e02d0db76fcf0370d74238e70e98ba7e723d1a762732f3cb8a000a0e8cd","impliedFormat":1},{"version":"96b6b6f78abb6edffd020e84466e53cd5646181350546b3a1a27e4d5c8bc2e49","impliedFormat":1},{"version":"aa80014bf1e34657a26496f2245202aada7a5aa50ef6fe837d98e6119be0c8f7","impliedFormat":1},{"version":"a432112e9fd77bfcf9686ced902d542644c9277cd26292812381ebd9750eba17","impliedFormat":1},{"version":"f646910361ec22fb03b9cddd701cea1b4e08c19faaf2e1f1a0cbd2ea3f4dd296","impliedFormat":1},{"version":"61b3940bd4e8e57d71f08a7e6ae42247ac7a529027735c81acb9423e27d25f38","impliedFormat":1},{"version":"d5579e1b121fc866fd02a690cc5f5521ee3408e54758fab701c1809ee1a14e2c","impliedFormat":1},{"version":"71575c1dcfc28c66d04ce052fab12e29ffc7fc2ee2600b321166cb5f521db1c2","impliedFormat":1},{"version":"30096e9a0d31a996f5e8d91976ff5da3f9db65f76c02727f4efaccf68af45a09","impliedFormat":1},{"version":"8d1d6f1e19429fc2dc04cacd53a117a03b854a742010de2ae52397a863bf2fbe","impliedFormat":1},{"version":"06b7e3172408f97cea206d9e831defa79781a6d56f205fafdd65803816982d56","impliedFormat":1},{"version":"3527954d38ad9ed3ff0fd17247f8c94ddcacfe62fa6f070a741ca4dfa721840b","impliedFormat":1},{"version":"d77c8aaa0440adc3c7f08c4d61bfd19eaa164c05d4aaeb96bd92bfe85890e57b","impliedFormat":1},{"version":"9fc5ebdc5ab32fadffe2aa10d524cdeee601a580b454b11606e987579e706187","impliedFormat":1},{"version":"f9e7ea6d5324204ea13dc554ccbfb0df7dbed531e8c23822c3966a441658afa6","impliedFormat":1},{"version":"3c206112006940848c84dd69894036115a944d1628cc90ee5a22bcf17fd7bc96","impliedFormat":1},{"version":"3aa41c401a49d65d38ba77755be9aabff66bacb2c5fd7f58001bc5af47f9b4b3","impliedFormat":1},{"version":"4d658a5505607a5dc86c0e711ba7502c396a002e67c5564d1804d5fccd2a07a9","impliedFormat":1},{"version":"8613c8ca02e06f075a238574a25e3e1ceced8b893e7f4d6b47b690d82cad949b","impliedFormat":1},{"version":"4d36d37ff5adce5b79b4a123c6828addc97ce9c86578e04fe45ef4c3ce8e7cd6","impliedFormat":1},{"version":"18db7de69084ee35368c07a74f3996e4bdc037effeea7c3ed2defa250dfcdfe2","impliedFormat":1},{"version":"2f37bd66d7ecce73771f8ca960c7a6ae003a4d0309c1644743df468fc2a0bb27","impliedFormat":1},{"version":"ccab85cc166fe76387031187c8ed7ce156975ec9bfcfdcbde25dc18cdc671ccc","impliedFormat":1},{"version":"6f6ebdc7f03dcc8996373b3ca0927672dccd72af9e1623a9c9114b961fb26e86","impliedFormat":1},{"version":"b03f863a5b9670514f99b6bbf36895d7102caab9ab72d3b8778fc3429937704a","impliedFormat":1},{"version":"3c44b0d212075d939fff25e6c97b04436a55252899d1247f29686a8133270a59","impliedFormat":1},{"version":"e6eb8c2dfabc1713abb667bd65603a3888d46320d3874c117b4c24a16a29dfc5","impliedFormat":1},{"version":"f7ec29c1118f3e6422a13113a705f52e2491a64c09bd6041e8900e218b3c58fc","impliedFormat":1},{"version":"13cb0e4ba5f0cf599e4eaa5528506ecfa284eef6d0f6f098517eb7cd18371d8b","impliedFormat":1},{"version":"8297d59fddbbc058d92a9bf5f9215dc645feb0779a73324588b74abd8b6f5742","impliedFormat":1},{"version":"e7471eec8618d24f3ad57f18b0c8a6932bf49af28684a2762d27df0a3740a739","impliedFormat":1},{"version":"a1ccc596297ff097bae0f22ced15db88c5c2c1c8edf9f7db63ee8e0738089dc8","impliedFormat":1},{"version":"dff5c929e4fbf17a155adcd74e8b4bdfd35d1dbccad373dd406547d7c88de0be","impliedFormat":1},{"version":"8e75511a2ff565fcc0356ae0fa2a3fe33dde535acb3f052eb8acde6523c31ea7","impliedFormat":1},{"version":"0248dcbfe1a7cf94a06c6e1ed356a06d3a31a3f8ae0b778742fcf3856395f092","impliedFormat":1},{"version":"6640a6448bc3de4e2dc41ce5335f64053b5b2faddb51fa12ea7b8d80e0dec244","impliedFormat":1},{"version":"b3cff05837a161fcb67896d62da40b59e5ae61fdb07239b537493d6bb930116f","impliedFormat":1},{"version":"484b269d5d5d007f24d8bf97e162ac5ab944f41dce67d9f213d9a41b4e37f3c3","impliedFormat":1},{"version":"a268804bceba21eb8207968af124805239cf9c165962b84be0c9486c600040b7","impliedFormat":1},{"version":"963f15f29b61c25ea9cd4c684dce3188bca77f1b78a7d0951a15c9c581784206","impliedFormat":1},{"version":"41493b7a4cafe332466eb3ce3441e0699f1b8dfa03360ce61e9c1df0172c05b2","impliedFormat":1},{"version":"6a6701ae8452f26f3d8342740d6f09d00633d324a697a85b6da0768af3135a95","impliedFormat":1},{"version":"7ea2e0332336c942271a4f41faf52104280f59d252a231a9e18210900a0eef0c","impliedFormat":1},{"version":"665cb1d1c0256005897dce9383d39e3666ba4e3154390759073e8f1a3cf3fd9e","impliedFormat":1},{"version":"e67c8d5b0bc4c1ffa1c9fd4c24f6e377ddcbc267eaa58c469721983090d9136f","impliedFormat":1},{"version":"87b305d8104c5a708de8bcd1a25dda64e925deb4fa74c25c9352bc6f01760baf","impliedFormat":1},{"version":"e5639037a16f1b0e50bb372236cfb23a61c37390ad8c854c46ffc4b83a126b8b","impliedFormat":1},{"version":"45abec77bf59857a6ae956d61f0f4176fd001d09d57fe7822f77a1ecc0e801cc","impliedFormat":1},{"version":"89dc7b4a49dffd1a1da71e15d4189e785abc58a4f5f1a40c2cadd8acab7a7063","impliedFormat":1},{"version":"53333f60b5e6871ffc307afd61bde499f10d8e2d295b5aaa45cca8011a6df428","impliedFormat":1},{"version":"8476667d8e9c69d512e8812c0269c9173ca926f8cf88a8abaff8c885516a5ae2","impliedFormat":1},{"version":"ee6f02df42a5f1f332fd37d9a14dd8eff9a08330a49b9dbcd54a8c448562c33c","impliedFormat":1},{"version":"09eec98b368e47af834c1d1ef97999506ee1ebec34e000c11dc0a1963c8a0320","impliedFormat":1},{"version":"c4009c569ca787a43a5e7337025ea0c3df453699cc9165e687dce1f57cb3eb64","impliedFormat":1},{"version":"2840e1ed437c0efa7b94f972e4555ae52be11530af4f3d0e33b8d82a2ef19f0d","impliedFormat":1},{"version":"51a8ec53dad610df52180f2d9744fc114ef66d28f37da141d49fafbd8bad199f","impliedFormat":1},{"version":"de29cdd8da03b5d43717fdf89ebbbb3651eb97c3bc76add0949aab240d996cdf","impliedFormat":1},{"version":"ea123fd86b83dd0695e83a7371b91460df81682b13ad7ef82a3e6eec3448d68c","impliedFormat":1},{"version":"41995d591a7ab1d813dd47d8b77f90879880743c1623f07d2c61437636854047","impliedFormat":1},{"version":"390e6d6cdcc1a226bb0edcecd20815c23fd0716e0d2f27f2c25e06cb569181c5","impliedFormat":1},{"version":"8f1241f5d9f0d3d72117768b3c974e462840fbd85026fb66685078945404cf2f","impliedFormat":1},{"version":"40a8e14d843eaae04e9e3c349d0f0b0499d99f77e0062528ef5e942e474cacc0","signature":"49ca5504ce19087b5346558fb3fbe819f447db2d8970b5b1e0f0b8d0923983f6"},{"version":"ca7b4934b923af72eab17c5b3f09dacb8a7c4f90d4e8806d1c23cb8a4b0963bf","signature":"07674efcf194a31ea63d0d7f026e31718340ea0f4940e4f7687262227353d476"},{"version":"e32646e7f5ab9b087715e9442f81c8de26e88b3ca65388b6223044941d2c1ed3","signature":"8ba1c20d878eb084c898d1679c5e15a102c3a1b97c0b0877dda7a4eeceb2d91d"},{"version":"c11c53ae259bb3e7ea68e34d496502c1364b2da69ffe8604dc801ecb77fa9633","signature":"66de6dcdca7c30338e79e9afc9819e401524b1f77f6140b24271aae77c7be285"},{"version":"f3eb63365b043c0023c9c316e6dc70cb48db83aef3e3166de8198a0a4c391512","signature":"21e45b58ffc74dac822420783848866f5ea11549df9f2df6091c37bddb353df7"},{"version":"e22c5dd381d32cbe91698046908fa2d39102e66ac7055e0a6b24f382d9a9bddd","signature":"dc6cafc0e3025b33fb78d8b8b043043fea951c991fa23f40a3223d4a72e37116"},{"version":"fb65d234a08f84965bdb10f7b0c237ca54640048dae0036e2597dc9d1cbd619b","signature":"4bfc1eda86bb0569c2b589ec54bf8f648961b55983600cb8684242224c9e6bfb"},{"version":"293a23f859fb79672ea198cd582b52eff63eeac0b4fbe443b7b63ba9688845d8","signature":"bcd1a1176a23df82ec9c1b28bbdbf0c8ba38108822c9ee91909bf3c80c5828c1"},{"version":"8c437caf352adcd047a2892cb5ae184e854c98e3d003992692be53e21b6b0ea5","signature":"edc549f3179ea0fa1126572890c8e25178f74c3d26029cc3bae5fdb725b2ebac"},{"version":"88cb2a248a93500c5ba97ea6372039563815d0b9f821a7a47ca2904644aef344","signature":"a7accbcf23d77ac85d66199d2fac5577e52074f8f976fc23ec95646ee7c38fbd"},{"version":"896726ee49943351c6e9ef43a2f2a4e078260b5198e05677a5d82452f89f17d6","signature":"ca9d9ea34e5b30291ef8bb8e81771071420e354f6a5104296cdec499b7ad2afb"},{"version":"fbbfcefc1ff9787e57347c2c19b1358253d26ef16b5a223d17218d3b4cb8c3d7","signature":"b3d13b8c63e4d0ee7076f5a0c631a15f83b5e861103a56faef3d1bf738f5f0ee"},{"version":"db365fbdfd131401492cbd36b05134f7f1aefefbeb9d8ea0c51b299c237eb1f0","signature":"b341222d4a407169e796b9cfd72cf5f6381b1608ce24e4b3bc8f7540d82d07de"},{"version":"dff93e0997c4e64ff29e9f70cad172c0b438c4f58c119f17a51c94d48164475a","impliedFormat":1},{"version":"fd1ddf926b323dfa439be49c1d41bbe233fe5656975a11183aeb3bf2addfa3bb","impliedFormat":1},{"version":"6dda11db28da6bcc7ff09242cd1866bdddd0ae91e2db3bea03ba66112399641a","impliedFormat":1},{"version":"ea4cd1e72af1aa49cf208b9cb4caf542437beb7a7a5b522f50a5f1b7480362ed","impliedFormat":1},{"version":"903a7d68a222d94da11a5a89449fdd5dd75d83cd95af34c0242e10b85ec33a93","impliedFormat":1},{"version":"e7fe2e7ed5c3a7beff60361632be19a8943e53466b7dd69c34f89faf473206d7","impliedFormat":1},{"version":"b4896cee83379e159f83021e262223354db79e439092e485611163e2082224ff","impliedFormat":1},{"version":"5243e79a643e41d9653011d6c66e95048fc0478eb8593dc079b70877a2e3990e","impliedFormat":1},{"version":"76e7352249c42b9d54fe1f9e1ebcef777da1cb2eb33038366af49469d433597b","impliedFormat":1},{"version":"88cb622dd0ec1ef860e5c27fa884e60d2eba5ae22c7907dff82c56a69bdd2c8a","impliedFormat":1},{"version":"eb234b3e285e8bc071bdddc1ec0460095e13ead6222d44b02c4e0869522f9ba3","impliedFormat":1},{"version":"c85114872760189e50fef131944427b0fb367f0cc0b6dce164bb427a6fd89381","impliedFormat":1},{"version":"5ad69b0d7e7bdbcd3adfdb6a3e306e935c9c2711b1c60493646504a2f991346e","impliedFormat":1},{"version":"a12a667efdeb03b529bd4ebb4032998ddd32743799f59f9f18b186f8e63a2cf1","impliedFormat":1},{"version":"cee7efa0ae4c58deab218d1df0d1bf84abfd5c356cff28bca1421489cba13a19","impliedFormat":1},{"version":"f9e034b1ae29825c00532e08ea852b0c72885c343ee48d2975db0a6481218ab3","impliedFormat":1},{"version":"1193f49cbb883f40326461fe379e58ffa4c18d15bf6d6a1974ad2894e4fb20f3","impliedFormat":1},{"version":"8f1241f5d9f0d3d72117768b3c974e462840fbd85026fb66685078945404cf2f","impliedFormat":1},{"version":"32262546abd94e6164de18f523ea601d4f60e13577095b24f6cd8ce6b9f0cef3","signature":"0f10e26b0bd5179158d0a79a222d0f3ae9054be281fb7d2cb587bd358b458eb5"},{"version":"717cddbdc046543af60e5dc3d26e97d68155574237af25c8b67633e913f0c735","signature":"a7ad670f373dd5665c73c7dc09a8e28b976a63bd7ed08def7c1c13456e87d3dc"},{"version":"8bc1351e61103f0f4cb5df6026c80886106390709faffe4aaf00174a41598c99","signature":"bfe706aafb8659b1036a2721b73235a7f0c5cb65365105adec29a0d69b786984"},{"version":"177b820a4ff1e39c93a3975b9fb94b3b9f9bf84762606f21e9a5793aa7eb6d72","signature":"aa1725e38b5a0b4009f6a74f296f173e7926c119a60454dbd2e523861735df69"},{"version":"03c92769f389dbd9e45232f7eb01c3e0f482b62555aaf2029dcbf380d5cee9e4","impliedFormat":1},{"version":"17668c1aab598920796050ee5a00d961ede5e92595f6ac8908a975ed75a537e5","impliedFormat":1},{"version":"afab4dbcb8ec9eee109a48bc1026432644218aad02868228e334d3379cfd0805","signature":"f2368b2dca5f162cbf34a014561f3613490a6313df9ff99558ee61ad9829032b"},{"version":"ea7ee0cf81c5d16d059f09473d082df44a208c98562b5a7ea9f8f002fb779fd1","signature":"66f2baf027b9cf63c93835504daf4d21e06068cd8aa1fbabf8b46762207cec2a"},{"version":"72aa1c89fcde6754075e6bdbc47385b5d553e5414030f7212623b6dd20505b3b","signature":"a28b5c0c372fb375910b3fe3c3ce4331509bc18ccef7cc39c9ee9d8daf8225d1"},{"version":"40a86c3feb801ebae6c10c56852873610a2c8beff6aba2840fd269458b08035e","signature":"b0cab10ede4434ec226c743e849dbe3fa6f1e53af753fec14a1e551837694791"},{"version":"e603d24d46fc59de0e87e42ade421e5b24e66abc0a18adb52f60298fb77b1fa7","signature":"82c1bdff6d8f365f65e8619a9d0d945f13a6d84a652d43c188bac3de70ac8135"},{"version":"df904b3dd8810291b56b67d8b976fbcf76a43674441c97598591cc97d3514ab6","signature":"9cab9bf4bf30e9580ee770a86c75a19695a6e862f55ee39f752807f39840787c"},{"version":"037579789156e579f2ad4289eb31c70223d30d218193767ea1d00876349d73b8","signature":"98497e3f7ee9145cef4745cc9a5c9a41d835e2d50a552329afa8310c5d37e8a3"},{"version":"0cd0b6be12b69bd4d22c5f779bc01b2ed0bcf4153f8e795c8b090d47029fe8c0","signature":"616b6d9d8e12a694ec3c816791f1f4f8c8a60ddf1573f86347830daa82a9861d"},{"version":"64b8d761d149aaa2094f5d265784a8fd3bdb132df3e71b1faf752c35efb0f6c1","impliedFormat":99},{"version":"e0b5e1ce5b95814c1ee6362099ef06b6d8e8cc45c211f210b3b66cf5b8951503","signature":"83075013a5585607d78937d40e486f6c4f10da9206f02391b0c854c582802d74"},{"version":"6434746153334dcef3cff63406522c4f04a75c791dd2a03541300bca903ed8dd","signature":"186557af0bf81eb67ef3f7a020ed63e4f89e384fc18f73ab524ffd09dfeff77b"},{"version":"5e2261982ab73f2a5b30e630f7c4709519dcd83bff2fb813290813110f06f4fd","signature":"db9012a68043650290629d0b2591e472be1031a3208f7fe80bd64bec1342d1e4"},{"version":"2cdb1b3afb4879e8cec12f13557f0525dc6790786c6f1b6026914c6165d3d667","signature":"05804cff4bfe96535636637e14fe36d801f46ac2196880f9f0a7b6a1bf2367ae"},{"version":"81dad912718eebf3358ddd6764a6169e99e850a72ad48cae95b9d780b996437a","signature":"83e4a5f9979aeea8b242a2cd79fdb924147abbdd7794b12ced8d4eb6475d5e80"},{"version":"2103dd12c0a902cb2821ee83609165da5f3a66a19d75894cdb88361bbed6c8e4","signature":"f1cd1321749cd89b60479d503bf3fd50fb2c6f02aac579a99f4c148406798d65"},{"version":"f269e48de989922077068e45c05e553d13953de0fbd9444fb2c83d3e0eca2f05","signature":"304ea596a50f1cb26b4aea7c1070d7f7f91be8c0f6a042a457a8c2aeb5b6331d"},{"version":"acb789fc4b9cd2098d968efb622c15e2973b41bdcbf8a39b402092fcbc4dac5d","signature":"397feba80f02e331ac0e36fda32fcea4afff0e059c49d333d4e437a5724da6f3"},{"version":"a4e9358650d53831198f528c5889b107a53e4fce986c3e828c5d0c75d04818d2","signature":"b0dca8f7923f4463c64c59855b0134ed3b65e292eaf1d83b5f1471e2f8b7a2aa"},{"version":"026efc27def1ee77c790ae5ea021708aea846d5f5bd1a267bbc9c4d20a3b0371","signature":"43ed1758900c7303c7712b9df54dc8754c836613cdd3ad50be8a78f47c6862e1"},{"version":"04ede5556e2681d9978e5c37bc0f84763d6aebbf8be539edfe0718eec4f525be","signature":"b038efa8301aef5579777ae1e9cb8c6bc39660ac320ce5968158bbbe261f9890"},{"version":"d52b4165b7d1a04f0bd5aa4d4b87ecec41abf0ac53fe84b71ca1d45c26688234","signature":"fdaa304e909f36c039942e8782e95eb9ea56d62257f36dec764d9f379a62dc59"},{"version":"fd771f70f880e943deb69722fe96adb729ac7f66144b407aa2f1b599f62dd495","signature":"12cf3e9f6b047db713b15839e1d8d0a433a9e4116e353d158239cd801339b084"},{"version":"7ed88a65ecbe2c326d1153b2fc674a2a721ae8b28ecbdde18386314d1a19988b","signature":"d39702f23fedac076a5bf0959fcd2fb52b098df19da2952b3f9a92c8a3c7537d"},{"version":"04de5584b953b03611eeef01ba9948607def8f64f1e7fbc840752b13b4521b52","impliedFormat":1},{"version":"8b0b6a4c032a56d5651f7dd02ba3f05fbfe4131c4095093633cda3cae0991972","impliedFormat":1},{"version":"192a0c215bffe5e4ac7b9ff1e90e94bf4dfdad4f0f69a5ae07fccc36435ebb87","impliedFormat":1},{"version":"3ef8565e3d254583cced37534f161c31e3a8f341ff005c98b582c6d8c9274538","impliedFormat":1},{"version":"d7e42a3800e287d2a1af8479c7dd58c8663e80a01686cb89e0068be6c777d687","impliedFormat":1},{"version":"1098034333d3eb3c1d974435cacba9bd5a625711453412b3a514774fec7ca748","impliedFormat":1},{"version":"f2388b97b898a93d5a864e85627e3af8638695ebfa6d732ecd39d382824f0e63","impliedFormat":1},{"version":"a021f1dda1029ce423656e9aa3ceab92f3578a76245b59168a04ce94e6b87860","impliedFormat":1},{"version":"f477375e6f0bf2a638a71d4e7a3da8885e3a03f3e5350688541d136b10b762a6","impliedFormat":1},{"version":"a44d6ea4dc70c3d789e9cef3cc42b79c78d17d3ce07f5fd278a7e1cbe824da56","impliedFormat":1},{"version":"55cd8cbc22fe648429a787e16a9cd2dc501a2aafd28c00254ad120ef68a581c0","impliedFormat":1},{"version":"ba4900e9d6f9795a72e8f5ca13c18861821a3fc3ae7858acb0a3366091a47afb","impliedFormat":1},{"version":"7778e2cc5f74ef263a880159aa7fa67254d6232e94dd03429a75597a622537a7","impliedFormat":1},{"version":"8e06a1ef49502a62039eeb927a1bd7561b0bce48bd423a929e2e478fd827c273","impliedFormat":1},{"version":"7ec3d0b061da85d6ff50c337e3248a02a72088462739d88f33b9337dba488c4f","impliedFormat":1},{"version":"2f554c6798b731fc39ff4e3d86aadc932fdeaa063e3cbab025623ff5653c0031","impliedFormat":1},{"version":"fe4613c6c0d23edc04cd8585bdd86bc7337dc6265fb52037d11ca19eeb5e5aaf","impliedFormat":1},{"version":"53b26fbee1a21a6403cf4625d0e501a966b9ccf735754b854366cee8984b711c","impliedFormat":1},{"version":"9ff247206ec5dffdfadddfded2c9d9ad5f714821bb56760be40ed89121f192f4","impliedFormat":1},{"version":"98c6ddd06251098b3302e7094cbc9ab54a2ea88069f5416b7d0b8daee2ff8aa2","impliedFormat":1},{"version":"8c59d8256086ed17676139ee43c1155673e357ab956fb9d00711a7cac73e059d","impliedFormat":1},{"version":"cfe88132f67aa055a3f49d59b01585fa8d890f5a66a0a13bb71973d57573eee7","impliedFormat":1},{"version":"53ce488a97f0b50686ade64252f60a1e491591dd7324f017b86d78239bd232ca","impliedFormat":1},{"version":"50fd11b764194f06977c162c37e5a70bcf0d3579bf82dd4de4eee3ac68d0f82f","impliedFormat":1},{"version":"e0ceb647dcdf6b27fd37e8b0406c7eafb8adfc99414837f3c9bfd28ffed6150a","impliedFormat":1},{"version":"99579aa074ed298e7a3d6a47e68f0cd099e92411212d5081ce88344a5b1b528d","impliedFormat":1},{"version":"096e4ddaa8f0aa8b0ceadd6ab13c3fab53e8a0280678c405160341332eca3cd7","impliedFormat":1},{"version":"415b55892d813a74be51742edd777bbced1f1417848627bf71725171b5325133","impliedFormat":1},{"version":"942ab34f62ac3f3d20014615b6442b6dc51815e30a878ebc390dd70e0dec63bf","impliedFormat":1},{"version":"7a671bf8b4ad81b8b8aea76213ca31b8a5de4ba39490fbdee249fc5ba974a622","impliedFormat":1},{"version":"8e07f13fb0f67e12863b096734f004e14c5ebfd34a524ed4c863c80354c25a44","impliedFormat":1},{"version":"9faa56e38ed5637228530065a9bab19a4dc5a326fbdd1c99e73a310cfed4fcde","impliedFormat":1},{"version":"7d4ad85174f559d8e6ed28a5459aebfc0a7b0872f7775ca147c551e7765e3285","impliedFormat":1},{"version":"d422f0c340060a53cb56d0db24dd170e31e236a808130ab106f7ab2c846f1cdb","impliedFormat":1},{"version":"424403ef35c4c97a7f00ea85f4a5e2f088659c731e75dbe0c546137cb64ef8d8","impliedFormat":1},{"version":"16900e9a60518461d7889be8efeca3fe2cbcd3f6ce6dee70fea81dfbf8990a76","impliedFormat":1},{"version":"6daf17b3bd9499bd0cc1733ab227267d48cd0145ed9967c983ccb8f52eb72d6e","impliedFormat":1},{"version":"e4177e6220d0fef2500432c723dbd2eb9a27dcb491344e6b342be58cc1379ec0","impliedFormat":1},{"version":"ddc62031f48165334486ad1943a1e4ed40c15c94335697cb1e1fd19a182e3102","impliedFormat":1},{"version":"b3f4224eb155d7d13eb377ef40baa1f158f4637aa6de6297dfeeacefd6247476","impliedFormat":1},{"version":"4a168e11fe0f46918721d2f6fcdb676333395736371db1c113ae30b6fde9ccd2","impliedFormat":1},{"version":"5b0a75a5cced0bed0d733bde2da0bbb5d8c8c83d3073444ae52df5f16aefb6ab","impliedFormat":1},{"version":"ef2c1585cad462bdf65f2640e7bcd75cd0dbc45bae297e75072e11fe3db017fa","impliedFormat":1},{"version":"ef809928a4085de826f5b0c84175a56d32dd353856f5b9866d78b8419f8ea9bc","impliedFormat":1},{"version":"6f6eadb32844b0ec7b322293b011316486894f110443197c4c9fbcba01b3b2fa","impliedFormat":1},{"version":"a51e08f41e3e948c287268a275bfe652856a10f68ddd2bf3e3aaf5b8cdb9ef85","impliedFormat":1},{"version":"862f7d760ef37f0ae2c17de82e5fbf336b37d5c1b0dcf39dcd5468f90a7fdd54","impliedFormat":1},{"version":"af48a76b75041e2b3e7bd8eed786c07f39ea896bb2ff165e27e18208d09b8bee","impliedFormat":1},{"version":"cb524ec077f3963e13e85747c6b53fbdf6bf407c84ca1873c6e43da1e96bee6d","impliedFormat":1},{"version":"deb092bc337b2cb0a1b14f3d43f56bc663e1447694e6d479d6df8296bdd452d6","impliedFormat":1},{"version":"041bc1c3620322cb6152183857601707ef6626e9d99f736e8780533689fb1bf9","impliedFormat":1},{"version":"22bd7c75de7d68e075975bf1123de5bccecfd06688afff2e2022b4c70bfc91c3","impliedFormat":1},{"version":"128e7c2ffd37aa29e05367400d718b0e4770cefb1e658d8783ec80a16bc0643a","impliedFormat":1},{"version":"076ac4f2d642c473fa7f01c8c1b7b4ef58f921130174d9cf78430651f44c43ec","impliedFormat":1},{"version":"396c1e5a39706999ec8cc582916e05fcb4f901631d2c192c1292e95089a494d9","impliedFormat":1},{"version":"89df75d28f34fc698fe261f9489125b4e5828fbd62d863bbe93373d3ed995056","impliedFormat":1},{"version":"8ccf5843249a042f4553a308816fe8a03aa423e55544637757d0cfa338bb5186","impliedFormat":1},{"version":"93b44aa4a7b27ba57d9e2bad6fb7943956de85c5cc330d2c3e30cd25b4583d44","impliedFormat":1},{"version":"a0c6216075f54cafdfa90412596b165ff85e2cadd319c49557cc8410f487b77c","impliedFormat":1},{"version":"3c359d811ec0097cba00fb2afd844b125a2ddf4cad88afaf864e88c8d3d358bd","impliedFormat":1},{"version":"3c0b38e8bf11bf3ab87b5116ae8e7b2cad0147b1c80f2b77989dea6f0b93e024","impliedFormat":1},{"version":"8df06e1cd5bb3bf31529cc0db74fa2e57f7de1f6042726679eb8bc1f57083a99","impliedFormat":1},{"version":"d62f09256941e92a95b78ae2267e4cf5ff2ca8915d62b9561b1bc85af1baf428","impliedFormat":1},{"version":"e6223b7263dd7a49f4691bf8df2b1e69f764fb46972937e6f9b28538d050b1ba","impliedFormat":1},{"version":"d9b59eb4e79a0f7a144ee837afb3f1afbc4dab031e49666067a2b5be94b36bd4","impliedFormat":1},{"version":"1db014db736a09668e0c0576585174dbcfd6471bb5e2d79f151a241e0d18d66b","impliedFormat":1},{"version":"8a153d30edde9cefd102e5523b5a9673c298fc7cf7af5173ae946cbb8dd48f11","impliedFormat":1},{"version":"abaaf8d606990f505ee5f76d0b45a44df60886a7d470820fcfb2c06eafa99659","impliedFormat":1},{"version":"51a66bfa412057e786a712733107547ceb6f539061f5bf1c6e5a96e4ccf4f83c","impliedFormat":1},{"version":"d92a80c2c05cf974704088f9da904fe5eadc0b3ad49ddd1ef70ca8028b5adda1","impliedFormat":1},{"version":"fbd7450f20b4486c54f8a90486c395b14f76da66ba30a7d83590e199848f0660","impliedFormat":1},{"version":"ece5b0e45c865645ab65880854899a5422a0b76ada7baa49300c76d38a530ee1","impliedFormat":1},{"version":"62d89ac385aeab821e2d55b4f9a23a277d44f33c67fefe4859c17b80fdb397ea","impliedFormat":1},{"version":"f4dee11887c5564886026263c6ee65c0babc971b2b8848d85c35927af25da827","impliedFormat":1},{"version":"fb8dd49a4cd6d802be4554fbab193bb06e2035905779777f32326cb57cf6a2c2","impliedFormat":1},{"version":"e403ecdfba83013b5eb0e648a92ce182bff2a45ccb81db3035a69081563c2830","impliedFormat":1},{"version":"82d3e00d56a71fc169f3cf9ec5f5ffcc92f6c0e67d4dfc130dafe9f1886d5515","impliedFormat":1},{"version":"b8d57effce2d49a5493debbd8c644e8d52fbe66e2c6d451371375ef5f7bccb8e","impliedFormat":1},{"version":"9963d9857df2df335d1232a12eccbe5c777537a244f4b39406b27bf4736202f6","impliedFormat":1},{"version":"1b33478647aa1b771314745807397002a410c746480e9447db959110999873ce","impliedFormat":1},{"version":"b8d58ef4128a6e8e4b80803e5b67b2aaf1436c133ce39e514b9c004e21b2867e","impliedFormat":1},{"version":"3cd50f6a83629c0ec330fc482e587bfa96532d4c9ce85e6c3ddf9f52f63eee11","impliedFormat":1},{"version":"9fac6ebf3c60ced53dd21def30a679ec225fc3ff4b8d66b86326c285a4eebb5a","impliedFormat":1},{"version":"8cb83cb98c460cd716d2a98b64eb1a07a3a65c7362436550e02f5c2d212871d1","impliedFormat":1},{"version":"07bc8a3551e39e70c38e7293b1a09916867d728043e352b119f951742cb91624","impliedFormat":1},{"version":"e47adc2176f43c617c0ab47f2d9b2bb1706d9e0669bf349a30c3fe09ddd63261","impliedFormat":1},{"version":"7fec79dfd7319fec7456b1b53134edb54c411ba493a0aef350eee75a4f223eeb","impliedFormat":1},{"version":"189c489705bb96a308dcde9b3336011d08bfbca568bcaf5d5d55c05468e9de7a","impliedFormat":1},{"version":"98f4b1074567341764b580bf14c5aabe82a4390d11553780814f7e932970a6f7","impliedFormat":1},{"version":"1dd24cbf39199100fbe2f3dbd1c7203c240c41d95f66301ecc7650ae77875be1","impliedFormat":1},{"version":"2e252235037a2cd8feebfbf74aa460f783e5d423895d13f29a934d7655a1f8be","impliedFormat":1},{"version":"763f4ac187891a6d71ae8821f45eef7ff915b5d687233349e2c8a76c22b3bf2a","impliedFormat":1},{"version":"25e5c8b73c6ad21f39e8e72f954090f30b431a993252bccea5bdad4a3d93c760","impliedFormat":1},{"version":"5bf595f68b7c1d46ae8385e3363c6e0d4695b6da58a84c6340489fc07ffc73f8","impliedFormat":1},{"version":"b87682ddc9e2c3714ca66991cdd86ff7e18cae6fd010742a93bd612a07d19697","impliedFormat":1},{"version":"0d621d4e5ae0224d434f840a32f871bad9e9236dd18b13bb34164a769c4a964e","impliedFormat":1},{"version":"86bf2bfe29d0bc3fbc68e64c25ea6eab9bcb3c518ae941012ed75b1e87d391ae","impliedFormat":1},{"version":"3c74d80d1dd95437cc9bbf22d88199e7410fd85af06171327125bcf4025deae8","impliedFormat":1},{"version":"00b4f8b82e78f658b7e269c95d07e55d391235ce34d432764687441177ae7f64","impliedFormat":1},{"version":"57880096566780d72e02a5b34d8577e78cdf072bfd624452a95d65bd8f07cbe0","impliedFormat":1},{"version":"10ac50eaf9eb62c048efe576592b14830a757f7ea7ed28ee8deafc19c9845297","impliedFormat":1},{"version":"e75af112e5487476f7c427945fbd76ca46b28285586ad349a25731d196222d56","impliedFormat":1},{"version":"e91adad3da69c366d57067fcf234030b8a05bcf98c25a759a7a5cd22398ac201","impliedFormat":1},{"version":"d7d6e1974124a2dad1a1b816ba2436a95f44feeda0573d6c9fb355f590cf9086","impliedFormat":1},{"version":"464413fcd7e7a3e1d3f2676dc5ef4ebe211c10e3107e126d4516d79439e4e808","impliedFormat":1},{"version":"18f912e4672327b3dd17d70e91da6fcd79d497ba01dde9053a23e7691f56908c","impliedFormat":1},{"version":"2974e2f06de97e1d6e61d1462b54d7da2c03b3e8458ee4b3dc36273bc6dda990","impliedFormat":1},{"version":"d8c1697db4bb3234ff3f8481545284992f1516bc712421b81ee3ef3f226ae112","impliedFormat":1},{"version":"59b6cce93747f7eb2c0405d9f32b77874e059d9881ec8f1b65ff6c068fcce6f2","impliedFormat":1},{"version":"e2c3c3ca3818d610599392a9431e60ec021c5d59262ecd616538484990f6e331","impliedFormat":1},{"version":"e3cd60be3c4f95c43420be67eaa21637585b7c1a8129f9b39983bbd294f9513c","impliedFormat":1},{"version":"cc137d7ea6ad91ac1579463f2d25c0df4853c4e068e7fd9be5b6c27088760797","affectsGlobalScope":true,"impliedFormat":1},{"version":"979ca4ac6ee6b542298a47080cb9f566ed94de6fb9a453c8346a247a5ae5dc43","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"fb893a0dfc3c9fb0f9ca93d0648694dd95f33cbad2c0f2c629f842981dfd4e2e","impliedFormat":1},{"version":"3eb11dbf3489064a47a2e1cf9d261b1f100ef0b3b50ffca6c44dd99d6dd81ac1","impliedFormat":1}],"root":[548,[747,759],[778,781],[784,791],[793,806],919],"options":{"allowSyntheticDefaultImports":true,"declaration":true,"emitDecoratorMetadata":true,"experimentalDecorators":true,"module":1,"noFallthroughCasesInSwitch":false,"noImplicitAny":false,"outDir":"./","removeComments":true,"skipLibCheck":true,"sourceMap":true,"strictBindCallApply":false,"strictNullChecks":false,"target":4},"referencedMap":[[330,1],[317,1],[54,1],[306,2],[307,2],[308,1],[309,3],[319,4],[310,2],[311,5],[312,1],[313,1],[314,2],[315,2],[316,2],[318,6],[326,7],[328,1],[325,1],[332,8],[329,1],[327,1],[323,9],[324,10],[331,11],[333,12],[320,1],[322,13],[321,14],[260,1],[263,15],[259,1],[855,1],[261,1],[262,1],[336,16],[337,16],[338,16],[339,16],[340,16],[341,16],[342,16],[335,17],[343,16],[357,18],[344,16],[334,1],[345,16],[346,16],[347,16],[348,16],[349,16],[350,16],[351,16],[352,16],[353,16],[354,16],[355,16],[356,16],[365,19],[363,20],[362,1],[361,1],[364,21],[405,22],[55,1],[56,1],[57,1],[837,23],[59,24],[843,25],[842,26],[249,27],[250,24],[385,1],[279,1],[280,1],[386,28],[251,1],[387,1],[388,29],[58,1],[253,30],[254,31],[252,32],[255,30],[256,1],[258,33],[270,34],[271,1],[276,35],[272,1],[273,1],[274,1],[275,1],[277,1],[278,36],[284,37],[287,38],[285,1],[286,1],[305,39],[288,1],[289,1],[886,40],[269,41],[267,42],[265,43],[266,44],[268,1],[296,45],[290,1],[299,46],[292,47],[297,48],[295,49],[298,50],[293,51],[294,52],[282,53],[301,54],[283,55],[303,56],[304,57],[291,1],[300,1],[257,1],[264,58],[302,59],[371,60],[366,1],[372,61],[367,62],[368,63],[369,64],[370,65],[373,66],[378,67],[376,68],[377,68],[384,69],[374,1],[375,70],[379,67],[381,71],[383,72],[382,73],[397,74],[390,75],[391,76],[392,76],[393,77],[394,77],[395,76],[396,76],[389,78],[399,79],[398,80],[401,81],[400,82],[402,83],[358,84],[360,85],[281,1],[359,53],[403,86],[380,87],[404,88],[760,3],[771,89],[772,90],[776,91],[761,1],[767,92],[769,93],[770,94],[762,1],[763,1],[766,95],[764,1],[765,1],[774,1],[775,96],[773,97],[777,98],[807,99],[808,100],[828,101],[829,102],[830,1],[831,103],[832,104],[841,105],[834,106],[838,107],[846,108],[844,3],[845,109],[835,110],[847,1],[849,111],[850,112],[851,113],[840,114],[836,115],[860,116],[848,117],[875,118],[833,119],[876,120],[873,121],[874,3],[898,122],[823,123],[819,124],[821,125],[872,126],[814,127],[862,128],[861,1],[822,129],[869,130],[826,131],[870,1],[871,132],[824,133],[825,134],[820,135],[818,136],[813,1],[866,137],[879,138],[877,3],[809,3],[865,139],[810,10],[811,102],[812,140],[816,141],[815,142],[878,143],[817,144],[854,145],[852,111],[853,146],[863,10],[864,147],[867,148],[882,149],[883,150],[880,151],[881,152],[884,153],[885,154],[887,155],[859,156],[856,157],[857,2],[858,146],[889,158],[888,159],[895,160],[827,3],[891,161],[890,3],[893,162],[892,1],[894,163],[839,164],[868,165],[897,166],[896,3],[537,1],[541,167],[546,168],[538,3],[540,169],[539,1],[542,170],[544,171],[545,172],[547,173],[902,174],[903,175],[917,176],[905,177],[904,178],[899,179],[900,1],[901,1],[916,180],[907,181],[908,181],[909,181],[910,181],[912,182],[911,181],[913,183],[914,184],[906,1],[915,185],[743,186],[740,187],[742,188],[745,189],[741,187],[739,190],[744,191],[746,192],[535,193],[534,194],[921,195],[531,196],[918,197],[536,198],[532,1],[920,1],[468,199],[469,199],[470,200],[408,201],[471,202],[472,203],[473,204],[406,1],[474,205],[475,206],[476,207],[477,208],[478,209],[479,210],[480,210],[481,211],[482,212],[483,213],[484,214],[409,1],[407,1],[485,215],[486,216],[487,217],[527,218],[488,219],[489,220],[490,219],[491,221],[492,222],[493,223],[494,224],[495,224],[496,224],[497,225],[498,226],[499,227],[500,228],[501,229],[502,230],[503,230],[504,231],[505,1],[506,1],[507,232],[508,233],[509,232],[510,234],[511,235],[512,236],[513,237],[514,238],[515,239],[516,240],[517,241],[518,242],[519,243],[520,244],[521,245],[522,246],[523,247],[524,248],[410,219],[411,1],[412,249],[413,250],[414,1],[415,251],[416,1],[459,252],[460,253],[461,254],[462,254],[463,255],[464,1],[465,202],[466,256],[467,253],[525,257],[526,258],[783,259],[782,260],[543,261],[529,1],[530,1],[528,262],[533,263],[609,264],[600,1],[601,1],[602,1],[603,1],[604,1],[605,1],[606,1],[607,1],[608,1],[792,1],[417,1],[768,265],[53,1],[563,1],[248,266],[221,1],[199,267],[197,267],[247,268],[212,269],[211,269],[112,270],[63,271],[219,270],[220,270],[222,272],[223,270],[224,273],[123,274],[225,270],[196,270],[226,270],[227,275],[228,270],[229,269],[230,276],[231,270],[232,270],[233,270],[234,270],[235,269],[236,270],[237,270],[238,270],[239,270],[240,277],[241,270],[242,270],[243,270],[244,270],[245,270],[62,268],[65,273],[66,273],[67,273],[68,273],[69,273],[70,273],[71,273],[72,270],[74,278],[75,273],[73,273],[76,273],[77,273],[78,273],[79,273],[80,273],[81,273],[82,270],[83,273],[84,273],[85,273],[86,273],[87,273],[88,270],[89,273],[90,273],[91,273],[92,273],[93,273],[94,273],[95,270],[97,279],[96,273],[98,273],[99,273],[100,273],[101,273],[102,277],[103,270],[104,270],[118,280],[106,281],[107,273],[108,273],[109,270],[110,273],[111,273],[113,282],[114,273],[115,273],[116,273],[117,273],[119,273],[120,273],[121,273],[122,273],[124,283],[125,273],[126,273],[127,273],[128,270],[129,273],[130,284],[131,284],[132,284],[133,270],[134,273],[135,273],[136,273],[141,273],[137,273],[138,270],[139,273],[140,270],[142,273],[143,273],[144,273],[145,273],[146,273],[147,273],[148,270],[149,273],[150,273],[151,273],[152,273],[153,273],[154,273],[155,273],[156,273],[157,273],[158,273],[159,273],[160,273],[161,273],[162,273],[163,273],[164,273],[165,285],[166,273],[167,273],[168,273],[169,273],[170,273],[171,273],[172,270],[173,270],[174,270],[175,270],[176,270],[177,273],[178,273],[179,273],[180,273],[198,286],[246,270],[183,287],[182,288],[206,289],[205,290],[201,291],[200,290],[202,292],[191,293],[189,294],[204,295],[203,292],[190,1],[192,296],[105,297],[61,298],[60,273],[195,1],[187,299],[188,300],[185,1],[186,301],[184,273],[193,302],[64,303],[213,1],[214,1],[207,1],[210,269],[209,1],[215,1],[216,1],[208,304],[217,1],[218,1],[181,305],[194,306],[630,307],[628,308],[629,309],[626,310],[620,311],[631,312],[632,310],[634,311],[633,311],[635,313],[622,1],[625,314],[621,315],[627,311],[637,316],[638,316],[639,316],[640,316],[641,316],[642,316],[643,316],[644,316],[645,316],[646,316],[674,317],[636,1],[675,318],[676,316],[647,316],[648,316],[649,316],[650,316],[651,316],[652,316],[653,316],[654,316],[655,316],[656,316],[657,316],[658,316],[659,316],[660,316],[661,316],[662,316],[663,316],[665,316],[666,316],[664,316],[667,316],[668,316],[669,316],[670,316],[671,316],[672,316],[673,316],[738,319],[686,315],[677,1],[678,1],[679,1],[680,1],[687,315],[681,1],[682,1],[683,1],[684,1],[685,1],[692,320],[693,320],[691,321],[614,1],[613,315],[615,315],[612,315],[618,322],[619,323],[688,315],[689,315],[690,324],[697,325],[694,311],[696,326],[698,327],[695,328],[699,329],[701,315],[700,315],[617,330],[623,331],[703,332],[624,333],[702,1],[616,1],[704,1],[705,1],[707,1],[708,1],[709,1],[720,1],[710,1],[711,1],[712,1],[713,1],[714,1],[715,1],[716,1],[717,1],[719,1],[721,1],[718,1],[722,1],[723,1],[724,1],[725,1],[726,1],[727,1],[706,1],[728,1],[729,1],[730,1],[732,1],[733,1],[734,1],[735,1],[731,1],[736,315],[737,1],[555,334],[559,335],[556,336],[558,336],[557,336],[560,337],[549,1],[550,1],[562,1],[567,338],[569,339],[598,340],[575,340],[576,340],[573,1],[577,341],[578,340],[586,342],[587,342],[588,342],[589,342],[590,342],[591,342],[592,342],[574,340],[593,343],[594,343],[595,344],[596,343],[579,340],[580,340],[599,345],[581,340],[582,340],[583,340],[584,340],[585,341],[597,346],[570,347],[554,1],[611,348],[561,334],[564,349],[571,350],[551,1],[552,1],[568,351],[553,1],[565,352],[572,353],[566,1],[610,354],[50,1],[51,1],[8,1],[9,1],[13,1],[12,1],[2,1],[14,1],[15,1],[16,1],[17,1],[18,1],[19,1],[20,1],[21,1],[3,1],[22,1],[23,1],[4,1],[24,1],[52,1],[28,1],[25,1],[26,1],[27,1],[29,1],[30,1],[31,1],[5,1],[32,1],[33,1],[34,1],[35,1],[6,1],[39,1],[36,1],[37,1],[38,1],[40,1],[7,1],[41,1],[46,1],[47,1],[42,1],[43,1],[44,1],[45,1],[1,1],[48,1],[49,1],[11,1],[10,1],[435,355],[447,356],[433,357],[448,358],[457,359],[424,360],[425,361],[423,362],[456,265],[451,363],[455,364],[427,365],[444,366],[426,367],[454,368],[421,369],[422,363],[428,370],[429,1],[434,371],[432,370],[419,372],[458,373],[449,374],[438,375],[437,370],[439,376],[442,377],[436,378],[440,379],[452,265],[430,380],[431,381],[443,382],[420,358],[446,383],[445,370],[441,384],[450,1],[418,1],[453,385],[759,386],[806,387],[786,388],[780,389],[758,3],[548,390],[784,391],[785,392],[805,393],[789,394],[791,395],[790,396],[779,397],[800,398],[801,399],[799,400],[797,401],[798,402],[796,403],[919,404],[803,405],[804,406],[802,407],[794,408],[795,409],[793,410],[778,411],[755,412],[749,413],[750,414],[747,415],[751,416],[748,417],[754,412],[756,418],[753,412],[752,412],[781,419],[757,420],[788,421],[787,422]],"version":"5.9.3"} \ No newline at end of file diff --git a/dist/users/users.module.d.ts b/dist/users/users.module.d.ts new file mode 100644 index 0000000..d1340f4 --- /dev/null +++ b/dist/users/users.module.d.ts @@ -0,0 +1,2 @@ +export declare class UsersModule { +} diff --git a/dist/users/users.module.js b/dist/users/users.module.js new file mode 100644 index 0000000..234450d --- /dev/null +++ b/dist/users/users.module.js @@ -0,0 +1,24 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UsersModule = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const user_model_1 = require("../models/user.model"); +const users_service_1 = require("./users.service"); +let UsersModule = class UsersModule { +}; +exports.UsersModule = UsersModule; +exports.UsersModule = UsersModule = __decorate([ + (0, common_1.Module)({ + imports: [sequelize_1.SequelizeModule.forFeature([user_model_1.User])], + providers: [users_service_1.UsersService], + exports: [users_service_1.UsersService], + }) +], UsersModule); +//# sourceMappingURL=users.module.js.map \ No newline at end of file diff --git a/dist/users/users.module.js.map b/dist/users/users.module.js.map new file mode 100644 index 0000000..4187bef --- /dev/null +++ b/dist/users/users.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"users.module.js","sourceRoot":"","sources":["../../src/users/users.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,iDAAoD;AACpD,qDAA4C;AAC5C,mDAA+C;AAOxC,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IALvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,2BAAe,CAAC,UAAU,CAAC,CAAC,iBAAI,CAAC,CAAC,CAAC;QAC7C,SAAS,EAAE,CAAC,4BAAY,CAAC;QACzB,OAAO,EAAE,CAAC,4BAAY,CAAC;KACxB,CAAC;GACW,WAAW,CAAG"} \ No newline at end of file diff --git a/dist/users/users.service.d.ts b/dist/users/users.service.d.ts new file mode 100644 index 0000000..7e25423 --- /dev/null +++ b/dist/users/users.service.d.ts @@ -0,0 +1,8 @@ +import { User } from '../models/user.model'; +export declare class UsersService { + private userModel; + constructor(userModel: typeof User); + findOne(username: string): Promise; + findById(id: number): Promise; + create(createUserDto: any): Promise; +} diff --git a/dist/users/users.service.js b/dist/users/users.service.js new file mode 100644 index 0000000..66cd148 --- /dev/null +++ b/dist/users/users.service.js @@ -0,0 +1,39 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UsersService = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const user_model_1 = require("../models/user.model"); +let UsersService = class UsersService { + constructor(userModel) { + this.userModel = userModel; + } + async findOne(username) { + return this.userModel.findOne({ where: { username } }); + } + async findById(id) { + return this.userModel.findByPk(id); + } + async create(createUserDto) { + return this.userModel.create(createUserDto); + } +}; +exports.UsersService = UsersService; +exports.UsersService = UsersService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, sequelize_1.InjectModel)(user_model_1.User)), + __metadata("design:paramtypes", [Object]) +], UsersService); +//# sourceMappingURL=users.service.js.map \ No newline at end of file diff --git a/dist/users/users.service.js.map b/dist/users/users.service.js.map new file mode 100644 index 0000000..10a65c4 --- /dev/null +++ b/dist/users/users.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"users.service.js","sourceRoot":"","sources":["../../src/users/users.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,iDAAgD;AAChD,qDAA4C;AAGrC,IAAM,YAAY,GAAlB,MAAM,YAAY;IACvB,YAEU,SAAsB;QAAtB,cAAS,GAAT,SAAS,CAAa;IAC7B,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,aAAkB;QAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAC9C,CAAC;CACF,CAAA;AAjBY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,uBAAW,EAAC,iBAAI,CAAC,CAAA;;GAFT,YAAY,CAiBxB"} \ No newline at end of file diff --git a/dist/utils/utils.module.d.ts b/dist/utils/utils.module.d.ts new file mode 100644 index 0000000..8db2fc0 --- /dev/null +++ b/dist/utils/utils.module.d.ts @@ -0,0 +1,2 @@ +export declare class UtilsModule { +} diff --git a/dist/utils/utils.module.js b/dist/utils/utils.module.js new file mode 100644 index 0000000..ae2592f --- /dev/null +++ b/dist/utils/utils.module.js @@ -0,0 +1,45 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UtilsModule = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const utils_service_1 = require("./utils.service"); +const user_model_1 = require("../models/user.model"); +const food_item_model_1 = require("../models/food-item.model"); +const meal_model_1 = require("../models/meal.model"); +const meal_food_model_1 = require("../models/meal-food.model"); +const water_log_model_1 = require("../models/water-log.model"); +const weight_log_model_1 = require("../models/weight-log.model"); +const meal_plan_model_1 = require("../models/meal-plan.model"); +const planned_food_model_1 = require("../models/planned-food.model"); +const daily_summary_model_1 = require("../models/daily-summary.model"); +let UtilsModule = class UtilsModule { +}; +exports.UtilsModule = UtilsModule; +exports.UtilsModule = UtilsModule = __decorate([ + (0, common_1.Global)(), + (0, common_1.Module)({ + imports: [ + sequelize_1.SequelizeModule.forFeature([ + user_model_1.User, + food_item_model_1.FoodItem, + meal_model_1.Meal, + meal_food_model_1.MealFood, + water_log_model_1.WaterLog, + weight_log_model_1.WeightLog, + meal_plan_model_1.MealPlan, + planned_food_model_1.PlannedFood, + daily_summary_model_1.DailySummary, + ]), + ], + providers: [utils_service_1.UtilsService], + exports: [utils_service_1.UtilsService], + }) +], UtilsModule); +//# sourceMappingURL=utils.module.js.map \ No newline at end of file diff --git a/dist/utils/utils.module.js.map b/dist/utils/utils.module.js.map new file mode 100644 index 0000000..183c964 --- /dev/null +++ b/dist/utils/utils.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.module.js","sourceRoot":"","sources":["../../src/utils/utils.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAChD,iDAAoD;AACpD,mDAA+C;AAC/C,qDAA4C;AAC5C,+DAAqD;AACrD,qDAA4C;AAC5C,+DAAqD;AACrD,+DAAqD;AACrD,iEAAuD;AACvD,+DAAqD;AACrD,qEAA2D;AAC3D,uEAA6D;AAoBtD,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IAlBvB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,2BAAe,CAAC,UAAU,CAAC;gBACzB,iBAAI;gBACJ,0BAAQ;gBACR,iBAAI;gBACJ,0BAAQ;gBACR,0BAAQ;gBACR,4BAAS;gBACT,0BAAQ;gBACR,gCAAW;gBACX,kCAAY;aACb,CAAC;SACH;QACD,SAAS,EAAE,CAAC,4BAAY,CAAC;QACzB,OAAO,EAAE,CAAC,4BAAY,CAAC;KACxB,CAAC;GACW,WAAW,CAAG"} \ No newline at end of file diff --git a/dist/utils/utils.service.d.ts b/dist/utils/utils.service.d.ts new file mode 100644 index 0000000..44fef12 --- /dev/null +++ b/dist/utils/utils.service.d.ts @@ -0,0 +1,54 @@ +import { User } from '../models/user.model'; +import { FoodItem } from '../models/food-item.model'; +import { Meal } from '../models/meal.model'; +import { WaterLog } from '../models/water-log.model'; +import { WeightLog } from '../models/weight-log.model'; +import { MealPlan } from '../models/meal-plan.model'; +import { PlannedFood } from '../models/planned-food.model'; +import { DailySummary } from '../models/daily-summary.model'; +export declare class UtilsService { + private userModel; + private foodItemModel; + private mealModel; + private waterLogModel; + private weightLogModel; + private mealPlanModel; + private plannedFoodModel; + private dailySummaryModel; + constructor(userModel: typeof User, foodItemModel: typeof FoodItem, mealModel: typeof Meal, waterLogModel: typeof WaterLog, weightLogModel: typeof WeightLog, mealPlanModel: typeof MealPlan, plannedFoodModel: typeof PlannedFood, dailySummaryModel: typeof DailySummary); + calculateBMR(weightKg: number, heightCm: number, age: number, gender: string): number; + calculateTDEE(bmr: number, activityLevel: string): number; + calculateMacroTargets(weightKg: number, goalType?: string): { + protein_g: number; + carbs_g: number; + fat_g: number; + }; + calculateDailyTotals(userId: number, targetDate?: string | Date): Promise<{ + calories: number; + protein: number; + carbs: number; + fat: number; + meals: any[]; + }>; + calculateWaterTotal(userId: number, targetDate?: string | Date): Promise<{ + total_ml: number; + logs: { + id: any; + amount_ml: number; + time: string; + }[]; + }>; + getWeightTrend(userId: number, days?: number): Promise<{ + date: Date; + weight_kg: number; + }[]>; + getCalorieTrend(userId: number, days?: number): Promise; + updateDailySummary(userId: number, targetDate?: string | Date): Promise; + getMacroPercentages(proteinG: number, carbsG: number, fatG: number): { + protein: number; + carbs: number; + fat: number; + }; + suggestFoodsForMacros(remainingProtein: number, remainingCarbs: number, remainingFat: number): any[]; + generateDailyMealPlan(userId: number, dateStr: string): Promise; +} diff --git a/dist/utils/utils.service.js b/dist/utils/utils.service.js new file mode 100644 index 0000000..3acb872 --- /dev/null +++ b/dist/utils/utils.service.js @@ -0,0 +1,385 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UtilsService = void 0; +const common_1 = require("@nestjs/common"); +const sequelize_1 = require("@nestjs/sequelize"); +const sequelize_2 = require("sequelize"); +const user_model_1 = require("../models/user.model"); +const food_item_model_1 = require("../models/food-item.model"); +const meal_model_1 = require("../models/meal.model"); +const meal_food_model_1 = require("../models/meal-food.model"); +const water_log_model_1 = require("../models/water-log.model"); +const weight_log_model_1 = require("../models/weight-log.model"); +const meal_plan_model_1 = require("../models/meal-plan.model"); +const planned_food_model_1 = require("../models/planned-food.model"); +const daily_summary_model_1 = require("../models/daily-summary.model"); +let UtilsService = class UtilsService { + constructor(userModel, foodItemModel, mealModel, waterLogModel, weightLogModel, mealPlanModel, plannedFoodModel, dailySummaryModel) { + this.userModel = userModel; + this.foodItemModel = foodItemModel; + this.mealModel = mealModel; + this.waterLogModel = waterLogModel; + this.weightLogModel = weightLogModel; + this.mealPlanModel = mealPlanModel; + this.plannedFoodModel = plannedFoodModel; + this.dailySummaryModel = dailySummaryModel; + } + calculateBMR(weightKg, heightCm, age, gender) { + let bmr; + if (gender.toLowerCase() === 'male') { + bmr = 10 * weightKg + 6.25 * heightCm - 5 * age + 5; + } + else { + bmr = 10 * weightKg + 6.25 * heightCm - 5 * age - 161; + } + return Math.round(bmr); + } + calculateTDEE(bmr, activityLevel) { + const multipliers = { + sedentary: 1.2, + light: 1.375, + moderate: 1.55, + active: 1.725, + very_active: 1.9, + }; + const multiplier = multipliers[activityLevel] || 1.55; + return Math.round(bmr * multiplier); + } + calculateMacroTargets(weightKg, goalType = 'recomp') { + let protein, carbs, fat; + if (goalType === 'muscle_gain') { + protein = weightKg * 2.4; + carbs = weightKg * 3.5; + fat = weightKg * 1.0; + } + else if (goalType === 'weight_loss') { + protein = weightKg * 2.2; + carbs = weightKg * 2.0; + fat = weightKg * 0.8; + } + else { + protein = weightKg * 2.2; + carbs = weightKg * 2.5; + fat = weightKg * 0.9; + } + return { + protein_g: Math.round(protein), + carbs_g: Math.round(carbs), + fat_g: Math.round(fat), + }; + } + async calculateDailyTotals(userId, targetDate = new Date()) { + const dateStr = targetDate instanceof Date ? targetDate.toISOString().split('T')[0] : targetDate; + const meals = await this.mealModel.findAll({ + where: { + UserId: userId, + date: dateStr, + }, + include: [ + { + model: meal_food_model_1.MealFood, + include: [food_item_model_1.FoodItem], + }, + ], + }); + const totals = { + calories: 0, + protein: 0, + carbs: 0, + fat: 0, + meals: [], + }; + for (const meal of meals) { + const mealTotals = { + calories: 0, + protein: 0, + carbs: 0, + fat: 0, + }; + const mealFoods = []; + for (const mf of meal.mealFoods) { + const quantity = mf.quantity || 1.0; + const food = mf.foodItem; + const calories = mf.calories_consumed || food.calories * quantity; + const protein = mf.protein_consumed || food.protein_g * quantity; + const carbs = mf.carbs_consumed || food.carbs_g * quantity; + const fat = mf.fat_consumed || food.fat_g * quantity; + mealTotals.calories += calories; + mealTotals.protein += protein; + mealTotals.carbs += carbs; + mealTotals.fat += fat; + mealFoods.push({ + name: food.name, + quantity: quantity, + calories: calories, + }); + } + totals.calories += mealTotals.calories; + totals.protein += mealTotals.protein; + totals.carbs += mealTotals.carbs; + totals.fat += mealTotals.fat; + totals.meals.push({ + id: meal.id, + type: meal.meal_type, + time: meal.time ? meal.time.substring(0, 5) : null, + totals: mealTotals, + foods: mealFoods, + }); + } + return totals; + } + async calculateWaterTotal(userId, targetDate = new Date()) { + const dateStr = targetDate instanceof Date ? targetDate.toISOString().split('T')[0] : targetDate; + const waterLogs = await this.waterLogModel.findAll({ + where: { + UserId: userId, + date: dateStr, + }, + }); + const total = waterLogs.reduce((sum, log) => sum + log.amount_ml, 0); + return { + total_ml: total, + logs: waterLogs.map((log) => ({ + id: log.id, + amount_ml: log.amount_ml, + time: log.time ? log.time.substring(0, 5) : null, + })), + }; + } + async getWeightTrend(userId, days = 7) { + const endDate = new Date(); + const startDate = new Date(); + startDate.setDate(endDate.getDate() - (days - 1)); + const startDateStr = startDate.toISOString().split('T')[0]; + const endDateStr = endDate.toISOString().split('T')[0]; + const weightLogs = await this.weightLogModel.findAll({ + where: { + UserId: userId, + date: { + [sequelize_2.Op.between]: [startDateStr, endDateStr], + }, + }, + order: [['date', 'ASC']], + }); + return weightLogs.map((log) => ({ + date: log.date, + weight_kg: log.weight_kg, + })); + } + async getCalorieTrend(userId, days = 7) { + const endDate = new Date(); + const startDate = new Date(); + startDate.setDate(endDate.getDate() - (days - 1)); + const trend = []; + const currentDate = new Date(startDate); + while (currentDate <= endDate) { + const dateStr = currentDate.toISOString().split('T')[0]; + const totals = await this.calculateDailyTotals(userId, dateStr); + trend.push({ + date: dateStr, + calories: Math.round(totals.calories), + protein: Math.round(totals.protein), + carbs: Math.round(totals.carbs), + fat: Math.round(totals.fat), + }); + currentDate.setDate(currentDate.getDate() + 1); + } + return trend; + } + async updateDailySummary(userId, targetDate = new Date()) { + const dateStr = targetDate instanceof Date ? targetDate.toISOString().split('T')[0] : targetDate; + const nutrition = await this.calculateDailyTotals(userId, dateStr); + const water = await this.calculateWaterTotal(userId, dateStr); + const weightLog = await this.weightLogModel.findOne({ + where: { + UserId: userId, + date: dateStr, + }, + }); + const weight = weightLog ? weightLog.weight_kg : null; + const user = await this.userModel.findByPk(userId); + const targetCalories = user ? user.target_daily_calories : 2000; + let summary = await this.dailySummaryModel.findOne({ + where: { + UserId: userId, + date: dateStr, + }, + }); + if (!summary) { + summary = await this.dailySummaryModel.create({ + UserId: userId, + date: dateStr, + }); + } + summary.total_calories = nutrition.calories; + summary.total_protein_g = nutrition.protein; + summary.total_carbs_g = nutrition.carbs; + summary.total_fat_g = nutrition.fat; + summary.total_water_ml = water.total_ml; + summary.calories_remaining = targetCalories - nutrition.calories; + summary.weight_kg = weight; + try { + await summary.save(); + return summary; + } + catch (e) { + console.error(`Error updating daily summary: ${e}`); + return null; + } + } + getMacroPercentages(proteinG, carbsG, fatG) { + const proteinCal = proteinG * 4; + const carbsCal = carbsG * 4; + const fatCal = fatG * 9; + const totalCal = proteinCal + carbsCal + fatCal; + if (totalCal === 0) { + return { protein: 0, carbs: 0, fat: 0 }; + } + return { + protein: Math.round((proteinCal / totalCal) * 100), + carbs: Math.round((carbsCal / totalCal) * 100), + fat: Math.round((fatCal / totalCal) * 100), + }; + } + suggestFoodsForMacros(remainingProtein, remainingCarbs, remainingFat) { + const suggestions = []; + if (remainingProtein > 30) { + suggestions.push({ + category: 'High Protein Ulam', + examples: ['Grilled Tilapia', 'Chicken Tinola', 'Grilled Chicken'], + }); + } + if (remainingCarbs > 40) { + suggestions.push({ + category: 'Carbs', + examples: ['White Rice', 'Pandesal', 'Sweet Potato'], + }); + } + if (remainingFat > 20) { + suggestions.push({ + category: 'Healthy Fats', + examples: ['Sisig', 'Lechon Kawali', 'Bicol Express'], + }); + } + if (remainingProtein > 20 && remainingCarbs > 30) { + suggestions.push({ + category: 'Balanced Meals', + examples: ['Tapsilog', 'Chicken Adobo with Rice', 'Sinigang'], + }); + } + return suggestions; + } + async generateDailyMealPlan(userId, dateStr) { + try { + const user = await this.userModel.findByPk(userId); + const targetCalories = user ? user.target_daily_calories : 2000; + const targets = { + breakfast: Math.round(targetCalories * 0.25), + lunch: Math.round(targetCalories * 0.35), + dinner: Math.round(targetCalories * 0.3), + snack: Math.round(targetCalories * 0.1), + }; + const foods = await this.foodItemModel.findAll(); + const foodByCat = { + almusal: foods.filter((f) => f.category === 'almusal'), + ulam: foods.filter((f) => ['ulam', 'sabaw'].includes(f.category)), + kanin: foods.filter((f) => f.category === 'kanin'), + gulay: foods.filter((f) => f.category === 'gulay'), + meryenda: foods.filter((f) => f.category === 'meryenda'), + }; + const allFoods = foods; + const pickRandom = (arr) => (arr.length > 0 ? arr[Math.floor(Math.random() * arr.length)] : null); + const generateMeal = async (mealType, targetCal) => { + let currentCal = 0; + const selectedFoods = []; + if (mealType === 'breakfast') { + const main = pickRandom(foodByCat.almusal) || pickRandom(allFoods); + if (main) { + selectedFoods.push({ food: main, qty: 1 }); + currentCal += main.calories; + } + } + else if (['lunch', 'dinner'].includes(mealType)) { + const rice = pickRandom(foodByCat.kanin); + const ulam = pickRandom(foodByCat.ulam) || pickRandom(allFoods); + const gulay = pickRandom(foodByCat.gulay); + if (rice) { + selectedFoods.push({ food: rice, qty: 1 }); + currentCal += rice.calories; + } + if (ulam) { + selectedFoods.push({ food: ulam, qty: 1 }); + currentCal += ulam.calories; + } + if (gulay && currentCal < targetCal) { + selectedFoods.push({ food: gulay, qty: 1 }); + currentCal += gulay.calories; + } + } + else if (mealType === 'snack') { + const snack = pickRandom(foodByCat.meryenda) || pickRandom(allFoods); + if (snack) { + selectedFoods.push({ food: snack, qty: 1 }); + currentCal += snack.calories; + } + } + if (currentCal > 0 && selectedFoods.length > 0) { + const mealPlan = await this.mealPlanModel.create({ + UserId: userId, + date: dateStr, + meal_type: mealType, + is_completed: false, + }); + for (const item of selectedFoods) { + await this.plannedFoodModel.create({ + MealPlanId: mealPlan.id, + FoodItemId: item.food.id, + quantity: item.qty, + }); + } + } + }; + await this.mealPlanModel.destroy({ + where: { + UserId: userId, + date: dateStr, + }, + }); + await generateMeal('breakfast', targets.breakfast); + await generateMeal('lunch', targets.lunch); + await generateMeal('dinner', targets.dinner); + await generateMeal('snack', targets.snack); + return true; + } + catch (error) { + console.error('Error generating meal plan:', error); + throw error; + } + } +}; +exports.UtilsService = UtilsService; +exports.UtilsService = UtilsService = __decorate([ + (0, common_1.Injectable)(), + __param(0, (0, sequelize_1.InjectModel)(user_model_1.User)), + __param(1, (0, sequelize_1.InjectModel)(food_item_model_1.FoodItem)), + __param(2, (0, sequelize_1.InjectModel)(meal_model_1.Meal)), + __param(3, (0, sequelize_1.InjectModel)(water_log_model_1.WaterLog)), + __param(4, (0, sequelize_1.InjectModel)(weight_log_model_1.WeightLog)), + __param(5, (0, sequelize_1.InjectModel)(meal_plan_model_1.MealPlan)), + __param(6, (0, sequelize_1.InjectModel)(planned_food_model_1.PlannedFood)), + __param(7, (0, sequelize_1.InjectModel)(daily_summary_model_1.DailySummary)), + __metadata("design:paramtypes", [Object, Object, Object, Object, Object, Object, Object, Object]) +], UtilsService); +//# sourceMappingURL=utils.service.js.map \ No newline at end of file diff --git a/dist/utils/utils.service.js.map b/dist/utils/utils.service.js.map new file mode 100644 index 0000000..f11e05d --- /dev/null +++ b/dist/utils/utils.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.service.js","sourceRoot":"","sources":["../../src/utils/utils.service.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/models/index.js b/models/index.js deleted file mode 100644 index 7a56ef1..0000000 --- a/models/index.js +++ /dev/null @@ -1,191 +0,0 @@ -const Sequelize = require('sequelize'); -const path = require('path'); -const bcrypt = require('bcryptjs'); - -// Initialize database -const dbPath = process.env.DATABASE_URL || 'sqlite://calorie_tracker.db'; -const storagePath = dbPath.startsWith('sqlite://') - ? dbPath.replace('sqlite://', '') - : path.join(__dirname, '../data/calorie_tracker.db'); - -// Ensure storage path is absolute or relative to cwd correctly -// For Docker, we use /app/data/calorie_tracker.db -const sequelize = new Sequelize({ - dialect: 'sqlite', - storage: storagePath.startsWith('/') ? storagePath : path.join(process.cwd(), 'data', 'calorie_tracker.db'), - logging: false -}); - -const db = {}; - -// User Model -const User = sequelize.define('User', { - username: { type: Sequelize.STRING(80), unique: true, allowNull: false }, - password: { type: Sequelize.STRING(200), allowNull: false }, - name: Sequelize.STRING(100), - age: Sequelize.INTEGER, - gender: Sequelize.STRING(10), - height_cm: Sequelize.FLOAT, - weight_kg: Sequelize.FLOAT, - activity_level: { type: Sequelize.STRING(20), defaultValue: 'moderate' }, - target_daily_calories: { type: Sequelize.INTEGER, defaultValue: 2000 } -}); - -// Method to verify password -User.prototype.validPassword = function(password) { - return bcrypt.compareSync(password, this.password); -}; - -// Hook to hash password -User.beforeCreate(async (user) => { - if (user.password) { - user.password = await bcrypt.hash(user.password, 10); - } -}); - -// FoodItem Model -const FoodItem = sequelize.define('FoodItem', { - name: { type: Sequelize.STRING(200), allowNull: false }, - name_tagalog: Sequelize.STRING(200), - category: Sequelize.STRING(50), - calories: { type: Sequelize.FLOAT, allowNull: false }, - protein_g: { type: Sequelize.FLOAT, defaultValue: 0 }, - carbs_g: { type: Sequelize.FLOAT, defaultValue: 0 }, - fat_g: { type: Sequelize.FLOAT, defaultValue: 0 }, - fiber_g: { type: Sequelize.FLOAT, defaultValue: 0 }, - sugar_g: { type: Sequelize.FLOAT, defaultValue: 0 }, - sodium_mg: { type: Sequelize.FLOAT, defaultValue: 0 }, - serving_size_g: { type: Sequelize.FLOAT, defaultValue: 100 }, - serving_description: Sequelize.STRING(100), - source: { type: Sequelize.STRING(20), defaultValue: 'manual' }, - is_filipino: { type: Sequelize.BOOLEAN, defaultValue: false }, - is_favorite: { type: Sequelize.BOOLEAN, defaultValue: false }, - api_data: Sequelize.TEXT, - last_updated: { type: Sequelize.DATE, defaultValue: Sequelize.NOW } -}); - -// Meal Model -const Meal = sequelize.define('Meal', { - date: { type: Sequelize.DATEONLY, allowNull: false, defaultValue: Sequelize.NOW }, - meal_type: { type: Sequelize.STRING(20), allowNull: false }, - time: Sequelize.TIME, - notes: Sequelize.TEXT -}); - -// MealFood Model -const MealFood = sequelize.define('MealFood', { - quantity: { type: Sequelize.FLOAT, allowNull: false, defaultValue: 1.0 }, - quantity_grams: Sequelize.FLOAT, - calories_consumed: Sequelize.FLOAT, - protein_consumed: Sequelize.FLOAT, - carbs_consumed: Sequelize.FLOAT, - fat_consumed: Sequelize.FLOAT -}); - -// WaterLog Model -const WaterLog = sequelize.define('WaterLog', { - date: { type: Sequelize.DATEONLY, allowNull: false, defaultValue: Sequelize.NOW }, - amount_ml: { type: Sequelize.INTEGER, allowNull: false }, - time: { type: Sequelize.TIME, defaultValue: Sequelize.NOW } -}); - -// WeightLog Model -const WeightLog = sequelize.define('WeightLog', { - date: { type: Sequelize.DATEONLY, allowNull: false, defaultValue: Sequelize.NOW }, - weight_kg: { type: Sequelize.FLOAT, allowNull: false }, - body_fat_percentage: Sequelize.FLOAT, - notes: Sequelize.TEXT, - time: { type: Sequelize.TIME, defaultValue: Sequelize.NOW } -}); - -// MealPlan Model -const MealPlan = sequelize.define('MealPlan', { - date: { type: Sequelize.DATEONLY, allowNull: false }, - meal_type: { type: Sequelize.STRING(20), allowNull: false }, - is_completed: { type: Sequelize.BOOLEAN, defaultValue: false }, - notes: Sequelize.TEXT -}); - -// PlannedFood Model -const PlannedFood = sequelize.define('PlannedFood', { - quantity: { type: Sequelize.FLOAT, allowNull: false, defaultValue: 1.0 } -}); - -// UserGoal Model -const UserGoal = sequelize.define('UserGoal', { - goal_type: { type: Sequelize.STRING(20), defaultValue: 'recomp' }, - target_weight_kg: Sequelize.FLOAT, - weekly_goal_kg: { type: Sequelize.FLOAT, defaultValue: 0.5 }, - target_protein_g: { type: Sequelize.INTEGER, defaultValue: 150 }, - target_carbs_g: { type: Sequelize.INTEGER, defaultValue: 200 }, - target_fat_g: { type: Sequelize.INTEGER, defaultValue: 60 }, - target_water_ml: { type: Sequelize.INTEGER, defaultValue: 2000 } -}); - -// DailySummary Model -const DailySummary = sequelize.define('DailySummary', { - date: { type: Sequelize.DATEONLY, allowNull: false }, - total_calories: { type: Sequelize.FLOAT, defaultValue: 0 }, - total_protein_g: { type: Sequelize.FLOAT, defaultValue: 0 }, - total_carbs_g: { type: Sequelize.FLOAT, defaultValue: 0 }, - total_fat_g: { type: Sequelize.FLOAT, defaultValue: 0 }, - total_water_ml: { type: Sequelize.INTEGER, defaultValue: 0 }, - calories_remaining: Sequelize.FLOAT, - weight_kg: Sequelize.FLOAT, - notes: Sequelize.TEXT -}); - -// APICache Model -const APICache = sequelize.define('APICache', { - query: { type: Sequelize.STRING(200), allowNull: false, unique: true }, - api_source: Sequelize.STRING(50), - response_json: Sequelize.TEXT, - cached_at: { type: Sequelize.DATE, defaultValue: Sequelize.NOW } -}); - -// Relationships -User.hasMany(Meal, { onDelete: 'CASCADE' }); -Meal.belongsTo(User); - -User.hasMany(WeightLog, { onDelete: 'CASCADE' }); -WeightLog.belongsTo(User); - -User.hasMany(WaterLog, { onDelete: 'CASCADE' }); -WaterLog.belongsTo(User); - -User.hasMany(MealPlan, { onDelete: 'CASCADE' }); -MealPlan.belongsTo(User); - -User.hasOne(UserGoal, { onDelete: 'CASCADE' }); -UserGoal.belongsTo(User); - -Meal.hasMany(MealFood, { onDelete: 'CASCADE' }); -MealFood.belongsTo(Meal); - -FoodItem.hasMany(MealFood); -MealFood.belongsTo(FoodItem); - -MealPlan.hasMany(PlannedFood, { onDelete: 'CASCADE' }); -PlannedFood.belongsTo(MealPlan); - -FoodItem.hasMany(PlannedFood); -PlannedFood.belongsTo(FoodItem); - -User.hasMany(DailySummary, { onDelete: 'CASCADE' }); -DailySummary.belongsTo(User); - -db.sequelize = sequelize; -db.Sequelize = Sequelize; -db.User = User; -db.FoodItem = FoodItem; -db.Meal = Meal; -db.MealFood = MealFood; -db.WaterLog = WaterLog; -db.WeightLog = WeightLog; -db.MealPlan = MealPlan; -db.PlannedFood = PlannedFood; -db.UserGoal = UserGoal; -db.DailySummary = DailySummary; -db.APICache = APICache; - -module.exports = db; diff --git a/package-lock.json b/package-lock.json index 65f9e3f..7e25f79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,23 +8,63 @@ "name": "calorie-tracker", "version": "1.0.0", "dependencies": { + "@nestjs/common": "^11.1.12", + "@nestjs/config": "^4.0.2", + "@nestjs/core": "^11.1.12", + "@nestjs/passport": "^11.0.5", + "@nestjs/platform-express": "^11.1.12", + "@nestjs/sequelize": "^11.0.1", + "@types/express-session": "^1.18.2", + "@types/passport-local": "^1.0.38", "axios": "^1.6.0", "bcryptjs": "^2.4.3", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.3", "connect-sqlite3": "^0.9.13", "dotenv": "^16.3.1", "ejs": "^3.1.9", "express": "^4.18.2", "express-ejs-layouts": "^2.5.1", "express-flash": "^0.0.2", - "express-session": "^1.17.3", + "express-session": "^1.19.0", "method-override": "^3.0.0", "passport": "^0.6.0", "passport-local": "^1.0.0", - "sequelize": "^6.33.0", - "sqlite3": "^5.1.6" + "reflect-metadata": "^0.2.2", + "rxjs": "^7.8.2", + "sequelize": "^6.37.7", + "sequelize-typescript": "^2.1.6", + "sqlite3": "^5.1.7" }, "devDependencies": { - "nodemon": "^3.0.1" + "@types/express": "^5.0.6", + "@types/node": "^25.1.0", + "nodemon": "^3.0.1", + "ts-node": "^10.9.2", + "typescript": "^5.9.3" + } + }, + "node_modules/@borewit/text-codec": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.1.tgz", + "integrity": "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" } }, "node_modules/@gar/promisify": { @@ -34,6 +74,515 @@ "license": "MIT", "optional": true }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@nestjs/common": { + "version": "11.1.12", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.12.tgz", + "integrity": "sha512-v6U3O01YohHO+IE3EIFXuRuu3VJILWzyMmSYZXpyBbnp0hk0mFyHxK2w3dF4I5WnbwiRbWlEXdeXFvPQ7qaZzw==", + "license": "MIT", + "peer": true, + "dependencies": { + "file-type": "21.3.0", + "iterare": "1.2.1", + "load-esm": "1.0.3", + "tslib": "2.8.1", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": ">=0.4.1", + "class-validator": ">=0.13.2", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-4.0.2.tgz", + "integrity": "sha512-McMW6EXtpc8+CwTUwFdg6h7dYcBUpH5iUILCclAsa+MbCEvC9ZKu4dCHRlJqALuhjLw97pbQu62l4+wRwGeZqA==", + "license": "MIT", + "dependencies": { + "dotenv": "16.4.7", + "dotenv-expand": "12.0.1", + "lodash": "4.17.21" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "rxjs": "^7.1.0" + } + }, + "node_modules/@nestjs/config/node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@nestjs/config/node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/@nestjs/core": { + "version": "11.1.12", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.12.tgz", + "integrity": "sha512-97DzTYMf5RtGAVvX1cjwpKRiCUpkeQ9CCzSAenqkAhOmNVVFaApbhuw+xrDt13rsCa2hHVOYPrV4dBgOYMJjsA==", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@nuxt/opencollective": "0.4.1", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "8.3.0", + "tslib": "2.8.1", + "uid": "2.0.2" + }, + "engines": { + "node": ">= 20" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/microservices": "^11.0.0", + "@nestjs/platform-express": "^11.0.0", + "@nestjs/websockets": "^11.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } + } + }, + "node_modules/@nestjs/core/node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/passport": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-11.0.5.tgz", + "integrity": "sha512-ulQX6mbjlws92PIM15Naes4F4p2JoxGnIJuUsdXQPT+Oo2sqQmENEZXM7eYuimocfHnKlcfZOuyzbA33LwUlOQ==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "passport": "^0.5.0 || ^0.6.0 || ^0.7.0" + } + }, + "node_modules/@nestjs/platform-express": { + "version": "11.1.12", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.12.tgz", + "integrity": "sha512-GYK/vHI0SGz5m8mxr7v3Urx8b9t78Cf/dj5aJMZlGd9/1D9OI1hAl00BaphjEXINUJ/BQLxIlF2zUjrYsd6enQ==", + "license": "MIT", + "dependencies": { + "cors": "2.8.5", + "express": "5.2.1", + "multer": "2.0.2", + "path-to-regexp": "8.3.0", + "tslib": "2.8.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/core": "^11.0.0" + } + }, + "node_modules/@nestjs/platform-express/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nestjs/platform-express/node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/platform-express/node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/platform-express/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/@nestjs/platform-express/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@nestjs/platform-express/node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/platform-express/node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/platform-express/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@nestjs/platform-express/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/platform-express/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@nestjs/platform-express/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nestjs/platform-express/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nestjs/platform-express/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/platform-express/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/@nestjs/platform-express/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nestjs/platform-express/node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/platform-express/node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/@nestjs/platform-express/node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/platform-express/node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/platform-express/node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nestjs/sequelize": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@nestjs/sequelize/-/sequelize-11.0.1.tgz", + "integrity": "sha512-Zh1D2jRm736JeY9W+UyXGqHc7hfisl9232DY0//cbEGudom7s4LlJyWx+YP3n2GBS7z/G91+UFKPDq3UxttVpQ==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0", + "reflect-metadata": "^0.1.13 || ^0.2.0", + "rxjs": "^7.2.0", + "sequelize": "^6.3.5", + "sequelize-typescript": "^2.0.0" + } + }, "node_modules/@npmcli/fs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", @@ -60,6 +609,68 @@ "node": ">=10" } }, + "node_modules/@nuxt/opencollective": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.4.1.tgz", + "integrity": "sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==", + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": "^14.18.0 || >=16.10.0", + "npm": ">=5.10.0" + } + }, + "node_modules/@tokenizer/inflate": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz", + "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "token-types": "^6.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@tokenizer/inflate/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@tokenizer/inflate/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -70,6 +681,53 @@ "node": ">= 6" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -79,6 +737,44 @@ "@types/ms": "*" } }, + "node_modules/@types/express": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^2" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express-session": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.2.tgz", + "integrity": "sha512-k+I0BxwVXsnEU2hV77cCobC08kIsn4y44C3gC0b46uxZVMaXA04lSPgRLR/bSL2w0t0ShJiG8o4jPzRG/nscFg==", + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "license": "MIT" + }, "node_modules/@types/ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", @@ -90,15 +786,78 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.1.0.tgz", "integrity": "sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } }, + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-local": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", + "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*" + } + }, "node_modules/@types/validator": { "version": "13.15.10", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz", "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/abbrev": { "version": "1.1.1", @@ -120,6 +879,32 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -209,6 +994,12 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, "node_modules/aproba": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", @@ -231,6 +1022,13 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -395,6 +1193,23 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -497,6 +1312,25 @@ "node": ">=10" } }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "license": "MIT", + "peer": true + }, + "node_modules/class-validator": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.3.tgz", + "integrity": "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/validator": "^13.15.3", + "libphonenumber-js": "^1.11.1", + "validator": "^13.15.20" + } + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -533,9 +1367,23 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "devOptional": true, "license": "MIT" }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, "node_modules/connect-flash": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", @@ -555,6 +1403,15 @@ "node": ">=0.4.x" } }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -598,6 +1455,26 @@ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -675,6 +1552,16 @@ "node": ">=8" } }, + "node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dotenv": { "version": "16.6.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", @@ -687,6 +1574,21 @@ "url": "https://dotenvx.com" } }, + "node_modules/dotenv-expand": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-12.0.1.tgz", + "integrity": "sha512-LaKRbou8gt0RNID/9RoI+J2rvXsBRPMV7p+ElHlPhcSARbCPDYcYG2s1TIzAfWv4YSgyY5taidWzzs31lNV3yQ==", + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dottie": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", @@ -947,6 +1849,30 @@ "url": "https://opencollective.com/express" } }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, + "node_modules/file-type": { + "version": "21.3.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.0.tgz", + "integrity": "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==", + "license": "MIT", + "dependencies": { + "@tokenizer/inflate": "^0.4.1", + "strtok3": "^10.3.4", + "token-types": "^6.1.1", + "uint8array-extras": "^1.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -1069,8 +1995,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "license": "ISC", - "optional": true + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -1491,7 +2416,6 @@ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "license": "ISC", - "optional": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -1591,6 +2515,12 @@ "node": ">=0.12.0" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1598,6 +2528,15 @@ "license": "ISC", "optional": true }, + "node_modules/iterare": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", + "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "license": "ISC", + "engines": { + "node": ">=6" + } + }, "node_modules/jake": { "version": "10.9.4", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", @@ -1615,6 +2554,31 @@ "node": ">=10" } }, + "node_modules/libphonenumber-js": { + "version": "1.12.36", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.36.tgz", + "integrity": "sha512-woWhKMAVx1fzzUnMCyOzglgSgf6/AFHLASdOBcchYCyvWSGWt12imw3iu2hdI5d4dGZRsNWAmWiz37sDKUPaRQ==", + "license": "MIT" + }, + "node_modules/load-esm": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/load-esm/-/load-esm-1.0.3.tgz", + "integrity": "sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + }, + { + "type": "buymeacoffee", + "url": "https://buymeacoffee.com/borewit" + } + ], + "license": "MIT", + "engines": { + "node": ">=13.2.0" + } + }, "node_modules/lodash": { "version": "4.17.23", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", @@ -1634,6 +2598,13 @@ "node": ">=10" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, "node_modules/make-fetch-happen": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", @@ -1928,6 +2899,36 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/napi-build-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", @@ -2107,6 +3108,15 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -2179,6 +3189,7 @@ "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", "license": "MIT", + "peer": true, "dependencies": { "passport-strategy": "1.x.x", "pause": "0.0.1", @@ -2216,7 +3227,6 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "license": "MIT", - "optional": true, "engines": { "node": ">=0.10.0" } @@ -2430,6 +3440,13 @@ "node": ">=8.10.0" } }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0", + "peer": true + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -2463,6 +3480,65 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/router/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/router/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/router/node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -2542,6 +3618,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@types/debug": "^4.1.8", "@types/validator": "^13.7.17", @@ -2602,6 +3679,68 @@ "node": ">= 10.0.0" } }, + "node_modules/sequelize-typescript": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/sequelize-typescript/-/sequelize-typescript-2.1.6.tgz", + "integrity": "sha512-Vc2N++3en346RsbGjL3h7tgAl2Y7V+2liYTAOZ8XL0KTw3ahFHsyAUzOwct51n+g70I1TOUDgs06Oh6+XGcFkQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "glob": "7.2.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "@types/validator": "*", + "reflect-metadata": "*", + "sequelize": ">=6.20.1" + } + }, + "node_modules/sequelize-typescript/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/sequelize-typescript/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sequelize-typescript/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/sequelize/node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -2902,6 +4041,14 @@ "node": ">= 0.8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -2948,6 +4095,22 @@ "node": ">=0.10.0" } }, + "node_modules/strtok3": { + "version": "10.3.4", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", + "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -3044,6 +4207,24 @@ "node": ">=0.6" } }, + "node_modules/token-types": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", + "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", + "license": "MIT", + "dependencies": { + "@borewit/text-codec": "^0.2.1", + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/toposort-class": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", @@ -3060,6 +4241,56 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -3085,6 +4316,39 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "license": "MIT", + "dependencies": { + "@lukeed/csprng": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -3097,6 +4361,18 @@ "node": ">= 0.8" } }, + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -3163,6 +4439,13 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, "node_modules/validator": { "version": "13.15.26", "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz", @@ -3222,11 +4505,30 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } } } } diff --git a/package.json b/package.json index bd7448d..fdbb635 100644 --- a/package.json +++ b/package.json @@ -6,25 +6,44 @@ "scripts": { "start": "node server.js", "dev": "nodemon server.js", - "seed": "node scripts/seed.js" + "seed": "node scripts/seed.js", + "start:nest": "ts-node src/main.ts", + "start:dev:nest": "nodemon --watch 'src/**/*.ts' --exec \"ts-node\" src/main.ts" }, "dependencies": { + "@nestjs/common": "^11.1.12", + "@nestjs/config": "^4.0.2", + "@nestjs/core": "^11.1.12", + "@nestjs/passport": "^11.0.5", + "@nestjs/platform-express": "^11.1.12", + "@nestjs/sequelize": "^11.0.1", + "@types/express-session": "^1.18.2", + "@types/passport-local": "^1.0.38", "axios": "^1.6.0", "bcryptjs": "^2.4.3", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.3", "connect-sqlite3": "^0.9.13", "dotenv": "^16.3.1", "ejs": "^3.1.9", "express": "^4.18.2", "express-ejs-layouts": "^2.5.1", "express-flash": "^0.0.2", - "express-session": "^1.17.3", + "express-session": "^1.19.0", "method-override": "^3.0.0", "passport": "^0.6.0", "passport-local": "^1.0.0", - "sequelize": "^6.33.0", - "sqlite3": "^5.1.6" + "reflect-metadata": "^0.2.2", + "rxjs": "^7.8.2", + "sequelize": "^6.37.7", + "sequelize-typescript": "^2.1.6", + "sqlite3": "^5.1.7" }, "devDependencies": { - "nodemon": "^3.0.1" + "@types/express": "^5.0.6", + "@types/node": "^25.1.0", + "nodemon": "^3.0.1", + "ts-node": "^10.9.2", + "typescript": "^5.9.3" } } diff --git a/server.js b/server.js deleted file mode 100644 index e4b478e..0000000 --- a/server.js +++ /dev/null @@ -1,754 +0,0 @@ -require('dotenv').config(); -const express = require('express'); -const session = require('express-session'); -const passport = require('passport'); -const LocalStrategy = require('passport-local').Strategy; -const expressLayouts = require('express-ejs-layouts'); -const flash = require('express-flash'); -const methodOverride = require('method-override'); -const path = require('path'); -const SQLiteStore = require('connect-sqlite3')(session); -const db = require('./models'); -const utils = require('./utils'); -const { NutritionAPI, searchAllSources } = require('./utils/api_client'); - -const app = express(); -const PORT = process.env.PORT || 5001; - -// Initialize API Client -const apiClient = new NutritionAPI(process.env.API_NINJAS_KEY); - -// Passport Config -passport.use(new LocalStrategy( - async (username, password, done) => { - try { - const user = await db.User.findOne({ where: { username } }); - if (!user) { - return done(null, false, { message: 'Incorrect username.' }); - } - if (!user.validPassword(password)) { - return done(null, false, { message: 'Incorrect password.' }); - } - return done(null, user); - } catch (err) { - return done(err); - } - } -)); - -passport.serializeUser((user, done) => { - done(null, user.id); -}); - -passport.deserializeUser(async (id, done) => { - try { - const user = await db.User.findByPk(id); - done(null, user); - } catch (err) { - done(err); - } -}); - -// Middleware -app.set('view engine', 'ejs'); -app.set('views', path.join(__dirname, 'views')); -app.set('layout', 'layout'); -app.use(expressLayouts); -app.use(express.static(path.join(__dirname, 'public'))); -app.use(express.urlencoded({ extended: true })); -app.use(express.json()); -app.use(methodOverride('_method')); - -// Session -app.use(session({ - store: new SQLiteStore({ db: 'sessions.db', dir: './data' }), - secret: process.env.SECRET_KEY || 'secret', - resave: false, - saveUninitialized: false, - cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 } // 30 days -})); - -app.use(passport.initialize()); -app.use(passport.session()); -app.use(flash()); - -// Global Variables -app.use((req, res, next) => { - res.locals.current_user = req.user; - res.locals.success_msg = req.flash('success_msg'); - res.locals.error_msg = req.flash('error_msg'); - res.locals.error = req.flash('error'); - res.locals.path = req.path; - next(); -}); - -// Helper functions for templates -app.locals.round = Math.round; - -// Auth Middleware -function ensureAuthenticated(req, res, next) { - if (req.isAuthenticated()) { - return next(); - } - req.flash('error_msg', 'Please log in to view that resource'); - res.redirect('/login'); -} - -// Routes -app.get('/', (req, res) => { - if (req.isAuthenticated()) { - res.redirect('/dashboard'); - } else { - res.redirect('/login'); - } -}); - -app.get('/login', (req, res) => { - res.render('login'); -}); - -app.post('/login', passport.authenticate('local', { - successRedirect: '/dashboard', - failureRedirect: '/login', - failureFlash: true -})); - -app.get('/register', (req, res) => { - res.render('register'); -}); - -app.post('/register', async (req, res) => { - const { username, password, name } = req.body; - try { - const existingUser = await db.User.findOne({ where: { username } }); - if (existingUser) { - req.flash('error', 'Username already exists'); - return res.redirect('/register'); - } - await db.User.create({ username, password, name }); - req.flash('success_msg', 'You are now registered and can log in'); - res.redirect('/login'); - } catch (err) { - console.error(err); - req.flash('error', 'Error registering user'); - res.redirect('/register'); - } -}); - -app.get('/logout', (req, res, next) => { - req.logout((err) => { - if (err) { return next(err); } - req.flash('success_msg', 'You are logged out'); - res.redirect('/login'); - }); -}); - -app.get('/dashboard', ensureAuthenticated, async (req, res) => { - try { - const today = new Date(); - const dateStr = today.toISOString().split('T')[0]; - - // Get daily totals - const nutrition = await utils.calculateDailyTotals(req.user.id, dateStr); - const water = await utils.calculateWaterTotal(req.user.id, dateStr); - - // Get user goals - let goals = await db.UserGoal.findOne({ where: { UserId: req.user.id } }); - if (!goals) { - goals = await db.UserGoal.create({ - UserId: req.user.id, - target_protein_g: 150, - target_carbs_g: 200, - target_fat_g: 60, - target_water_ml: 2000 - }); - } - - // Get weight info - const weightLogToday = await db.WeightLog.findOne({ - where: { UserId: req.user.id, date: dateStr } - }); - - const yesterday = new Date(today); - yesterday.setDate(yesterday.getDate() - 1); - const yesterdayStr = yesterday.toISOString().split('T')[0]; - - const weightLogYesterday = await db.WeightLog.findOne({ - where: { UserId: req.user.id, date: yesterdayStr } - }); - - let weightChange = null; - if (weightLogToday && weightLogYesterday) { - weightChange = weightLogToday.weight_kg - weightLogYesterday.weight_kg; - } - - // Calculate remaining - const remaining = { - calories: req.user.target_daily_calories - nutrition.calories, - protein: goals.target_protein_g - nutrition.protein, - carbs: goals.target_carbs_g - nutrition.carbs, - fat: goals.target_fat_g - nutrition.fat, - water: goals.target_water_ml - water.total_ml - }; - - // Get macro percentages - const macroPercentages = utils.getMacroPercentages( - nutrition.protein, - nutrition.carbs, - nutrition.fat - ); - - // Get trends - const weightTrend = await utils.getWeightTrend(req.user.id, 7); - const calorieTrend = await utils.getCalorieTrend(req.user.id, 7); - - // Suggestions - const suggestions = utils.suggestFoodsForMacros( - remaining.protein, - remaining.carbs, - remaining.fat - ); - - res.render('dashboard', { - nutrition, - water, - goals, - remaining, - macro_percentages: macroPercentages, - weight_today: weightLogToday, - weight_change: weightChange, - weight_trend: weightTrend, - calorie_trend: calorieTrend, - suggestions, - today: dateStr - }); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error loading dashboard'); - res.render('dashboard', { - nutrition: { calories: 0, protein: 0, carbs: 0, fat: 0 }, - water: { total_ml: 0 }, - goals: { target_water_ml: 2000 }, - remaining: { calories: 2000, protein: 150, carbs: 200, fat: 60, water: 2000 }, - macro_percentages: { protein: 0, carbs: 0, fat: 0 }, - weight_trend: [], - calorie_trend: [], - suggestions: [], - today: new Date().toISOString().split('T')[0] - }); - } -}); - -app.get('/add-meal', ensureAuthenticated, (req, res) => { - res.render('add_meal', { today: new Date().toISOString().split('T')[0] }); -}); - -app.post('/add-meal', ensureAuthenticated, async (req, res) => { - try { - let { date, meal_type, time, 'food_id[]': foodIds, 'quantity[]': quantities } = req.body; - - if (!foodIds) { - req.flash('error_msg', 'Please add at least one food item'); - return res.redirect('/add-meal'); - } - - // Normalize input (handle single item vs array) - if (!Array.isArray(foodIds)) { - foodIds = [foodIds]; - quantities = [quantities]; - } - - const meal = await db.Meal.create({ - UserId: req.user.id, - date: date || new Date(), - meal_type, - time: time || null - }); - - for (let i = 0; i < foodIds.length; i++) { - const foodId = foodIds[i]; - const quantity = quantities[i]; - - if (foodId && quantity) { - const food = await db.FoodItem.findByPk(foodId); - if (food) { - await db.MealFood.create({ - MealId: meal.id, - FoodItemId: foodId, - quantity: quantity, - calories_consumed: food.calories * quantity, - protein_consumed: food.protein_g * quantity, - carbs_consumed: food.carbs_g * quantity, - fat_consumed: food.fat_g * quantity - }); - } - } - } - - await utils.updateDailySummary(req.user.id, date); - - req.flash('success_msg', 'Meal added successfully!'); - res.redirect('/dashboard'); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error adding meal'); - res.redirect('/add-meal'); - } -}); - -app.get('/api/search-food', ensureAuthenticated, async (req, res) => { - const query = req.query.q || ''; - if (query.length < 2) { - return res.json([]); - } - - try { - const results = await searchAllSources(query, apiClient); - res.json(results); - } catch (err) { - console.error(err); - res.status(500).json({ error: 'Server error' }); - } -}); - -app.post('/api/add-food', ensureAuthenticated, async (req, res) => { - try { - const data = req.body; - const food = await apiClient.saveFoodToDb(data); - - if (food) { - res.json({ - success: true, - food_id: food.id, - name: food.name - }); - } else { - res.status(500).json({ success: false }); - } - } catch (err) { - console.error(err); - res.status(500).json({ success: false }); - } -}); - -app.post('/add-water', ensureAuthenticated, async (req, res) => { - try { - const amountMl = parseInt(req.body.amount_ml) || 250; - const date = req.body.date || new Date().toISOString().split('T')[0]; - - await db.WaterLog.create({ - UserId: req.user.id, - date: date, - amount_ml: amountMl, - time: new Date() - }); - - await utils.updateDailySummary(req.user.id, date); - - req.flash('success_msg', `Added ${amountMl}ml of water!`); - res.redirect('/dashboard'); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error adding water'); - res.redirect('/dashboard'); - } -}); - -app.post('/add-weight', ensureAuthenticated, async (req, res) => { - try { - const weightKg = parseFloat(req.body.weight_kg); - const date = req.body.date || new Date().toISOString().split('T')[0]; - - let weightLog = await db.WeightLog.findOne({ - where: { UserId: req.user.id, date: date } - }); - - if (weightLog) { - weightLog.weight_kg = weightKg; - weightLog.time = new Date(); - await weightLog.save(); - } else { - await db.WeightLog.create({ - UserId: req.user.id, - date: date, - weight_kg: weightKg, - time: new Date() - }); - } - - await utils.updateDailySummary(req.user.id, date); - - res.redirect('/dashboard'); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error adding weight'); - res.redirect('/dashboard'); - } -}); - -app.get('/goals', ensureAuthenticated, async (req, res) => { - try { - const userGoals = await db.UserGoal.findOne({ where: { UserId: req.user.id } }); - - let bmr = null; - let tdee = null; - - if (req.user.weight_kg && req.user.height_cm && req.user.age) { - bmr = utils.calculateBMR( - req.user.weight_kg, - req.user.height_cm, - req.user.age, - req.user.gender || 'male' - ); - tdee = utils.calculateTDEE(bmr, req.user.activity_level || 'moderate'); - } - - res.render('goals', { - goals: userGoals, - bmr, - tdee - }); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error loading goals'); - res.redirect('/dashboard'); - } -}); - -app.post('/goals', ensureAuthenticated, async (req, res) => { - try { - // Update user info - const user = await db.User.findByPk(req.user.id); - user.age = parseInt(req.body.age) || 25; - user.gender = req.body.gender || 'male'; - user.height_cm = parseFloat(req.body.height_cm) || 170; - user.weight_kg = parseFloat(req.body.weight_kg) || 70; - user.activity_level = req.body.activity_level || 'moderate'; - - // Calculate targets - const bmr = utils.calculateBMR(user.weight_kg, user.height_cm, user.age, user.gender); - const tdee = utils.calculateTDEE(bmr, user.activity_level); - - const goalType = req.body.goal_type || 'recomp'; - let targetCalories; - - if (goalType === 'weight_loss') { - targetCalories = tdee - 500; - } else if (goalType === 'muscle_gain') { - targetCalories = tdee + 300; - } else { - targetCalories = tdee; - } - - user.target_daily_calories = Math.round(targetCalories); - await user.save(); - - // Update or create goals - let userGoals = await db.UserGoal.findOne({ where: { UserId: req.user.id } }); - if (!userGoals) { - userGoals = await db.UserGoal.create({ UserId: req.user.id }); - } - - userGoals.goal_type = goalType; - userGoals.target_weight_kg = parseFloat(req.body.target_weight_kg) || 70; - - // Calculate macros - const macros = utils.calculateMacroTargets(user.weight_kg, goalType); - userGoals.target_protein_g = macros.protein_g; - userGoals.target_carbs_g = macros.carbs_g; - userGoals.target_fat_g = macros.fat_g; - userGoals.target_water_ml = parseInt(req.body.target_water_ml) || 2000; - - await userGoals.save(); - - req.flash('success_msg', 'Goals updated successfully!'); - res.redirect('/goals'); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error updating goals'); - res.redirect('/goals'); - } -}); - -app.get('/foods', ensureAuthenticated, async (req, res) => { - try { - const category = req.query.category || 'all'; - const searchQuery = req.query.q || ''; - - const whereClause = {}; - - if (category !== 'all') { - whereClause.category = category; - } - - if (searchQuery) { - whereClause[db.Sequelize.Op.or] = [ - { name: { [db.Sequelize.Op.like]: `%${searchQuery}%` } }, - { name_tagalog: { [db.Sequelize.Op.like]: `%${searchQuery}%` } } - ]; - } - - const filipinoWhere = { ...whereClause, is_filipino: true }; - const otherWhere = { ...whereClause, is_filipino: false }; - - const filipinoFoods = await db.FoodItem.findAll({ - where: filipinoWhere, - order: [['name', 'ASC']] - }); - - const otherFoods = await db.FoodItem.findAll({ - where: otherWhere, - limit: 20, - order: [['name', 'ASC']] - }); - - const categories = ['all', 'kanin', 'ulam', 'sabaw', 'gulay', 'meryenda', 'almusal']; - - res.render('foods', { - filipino_foods: filipinoFoods, - other_foods: otherFoods, - categories, - current_category: category, - search_query: searchQuery - }); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error loading foods'); - res.redirect('/dashboard'); - } -}); - -app.get('/progress', ensureAuthenticated, async (req, res) => { - try { - const days = parseInt(req.query.days) || 30; - - const weightTrend = await utils.getWeightTrend(req.user.id, days); - const calorieTrend = await utils.getCalorieTrend(req.user.id, days); - - let avgCalories = 0, avgProtein = 0, avgCarbs = 0, avgFat = 0; - - if (calorieTrend.length > 0) { - avgCalories = calorieTrend.reduce((sum, d) => sum + d.calories, 0) / calorieTrend.length; - avgProtein = calorieTrend.reduce((sum, d) => sum + d.protein, 0) / calorieTrend.length; - avgCarbs = calorieTrend.reduce((sum, d) => sum + d.carbs, 0) / calorieTrend.length; - avgFat = calorieTrend.reduce((sum, d) => sum + d.fat, 0) / calorieTrend.length; - } - - let weightChange = null; - if (weightTrend.length >= 2) { - weightChange = weightTrend[weightTrend.length - 1].weight_kg - weightTrend[0].weight_kg; - } - - res.render('progress', { - weight_trend: weightTrend, - calorie_trend: calorieTrend, - avg_calories: Math.round(avgCalories), - avg_protein: Math.round(avgProtein), - avg_carbs: Math.round(avgCarbs), - avg_fat: Math.round(avgFat), - weight_change: weightChange, - days - }); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error loading progress'); - res.redirect('/dashboard'); - } -}); - -app.get('/meal-planner', ensureAuthenticated, async (req, res) => { - try { - const today = new Date(); - // Calculate Monday of current week - const day = today.getDay(); - const diff = today.getDate() - day + (day === 0 ? -6 : 1); // adjust when day is sunday - const startDate = new Date(today); - startDate.setDate(diff); - - const dates = []; - for (let i = 0; i < 7; i++) { - const d = new Date(startDate); - d.setDate(startDate.getDate() + i); - dates.push(d); - } - - const mealPlans = {}; - - for (const d of dates) { - const dateStr = d.toISOString().split('T')[0]; - - const plans = await db.MealPlan.findAll({ - where: { UserId: req.user.id, date: dateStr }, - include: [{ - model: db.PlannedFood, - include: [db.FoodItem] - }] - }); - - mealPlans[dateStr] = plans.map(p => { - let calories = 0, protein = 0, carbs = 0, fat = 0; - const foods = []; - - if (p.PlannedFoods) { - p.PlannedFoods.forEach(pf => { - if (pf.FoodItem) { - const q = pf.quantity || 1; - calories += pf.FoodItem.calories * q; - protein += pf.FoodItem.protein_g * q; - carbs += pf.FoodItem.carbs_g * q; - fat += pf.FoodItem.fat_g * q; - - foods.push({ - name: pf.FoodItem.name, - quantity: q - }); - } - }); - } - - return { - id: p.id, - meal_type: p.meal_type, - is_completed: p.is_completed, - foods: foods, - totals: { - calories, protein, carbs, fat - } - }; - }); - } - - res.render('meal_planner', { - dates: dates.map(d => d.toISOString().split('T')[0]), - meal_plans: mealPlans, - today: new Date().toISOString().split('T')[0] - }); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error loading meal planner'); - res.redirect('/dashboard'); - } -}); - -app.post('/meal-planner/auto-generate', ensureAuthenticated, async (req, res) => { - try { - const { date } = req.body; - - if (!date) { - req.flash('error_msg', 'Please select a date'); - return res.redirect('/meal-planner'); - } - - await utils.generateDailyMealPlan(req.user.id, date); - - req.flash('success_msg', 'Meal plan generated successfully!'); - res.redirect('/meal-planner'); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error generating meal plan'); - res.redirect('/meal-planner'); - } -}); - -app.post('/meal-planner/add', ensureAuthenticated, async (req, res) => { - try { - let { date, meal_type, 'food_id[]': foodIds, 'quantity[]': quantities } = req.body; - - if (!foodIds) { - req.flash('error_msg', 'Please add at least one food item'); - return res.redirect('/meal-planner'); - } - - // Normalize input - if (!Array.isArray(foodIds)) { - foodIds = [foodIds]; - quantities = [quantities]; - } - - // Find or create meal plan - let mealPlan = await db.MealPlan.findOne({ - where: { - UserId: req.user.id, - date: date, - meal_type: meal_type - } - }); - - if (!mealPlan) { - mealPlan = await db.MealPlan.create({ - UserId: req.user.id, - date: date, - meal_type: meal_type - }); - } - - // Add foods - for (let i = 0; i < foodIds.length; i++) { - const foodId = foodIds[i]; - const quantity = quantities[i]; - - if (foodId && quantity) { - await db.PlannedFood.create({ - MealPlanId: mealPlan.id, - FoodItemId: foodId, - quantity: quantity - }); - } - } - - req.flash('success_msg', 'Meal plan updated!'); - res.redirect('/meal-planner'); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error adding meal plan'); - res.redirect('/meal-planner'); - } -}); - -app.post('/meal-planner/complete/:id', ensureAuthenticated, async (req, res) => { - try { - const plan = await db.MealPlan.findOne({ - where: { id: req.params.id, UserId: req.user.id } - }); - - if (plan) { - plan.is_completed = !plan.is_completed; - await plan.save(); - - // If marked complete, optionally create actual meal log? - // For now just toggle status as per request simplicity. - } - - res.redirect('/meal-planner'); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error updating plan status'); - res.redirect('/meal-planner'); - } -}); - -app.post('/meal-planner/delete/:id', ensureAuthenticated, async (req, res) => { - try { - await db.MealPlan.destroy({ - where: { id: req.params.id, UserId: req.user.id } - }); - req.flash('success_msg', 'Meal plan deleted'); - res.redirect('/meal-planner'); - } catch (err) { - console.error(err); - req.flash('error_msg', 'Error deleting meal plan'); - res.redirect('/meal-planner'); - } -}); - -// Database Sync and Server Start -const startServer = async () => { - try { - await db.sequelize.sync(); - app.listen(PORT, () => console.log(`Server started on port ${PORT}`)); - } catch (err) { - console.error('Database connection error:', err); - } -}; - -startServer(); diff --git a/src/app.controller.ts b/src/app.controller.ts new file mode 100644 index 0000000..4bcd1bf --- /dev/null +++ b/src/app.controller.ts @@ -0,0 +1,67 @@ +import { Controller, Get, Post, Body, Res, UseGuards, Req, Render, Redirect } from '@nestjs/common'; +import { Response, Request } from 'express'; +import { LocalAuthGuard } from './auth/guards/local-auth.guard'; +import { UsersService } from './users/users.service'; +import { AuthenticatedGuard } from './auth/guards/authenticated.guard'; + +@Controller() +export class AppController { + constructor(private usersService: UsersService) {} + + @Get() + root(@Req() req, @Res() res: Response) { + if (req.isAuthenticated()) { + return res.redirect('/dashboard'); + } else { + return res.redirect('/login'); + } + } + + @Get('login') + @Render('login') + login() { + return {}; + } + + @UseGuards(LocalAuthGuard) + @Post('login') + loginPost(@Res() res: Response) { + res.redirect('/dashboard'); + } + + @Get('register') + @Render('register') + register() { + return {}; + } + + @Post('register') + async registerPost(@Body() body, @Res() res: Response, @Req() req) { + const { username, password, name } = body; + try { + const existingUser = await this.usersService.findOne(username); + if (existingUser) { + req.flash('error', 'Username already exists'); + return res.redirect('/register'); + } + await this.usersService.create({ username, password, name }); + req.flash('success_msg', 'You are now registered and can log in'); + res.redirect('/login'); + } catch (err) { + console.error(err); + req.flash('error', 'Error registering user'); + res.redirect('/register'); + } + } + + @Get('logout') + logout(@Req() req, @Res() res: Response) { + req.logout((err) => { + if (err) { + console.error(err); + } + req.flash('success_msg', 'You are logged out'); + res.redirect('/login'); + }); + } +} diff --git a/src/app.module.ts b/src/app.module.ts new file mode 100644 index 0000000..2859bb1 --- /dev/null +++ b/src/app.module.ts @@ -0,0 +1,40 @@ +import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { DatabaseModule } from './database/database.module'; +import { AuthModule } from './auth/auth.module'; +import { UsersModule } from './users/users.module'; +import { AppController } from './app.controller'; +import { UtilsModule } from './utils/utils.module'; +import { DashboardModule } from './dashboard/dashboard.module'; +import { MealsModule } from './meals/meals.module'; +import { GoalsModule } from './goals/goals.module'; +import { FoodsModule } from './foods/foods.module'; +import { MealPlannerModule } from './meal-planner/meal-planner.module'; +import { LocalsMiddleware } from './common/middleware/locals.middleware'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + envFilePath: '.env', + }), + DatabaseModule, + AuthModule, + UsersModule, + UtilsModule, + DashboardModule, + MealsModule, + GoalsModule, + FoodsModule, + MealPlannerModule, + ], + controllers: [AppController], + providers: [], +}) +export class AppModule { + configure(consumer: MiddlewareConsumer) { + consumer + .apply(LocalsMiddleware) + .forRoutes({ path: '*', method: RequestMethod.ALL }); + } +} diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts new file mode 100644 index 0000000..066629d --- /dev/null +++ b/src/auth/auth.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { AuthService } from './auth.service'; +import { UsersModule } from '../users/users.module'; +import { PassportModule } from '@nestjs/passport'; +import { LocalStrategy } from './local.strategy'; +import { SessionSerializer } from './session.serializer'; + +@Module({ + imports: [UsersModule, PassportModule.register({ session: true })], + providers: [AuthService, LocalStrategy, SessionSerializer], + exports: [AuthService], +}) +export class AuthModule {} diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts new file mode 100644 index 0000000..bd544a9 --- /dev/null +++ b/src/auth/auth.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { UsersService } from '../users/users.service'; + +@Injectable() +export class AuthService { + constructor(private usersService: UsersService) {} + + async validateUser(username: string, pass: string): Promise { + const user = await this.usersService.findOne(username); + if (user && user.validPassword(pass)) { + // Return user object without password? Or just the user model. + // Passport serializer will handle the rest. + return user; + } + return null; + } +} diff --git a/src/auth/guards/authenticated.guard.ts b/src/auth/guards/authenticated.guard.ts new file mode 100644 index 0000000..6465140 --- /dev/null +++ b/src/auth/guards/authenticated.guard.ts @@ -0,0 +1,9 @@ +import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; + +@Injectable() +export class AuthenticatedGuard implements CanActivate { + async canActivate(context: ExecutionContext) { + const request = context.switchToHttp().getRequest(); + return request.isAuthenticated(); + } +} diff --git a/src/auth/guards/local-auth.guard.ts b/src/auth/guards/local-auth.guard.ts new file mode 100644 index 0000000..7507460 --- /dev/null +++ b/src/auth/guards/local-auth.guard.ts @@ -0,0 +1,12 @@ +import { ExecutionContext, Injectable } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; + +@Injectable() +export class LocalAuthGuard extends AuthGuard('local') { + async canActivate(context: ExecutionContext) { + const result = (await super.canActivate(context)) as boolean; + const request = context.switchToHttp().getRequest(); + await super.logIn(request); + return result; + } +} diff --git a/src/auth/local.strategy.ts b/src/auth/local.strategy.ts new file mode 100644 index 0000000..00d7ab7 --- /dev/null +++ b/src/auth/local.strategy.ts @@ -0,0 +1,19 @@ +import { Strategy } from 'passport-local'; +import { PassportStrategy } from '@nestjs/passport'; +import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { AuthService } from './auth.service'; + +@Injectable() +export class LocalStrategy extends PassportStrategy(Strategy) { + constructor(private authService: AuthService) { + super(); + } + + async validate(username: string, pass: string): Promise { + const user = await this.authService.validateUser(username, pass); + if (!user) { + throw new UnauthorizedException(); + } + return user; + } +} diff --git a/src/auth/session.serializer.ts b/src/auth/session.serializer.ts new file mode 100644 index 0000000..0ec1bd6 --- /dev/null +++ b/src/auth/session.serializer.ts @@ -0,0 +1,19 @@ +import { PassportSerializer } from '@nestjs/passport'; +import { Injectable } from '@nestjs/common'; +import { UsersService } from '../users/users.service'; + +@Injectable() +export class SessionSerializer extends PassportSerializer { + constructor(private readonly usersService: UsersService) { + super(); + } + + serializeUser(user: any, done: Function) { + done(null, user.id); + } + + async deserializeUser(userId: any, done: Function) { + const user = await this.usersService.findById(userId); + done(null, user); + } +} diff --git a/src/common/middleware/locals.middleware.ts b/src/common/middleware/locals.middleware.ts new file mode 100644 index 0000000..b2c1864 --- /dev/null +++ b/src/common/middleware/locals.middleware.ts @@ -0,0 +1,15 @@ +import { Injectable, NestMiddleware } from '@nestjs/common'; +import { Request, Response, NextFunction } from 'express'; + +@Injectable() +export class LocalsMiddleware implements NestMiddleware { + use(req: Request, res: Response, next: NextFunction) { + const reqAny = req as any; + res.locals.current_user = reqAny.user; + res.locals.success_msg = reqAny.flash('success_msg'); + res.locals.error_msg = reqAny.flash('error_msg'); + res.locals.error = reqAny.flash('error'); + res.locals.path = req.path; + next(); + } +} diff --git a/src/dashboard/dashboard.controller.ts b/src/dashboard/dashboard.controller.ts new file mode 100644 index 0000000..ff92a1a --- /dev/null +++ b/src/dashboard/dashboard.controller.ts @@ -0,0 +1,120 @@ +import { Controller, Get, Render, UseGuards, Req, Res } from '@nestjs/common'; +import { AuthenticatedGuard } from '../auth/guards/authenticated.guard'; +import { UtilsService } from '../utils/utils.service'; +import { UserGoal } from '../models/user-goal.model'; +import { WeightLog } from '../models/weight-log.model'; +import { InjectModel } from '@nestjs/sequelize'; +import { Response } from 'express'; + +@Controller('dashboard') +@UseGuards(AuthenticatedGuard) +export class DashboardController { + constructor( + private utilsService: UtilsService, + @InjectModel(UserGoal) private userGoalModel: typeof UserGoal, + @InjectModel(WeightLog) private weightLogModel: typeof WeightLog, + ) {} + + @Get() + @Render('dashboard') + async getDashboard(@Req() req, @Res() res: Response) { + try { + const today = new Date(); + const dateStr = today.toISOString().split('T')[0]; + + // Get daily totals + const nutrition = await this.utilsService.calculateDailyTotals(req.user.id, dateStr); + const water = await this.utilsService.calculateWaterTotal(req.user.id, dateStr); + + // Get user goals + let goals = await this.userGoalModel.findOne({ where: { UserId: req.user.id } }); + if (!goals) { + goals = await this.userGoalModel.create({ + UserId: req.user.id, + target_protein_g: 150, + target_carbs_g: 200, + target_fat_g: 60, + target_water_ml: 2000, + } as any); + } + + // Get weight info + const weightLogToday = await this.weightLogModel.findOne({ + where: { UserId: req.user.id, date: dateStr }, + }); + + const yesterday = new Date(today); + yesterday.setDate(yesterday.getDate() - 1); + const yesterdayStr = yesterday.toISOString().split('T')[0]; + + const weightLogYesterday = await this.weightLogModel.findOne({ + where: { UserId: req.user.id, date: yesterdayStr }, + }); + + let weightChange = null; + if (weightLogToday && weightLogYesterday) { + weightChange = weightLogToday.weight_kg - weightLogYesterday.weight_kg; + } + + // Calculate remaining + const remaining = { + calories: req.user.target_daily_calories - nutrition.calories, + protein: goals.target_protein_g - nutrition.protein, + carbs: goals.target_carbs_g - nutrition.carbs, + fat: goals.target_fat_g - nutrition.fat, + water: goals.target_water_ml - water.total_ml, + }; + + // Get macro percentages + const macro_percentages = this.utilsService.getMacroPercentages( + nutrition.protein, + nutrition.carbs, + nutrition.fat, + ); + + // Get suggestions + const suggestions = this.utilsService.suggestFoodsForMacros( + remaining.protein, + remaining.carbs, + remaining.fat, + ); + + // Get trends + const calorie_trend = await this.utilsService.getCalorieTrend(req.user.id); + const weight_trend = await this.utilsService.getWeightTrend(req.user.id); + + return { + user: req.user, + current_user: req.user, + nutrition, + water, + goals, + weightLogToday, + weightChange, + remaining, + macro_percentages, + suggestions, + calorie_trend, + weight_trend, + }; + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error loading dashboard'); + // Return minimal data to render the view without crashing + return { + user: req.user, + current_user: req.user, + nutrition: { calories: 0, protein: 0, carbs: 0, fat: 0, meals: [] }, + water: { total_ml: 0, logs: [] }, + goals: null, + weightLogToday: null, + weightChange: null, + remaining: { calories: 0, protein: 0, carbs: 0, fat: 0, water: 0 }, + macro_percentages: { protein: 0, carbs: 0, fat: 0 }, + suggestions: [], + calorie_trend: [], + weight_trend: [], + }; + } + } +} diff --git a/src/dashboard/dashboard.module.ts b/src/dashboard/dashboard.module.ts new file mode 100644 index 0000000..f621198 --- /dev/null +++ b/src/dashboard/dashboard.module.ts @@ -0,0 +1,16 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { DashboardController } from './dashboard.controller'; +import { ProgressController } from './progress.controller'; +import { UserGoal } from '../models/user-goal.model'; +import { WeightLog } from '../models/weight-log.model'; +import { UtilsModule } from '../utils/utils.module'; + +@Module({ + imports: [ + SequelizeModule.forFeature([UserGoal, WeightLog]), + UtilsModule, + ], + controllers: [DashboardController, ProgressController], +}) +export class DashboardModule {} diff --git a/src/dashboard/progress.controller.ts b/src/dashboard/progress.controller.ts new file mode 100644 index 0000000..a67eefc --- /dev/null +++ b/src/dashboard/progress.controller.ts @@ -0,0 +1,63 @@ +import { Controller, Get, Render, UseGuards, Req, Query } from '@nestjs/common'; +import { AuthenticatedGuard } from '../auth/guards/authenticated.guard'; +import { UtilsService } from '../utils/utils.service'; + +@Controller('progress') +@UseGuards(AuthenticatedGuard) +export class ProgressController { + constructor(private utilsService: UtilsService) {} + + @Get() + @Render('progress') + async getProgress(@Req() req, @Query('days') daysQuery: string) { + try { + const days = parseInt(daysQuery) || 30; + + const weightTrend = await this.utilsService.getWeightTrend(req.user.id, days); + const calorieTrend = await this.utilsService.getCalorieTrend(req.user.id, days); + + let avgCalories = 0, + avgProtein = 0, + avgCarbs = 0, + avgFat = 0; + + if (calorieTrend.length > 0) { + avgCalories = calorieTrend.reduce((sum, d) => sum + d.calories, 0) / calorieTrend.length; + avgProtein = calorieTrend.reduce((sum, d) => sum + d.protein, 0) / calorieTrend.length; + avgCarbs = calorieTrend.reduce((sum, d) => sum + d.carbs, 0) / calorieTrend.length; + avgFat = calorieTrend.reduce((sum, d) => sum + d.fat, 0) / calorieTrend.length; + } + + let weightChange = null; + if (weightTrend.length >= 2) { + weightChange = weightTrend[weightTrend.length - 1].weight_kg - weightTrend[0].weight_kg; + } + + return { + user: req.user, + weight_trend: weightTrend, + calorie_trend: calorieTrend, + avg_calories: Math.round(avgCalories), + avg_protein: Math.round(avgProtein), + avg_carbs: Math.round(avgCarbs), + avg_fat: Math.round(avgFat), + weight_change: weightChange, + days, + }; + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error loading progress'); + return { + user: req.user, + weight_trend: [], + calorie_trend: [], + avg_calories: 0, + avg_protein: 0, + avg_carbs: 0, + avg_fat: 0, + weight_change: null, + days: 30, + }; + } + } +} diff --git a/src/database/database.module.ts b/src/database/database.module.ts new file mode 100644 index 0000000..25384df --- /dev/null +++ b/src/database/database.module.ts @@ -0,0 +1,44 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { User } from '../models/user.model'; +import { FoodItem } from '../models/food-item.model'; +import { Meal } from '../models/meal.model'; +import { MealFood } from '../models/meal-food.model'; +import { WaterLog } from '../models/water-log.model'; +import { WeightLog } from '../models/weight-log.model'; +import { MealPlan } from '../models/meal-plan.model'; +import { PlannedFood } from '../models/planned-food.model'; +import { UserGoal } from '../models/user-goal.model'; +import { DailySummary } from '../models/daily-summary.model'; +import { APICache } from '../models/api-cache.model'; + +@Module({ + imports: [ + SequelizeModule.forRootAsync({ + imports: [ConfigModule], + useFactory: (configService: ConfigService) => ({ + dialect: 'sqlite', + storage: configService.get('DATABASE_URL') ? configService.get('DATABASE_URL').replace('sqlite://', '') : 'data/calorie_tracker.db', + models: [ + User, + FoodItem, + Meal, + MealFood, + WaterLog, + WeightLog, + MealPlan, + PlannedFood, + UserGoal, + DailySummary, + APICache, + ], + autoLoadModels: true, + synchronize: true, + logging: false, + }), + inject: [ConfigService], + }), + ], +}) +export class DatabaseModule {} diff --git a/src/foods/foods.controller.ts b/src/foods/foods.controller.ts new file mode 100644 index 0000000..73490b8 --- /dev/null +++ b/src/foods/foods.controller.ts @@ -0,0 +1,32 @@ +import { Controller, Get, Query, Render, UseGuards, Req } from '@nestjs/common'; +import { AuthenticatedGuard } from '../auth/guards/authenticated.guard'; +import { FoodsService } from './foods.service'; + +@Controller('foods') +@UseGuards(AuthenticatedGuard) +export class FoodsController { + constructor(private foodsService: FoodsService) {} + + @Get() + @Render('foods') + async getFoods(@Req() req, @Query('category') category: string, @Query('q') q: string) { + try { + const data = await this.foodsService.getFoods(category, q); + return { + user: req.user, + ...data, + }; + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error loading foods'); + return { + user: req.user, + filipino_foods: [], + other_foods: [], + categories: [], + current_category: 'all', + search_query: '', + }; + } + } +} diff --git a/src/foods/foods.module.ts b/src/foods/foods.module.ts new file mode 100644 index 0000000..a6b8cca --- /dev/null +++ b/src/foods/foods.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { FoodsController } from './foods.controller'; +import { FoodsService } from './foods.service'; +import { FoodItem } from '../models/food-item.model'; + +@Module({ + imports: [SequelizeModule.forFeature([FoodItem])], + controllers: [FoodsController], + providers: [FoodsService], +}) +export class FoodsModule {} diff --git a/src/foods/foods.service.ts b/src/foods/foods.service.ts new file mode 100644 index 0000000..f16ea33 --- /dev/null +++ b/src/foods/foods.service.ts @@ -0,0 +1,50 @@ +import { Injectable } from '@nestjs/common'; +import { InjectModel } from '@nestjs/sequelize'; +import { Op } from 'sequelize'; +import { FoodItem } from '../models/food-item.model'; + +@Injectable() +export class FoodsService { + constructor( + @InjectModel(FoodItem) private foodItemModel: typeof FoodItem, + ) {} + + async getFoods(category: string = 'all', searchQuery: string = '') { + const whereClause: any = {}; + + if (category !== 'all') { + whereClause.category = category; + } + + if (searchQuery) { + whereClause[Op.or] = [ + { name: { [Op.like]: `%${searchQuery}%` } }, + { name_tagalog: { [Op.like]: `%${searchQuery}%` } }, + ]; + } + + const filipinoWhere = { ...whereClause, is_filipino: true }; + const otherWhere = { ...whereClause, is_filipino: false }; + + const filipinoFoods = await this.foodItemModel.findAll({ + where: filipinoWhere, + order: [['name', 'ASC']], + }); + + const otherFoods = await this.foodItemModel.findAll({ + where: otherWhere, + limit: 20, + order: [['name', 'ASC']], + }); + + const categories = ['all', 'kanin', 'ulam', 'sabaw', 'gulay', 'meryenda', 'almusal']; + + return { + filipino_foods: filipinoFoods, + other_foods: otherFoods, + categories, + current_category: category, + search_query: searchQuery, + }; + } +} diff --git a/src/goals/goals.controller.ts b/src/goals/goals.controller.ts new file mode 100644 index 0000000..29f3f81 --- /dev/null +++ b/src/goals/goals.controller.ts @@ -0,0 +1,46 @@ +import { Controller, Get, Post, Body, Req, Res, UseGuards, Render } from '@nestjs/common'; +import { Response } from 'express'; +import { AuthenticatedGuard } from '../auth/guards/authenticated.guard'; +import { GoalsService } from './goals.service'; + +@Controller('goals') +@UseGuards(AuthenticatedGuard) +export class GoalsController { + constructor(private goalsService: GoalsService) {} + + @Get() + @Render('goals') + async getGoals(@Req() req) { + try { + const data = await this.goalsService.getGoals(req.user.id); + return { + user: req.user, + goals: data.goals, + bmr: data.bmr, + tdee: data.tdee, + }; + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error loading goals'); + return { + user: req.user, + goals: null, + bmr: null, + tdee: null, + }; + } + } + + @Post() + async updateGoals(@Req() req, @Body() body, @Res() res: Response) { + try { + await this.goalsService.updateGoals(req.user.id, body); + req.flash('success_msg', 'Goals updated successfully!'); + res.redirect('/goals'); + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error updating goals'); + res.redirect('/goals'); + } + } +} diff --git a/src/goals/goals.module.ts b/src/goals/goals.module.ts new file mode 100644 index 0000000..c8a6ec0 --- /dev/null +++ b/src/goals/goals.module.ts @@ -0,0 +1,17 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { GoalsController } from './goals.controller'; +import { GoalsService } from './goals.service'; +import { User } from '../models/user.model'; +import { UserGoal } from '../models/user-goal.model'; +import { UtilsModule } from '../utils/utils.module'; + +@Module({ + imports: [ + SequelizeModule.forFeature([User, UserGoal]), + UtilsModule, + ], + controllers: [GoalsController], + providers: [GoalsService], +}) +export class GoalsModule {} diff --git a/src/goals/goals.service.ts b/src/goals/goals.service.ts new file mode 100644 index 0000000..ac0af00 --- /dev/null +++ b/src/goals/goals.service.ts @@ -0,0 +1,100 @@ +import { Injectable } from '@nestjs/common'; +import { InjectModel } from '@nestjs/sequelize'; +import { User } from '../models/user.model'; +import { UserGoal } from '../models/user-goal.model'; +import { UtilsService } from '../utils/utils.service'; + +@Injectable() +export class GoalsService { + constructor( + @InjectModel(User) private userModel: typeof User, + @InjectModel(UserGoal) private userGoalModel: typeof UserGoal, + private utilsService: UtilsService, + ) {} + + async getGoals(userId: number) { + const user = await this.userModel.findByPk(userId); + const userGoals = await this.userGoalModel.findOne({ where: { UserId: userId } }); + + let bmr = null; + let tdee = null; + + if (user && user.weight_kg && user.height_cm && user.age) { + bmr = this.utilsService.calculateBMR( + user.weight_kg, + user.height_cm, + user.age, + user.gender || 'male', + ); + tdee = this.utilsService.calculateTDEE(bmr, user.activity_level || 'moderate'); + } + + return { + goals: userGoals, + bmr, + tdee, + user, + }; + } + + async updateGoals(userId: number, data: any) { + // Update user info + const user = await this.userModel.findByPk(userId); + if (!user) { + throw new Error('User not found'); + } + + user.age = parseInt(data.age) || 25; + user.gender = data.gender || 'male'; + user.height_cm = parseFloat(data.height_cm) || 170; + user.weight_kg = parseFloat(data.weight_kg) || 70; + user.activity_level = data.activity_level || 'moderate'; + + // Calculate targets + const bmr = this.utilsService.calculateBMR( + user.weight_kg, + user.height_cm, + user.age, + user.gender, + ); + const tdee = this.utilsService.calculateTDEE(bmr, user.activity_level); + + const goalType = data.goal_type || 'recomp'; + let targetCalories; + + if (goalType === 'weight_loss') { + targetCalories = tdee - 500; + } else if (goalType === 'muscle_gain') { + targetCalories = tdee + 300; + } else { + targetCalories = tdee; + } + + user.target_daily_calories = Math.round(targetCalories); + await user.save(); + + // Update or create goals + let userGoals = await this.userGoalModel.findOne({ where: { UserId: userId } }); + if (!userGoals) { + userGoals = await this.userGoalModel.create({ UserId: userId } as any); + } + + userGoals.goal_type = goalType; + userGoals.target_weight_kg = parseFloat(data.target_weight_kg) || 70; + + // Calculate macros + const macros = this.utilsService.calculateMacroTargets(user.weight_kg, goalType); + userGoals.target_protein_g = macros.protein_g; + userGoals.target_carbs_g = macros.carbs_g; + userGoals.target_fat_g = macros.fat_g; + userGoals.target_water_ml = parseInt(data.target_water_ml) || 2000; + + await userGoals.save(); + + return { + success: true, + user, + goals: userGoals, + }; + } +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..65d6f30 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,60 @@ +import { NestFactory } from '@nestjs/core'; +import { NestExpressApplication } from '@nestjs/platform-express'; +import { AppModule } from './app.module'; +import * as session from 'express-session'; +import * as passport from 'passport'; +import * as flash from 'express-flash'; +import * as expressLayouts from 'express-ejs-layouts'; +import * as methodOverride from 'method-override'; +import * as path from 'path'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const SQLiteStore = require('connect-sqlite3')(session); + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + + // Static assets + app.useStaticAssets(path.join(__dirname, '..', 'public')); + + // Views + app.setBaseViewsDir(path.join(__dirname, '..', 'views')); + app.setViewEngine('ejs'); + + // Layouts + app.use(expressLayouts); + app.set('layout', 'layout'); + + // Method override + app.use(methodOverride('_method')); + + // Body parsing (built-in in NestJS, but ensuring extended urlencoded) + app.useBodyParser('urlencoded', { extended: true }); + + // Session + app.use( + session({ + store: new SQLiteStore({ db: 'sessions.db', dir: './data' }), + secret: process.env.SECRET_KEY || 'secret', + resave: false, + saveUninitialized: false, + cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 }, // 30 days + }), + ); + + // Passport + app.use(passport.initialize()); + app.use(passport.session()); + + // Flash + app.use(flash()); + + // Global variables (helper functions) + const expressApp = app.getHttpAdapter().getInstance(); + expressApp.locals.round = Math.round; + + const PORT = process.env.PORT || 3000; + await app.listen(PORT); + console.log(`Application is running on: ${await app.getUrl()}`); +} +bootstrap(); diff --git a/src/meal-planner/meal-planner.controller.ts b/src/meal-planner/meal-planner.controller.ts new file mode 100644 index 0000000..aeb18ba --- /dev/null +++ b/src/meal-planner/meal-planner.controller.ts @@ -0,0 +1,76 @@ +import { Controller, Get, Post, Body, Req, Res, UseGuards, Render, Param } from '@nestjs/common'; +import { Response } from 'express'; +import { AuthenticatedGuard } from '../auth/guards/authenticated.guard'; +import { MealPlannerService } from './meal-planner.service'; + +@Controller('meal-planner') +@UseGuards(AuthenticatedGuard) +export class MealPlannerController { + constructor(private mealPlannerService: MealPlannerService) {} + + @Get() + @Render('meal_planner') + async getMealPlanner(@Req() req) { + try { + const data = await this.mealPlannerService.getWeeklyMealPlans(req.user.id); + return { + user: req.user, + dates: data.dates, + meal_plans: data.mealPlans, + today: data.today, + }; + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error loading meal planner'); + return { + user: req.user, + dates: [], + meal_plans: {}, + today: new Date().toISOString().split('T')[0], + }; + } + } + + @Post('auto-generate') + async autoGenerate(@Req() req, @Body() body, @Res() res: Response) { + try { + const { date } = body; + if (!date) { + req.flash('error_msg', 'Please select a date'); + return res.redirect('/meal-planner'); + } + + await this.mealPlannerService.autoGenerate(req.user.id, date); + req.flash('success_msg', 'Meal plan generated successfully!'); + res.redirect('/meal-planner'); + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error generating meal plan'); + res.redirect('/meal-planner'); + } + } + + @Post('add') + async addMealPlan(@Req() req, @Body() body, @Res() res: Response) { + try { + await this.mealPlannerService.addMealPlan(req.user.id, body); + req.flash('success_msg', 'Meal plan updated!'); + res.redirect('/meal-planner'); + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error adding meal plan'); + res.redirect('/meal-planner'); + } + } + + @Post('complete/:id') + async toggleComplete(@Req() req, @Param('id') id: number, @Res() res: Response) { + try { + await this.mealPlannerService.toggleComplete(req.user.id, id); + res.json({ success: true }); + } catch (err) { + console.error(err); + res.status(500).json({ success: false }); + } + } +} diff --git a/src/meal-planner/meal-planner.module.ts b/src/meal-planner/meal-planner.module.ts new file mode 100644 index 0000000..0837ae1 --- /dev/null +++ b/src/meal-planner/meal-planner.module.ts @@ -0,0 +1,18 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { MealPlannerController } from './meal-planner.controller'; +import { MealPlannerService } from './meal-planner.service'; +import { MealPlan } from '../models/meal-plan.model'; +import { PlannedFood } from '../models/planned-food.model'; +import { FoodItem } from '../models/food-item.model'; +import { UtilsModule } from '../utils/utils.module'; + +@Module({ + imports: [ + SequelizeModule.forFeature([MealPlan, PlannedFood, FoodItem]), + UtilsModule, + ], + controllers: [MealPlannerController], + providers: [MealPlannerService], +}) +export class MealPlannerModule {} diff --git a/src/meal-planner/meal-planner.service.ts b/src/meal-planner/meal-planner.service.ts new file mode 100644 index 0000000..5cda2b8 --- /dev/null +++ b/src/meal-planner/meal-planner.service.ts @@ -0,0 +1,155 @@ +import { Injectable } from '@nestjs/common'; +import { InjectModel } from '@nestjs/sequelize'; +import { MealPlan } from '../models/meal-plan.model'; +import { PlannedFood } from '../models/planned-food.model'; +import { FoodItem } from '../models/food-item.model'; +import { UtilsService } from '../utils/utils.service'; + +@Injectable() +export class MealPlannerService { + constructor( + @InjectModel(MealPlan) private mealPlanModel: typeof MealPlan, + @InjectModel(PlannedFood) private plannedFoodModel: typeof PlannedFood, + @InjectModel(FoodItem) private foodItemModel: typeof FoodItem, + private utilsService: UtilsService, + ) {} + + async getWeeklyMealPlans(userId: number) { + const today = new Date(); + const day = today.getDay(); + const diff = today.getDate() - day + (day === 0 ? -6 : 1); // adjust when day is sunday + const startDate = new Date(today); + startDate.setDate(diff); + + const dates = []; + for (let i = 0; i < 7; i++) { + const d = new Date(startDate); + d.setDate(startDate.getDate() + i); + dates.push(d); + } + + const mealPlans = {}; + + for (const d of dates) { + const dateStr = d.toISOString().split('T')[0]; + + const plans = await this.mealPlanModel.findAll({ + where: { UserId: userId, date: dateStr }, + include: [ + { + model: PlannedFood, + include: [FoodItem], + }, + ], + }); + + mealPlans[dateStr] = plans.map((p) => { + let calories = 0, + protein = 0, + carbs = 0, + fat = 0; + const foods = []; + + if (p.plannedFoods) { + p.plannedFoods.forEach((pf) => { + if (pf.foodItem) { + const q = pf.quantity || 1; + calories += pf.foodItem.calories * q; + protein += pf.foodItem.protein_g * q; + carbs += pf.foodItem.carbs_g * q; + fat += pf.foodItem.fat_g * q; + + foods.push({ + name: pf.foodItem.name, + quantity: q, + }); + } + }); + } + + return { + id: p.id, + meal_type: p.meal_type, + is_completed: p.is_completed, + foods: foods, + totals: { + calories, + protein, + carbs, + fat, + }, + }; + }); + } + + return { + dates: dates.map((d) => d.toISOString().split('T')[0]), + mealPlans, + today: new Date().toISOString().split('T')[0], + }; + } + + async autoGenerate(userId: number, date: string) { + return this.utilsService.generateDailyMealPlan(userId, date); + } + + async addMealPlan(userId: number, data: any) { + let { date, meal_type, 'food_id[]': foodIds, 'quantity[]': quantities } = data; + + if (!foodIds) { + throw new Error('Please add at least one food item'); + } + + // Normalize input + if (!Array.isArray(foodIds)) { + foodIds = [foodIds]; + quantities = [quantities]; + } + + // Find or create meal plan + let mealPlan = await this.mealPlanModel.findOne({ + where: { + UserId: userId, + date: date, + meal_type: meal_type, + }, + }); + + if (!mealPlan) { + mealPlan = await this.mealPlanModel.create({ + UserId: userId, + date: date, + meal_type: meal_type, + } as any); + } + + // Add foods + for (let i = 0; i < foodIds.length; i++) { + const foodId = foodIds[i]; + const quantity = quantities[i]; + + if (foodId && quantity) { + await this.plannedFoodModel.create({ + MealPlanId: mealPlan.id, + FoodItemId: foodId, + quantity: quantity, + } as any); + } + } + + return mealPlan; + } + + async toggleComplete(userId: number, planId: number) { + const plan = await this.mealPlanModel.findOne({ + where: { id: planId, UserId: userId }, + }); + + if (plan) { + plan.is_completed = !plan.is_completed; + await plan.save(); + return plan; + } + return null; + } +} diff --git a/src/meals/meals.controller.ts b/src/meals/meals.controller.ts new file mode 100644 index 0000000..88ad01f --- /dev/null +++ b/src/meals/meals.controller.ts @@ -0,0 +1,168 @@ +import { Controller, Get, Post, Body, Req, Res, UseGuards, Query } from '@nestjs/common'; +import { Response } from 'express'; +import { InjectModel } from '@nestjs/sequelize'; +import { AuthenticatedGuard } from '../auth/guards/authenticated.guard'; +import { UtilsService } from '../utils/utils.service'; +import { NutritionService } from './nutrition.service'; +import { Meal } from '../models/meal.model'; +import { MealFood } from '../models/meal-food.model'; +import { FoodItem } from '../models/food-item.model'; +import { WaterLog } from '../models/water-log.model'; +import { WeightLog } from '../models/weight-log.model'; + +@Controller() +@UseGuards(AuthenticatedGuard) +export class MealsController { + constructor( + private utilsService: UtilsService, + private nutritionService: NutritionService, + @InjectModel(Meal) private mealModel: typeof Meal, + @InjectModel(MealFood) private mealFoodModel: typeof MealFood, + @InjectModel(FoodItem) private foodItemModel: typeof FoodItem, + @InjectModel(WaterLog) private waterLogModel: typeof WaterLog, + @InjectModel(WeightLog) private weightLogModel: typeof WeightLog, + ) {} + + @Get('add-meal') + addMealPage(@Req() req, @Res() res: Response) { + res.render('add_meal', { today: new Date().toISOString().split('T')[0] }); + } + + @Post('add-meal') + async addMeal(@Req() req, @Res() res: Response, @Body() body) { + try { + let { date, meal_type, time, 'food_id[]': foodIds, 'quantity[]': quantities } = body; + + if (!foodIds) { + req.flash('error_msg', 'Please add at least one food item'); + return res.redirect('/add-meal'); + } + + // Normalize input (handle single item vs array) + if (!Array.isArray(foodIds)) { + foodIds = [foodIds]; + quantities = [quantities]; + } + + const meal = await this.mealModel.create({ + UserId: req.user.id, + date: date || new Date(), + meal_type, + time: time || null, + } as any); + + for (let i = 0; i < foodIds.length; i++) { + const foodId = foodIds[i]; + const quantity = quantities[i]; + + if (foodId && quantity) { + const food = await this.foodItemModel.findByPk(foodId); + if (food) { + await this.mealFoodModel.create({ + MealId: meal.id, + FoodItemId: foodId, + quantity: quantity, + calories_consumed: food.calories * quantity, + protein_consumed: food.protein_g * quantity, + carbs_consumed: food.carbs_g * quantity, + fat_consumed: food.fat_g * quantity, + } as any); + } + } + } + + await this.utilsService.updateDailySummary(req.user.id, date); + + req.flash('success_msg', 'Meal added successfully!'); + res.redirect('/dashboard'); + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error adding meal'); + res.redirect('/add-meal'); + } + } + + @Get('api/search-food') + async searchFood(@Query('q') query: string) { + if (!query || query.length < 2) { + return []; + } + return this.nutritionService.searchAllSources(query); + } + + @Post('api/add-food') + async addFood(@Body() body) { + try { + const food = await this.nutritionService.saveFoodToDb(body); + if (food) { + return { + success: true, + food_id: food.id, + name: food.name, + }; + } else { + return { success: false }; + } + } catch (err) { + console.error(err); + return { success: false }; + } + } + + @Post('add-water') + async addWater(@Req() req, @Res() res: Response, @Body() body) { + try { + const amountMl = parseInt(body.amount_ml) || 250; + const date = body.date || new Date().toISOString().split('T')[0]; + + await this.waterLogModel.create({ + UserId: req.user.id, + date: date, + amount_ml: amountMl, + time: new Date().toISOString(), // Use ISO string or appropriate time format + } as any); + + await this.utilsService.updateDailySummary(req.user.id, date); + + req.flash('success_msg', `Added ${amountMl}ml of water!`); + res.redirect('/dashboard'); + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error adding water'); + res.redirect('/dashboard'); + } + } + + @Post('add-weight') + async addWeight(@Req() req, @Res() res: Response, @Body() body) { + try { + const weightKg = parseFloat(body.weight_kg); + const date = body.date || new Date().toISOString().split('T')[0]; + + const weightLog = await this.weightLogModel.findOne({ + where: { UserId: req.user.id, date: date }, + }); + + if (weightLog) { + weightLog.weight_kg = weightKg; + weightLog.time = new Date().toISOString(); + await weightLog.save(); + } else { + await this.weightLogModel.create({ + UserId: req.user.id, + date: date, + weight_kg: weightKg, + time: new Date().toISOString(), + } as any); + } + + await this.utilsService.updateDailySummary(req.user.id, date); + + res.redirect('/dashboard'); + } catch (err) { + console.error(err); + req.flash('error_msg', 'Error adding weight'); + res.redirect('/dashboard'); + } + } +} diff --git a/src/meals/meals.module.ts b/src/meals/meals.module.ts new file mode 100644 index 0000000..62f773b --- /dev/null +++ b/src/meals/meals.module.ts @@ -0,0 +1,26 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { MealsController } from './meals.controller'; +import { NutritionService } from './nutrition.service'; +import { Meal } from '../models/meal.model'; +import { MealFood } from '../models/meal-food.model'; +import { FoodItem } from '../models/food-item.model'; +import { WaterLog } from '../models/water-log.model'; +import { WeightLog } from '../models/weight-log.model'; +import { APICache } from '../models/api-cache.model'; + +@Module({ + imports: [ + SequelizeModule.forFeature([ + Meal, + MealFood, + FoodItem, + WaterLog, + WeightLog, + APICache, + ]), + ], + controllers: [MealsController], + providers: [NutritionService], +}) +export class MealsModule {} diff --git a/src/meals/nutrition.service.ts b/src/meals/nutrition.service.ts new file mode 100644 index 0000000..a759bf9 --- /dev/null +++ b/src/meals/nutrition.service.ts @@ -0,0 +1,231 @@ +import { Injectable } from '@nestjs/common'; +import { InjectModel } from '@nestjs/sequelize'; +import { ConfigService } from '@nestjs/config'; +import { Op } from 'sequelize'; +import axios from 'axios'; +import { FoodItem } from '../models/food-item.model'; +import { APICache } from '../models/api-cache.model'; + +@Injectable() +export class NutritionService { + private apiKey: string; + private baseUrl: string; + private headers: any; + private cacheDurationDays: number; + + constructor( + private configService: ConfigService, + @InjectModel(FoodItem) private foodItemModel: typeof FoodItem, + @InjectModel(APICache) private apiCacheModel: typeof APICache, + ) { + this.apiKey = this.configService.get('API_NINJAS_KEY'); + this.baseUrl = 'https://api.api-ninjas.com/v1/nutrition'; + this.headers = { 'X-Api-Key': this.apiKey }; + this.cacheDurationDays = 30; + } + + async searchFood(query: string) { + // Check cache first + const cached = await this._getFromCache(query); + if (cached) { + return cached; + } + + // Make API request + try { + if (!this.apiKey) { + console.warn('API_NINJAS_KEY is not set'); + return []; + } + + const response = await axios.get(this.baseUrl, { + headers: this.headers, + params: { query: query }, + timeout: 10000, + }); + + if (response.status === 200) { + const data = response.data; + + // Cache the response + await this._saveToCache(query, 'api_ninjas', data); + + // Parse and return standardized format + return this._parseApiResponse(data); + } else { + console.error(`API Error: ${response.status}`); + return []; + } + } catch (error) { + console.error(`API Request failed: ${error.message}`); + return []; + } + } + + async _getFromCache(query: string) { + const cacheEntry = await this.apiCacheModel.findOne({ + where: { query: query.toLowerCase() }, + }); + + if (cacheEntry) { + // Check if cache is still valid (30 days) + const age = (new Date().getTime() - new Date(cacheEntry.cached_at).getTime()) / (1000 * 60 * 60 * 24); + if (age < this.cacheDurationDays) { + const data = JSON.parse(cacheEntry.response_json); + return this._parseApiResponse(data); + } + } + + return null; + } + + async _saveToCache(query: string, source: string, data: any) { + try { + let cacheEntry = await this.apiCacheModel.findOne({ + where: { query: query.toLowerCase() }, + }); + + if (cacheEntry) { + // Update existing cache + cacheEntry.response_json = JSON.stringify(data); + cacheEntry.cached_at = new Date(); + await cacheEntry.save(); + } else { + // Create new cache entry + await this.apiCacheModel.create({ + query: query.toLowerCase(), + api_source: source, + response_json: JSON.stringify(data), + cached_at: new Date(), + } as any); + } + } catch (error) { + console.error(`Cache save failed: ${error.message}`); + } + } + + _parseApiResponse(data: any[]) { + return data.map((item) => ({ + name: (item.name || '').replace(/\b\w/g, (l) => l.toUpperCase()), // Title case + calories: item.calories || 0, + protein_g: item.protein_g || 0, + carbs_g: item.carbohydrates_total_g || 0, + fat_g: item.fat_total_g || 0, + fiber_g: item.fiber_g || 0, + sugar_g: item.sugar_g || 0, + sodium_mg: item.sodium_mg || 0, + serving_size_g: item.serving_size_g || 100, + source: 'api_ninjas', + })); + } + + async saveFoodToDb(foodData: any) { + try { + // Check if food already exists + const existing = await this.foodItemModel.findOne({ + where: { + name: foodData.name, + source: foodData.source || 'api', + }, + }); + + if (existing) { + return existing; + } + + // Create new food item + const food = await this.foodItemModel.create({ + name: foodData.name, + calories: foodData.calories, + protein_g: foodData.protein_g || 0, + carbs_g: foodData.carbs_g || 0, + fat_g: foodData.fat_g || 0, + fiber_g: foodData.fiber_g || 0, + sugar_g: foodData.sugar_g || 0, + sodium_mg: foodData.sodium_mg || 0, + serving_size_g: foodData.serving_size_g || 100, + serving_description: foodData.serving_description || '1 serving', + source: foodData.source || 'api', + api_data: JSON.stringify(foodData), + } as any); + + return food; + } catch (error) { + console.error(`Error saving food to DB: ${error.message}`); + return null; + } + } + + async searchAllSources(query: string) { + const results = []; + + // 1. Search Filipino foods first + const filipinoFoods = await this.foodItemModel.findAll({ + where: { + is_filipino: true, + [Op.or]: [ + { name: { [Op.like]: `%${query}%` } }, + { name_tagalog: { [Op.like]: `%${query}%` } }, + ], + }, + limit: 5, + }); + + for (const food of filipinoFoods) { + results.push({ + id: food.id, + name: food.name, + name_tagalog: food.name_tagalog, + calories: food.calories, + protein_g: food.protein_g, + carbs_g: food.carbs_g, + fat_g: food.fat_g, + serving_description: food.serving_description, + source: 'filipino', + category: food.category, + }); + } + + // 2. Search other local foods + const otherFoods = await this.foodItemModel.findAll({ + where: { + is_filipino: false, + name: { [Op.like]: `%${query}%` }, + }, + limit: 5, + }); + + for (const food of otherFoods) { + results.push({ + id: food.id, + name: food.name, + calories: food.calories, + protein_g: food.protein_g, + carbs_g: food.carbs_g, + fat_g: food.fat_g, + serving_description: food.serving_description, + source: food.source, + }); + } + + // 3. If not enough results, search API + if (results.length < 3 && this.apiKey) { + const apiResults = await this.searchFood(query); + for (const foodData of apiResults.slice(0, 5)) { + results.push({ + name: foodData.name, + calories: foodData.calories, + protein_g: foodData.protein_g, + carbs_g: foodData.carbs_g || 0, + fat_g: foodData.fat_g || 0, + serving_description: '100g', // Standard API serving + source: 'api_ninjas', + // Pass raw data for saving later + raw_data: foodData, + }); + } + } + + return results; + } +} diff --git a/src/models/api-cache.model.ts b/src/models/api-cache.model.ts new file mode 100644 index 0000000..9c73570 --- /dev/null +++ b/src/models/api-cache.model.ts @@ -0,0 +1,16 @@ +import { Column, Model, Table, DataType } from 'sequelize-typescript'; + +@Table +export class APICache extends Model { + @Column({ unique: true, allowNull: false }) + query: string; + + @Column + api_source: string; + + @Column(DataType.TEXT) + response_json: string; + + @Column({ defaultValue: DataType.NOW }) + cached_at: Date; +} diff --git a/src/models/daily-summary.model.ts b/src/models/daily-summary.model.ts new file mode 100644 index 0000000..ec0002d --- /dev/null +++ b/src/models/daily-summary.model.ts @@ -0,0 +1,39 @@ +import { Column, Model, Table, BelongsTo, ForeignKey, DataType } from 'sequelize-typescript'; +import { User } from './user.model'; + +@Table +export class DailySummary extends Model { + @ForeignKey(() => User) + @Column + UserId: number; + + @BelongsTo(() => User) + user: User; + + @Column({ type: DataType.DATEONLY, allowNull: false }) + date: Date; + + @Column({ type: DataType.FLOAT, defaultValue: 0 }) + total_calories: number; + + @Column({ type: DataType.FLOAT, defaultValue: 0 }) + total_protein_g: number; + + @Column({ type: DataType.FLOAT, defaultValue: 0 }) + total_carbs_g: number; + + @Column({ type: DataType.FLOAT, defaultValue: 0 }) + total_fat_g: number; + + @Column({ defaultValue: 0 }) + total_water_ml: number; + + @Column(DataType.FLOAT) + calories_remaining: number; + + @Column(DataType.FLOAT) + weight_kg: number; + + @Column(DataType.TEXT) + notes: string; +} diff --git a/src/models/food-item.model.ts b/src/models/food-item.model.ts new file mode 100644 index 0000000..92d50aa --- /dev/null +++ b/src/models/food-item.model.ts @@ -0,0 +1,63 @@ +import { Column, Model, Table, HasMany, DataType } from 'sequelize-typescript'; +import { MealFood } from './meal-food.model'; +import { PlannedFood } from './planned-food.model'; + +@Table +export class FoodItem extends Model { + @Column({ allowNull: false }) + name: string; + + @Column + name_tagalog: string; + + @Column + category: string; + + @Column({ type: DataType.FLOAT, allowNull: false }) + calories: number; + + @Column({ type: DataType.FLOAT, defaultValue: 0 }) + protein_g: number; + + @Column({ type: DataType.FLOAT, defaultValue: 0 }) + carbs_g: number; + + @Column({ type: DataType.FLOAT, defaultValue: 0 }) + fat_g: number; + + @Column({ type: DataType.FLOAT, defaultValue: 0 }) + fiber_g: number; + + @Column({ type: DataType.FLOAT, defaultValue: 0 }) + sugar_g: number; + + @Column({ type: DataType.FLOAT, defaultValue: 0 }) + sodium_mg: number; + + @Column({ type: DataType.FLOAT, defaultValue: 100 }) + serving_size_g: number; + + @Column + serving_description: string; + + @Column({ defaultValue: 'manual' }) + source: string; + + @Column({ defaultValue: false }) + is_filipino: boolean; + + @Column({ defaultValue: false }) + is_favorite: boolean; + + @Column(DataType.TEXT) + api_data: string; + + @Column({ defaultValue: DataType.NOW }) + last_updated: Date; + + @HasMany(() => MealFood) + mealFoods: MealFood[]; + + @HasMany(() => PlannedFood) + plannedFoods: PlannedFood[]; +} diff --git a/src/models/meal-food.model.ts b/src/models/meal-food.model.ts new file mode 100644 index 0000000..d96fba7 --- /dev/null +++ b/src/models/meal-food.model.ts @@ -0,0 +1,38 @@ +import { Column, Model, Table, BelongsTo, ForeignKey, DataType } from 'sequelize-typescript'; +import { Meal } from './meal.model'; +import { FoodItem } from './food-item.model'; + +@Table +export class MealFood extends Model { + @ForeignKey(() => Meal) + @Column + MealId: number; + + @BelongsTo(() => Meal) + meal: Meal; + + @ForeignKey(() => FoodItem) + @Column + FoodItemId: number; + + @BelongsTo(() => FoodItem) + foodItem: FoodItem; + + @Column({ type: DataType.FLOAT, allowNull: false, defaultValue: 1.0 }) + quantity: number; + + @Column(DataType.FLOAT) + quantity_grams: number; + + @Column(DataType.FLOAT) + calories_consumed: number; + + @Column(DataType.FLOAT) + protein_consumed: number; + + @Column(DataType.FLOAT) + carbs_consumed: number; + + @Column(DataType.FLOAT) + fat_consumed: number; +} diff --git a/src/models/meal-plan.model.ts b/src/models/meal-plan.model.ts new file mode 100644 index 0000000..a64032f --- /dev/null +++ b/src/models/meal-plan.model.ts @@ -0,0 +1,28 @@ +import { Column, Model, Table, BelongsTo, HasMany, ForeignKey, DataType } from 'sequelize-typescript'; +import { User } from './user.model'; +import { PlannedFood } from './planned-food.model'; + +@Table +export class MealPlan extends Model { + @ForeignKey(() => User) + @Column + UserId: number; + + @BelongsTo(() => User) + user: User; + + @Column({ type: DataType.DATEONLY, allowNull: false }) + date: Date; + + @Column({ allowNull: false }) + meal_type: string; + + @Column({ defaultValue: false }) + is_completed: boolean; + + @Column(DataType.TEXT) + notes: string; + + @HasMany(() => PlannedFood) + plannedFoods: PlannedFood[]; +} diff --git a/src/models/meal.model.ts b/src/models/meal.model.ts new file mode 100644 index 0000000..f6e893e --- /dev/null +++ b/src/models/meal.model.ts @@ -0,0 +1,28 @@ +import { Column, Model, Table, BelongsTo, HasMany, ForeignKey, DataType } from 'sequelize-typescript'; +import { User } from './user.model'; +import { MealFood } from './meal-food.model'; + +@Table +export class Meal extends Model { + @ForeignKey(() => User) + @Column + UserId: number; + + @BelongsTo(() => User) + user: User; + + @Column({ type: DataType.DATEONLY, allowNull: false, defaultValue: DataType.NOW }) + date: Date; + + @Column({ allowNull: false }) + meal_type: string; + + @Column(DataType.TIME) + time: string; + + @Column(DataType.TEXT) + notes: string; + + @HasMany(() => MealFood) + mealFoods: MealFood[]; +} diff --git a/src/models/planned-food.model.ts b/src/models/planned-food.model.ts new file mode 100644 index 0000000..4a7fbf7 --- /dev/null +++ b/src/models/planned-food.model.ts @@ -0,0 +1,23 @@ +import { Column, Model, Table, BelongsTo, ForeignKey, DataType } from 'sequelize-typescript'; +import { MealPlan } from './meal-plan.model'; +import { FoodItem } from './food-item.model'; + +@Table +export class PlannedFood extends Model { + @ForeignKey(() => MealPlan) + @Column + MealPlanId: number; + + @BelongsTo(() => MealPlan) + mealPlan: MealPlan; + + @ForeignKey(() => FoodItem) + @Column + FoodItemId: number; + + @BelongsTo(() => FoodItem) + foodItem: FoodItem; + + @Column({ type: DataType.FLOAT, allowNull: false, defaultValue: 1.0 }) + quantity: number; +} diff --git a/src/models/user-goal.model.ts b/src/models/user-goal.model.ts new file mode 100644 index 0000000..de29ee1 --- /dev/null +++ b/src/models/user-goal.model.ts @@ -0,0 +1,33 @@ +import { Column, Model, Table, BelongsTo, ForeignKey, DataType } from 'sequelize-typescript'; +import { User } from './user.model'; + +@Table +export class UserGoal extends Model { + @ForeignKey(() => User) + @Column + UserId: number; + + @BelongsTo(() => User) + user: User; + + @Column({ defaultValue: 'recomp' }) + goal_type: string; + + @Column(DataType.FLOAT) + target_weight_kg: number; + + @Column({ type: DataType.FLOAT, defaultValue: 0.5 }) + weekly_goal_kg: number; + + @Column({ defaultValue: 150 }) + target_protein_g: number; + + @Column({ defaultValue: 200 }) + target_carbs_g: number; + + @Column({ defaultValue: 60 }) + target_fat_g: number; + + @Column({ defaultValue: 2000 }) + target_water_ml: number; +} diff --git a/src/models/user.model.ts b/src/models/user.model.ts new file mode 100644 index 0000000..e68afe5 --- /dev/null +++ b/src/models/user.model.ts @@ -0,0 +1,67 @@ +import { Column, DataType, Model, Table, HasMany, HasOne, BeforeCreate } from 'sequelize-typescript'; +import * as bcrypt from 'bcryptjs'; +import { Meal } from './meal.model'; +import { WeightLog } from './weight-log.model'; +import { WaterLog } from './water-log.model'; +import { MealPlan } from './meal-plan.model'; +import { UserGoal } from './user-goal.model'; +import { DailySummary } from './daily-summary.model'; + +@Table +export class User extends Model { + @Column({ type: DataType.STRING(80), unique: true, allowNull: false }) + username: string; + + @Column({ type: DataType.STRING(200), allowNull: false }) + password: string; + + @Column(DataType.STRING(100)) + name: string; + + @Column(DataType.INTEGER) + age: number; + + @Column(DataType.STRING(10)) + gender: string; + + @Column(DataType.FLOAT) + height_cm: number; + + @Column(DataType.FLOAT) + weight_kg: number; + + @Column({ type: DataType.STRING(20), defaultValue: 'moderate' }) + activity_level: string; + + @Column({ type: DataType.INTEGER, defaultValue: 2000 }) + target_daily_calories: number; + + @HasMany(() => Meal) + meals: Meal[]; + + @HasMany(() => WeightLog) + weightLogs: WeightLog[]; + + @HasMany(() => WaterLog) + waterLogs: WaterLog[]; + + @HasMany(() => MealPlan) + mealPlans: MealPlan[]; + + @HasOne(() => UserGoal) + goal: UserGoal; + + @HasMany(() => DailySummary) + dailySummaries: DailySummary[]; + + validPassword(password: string): boolean { + return bcrypt.compareSync(password, this.password); + } + + @BeforeCreate + static async hashPassword(user: User) { + if (user.password) { + user.password = await bcrypt.hash(user.password, 10); + } + } +} diff --git a/src/models/water-log.model.ts b/src/models/water-log.model.ts new file mode 100644 index 0000000..6111c0e --- /dev/null +++ b/src/models/water-log.model.ts @@ -0,0 +1,21 @@ +import { Column, Model, Table, BelongsTo, ForeignKey, DataType } from 'sequelize-typescript'; +import { User } from './user.model'; + +@Table +export class WaterLog extends Model { + @ForeignKey(() => User) + @Column + UserId: number; + + @BelongsTo(() => User) + user: User; + + @Column({ type: DataType.DATEONLY, allowNull: false, defaultValue: DataType.NOW }) + date: Date; + + @Column({ allowNull: false }) + amount_ml: number; + + @Column({ defaultValue: DataType.NOW }) + time: string; +} diff --git a/src/models/weight-log.model.ts b/src/models/weight-log.model.ts new file mode 100644 index 0000000..7da91f0 --- /dev/null +++ b/src/models/weight-log.model.ts @@ -0,0 +1,27 @@ +import { Column, Model, Table, BelongsTo, ForeignKey, DataType } from 'sequelize-typescript'; +import { User } from './user.model'; + +@Table +export class WeightLog extends Model { + @ForeignKey(() => User) + @Column + UserId: number; + + @BelongsTo(() => User) + user: User; + + @Column({ type: DataType.DATEONLY, allowNull: false, defaultValue: DataType.NOW }) + date: Date; + + @Column({ type: DataType.FLOAT, allowNull: false }) + weight_kg: number; + + @Column(DataType.FLOAT) + body_fat_percentage: number; + + @Column(DataType.TEXT) + notes: string; + + @Column({ defaultValue: DataType.NOW }) + time: string; +} diff --git a/src/users/users.module.ts b/src/users/users.module.ts new file mode 100644 index 0000000..d6189b3 --- /dev/null +++ b/src/users/users.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { User } from '../models/user.model'; +import { UsersService } from './users.service'; + +@Module({ + imports: [SequelizeModule.forFeature([User])], + providers: [UsersService], + exports: [UsersService], +}) +export class UsersModule {} diff --git a/src/users/users.service.ts b/src/users/users.service.ts new file mode 100644 index 0000000..5d8466e --- /dev/null +++ b/src/users/users.service.ts @@ -0,0 +1,23 @@ +import { Injectable } from '@nestjs/common'; +import { InjectModel } from '@nestjs/sequelize'; +import { User } from '../models/user.model'; + +@Injectable() +export class UsersService { + constructor( + @InjectModel(User) + private userModel: typeof User, + ) {} + + async findOne(username: string): Promise { + return this.userModel.findOne({ where: { username } }); + } + + async findById(id: number): Promise { + return this.userModel.findByPk(id); + } + + async create(createUserDto: any): Promise { + return this.userModel.create(createUserDto); + } +} diff --git a/src/utils/utils.module.ts b/src/utils/utils.module.ts new file mode 100644 index 0000000..d51927d --- /dev/null +++ b/src/utils/utils.module.ts @@ -0,0 +1,32 @@ +import { Module, Global } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { UtilsService } from './utils.service'; +import { User } from '../models/user.model'; +import { FoodItem } from '../models/food-item.model'; +import { Meal } from '../models/meal.model'; +import { MealFood } from '../models/meal-food.model'; +import { WaterLog } from '../models/water-log.model'; +import { WeightLog } from '../models/weight-log.model'; +import { MealPlan } from '../models/meal-plan.model'; +import { PlannedFood } from '../models/planned-food.model'; +import { DailySummary } from '../models/daily-summary.model'; + +@Global() +@Module({ + imports: [ + SequelizeModule.forFeature([ + User, + FoodItem, + Meal, + MealFood, + WaterLog, + WeightLog, + MealPlan, + PlannedFood, + DailySummary, + ]), + ], + providers: [UtilsService], + exports: [UtilsService], +}) +export class UtilsModule {} diff --git a/src/utils/utils.service.ts b/src/utils/utils.service.ts new file mode 100644 index 0000000..2b0c399 --- /dev/null +++ b/src/utils/utils.service.ts @@ -0,0 +1,414 @@ +import { Injectable } from '@nestjs/common'; +import { InjectModel } from '@nestjs/sequelize'; +import { Op } from 'sequelize'; +import { User } from '../models/user.model'; +import { FoodItem } from '../models/food-item.model'; +import { Meal } from '../models/meal.model'; +import { MealFood } from '../models/meal-food.model'; +import { WaterLog } from '../models/water-log.model'; +import { WeightLog } from '../models/weight-log.model'; +import { MealPlan } from '../models/meal-plan.model'; +import { PlannedFood } from '../models/planned-food.model'; +import { DailySummary } from '../models/daily-summary.model'; + +@Injectable() +export class UtilsService { + constructor( + @InjectModel(User) private userModel: typeof User, + @InjectModel(FoodItem) private foodItemModel: typeof FoodItem, + @InjectModel(Meal) private mealModel: typeof Meal, + @InjectModel(WaterLog) private waterLogModel: typeof WaterLog, + @InjectModel(WeightLog) private weightLogModel: typeof WeightLog, + @InjectModel(MealPlan) private mealPlanModel: typeof MealPlan, + @InjectModel(PlannedFood) private plannedFoodModel: typeof PlannedFood, + @InjectModel(DailySummary) private dailySummaryModel: typeof DailySummary, + ) {} + + calculateBMR(weightKg: number, heightCm: number, age: number, gender: string): number { + let bmr: number; + if (gender.toLowerCase() === 'male') { + bmr = 10 * weightKg + 6.25 * heightCm - 5 * age + 5; + } else { + bmr = 10 * weightKg + 6.25 * heightCm - 5 * age - 161; + } + return Math.round(bmr); + } + + calculateTDEE(bmr: number, activityLevel: string): number { + const multipliers: { [key: string]: number } = { + sedentary: 1.2, + light: 1.375, + moderate: 1.55, + active: 1.725, + very_active: 1.9, + }; + + const multiplier = multipliers[activityLevel] || 1.55; + return Math.round(bmr * multiplier); + } + + calculateMacroTargets(weightKg: number, goalType = 'recomp') { + let protein: number, carbs: number, fat: number; + + if (goalType === 'muscle_gain') { + protein = weightKg * 2.4; + carbs = weightKg * 3.5; + fat = weightKg * 1.0; + } else if (goalType === 'weight_loss') { + protein = weightKg * 2.2; + carbs = weightKg * 2.0; + fat = weightKg * 0.8; + } else { + protein = weightKg * 2.2; + carbs = weightKg * 2.5; + fat = weightKg * 0.9; + } + + return { + protein_g: Math.round(protein), + carbs_g: Math.round(carbs), + fat_g: Math.round(fat), + }; + } + + async calculateDailyTotals(userId: number, targetDate: string | Date = new Date()) { + const dateStr = targetDate instanceof Date ? targetDate.toISOString().split('T')[0] : targetDate; + + const meals = await this.mealModel.findAll({ + where: { + UserId: userId, + date: dateStr, + }, + include: [ + { + model: MealFood, + include: [FoodItem], + }, + ], + }); + + const totals = { + calories: 0, + protein: 0, + carbs: 0, + fat: 0, + meals: [], + }; + + for (const meal of meals) { + const mealTotals = { + calories: 0, + protein: 0, + carbs: 0, + fat: 0, + }; + + const mealFoods = []; + + for (const mf of meal.mealFoods) { + const quantity = mf.quantity || 1.0; + const food = mf.foodItem; + + const calories = mf.calories_consumed || food.calories * quantity; + const protein = mf.protein_consumed || food.protein_g * quantity; + const carbs = mf.carbs_consumed || food.carbs_g * quantity; + const fat = mf.fat_consumed || food.fat_g * quantity; + + mealTotals.calories += calories; + mealTotals.protein += protein; + mealTotals.carbs += carbs; + mealTotals.fat += fat; + + mealFoods.push({ + name: food.name, + quantity: quantity, + calories: calories, + }); + } + + totals.calories += mealTotals.calories; + totals.protein += mealTotals.protein; + totals.carbs += mealTotals.carbs; + totals.fat += mealTotals.fat; + + totals.meals.push({ + id: meal.id, + type: meal.meal_type, + time: meal.time ? meal.time.substring(0, 5) : null, + totals: mealTotals, + foods: mealFoods, + }); + } + + return totals; + } + + async calculateWaterTotal(userId: number, targetDate: string | Date = new Date()) { + const dateStr = targetDate instanceof Date ? targetDate.toISOString().split('T')[0] : targetDate; + + const waterLogs = await this.waterLogModel.findAll({ + where: { + UserId: userId, + date: dateStr, + }, + }); + + const total = waterLogs.reduce((sum, log) => sum + log.amount_ml, 0); + + return { + total_ml: total, + logs: waterLogs.map((log) => ({ + id: log.id, + amount_ml: log.amount_ml, + time: log.time ? log.time.substring(0, 5) : null, + })), + }; + } + + async getWeightTrend(userId: number, days = 7) { + const endDate = new Date(); + const startDate = new Date(); + startDate.setDate(endDate.getDate() - (days - 1)); + + const startDateStr = startDate.toISOString().split('T')[0]; + const endDateStr = endDate.toISOString().split('T')[0]; + + const weightLogs = await this.weightLogModel.findAll({ + where: { + UserId: userId, + date: { + [Op.between]: [startDateStr, endDateStr], + }, + }, + order: [['date', 'ASC']], + }); + + return weightLogs.map((log) => ({ + date: log.date, + weight_kg: log.weight_kg, + })); + } + + async getCalorieTrend(userId: number, days = 7) { + const endDate = new Date(); + const startDate = new Date(); + startDate.setDate(endDate.getDate() - (days - 1)); + + const trend = []; + const currentDate = new Date(startDate); + + while (currentDate <= endDate) { + const dateStr = currentDate.toISOString().split('T')[0]; + const totals = await this.calculateDailyTotals(userId, dateStr); + + trend.push({ + date: dateStr, + calories: Math.round(totals.calories), + protein: Math.round(totals.protein), + carbs: Math.round(totals.carbs), + fat: Math.round(totals.fat), + }); + + currentDate.setDate(currentDate.getDate() + 1); + } + + return trend; + } + + async updateDailySummary(userId: number, targetDate: string | Date = new Date()) { + const dateStr = targetDate instanceof Date ? targetDate.toISOString().split('T')[0] : targetDate; + + const nutrition = await this.calculateDailyTotals(userId, dateStr); + const water = await this.calculateWaterTotal(userId, dateStr); + + const weightLog = await this.weightLogModel.findOne({ + where: { + UserId: userId, + date: dateStr, + }, + }); + const weight = weightLog ? weightLog.weight_kg : null; + + const user = await this.userModel.findByPk(userId); + const targetCalories = user ? user.target_daily_calories : 2000; + + let summary = await this.dailySummaryModel.findOne({ + where: { + UserId: userId, + date: dateStr, + }, + }); + + if (!summary) { + summary = await this.dailySummaryModel.create({ + UserId: userId, + date: dateStr, + } as any); + } + + summary.total_calories = nutrition.calories; + summary.total_protein_g = nutrition.protein; + summary.total_carbs_g = nutrition.carbs; + summary.total_fat_g = nutrition.fat; + summary.total_water_ml = water.total_ml; + summary.calories_remaining = targetCalories - nutrition.calories; + summary.weight_kg = weight; + + try { + await summary.save(); + return summary; + } catch (e) { + console.error(`Error updating daily summary: ${e}`); + return null; + } + } + + getMacroPercentages(proteinG: number, carbsG: number, fatG: number) { + const proteinCal = proteinG * 4; + const carbsCal = carbsG * 4; + const fatCal = fatG * 9; + const totalCal = proteinCal + carbsCal + fatCal; + + if (totalCal === 0) { + return { protein: 0, carbs: 0, fat: 0 }; + } + + return { + protein: Math.round((proteinCal / totalCal) * 100), + carbs: Math.round((carbsCal / totalCal) * 100), + fat: Math.round((fatCal / totalCal) * 100), + }; + } + + suggestFoodsForMacros(remainingProtein: number, remainingCarbs: number, remainingFat: number) { + const suggestions = []; + + if (remainingProtein > 30) { + suggestions.push({ + category: 'High Protein Ulam', + examples: ['Grilled Tilapia', 'Chicken Tinola', 'Grilled Chicken'], + }); + } + + if (remainingCarbs > 40) { + suggestions.push({ + category: 'Carbs', + examples: ['White Rice', 'Pandesal', 'Sweet Potato'], + }); + } + + if (remainingFat > 20) { + suggestions.push({ + category: 'Healthy Fats', + examples: ['Sisig', 'Lechon Kawali', 'Bicol Express'], + }); + } + + if (remainingProtein > 20 && remainingCarbs > 30) { + suggestions.push({ + category: 'Balanced Meals', + examples: ['Tapsilog', 'Chicken Adobo with Rice', 'Sinigang'], + }); + } + + return suggestions; + } + + async generateDailyMealPlan(userId: number, dateStr: string) { + try { + const user = await this.userModel.findByPk(userId); + const targetCalories = user ? user.target_daily_calories : 2000; + + const targets = { + breakfast: Math.round(targetCalories * 0.25), + lunch: Math.round(targetCalories * 0.35), + dinner: Math.round(targetCalories * 0.3), + snack: Math.round(targetCalories * 0.1), + }; + + const foods = await this.foodItemModel.findAll(); + + const foodByCat = { + almusal: foods.filter((f) => f.category === 'almusal'), + ulam: foods.filter((f) => ['ulam', 'sabaw'].includes(f.category)), + kanin: foods.filter((f) => f.category === 'kanin'), + gulay: foods.filter((f) => f.category === 'gulay'), + meryenda: foods.filter((f) => f.category === 'meryenda'), + }; + + const allFoods = foods; + + const pickRandom = (arr: FoodItem[]) => (arr.length > 0 ? arr[Math.floor(Math.random() * arr.length)] : null); + + const generateMeal = async (mealType: string, targetCal: number) => { + let currentCal = 0; + const selectedFoods: { food: FoodItem; qty: number }[] = []; + + if (mealType === 'breakfast') { + const main = pickRandom(foodByCat.almusal) || pickRandom(allFoods); + if (main) { + selectedFoods.push({ food: main, qty: 1 }); + currentCal += main.calories; + } + } else if (['lunch', 'dinner'].includes(mealType)) { + const rice = pickRandom(foodByCat.kanin); + const ulam = pickRandom(foodByCat.ulam) || pickRandom(allFoods); + const gulay = pickRandom(foodByCat.gulay); + + if (rice) { + selectedFoods.push({ food: rice, qty: 1 }); + currentCal += rice.calories; + } + if (ulam) { + selectedFoods.push({ food: ulam, qty: 1 }); + currentCal += ulam.calories; + } + if (gulay && currentCal < targetCal) { + selectedFoods.push({ food: gulay, qty: 1 }); + currentCal += gulay.calories; + } + } else if (mealType === 'snack') { + const snack = pickRandom(foodByCat.meryenda) || pickRandom(allFoods); + if (snack) { + selectedFoods.push({ food: snack, qty: 1 }); + currentCal += snack.calories; + } + } + + if (currentCal > 0 && selectedFoods.length > 0) { + const mealPlan = await this.mealPlanModel.create({ + UserId: userId, + date: dateStr, + meal_type: mealType, + is_completed: false, + } as any); + + for (const item of selectedFoods) { + await this.plannedFoodModel.create({ + MealPlanId: mealPlan.id, + FoodItemId: item.food.id, + quantity: item.qty, + } as any); + } + } + }; + + await this.mealPlanModel.destroy({ + where: { + UserId: userId, + date: dateStr, + }, + }); + + await generateMeal('breakfast', targets.breakfast); + await generateMeal('lunch', targets.lunch); + await generateMeal('dinner', targets.dinner); + await generateMeal('snack', targets.snack); + + return true; + } catch (error) { + console.error('Error generating meal plan:', error); + throw error; + } + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..adb614c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2017", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} diff --git a/utils/api_client.js b/utils/api_client.js deleted file mode 100644 index 0a68f31..0000000 --- a/utils/api_client.js +++ /dev/null @@ -1,213 +0,0 @@ -const axios = require('axios'); -const db = require('../models'); -const { Op } = require('sequelize'); - -class NutritionAPI { - constructor(apiKey) { - this.apiKey = apiKey; - this.baseUrl = "https://api.api-ninjas.com/v1/nutrition"; - this.headers = { 'X-Api-Key': apiKey }; - this.cacheDurationDays = 30; - } - - async searchFood(query) { - // Check cache first - const cached = await this._getFromCache(query); - if (cached) { - return cached; - } - - // Make API request - try { - const response = await axios.get(this.baseUrl, { - headers: this.headers, - params: { query: query }, - timeout: 10000 - }); - - if (response.status === 200) { - const data = response.data; - - // Cache the response - await this._saveToCache(query, 'api_ninjas', data); - - // Parse and return standardized format - return this._parseApiResponse(data); - } else { - console.error(`API Error: ${response.status}`); - return []; - } - } catch (error) { - console.error(`API Request failed: ${error.message}`); - return []; - } - } - - async _getFromCache(query) { - const cacheEntry = await db.APICache.findOne({ - where: { query: query.toLowerCase() } - }); - - if (cacheEntry) { - // Check if cache is still valid (30 days) - const age = (new Date() - new Date(cacheEntry.cached_at)) / (1000 * 60 * 60 * 24); - if (age < this.cacheDurationDays) { - const data = JSON.parse(cacheEntry.response_json); - return this._parseApiResponse(data); - } - } - - return null; - } - - async _saveToCache(query, source, data) { - try { - let cacheEntry = await db.APICache.findOne({ - where: { query: query.toLowerCase() } - }); - - if (cacheEntry) { - // Update existing cache - cacheEntry.response_json = JSON.stringify(data); - cacheEntry.cached_at = new Date(); - await cacheEntry.save(); - } else { - // Create new cache entry - await db.APICache.create({ - query: query.toLowerCase(), - api_source: source, - response_json: JSON.stringify(data), - cached_at: new Date() - }); - } - } catch (error) { - console.error(`Cache save failed: ${error.message}`); - } - } - - _parseApiResponse(data) { - return data.map(item => ({ - name: (item.name || '').replace(/\b\w/g, l => l.toUpperCase()), // Title case - calories: item.calories || 0, - protein_g: item.protein_g || 0, - carbs_g: item.carbohydrates_total_g || 0, - fat_g: item.fat_total_g || 0, - fiber_g: item.fiber_g || 0, - sugar_g: item.sugar_g || 0, - sodium_mg: item.sodium_mg || 0, - serving_size_g: item.serving_size_g || 100, - source: 'api_ninjas' - })); - } - - async saveFoodToDb(foodData) { - try { - // Check if food already exists - const existing = await db.FoodItem.findOne({ - where: { - name: foodData.name, - source: foodData.source || 'api' - } - }); - - if (existing) { - return existing; - } - - // Create new food item - const food = await db.FoodItem.create({ - name: foodData.name, - calories: foodData.calories, - protein_g: foodData.protein_g || 0, - carbs_g: foodData.carbs_g || 0, - fat_g: foodData.fat_g || 0, - fiber_g: foodData.fiber_g || 0, - sugar_g: foodData.sugar_g || 0, - sodium_mg: foodData.sodium_mg || 0, - serving_size_g: foodData.serving_size_g || 100, - serving_description: foodData.serving_description || '1 serving', - source: foodData.source || 'api', - api_data: JSON.stringify(foodData) - }); - - return food; - } catch (error) { - console.error(`Error saving food to DB: ${error.message}`); - return null; - } - } -} - -async function searchAllSources(query, apiClient) { - const results = []; - - // 1. Search Filipino foods first - const filipinoFoods = await db.FoodItem.findAll({ - where: { - is_filipino: true, - [Op.or]: [ - { name: { [Op.like]: `%${query}%` } }, - { name_tagalog: { [Op.like]: `%${query}%` } } - ] - }, - limit: 5 - }); - - for (const food of filipinoFoods) { - results.push({ - id: food.id, - name: food.name, - name_tagalog: food.name_tagalog, - calories: food.calories, - protein_g: food.protein_g, - carbs_g: food.carbs_g, - fat_g: food.fat_g, - serving_description: food.serving_description, - source: 'filipino', - category: food.category - }); - } - - // 2. Search other local foods - const otherFoods = await db.FoodItem.findAll({ - where: { - is_filipino: false, - name: { [Op.like]: `%${query}%` } - }, - limit: 5 - }); - - for (const food of otherFoods) { - results.push({ - id: food.id, - name: food.name, - calories: food.calories, - protein_g: food.protein_g, - carbs_g: food.carbs_g, - fat_g: food.fat_g, - serving_description: food.serving_description, - source: food.source - }); - } - - // 3. If not enough results, search API - if (results.length < 3 && apiClient && apiClient.apiKey) { - const apiResults = await apiClient.searchFood(query); - for (const foodData of apiResults.slice(0, 5)) { - results.push({ - name: foodData.name, - calories: foodData.calories, - protein_g: foodData.protein_g, - carbs_g: foodData.carbs_g, - fat_g: foodData.fat_g, - serving_size_g: foodData.serving_size_g, - source: 'api_ninjas', - api_data: foodData - }); - } - } - - return results; -} - -module.exports = { NutritionAPI, searchAllSources }; diff --git a/utils/index.js b/utils/index.js deleted file mode 100644 index e8c1ce6..0000000 --- a/utils/index.js +++ /dev/null @@ -1,460 +0,0 @@ -const db = require('../models'); -const { Op } = require('sequelize'); - -function calculateBMR(weightKg, heightCm, age, gender) { - // Calculate Basal Metabolic Rate using Mifflin-St Jeor Equation - let bmr; - if (gender.toLowerCase() === 'male') { - bmr = (10 * weightKg) + (6.25 * heightCm) - (5 * age) + 5; - } else { - // female - bmr = (10 * weightKg) + (6.25 * heightCm) - (5 * age) - 161; - } - return Math.round(bmr); -} - -function calculateTDEE(bmr, activityLevel) { - // Calculate Total Daily Energy Expenditure - const multipliers = { - 'sedentary': 1.2, - 'light': 1.375, - 'moderate': 1.55, - 'active': 1.725, - 'very_active': 1.9 - }; - - const multiplier = multipliers[activityLevel] || 1.55; - return Math.round(bmr * multiplier); -} - -function calculateMacroTargets(weightKg, goalType = 'recomp') { - // Calculate macro targets based on body weight and goal - let protein, carbs, fat; - - if (goalType === 'muscle_gain') { - protein = weightKg * 2.4; // High protein for muscle building - carbs = weightKg * 3.5; // Higher carbs for energy - fat = weightKg * 1.0; // Moderate fat - } else if (goalType === 'weight_loss') { - protein = weightKg * 2.2; // High protein to preserve muscle - carbs = weightKg * 2.0; // Lower carbs for deficit - fat = weightKg * 0.8; // Lower fat - } else { - // recomp (body recomposition) - protein = weightKg * 2.2; // High protein - carbs = weightKg * 2.5; // Moderate carbs - fat = weightKg * 0.9; // Moderate fat - } - - return { - protein_g: Math.round(protein), - carbs_g: Math.round(carbs), - fat_g: Math.round(fat) - }; -} - -async function calculateDailyTotals(userId, targetDate = null) { - // Calculate total nutrition consumed for a given date - if (!targetDate) { - targetDate = new Date(); - } - - // Ensure date is in YYYY-MM-DD format if it's a string, or create date object - const dateStr = targetDate instanceof Date ? targetDate.toISOString().split('T')[0] : targetDate; - - // Get all meals for the date - const meals = await db.Meal.findAll({ - where: { - UserId: userId, - date: dateStr - }, - include: [{ - model: db.MealFood, - include: [db.FoodItem] - }] - }); - - const totals = { - calories: 0, - protein: 0, - carbs: 0, - fat: 0, - meals: [] - }; - - for (const meal of meals) { - const mealTotals = { - calories: 0, - protein: 0, - carbs: 0, - fat: 0 - }; - - const mealFoods = []; - - for (const mf of meal.MealFoods) { - // Calculate nutrition for this food item based on quantity - // If calculated values exist in MealFood, use them, otherwise calculate - const quantity = mf.quantity || 1.0; - const food = mf.FoodItem; - - const calories = mf.calories_consumed || (food.calories * quantity); - const protein = mf.protein_consumed || (food.protein_g * quantity); - const carbs = mf.carbs_consumed || (food.carbs_g * quantity); - const fat = mf.fat_consumed || (food.fat_g * quantity); - - mealTotals.calories += calories; - mealTotals.protein += protein; - mealTotals.carbs += carbs; - mealTotals.fat += fat; - - mealFoods.push({ - name: food.name, - quantity: quantity, - calories: calories - }); - } - - totals.calories += mealTotals.calories; - totals.protein += mealTotals.protein; - totals.carbs += mealTotals.carbs; - totals.fat += mealTotals.fat; - - totals.meals.push({ - id: meal.id, - type: meal.meal_type, - time: meal.time ? meal.time.substring(0, 5) : null, - totals: mealTotals, - foods: mealFoods - }); - } - - return totals; -} - -async function calculateWaterTotal(userId, targetDate = null) { - // Calculate total water intake for a given date - if (!targetDate) { - targetDate = new Date(); - } - - const dateStr = targetDate instanceof Date ? targetDate.toISOString().split('T')[0] : targetDate; - - const waterLogs = await db.WaterLog.findAll({ - where: { - UserId: userId, - date: dateStr - } - }); - - const total = waterLogs.reduce((sum, log) => sum + log.amount_ml, 0); - - return { - total_ml: total, - logs: waterLogs.map(log => ({ - id: log.id, - amount_ml: log.amount_ml, - time: log.time ? log.time.substring(0, 5) : null - })) - }; -} - -async function getWeightTrend(userId, days = 7) { - // Get weight trend for the past N days - const endDate = new Date(); - const startDate = new Date(); - startDate.setDate(endDate.getDate() - (days - 1)); - - const startDateStr = startDate.toISOString().split('T')[0]; - const endDateStr = endDate.toISOString().split('T')[0]; - - const weightLogs = await db.WeightLog.findAll({ - where: { - UserId: userId, - date: { - [Op.between]: [startDateStr, endDateStr] - } - }, - order: [['date', 'ASC']] - }); - - return weightLogs.map(log => ({ - date: log.date, - weight_kg: log.weight_kg - })); -} - -async function getCalorieTrend(userId, days = 7) { - // Get calorie intake trend for the past N days - const endDate = new Date(); - const startDate = new Date(); - startDate.setDate(endDate.getDate() - (days - 1)); - - const trend = []; - let currentDate = new Date(startDate); - - while (currentDate <= endDate) { - const dateStr = currentDate.toISOString().split('T')[0]; - const totals = await calculateDailyTotals(userId, dateStr); - - trend.push({ - date: dateStr, - calories: Math.round(totals.calories), - protein: Math.round(totals.protein), - carbs: Math.round(totals.carbs), - fat: Math.round(totals.fat) - }); - - currentDate.setDate(currentDate.getDate() + 1); - } - - return trend; -} - -async function updateDailySummary(userId, targetDate = null) { - // Update or create daily summary for a user - if (!targetDate) { - targetDate = new Date(); - } - - const dateStr = targetDate instanceof Date ? targetDate.toISOString().split('T')[0] : targetDate; - - // Calculate totals - const nutrition = await calculateDailyTotals(userId, dateStr); - const water = await calculateWaterTotal(userId, dateStr); - - // Get weight for the day - const weightLog = await db.WeightLog.findOne({ - where: { - UserId: userId, - date: dateStr - } - }); - const weight = weightLog ? weightLog.weight_kg : null; - - // Get user's calorie target - const user = await db.User.findByPk(userId); - const targetCalories = user ? user.target_daily_calories : 2000; - - // Find or create summary - let summary = await db.DailySummary.findOne({ - where: { - UserId: userId, - date: dateStr - } - }); - - if (!summary) { - summary = await db.DailySummary.create({ - UserId: userId, - date: dateStr - }); - } - - // Update values - summary.total_calories = nutrition.calories; - summary.total_protein_g = nutrition.protein; - summary.total_carbs_g = nutrition.carbs; - summary.total_fat_g = nutrition.fat; - summary.total_water_ml = water.total_ml; - summary.calories_remaining = targetCalories - nutrition.calories; - summary.weight_kg = weight; - - try { - await summary.save(); - return summary; - } catch (e) { - console.error(`Error updating daily summary: ${e}`); - return null; - } -} - -function getMacroPercentages(proteinG, carbsG, fatG) { - // Calculate macro distribution as percentages - const proteinCal = proteinG * 4; - const carbsCal = carbsG * 4; - const fatCal = fatG * 9; - const totalCal = proteinCal + carbsCal + fatCal; - - if (totalCal === 0) { - return { protein: 0, carbs: 0, fat: 0 }; - } - - return { - protein: Math.round((proteinCal / totalCal) * 100), - carbs: Math.round((carbsCal / totalCal) * 100), - fat: Math.round((fatCal / totalCal) * 100) - }; -} - -function suggestFoodsForMacros(remainingProtein, remainingCarbs, remainingFat) { - // Suggest Filipino foods based on remaining macros - const suggestions = []; - - // High protein needed - if (remainingProtein > 30) { - suggestions.push({ - category: 'High Protein Ulam', - examples: ['Grilled Tilapia', 'Chicken Tinola', 'Grilled Chicken'] - }); - } - - // High carbs needed - if (remainingCarbs > 40) { - suggestions.push({ - category: 'Carbs', - examples: ['White Rice', 'Pandesal', 'Sweet Potato'] - }); - } - - // High fat needed - if (remainingFat > 20) { - suggestions.push({ - category: 'Healthy Fats', - examples: ['Sisig', 'Lechon Kawali', 'Bicol Express'] - }); - } - - // Balanced meal needed - if (remainingProtein > 20 && remainingCarbs > 30) { - suggestions.push({ - category: 'Balanced Meals', - examples: ['Tapsilog', 'Chicken Adobo with Rice', 'Sinigang'] - }); - } - - return suggestions; -} - -async function generateDailyMealPlan(userId, dateStr) { - try { - // Get user's calorie target - const user = await db.User.findByPk(userId); - const targetCalories = user ? user.target_daily_calories : 2000; - - // Distribution: Breakfast 25%, Lunch 35%, Dinner 30%, Snack 10% - const targets = { - breakfast: Math.round(targetCalories * 0.25), - lunch: Math.round(targetCalories * 0.35), - dinner: Math.round(targetCalories * 0.30), - snack: Math.round(targetCalories * 0.10) - }; - - // Fetch all foods - const foods = await db.FoodItem.findAll(); - - // Categorize foods - const foodByCat = { - almusal: foods.filter(f => f.category === 'almusal'), - ulam: foods.filter(f => ['ulam', 'sabaw'].includes(f.category)), - kanin: foods.filter(f => f.category === 'kanin'), - gulay: foods.filter(f => f.category === 'gulay'), - meryenda: foods.filter(f => f.category === 'meryenda') - }; - - // Fallback if categories are empty (use all foods) - const allFoods = foods; - - // Helper to pick random item - const pickRandom = (arr) => arr.length > 0 ? arr[Math.floor(Math.random() * arr.length)] : null; - - // Helper to generate a meal - const generateMeal = async (mealType, targetCal) => { - let currentCal = 0; - const selectedFoods = []; - - // Strategy per meal type - if (mealType === 'breakfast') { - // Try almusal first - const main = pickRandom(foodByCat.almusal) || pickRandom(allFoods); - if (main) { - selectedFoods.push({ food: main, qty: 1 }); - currentCal += main.calories; - } - } else if (['lunch', 'dinner'].includes(mealType)) { - // Rice + Ulam + (maybe) Gulay - const rice = pickRandom(foodByCat.kanin); - const ulam = pickRandom(foodByCat.ulam) || pickRandom(allFoods); - const gulay = pickRandom(foodByCat.gulay); - - if (rice) { - selectedFoods.push({ food: rice, qty: 1 }); - currentCal += rice.calories; - } - if (ulam) { - selectedFoods.push({ food: ulam, qty: 1 }); - currentCal += ulam.calories; - } - // Add vegetable if we have room - if (gulay && currentCal < targetCal) { - selectedFoods.push({ food: gulay, qty: 1 }); - currentCal += gulay.calories; - } - } else if (mealType === 'snack') { - const snack = pickRandom(foodByCat.meryenda) || pickRandom(allFoods); - if (snack) { - selectedFoods.push({ food: snack, qty: 1 }); - currentCal += snack.calories; - } - } - - // Adjust quantities to closer match target (simple scaling) - if (currentCal > 0 && selectedFoods.length > 0) { - const ratio = targetCal / currentCal; - // Limit scaling to reasonable bounds (0.5x to 2.0x) to avoid weird portions - // But for simplicity, let's just create the plan as is, maybe adding another item if way under - - // Create MealPlan - const mealPlan = await db.MealPlan.create({ - UserId: userId, - date: dateStr, - meal_type: mealType, - is_completed: false - }); - - // Add foods - for (const item of selectedFoods) { - await db.PlannedFood.create({ - MealPlanId: mealPlan.id, - FoodItemId: item.food.id, - quantity: item.qty - }); - } - } - }; - - // Delete existing plans for this date? Or just append? - // Let's clear existing plans for this date to avoid duplicates if re-generating - await db.MealPlan.destroy({ - where: { - UserId: userId, - date: dateStr - } - }); - - // Generate for each meal type - await generateMeal('breakfast', targets.breakfast); - await generateMeal('lunch', targets.lunch); - await generateMeal('dinner', targets.dinner); - await generateMeal('snack', targets.snack); - - return true; - } catch (error) { - console.error('Error generating meal plan:', error); - throw error; - } -} - -module.exports = { - calculateBMR, - calculateTDEE, - calculateMacroTargets, - calculateDailyTotals, - calculateWaterTotal, - getWeightTrend, - getCalorieTrend, - updateDailySummary, - getMacroPercentages, - suggestFoodsForMacros, - generateDailyMealPlan -};