lapeh 2.6.17 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.env.example +1 -6
  2. package/README.md +19 -85
  3. package/bin/index.js +84 -180
  4. package/dist/lib/bootstrap.d.ts.map +1 -1
  5. package/dist/lib/bootstrap.js +17 -16
  6. package/dist/lib/core/store.d.ts +55 -0
  7. package/dist/lib/core/store.d.ts.map +1 -0
  8. package/dist/lib/core/store.js +66 -0
  9. package/dist/lib/middleware/error.d.ts.map +1 -1
  10. package/dist/lib/middleware/error.js +1 -20
  11. package/dist/lib/utils/validator.d.ts.map +1 -1
  12. package/dist/lib/utils/validator.js +3 -32
  13. package/dist/src/modules/Auth/auth.controller.d.ts.map +1 -1
  14. package/dist/src/modules/Auth/auth.controller.js +118 -105
  15. package/dist/src/modules/Rbac/rbac.controller.d.ts.map +1 -1
  16. package/dist/src/modules/Rbac/rbac.controller.js +141 -140
  17. package/dist/src/routes/index.d.ts.map +1 -1
  18. package/dist/src/routes/index.js +0 -5
  19. package/doc/en/CHEATSHEET.md +3 -7
  20. package/doc/en/CLI.md +16 -41
  21. package/doc/en/DEPLOYMENT.md +171 -245
  22. package/doc/en/GETTING_STARTED.md +1 -25
  23. package/doc/en/PACKAGES.md +2 -3
  24. package/doc/en/STRUCTURE.md +1 -11
  25. package/doc/en/TUTORIAL.md +61 -119
  26. package/doc/id/CHANGELOG.md +16 -0
  27. package/doc/id/CHEATSHEET.md +0 -4
  28. package/doc/id/CLI.md +19 -54
  29. package/doc/id/DEPLOYMENT.md +171 -245
  30. package/doc/id/GETTING_STARTED.md +91 -115
  31. package/doc/id/PACKAGES.md +0 -1
  32. package/doc/id/STRUCTURE.md +1 -11
  33. package/doc/id/TUTORIAL.md +51 -109
  34. package/gitignore.template +0 -10
  35. package/lib/bootstrap.ts +39 -38
  36. package/lib/core/store.ts +116 -0
  37. package/lib/middleware/error.ts +1 -21
  38. package/lib/utils/validator.ts +3 -39
  39. package/package.json +4 -18
  40. package/scripts/init-project.js +2 -108
  41. package/scripts/make-module.js +1 -12
  42. package/scripts/seed-json.js +158 -0
  43. package/src/modules/Auth/auth.controller.ts +156 -106
  44. package/src/modules/Rbac/rbac.controller.ts +193 -138
  45. package/src/routes/index.ts +0 -3
  46. package/src/routes/rbac.ts +42 -42
  47. package/storage/logs/.0337f5062fe676994d1dc340156e089444e3d6e0-audit.json +5 -10
  48. package/storage/logs/lapeh-2025-12-30.log +1093 -0
  49. package/tsconfig.build.json +1 -3
  50. package/tsconfig.json +0 -1
  51. package/lib/core/database.ts +0 -5
  52. package/prisma/base.prisma.template +0 -8
  53. package/prisma/migrations/20251225163737_init/migration.sql +0 -236
  54. package/prisma/migrations/20251226000329_create_pets_table/migration.sql +0 -11
  55. package/prisma/migrations/20251226001249_create_pets_table/migration.sql +0 -82
  56. package/prisma/migrations/20251226001717_restore_core_models/migration.sql +0 -236
  57. package/prisma/migrations/migration_lock.toml +0 -3
  58. package/prisma/schema.prisma +0 -197
  59. package/prisma/seed.ts +0 -411
  60. package/scripts/compile-schema.js +0 -64
  61. package/src/modules/Auth/auth.prisma +0 -106
  62. package/src/modules/Pets/pets.controller.ts +0 -238
  63. package/src/modules/Pets/pets.prisma +0 -9
  64. package/src/modules/Rbac/rbac.prisma +0 -68
  65. package/src/routes/pets.ts +0 -13
  66. package/storage/logs/lapeh-2025-12-26.log +0 -88
  67. package/storage/logs/lapeh-2025-12-27.log +0 -217
@@ -0,0 +1,55 @@
1
+ export interface User {
2
+ id: string;
3
+ email: string;
4
+ name: string;
5
+ password?: string;
6
+ uuid: string;
7
+ avatar?: string | null;
8
+ avatar_url?: string | null;
9
+ email_verified_at?: string | Date | null;
10
+ created_at: string | Date;
11
+ updated_at: string | Date;
12
+ }
13
+ export interface Role {
14
+ id: string;
15
+ name: string;
16
+ slug: string;
17
+ description?: string | null;
18
+ created_at: string | Date;
19
+ updated_at: string | Date;
20
+ }
21
+ export interface Permission {
22
+ id: string;
23
+ name: string;
24
+ slug: string;
25
+ description?: string | null;
26
+ created_at: string | Date;
27
+ updated_at: string | Date;
28
+ }
29
+ export interface UserRole {
30
+ id: string;
31
+ user_id: string;
32
+ role_id: string;
33
+ created_at: string | Date;
34
+ }
35
+ export interface RolePermission {
36
+ id: string;
37
+ role_id: string;
38
+ permission_id: string;
39
+ created_at: string | Date;
40
+ }
41
+ export interface UserPermission {
42
+ id: string;
43
+ user_id: string;
44
+ permission_id: string;
45
+ created_at: string | Date;
46
+ }
47
+ export declare const users: User[];
48
+ export declare const roles: Role[];
49
+ export declare const permissions: Permission[];
50
+ export declare const user_roles: UserRole[];
51
+ export declare const role_permissions: RolePermission[];
52
+ export declare const user_permissions: UserPermission[];
53
+ export declare function saveStore(): void;
54
+ export declare const generateId: () => string;
55
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../lib/core/store.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IACzC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAyCD,eAAO,MAAM,KAAK,EAAE,IAAI,EAAe,CAAC;AACxC,eAAO,MAAM,KAAK,EAAE,IAAI,EAAe,CAAC;AACxC,eAAO,MAAM,WAAW,EAAE,UAAU,EAAqB,CAAC;AAC1D,eAAO,MAAM,UAAU,EAAE,QAAQ,EAAoB,CAAC;AACtD,eAAO,MAAM,gBAAgB,EAAE,cAAc,EAA0B,CAAC;AACxE,eAAO,MAAM,gBAAgB,EAAE,cAAc,EAA0B,CAAC;AAGxE,wBAAgB,SAAS,SAUxB;AAGD,eAAO,MAAM,UAAU,cAAgD,CAAC"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateId = exports.user_permissions = exports.role_permissions = exports.user_roles = exports.permissions = exports.roles = exports.users = void 0;
7
+ exports.saveStore = saveStore;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ // Database file path
11
+ const dbPath = path_1.default.resolve(process.cwd(), "database.json");
12
+ // Load data function
13
+ function loadData() {
14
+ if (fs_1.default.existsSync(dbPath)) {
15
+ const raw = fs_1.default.readFileSync(dbPath, "utf-8");
16
+ return JSON.parse(raw);
17
+ }
18
+ return {
19
+ users: [],
20
+ roles: [
21
+ {
22
+ id: "1",
23
+ name: "Admin",
24
+ slug: "admin",
25
+ description: "Administrator",
26
+ created_at: new Date(),
27
+ updated_at: new Date(),
28
+ },
29
+ {
30
+ id: "2",
31
+ name: "User",
32
+ slug: "user",
33
+ description: "Standard User",
34
+ created_at: new Date(),
35
+ updated_at: new Date(),
36
+ },
37
+ ],
38
+ permissions: [],
39
+ user_roles: [],
40
+ role_permissions: [],
41
+ user_permissions: [],
42
+ };
43
+ }
44
+ const data = loadData();
45
+ // Export mutable arrays
46
+ exports.users = data.users;
47
+ exports.roles = data.roles;
48
+ exports.permissions = data.permissions;
49
+ exports.user_roles = data.user_roles;
50
+ exports.role_permissions = data.role_permissions;
51
+ exports.user_permissions = data.user_permissions;
52
+ // Helper to save data
53
+ function saveStore() {
54
+ const payload = {
55
+ users: exports.users,
56
+ roles: exports.roles,
57
+ permissions: exports.permissions,
58
+ user_roles: exports.user_roles,
59
+ role_permissions: exports.role_permissions,
60
+ user_permissions: exports.user_permissions,
61
+ };
62
+ fs_1.default.writeFileSync(dbPath, JSON.stringify(payload, null, 2), "utf-8");
63
+ }
64
+ // Helper to generate IDs
65
+ const generateId = () => Math.random().toString(36).substr(2, 9);
66
+ exports.generateId = generateId;
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../lib/middleware/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAM1D,wBAAgB,YAAY,CAC1B,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,YAAY,sCA2DpB"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../lib/middleware/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK1D,wBAAgB,YAAY,CAC1B,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,YAAY,sCAwCpB"}
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.errorHandler = errorHandler;
4
4
  const zod_1 = require("zod");
5
- const client_1 = require("@prisma/client");
6
5
  const response_1 = require("../utils/response");
7
6
  const logger_1 = require("../utils/logger");
8
7
  function errorHandler(err, req, res, _next) {
@@ -14,25 +13,7 @@ function errorHandler(err, req, res, _next) {
14
13
  }));
15
14
  return (0, response_1.sendError)(res, 400, "Validation Error", formattedErrors);
16
15
  }
17
- // 2. Prisma Errors
18
- if (err instanceof client_1.Prisma.PrismaClientKnownRequestError) {
19
- // P2002: Unique constraint failed
20
- if (err.code === "P2002") {
21
- const target = err.meta?.target || [];
22
- const fields = target.length > 0 ? target.join(", ") : "field";
23
- return (0, response_1.sendError)(res, 409, `Unique constraint failed on: ${fields}`);
24
- }
25
- // P2003: Foreign key constraint failed
26
- if (err.code === "P2003") {
27
- const field = err.meta?.field_name || "unknown field";
28
- return (0, response_1.sendError)(res, 400, `Foreign key constraint failed on: ${field}`);
29
- }
30
- // P2025: Record not found
31
- if (err.code === "P2025") {
32
- return (0, response_1.sendError)(res, 404, "Record not found");
33
- }
34
- }
35
- // 3. JWT Errors
16
+ // 2. JWT Errors
36
17
  if (err.name === "JsonWebTokenError") {
37
18
  return (0, response_1.sendError)(res, 401, "Invalid token");
38
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../lib/utils/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,SAAS,EAAsB,MAAM,KAAK,CAAC;AAGvD,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAkB;gBAG9B,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5C,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAavC;;;;;OAKG;IACH,MAAM,CAAC,IAAI,CACT,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5C,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAiDvC,OAAO,CAAC,MAAM,CAAC,eAAe;IAyN9B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAK/B;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAIhC;;OAEG;IACH,MAAM;IAKN;;OAEG;IACG,SAAS;YAUD,GAAG;IAgBjB,OAAO,CAAC,YAAY;IAuBpB,OAAO,CAAC,gBAAgB;CAoDzB"}
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../lib/utils/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,SAAS,EAAsB,MAAM,KAAK,CAAC;AAEvD,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAkB;gBAG9B,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5C,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAavC;;;;;OAKG;IACH,MAAM,CAAC,IAAI,CACT,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5C,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAiDvC,OAAO,CAAC,MAAM,CAAC,eAAe;IAsL9B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAK/B;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAIhC;;OAEG;IACH,MAAM;IAKN;;OAEG;IACG,SAAS;YAUD,GAAG;IAgBjB,OAAO,CAAC,YAAY;IAuBpB,OAAO,CAAC,gBAAgB;CAoDzB"}
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Validator = void 0;
4
4
  const zod_1 = require("zod");
5
- const database_1 = require("../core/database");
6
5
  class Validator {
7
6
  constructor(data, schema, messages = {}) {
8
7
  this.result = null;
@@ -205,37 +204,9 @@ class Validator {
205
204
  break;
206
205
  case "unique":
207
206
  // unique:table,column,ignore,idColumn
208
- const [table, column = "id", ignoreValue, ignoreColumn = "id"] = params;
209
- schema = schema.refine(async (val) => {
210
- if (!val)
211
- return true;
212
- const where = { [column]: val };
213
- if (ignoreValue && ignoreValue !== "null") {
214
- // Try to handle numeric IDs if ignoreValue looks numeric
215
- const ignoreVal = !isNaN(Number(ignoreValue))
216
- ? Number(ignoreValue)
217
- : ignoreValue;
218
- // But Prisma uses BigInt for IDs often in this project?
219
- // Let's assume string or number is fine, user can cast if needed.
220
- // In this project, IDs are BigInt.
221
- if (typeof ignoreVal === "number" ||
222
- /^\d+$/.test(String(ignoreValue))) {
223
- where[ignoreColumn] = { not: BigInt(ignoreValue) };
224
- }
225
- else {
226
- where[ignoreColumn] = { not: ignoreValue };
227
- }
228
- }
229
- try {
230
- // @ts-ignore
231
- const count = await database_1.prisma[table].count({ where });
232
- return count === 0;
233
- }
234
- catch (e) {
235
- console.error(`Validator unique check failed for table ${table}:`, e);
236
- return false;
237
- }
238
- }, { message: `The ${column} has already been taken.` });
207
+ // NOTE: Unique check requires Database implementation.
208
+ // Since v3.0.0 (No-ORM), this rule is disabled by default.
209
+ // You should implement your own uniqueness check manually in the controller.
239
210
  break;
240
211
  }
241
212
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../../../src/modules/Auth/auth.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAS5C,eAAO,MAAM,+BAA+B,QAAmB,CAAC;AA4EhE,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAiDzD;AAED,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA4EtD;AAED,wBAAsB,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAiCnD;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBASxD;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAmE7D;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAuD7D;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA4C/D;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAoC9D"}
1
+ {"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../../../src/modules/Auth/auth.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAU5C,eAAO,MAAM,+BAA+B,QAAmB,CAAC;AA4EhE,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA0DzD;AAED,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA6EtD;AAED,wBAAsB,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAuDnD;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBASxD;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAoE7D;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAwD7D;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA6C/D;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAkD9D"}
@@ -15,10 +15,11 @@ exports.updateProfile = updateProfile;
15
15
  const bcryptjs_1 = __importDefault(require("bcryptjs"));
16
16
  const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
17
17
  const uuid_1 = require("uuid");
18
- const database_1 = require("../../../lib/core/database");
19
18
  const response_1 = require("../../../lib/utils/response");
20
19
  const validator_1 = require("../../../lib/utils/validator");
21
20
  const serializer_1 = require("../../../lib/core/serializer");
21
+ const store_1 = require("../../../lib/core/store");
22
+ const redis_1 = require("../../../lib/core/redis");
22
23
  exports.ACCESS_TOKEN_EXPIRES_IN_SECONDS = 7 * 24 * 60 * 60;
23
24
  // --- Serializers ---
24
25
  const registerSchema = {
@@ -83,37 +84,43 @@ async function register(req, res) {
83
84
  return;
84
85
  }
85
86
  const { email, name, password } = await validator.validated();
86
- // Manual unique check removed as it is handled by validator
87
+ // Manual unique check (In-Memory)
88
+ if (store_1.users.find((u) => u.email === email)) {
89
+ (0, response_1.sendError)(res, 422, "Validation error", { email: "Email already taken" });
90
+ return;
91
+ }
87
92
  const hash = await bcryptjs_1.default.hash(password, 10);
88
- const user = await database_1.prisma.users.create({
89
- data: {
90
- email,
91
- name,
92
- password: hash,
93
- uuid: (0, uuid_1.v4)(),
94
- created_at: new Date(),
95
- updated_at: new Date(),
96
- },
97
- });
98
- const defaultRole = await database_1.prisma.roles.findUnique({
99
- where: { slug: "user" },
100
- });
93
+ const newUser = {
94
+ id: (store_1.users.length + 1).toString(), // Simple ID generation
95
+ email,
96
+ name,
97
+ password: hash,
98
+ uuid: (0, uuid_1.v4)(),
99
+ created_at: new Date(),
100
+ updated_at: new Date(),
101
+ avatar: null,
102
+ avatar_url: null,
103
+ email_verified_at: null,
104
+ remember_token: null,
105
+ };
106
+ store_1.users.push(newUser);
107
+ const defaultRole = store_1.roles.find((r) => r.slug === "user");
101
108
  if (defaultRole) {
102
- await database_1.prisma.user_roles.create({
103
- data: {
104
- user_id: user.id,
105
- role_id: defaultRole.id,
106
- created_at: new Date(),
107
- },
109
+ store_1.user_roles.push({
110
+ id: (store_1.user_roles.length + 1).toString(),
111
+ user_id: newUser.id,
112
+ role_id: defaultRole.id,
113
+ created_at: new Date(),
108
114
  });
109
115
  }
116
+ (0, store_1.saveStore)();
110
117
  (0, response_1.sendFastSuccess)(res, 201, registerSerializer, {
111
118
  status: "success",
112
- message: "Registration successful",
119
+ message: "Registration successful. You can now login.",
113
120
  data: {
114
- id: user.id.toString(),
115
- email: user.email,
116
- name: user.name,
121
+ id: newUser.id.toString(),
122
+ email: newUser.email,
123
+ name: newUser.name,
117
124
  role: defaultRole ? defaultRole.slug : "user",
118
125
  },
119
126
  });
@@ -128,16 +135,7 @@ async function login(req, res) {
128
135
  return;
129
136
  }
130
137
  const { email, password } = await validator.validated();
131
- const user = await database_1.prisma.users.findUnique({
132
- where: { email },
133
- include: {
134
- user_roles: {
135
- include: {
136
- role: true,
137
- },
138
- },
139
- },
140
- });
138
+ const user = store_1.users.find((u) => u.email === email);
141
139
  if (!user) {
142
140
  (0, response_1.sendError)(res, 401, "Email not registered", {
143
141
  field: "email",
@@ -145,7 +143,7 @@ async function login(req, res) {
145
143
  });
146
144
  return;
147
145
  }
148
- const ok = await bcryptjs_1.default.compare(password, user.password);
146
+ const ok = await bcryptjs_1.default.compare(password, user.password || "");
149
147
  if (!ok) {
150
148
  (0, response_1.sendError)(res, 401, "Invalid credentials", {
151
149
  field: "password",
@@ -158,8 +156,13 @@ async function login(req, res) {
158
156
  (0, response_1.sendError)(res, 500, "Server misconfigured");
159
157
  return;
160
158
  }
161
- const primaryUserRole = user.user_roles && user.user_roles.length > 0 && user.user_roles[0].role
162
- ? user.user_roles[0].role.slug
159
+ // Find user roles
160
+ const userRoleLinks = store_1.user_roles.filter((ur) => ur.user_id === user.id);
161
+ const userRoleObjects = userRoleLinks
162
+ .map((ur) => store_1.roles.find((r) => r.id === ur.role_id))
163
+ .filter((r) => r);
164
+ const primaryUserRole = userRoleObjects.length > 0 && userRoleObjects[0]
165
+ ? userRoleObjects[0].slug
163
166
  : "user";
164
167
  const accessExpiresInSeconds = exports.ACCESS_TOKEN_EXPIRES_IN_SECONDS;
165
168
  const accessExpiresAt = new Date(Date.now() + accessExpiresInSeconds * 1000).toISOString();
@@ -189,31 +192,40 @@ async function me(req, res) {
189
192
  (0, response_1.sendError)(res, 401, "Unauthorized");
190
193
  return;
191
194
  }
192
- const user = await database_1.prisma.users.findUnique({
193
- where: { id: payload.userId },
194
- include: {
195
- user_roles: {
196
- include: {
197
- role: true,
198
- },
199
- },
200
- },
201
- });
195
+ // Try to get from Redis
196
+ const cachedUser = await redis_1.redis.get(`user:${payload.userId}`);
197
+ if (cachedUser) {
198
+ const user = JSON.parse(cachedUser);
199
+ (0, response_1.sendFastSuccess)(res, 200, userProfileSerializer, {
200
+ status: "success",
201
+ message: "User profile (cached)",
202
+ data: user,
203
+ });
204
+ return;
205
+ }
206
+ const user = store_1.users.find((u) => u.id === payload.userId);
202
207
  if (!user) {
203
208
  (0, response_1.sendError)(res, 404, "User not found");
204
209
  return;
205
210
  }
206
- const { password, remember_token, ...rest } = user;
211
+ // Find user roles
212
+ const userRoleLinks = store_1.user_roles.filter((ur) => ur.user_id === user.id);
213
+ const userRoleObjects = userRoleLinks
214
+ .map((ur) => store_1.roles.find((r) => r.id === ur.role_id))
215
+ .filter((r) => r);
216
+ const primaryRoleSlug = userRoleObjects.length > 0 ? userRoleObjects[0]?.slug : "user";
217
+ const { password, ...rest } = user;
218
+ const userData = {
219
+ ...rest,
220
+ id: user.id.toString(),
221
+ role: primaryRoleSlug,
222
+ };
223
+ // Cache in Redis for 1 hour
224
+ await redis_1.redis.set(`user:${payload.userId}`, JSON.stringify(userData), "EX", 3600);
207
225
  (0, response_1.sendFastSuccess)(res, 200, userProfileSerializer, {
208
226
  status: "success",
209
227
  message: "User profile",
210
- data: {
211
- ...rest,
212
- id: user.id.toString(),
213
- role: user.user_roles && user.user_roles.length > 0 && user.user_roles[0].role
214
- ? user.user_roles[0].role.slug
215
- : "user",
216
- },
228
+ data: userData,
217
229
  });
218
230
  }
219
231
  async function logout(_req, res) {
@@ -246,22 +258,18 @@ async function refreshToken(req, res) {
246
258
  (0, response_1.sendError)(res, 401, "Invalid refresh token");
247
259
  return;
248
260
  }
249
- const user = await database_1.prisma.users.findUnique({
250
- where: { id: decoded.userId },
251
- include: {
252
- user_roles: {
253
- include: {
254
- role: true,
255
- },
256
- },
257
- },
258
- });
261
+ const user = store_1.users.find((u) => u.id === decoded.userId);
259
262
  if (!user) {
260
263
  (0, response_1.sendError)(res, 401, "Invalid refresh token");
261
264
  return;
262
265
  }
263
- const primaryUserRole = user.user_roles && user.user_roles.length > 0 && user.user_roles[0].role
264
- ? user.user_roles[0].role.slug
266
+ // Find user roles
267
+ const userRoleLinks = store_1.user_roles.filter((ur) => ur.user_id === user.id);
268
+ const userRoleObjects = userRoleLinks
269
+ .map((ur) => store_1.roles.find((r) => r.id === ur.role_id))
270
+ .filter((r) => r);
271
+ const primaryUserRole = userRoleObjects.length > 0 && userRoleObjects[0]
272
+ ? userRoleObjects[0].slug
265
273
  : "user";
266
274
  const accessExpiresInSeconds = exports.ACCESS_TOKEN_EXPIRES_IN_SECONDS;
267
275
  const accessExpiresAt = new Date(Date.now() + accessExpiresInSeconds * 1000).toISOString();
@@ -306,21 +314,19 @@ async function updateAvatar(req, res) {
306
314
  const userId = payload.userId;
307
315
  const avatar = file.filename;
308
316
  const avatar_url = process.env.AVATAR_BASE_URL || `/uploads/avatars/${file.filename}`;
309
- const updated = await database_1.prisma.users.update({
310
- where: { id: userId },
311
- data: {
312
- avatar,
313
- avatar_url,
314
- updated_at: new Date(),
315
- },
316
- });
317
- const { password, remember_token, ...rest } = updated;
318
- // Note: user_roles might not be fetched in update, so role defaults to "user" or fetched if needed.
319
- // Ideally we should refetch or pass existing role.
320
- // For now assuming role is preserved or handled by frontend state, but API should return it.
321
- // Let's rely on nullable role or simple "user" fallback if not present in `updated`.
322
- // Actually `update` returns what was updated. Relations are not included unless specified.
323
- // For now we will return it compatible with userProfileSchema.
317
+ const userIndex = store_1.users.findIndex((u) => u.id === userId);
318
+ if (userIndex === -1) {
319
+ (0, response_1.sendError)(res, 404, "User not found");
320
+ return;
321
+ }
322
+ store_1.users[userIndex] = {
323
+ ...store_1.users[userIndex],
324
+ avatar,
325
+ avatar_url,
326
+ updated_at: new Date(),
327
+ };
328
+ const updated = store_1.users[userIndex];
329
+ const { password, ...rest } = updated;
324
330
  (0, response_1.sendFastSuccess)(res, 200, userProfileSerializer, {
325
331
  status: "success",
326
332
  message: "Avatar updated successfully",
@@ -347,14 +353,13 @@ async function updatePassword(req, res) {
347
353
  return;
348
354
  }
349
355
  const { currentPassword, newPassword } = await validator.validated();
350
- const user = await database_1.prisma.users.findUnique({
351
- where: { id: payload.userId },
352
- });
353
- if (!user) {
356
+ const userIndex = store_1.users.findIndex((u) => u.id === payload.userId);
357
+ if (userIndex === -1) {
354
358
  (0, response_1.sendError)(res, 404, "User not found");
355
359
  return;
356
360
  }
357
- const ok = await bcryptjs_1.default.compare(currentPassword, user.password);
361
+ const user = store_1.users[userIndex];
362
+ const ok = await bcryptjs_1.default.compare(currentPassword, user.password || "");
358
363
  if (!ok) {
359
364
  (0, response_1.sendError)(res, 401, "Invalid credentials", {
360
365
  field: "currentPassword",
@@ -363,13 +368,11 @@ async function updatePassword(req, res) {
363
368
  return;
364
369
  }
365
370
  const hash = await bcryptjs_1.default.hash(newPassword, 10);
366
- await database_1.prisma.users.update({
367
- where: { id: user.id },
368
- data: {
369
- password: hash,
370
- updated_at: new Date(),
371
- },
372
- });
371
+ store_1.users[userIndex] = {
372
+ ...user,
373
+ password: hash,
374
+ updated_at: new Date(),
375
+ };
373
376
  (0, response_1.sendFastSuccess)(res, 200, voidSerializer, {
374
377
  status: "success",
375
378
  message: "Password updated successfully",
@@ -392,16 +395,26 @@ async function updateProfile(req, res) {
392
395
  }
393
396
  const { name, email } = await validator.validated();
394
397
  const userId = payload.userId;
395
- // Manual unique check removed as it is handled by validator
396
- const updated = await database_1.prisma.users.update({
397
- where: { id: userId },
398
- data: {
399
- name,
400
- email,
401
- updated_at: new Date(),
402
- },
403
- });
404
- const { password, remember_token, ...rest } = updated;
398
+ // Manual unique check (In-Memory)
399
+ if (store_1.users.find((u) => u.email === email && u.id !== userId)) {
400
+ (0, response_1.sendError)(res, 422, "Validation error", { email: "Email already taken" });
401
+ return;
402
+ }
403
+ const userIndex = store_1.users.findIndex((u) => u.id === userId);
404
+ if (userIndex === -1) {
405
+ (0, response_1.sendError)(res, 404, "User not found");
406
+ return;
407
+ }
408
+ store_1.users[userIndex] = {
409
+ ...store_1.users[userIndex],
410
+ name,
411
+ email,
412
+ updated_at: new Date(),
413
+ };
414
+ (0, store_1.saveStore)();
415
+ await redis_1.redis.del(`user:${userId}`);
416
+ const updated = store_1.users[userIndex];
417
+ const { password, ...rest } = updated;
405
418
  (0, response_1.sendFastSuccess)(res, 200, userProfileSerializer, {
406
419
  status: "success",
407
420
  message: "Profile updated successfully",
@@ -1 +1 @@
1
- {"version":3,"file":"rbac.controller.d.ts","sourceRoot":"","sources":["../../../../src/modules/Rbac/rbac.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAuD5C,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA6B3D;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAU3D;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAoC3D;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAgB3D;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA4BjE;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAajE;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAsCjE;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAsBjE;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA6CjE;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAuBnE;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA6CvE;AAED,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAuBzE;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA6CvE;AAED,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAuBzE"}
1
+ {"version":3,"file":"rbac.controller.d.ts","sourceRoot":"","sources":["../../../../src/modules/Rbac/rbac.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAkE5C,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAoC3D;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAO3D;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA+C3D;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA+B3D;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAmCjE;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAUjE;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA+CjE;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA+BjE;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAyCjE;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAuBnE;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAyCvE;AAED,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBA0BzE;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAwCvE;AAED,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAyBzE"}