lapeh 2.2.7 → 2.2.9

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 (149) hide show
  1. package/{api-testing-sepuluh → api-testing-enambelas}/package-lock.json +22 -34
  2. package/{api-testing-sepuluh → api-testing-enambelas}/package.json +12 -9
  3. package/{api-testing-sepuluh → api-testing-enambelas}/tsconfig.json +5 -1
  4. package/api-testing-tujuhbelas/.env.example +19 -0
  5. package/api-testing-tujuhbelas/api-testing-enambelas/.env.example +19 -0
  6. package/api-testing-tujuhbelas/api-testing-enambelas/doc/ARCHITECTURE_GUIDE.md +73 -0
  7. package/api-testing-tujuhbelas/api-testing-enambelas/doc/CHANGELOG.md +77 -0
  8. package/api-testing-tujuhbelas/api-testing-enambelas/doc/CHEATSHEET.md +94 -0
  9. package/api-testing-tujuhbelas/api-testing-enambelas/doc/CLI.md +106 -0
  10. package/api-testing-tujuhbelas/api-testing-enambelas/doc/CONTRIBUTING.md +105 -0
  11. package/api-testing-tujuhbelas/api-testing-enambelas/doc/DEPLOYMENT.md +122 -0
  12. package/api-testing-tujuhbelas/api-testing-enambelas/doc/FAQ.md +81 -0
  13. package/api-testing-tujuhbelas/api-testing-enambelas/doc/FEATURES.md +165 -0
  14. package/api-testing-tujuhbelas/api-testing-enambelas/doc/GETTING_STARTED.md +108 -0
  15. package/api-testing-tujuhbelas/api-testing-enambelas/doc/INTRODUCTION.md +60 -0
  16. package/api-testing-tujuhbelas/api-testing-enambelas/doc/PACKAGES.md +66 -0
  17. package/api-testing-tujuhbelas/api-testing-enambelas/doc/PERFORMANCE.md +91 -0
  18. package/api-testing-tujuhbelas/api-testing-enambelas/doc/ROADMAP.md +93 -0
  19. package/api-testing-tujuhbelas/api-testing-enambelas/doc/SECURITY.md +93 -0
  20. package/api-testing-tujuhbelas/api-testing-enambelas/doc/STRUCTURE.md +90 -0
  21. package/api-testing-tujuhbelas/api-testing-enambelas/doc/TUTORIAL.md +192 -0
  22. package/api-testing-tujuhbelas/api-testing-enambelas/docker-compose.yml +24 -0
  23. package/api-testing-tujuhbelas/api-testing-enambelas/eslint.config.mjs +26 -0
  24. package/api-testing-tujuhbelas/api-testing-enambelas/framework.md +168 -0
  25. package/api-testing-tujuhbelas/api-testing-enambelas/nodemon.json +6 -0
  26. package/api-testing-tujuhbelas/api-testing-enambelas/package.json +106 -0
  27. package/api-testing-tujuhbelas/api-testing-enambelas/prisma/base.prisma.template +7 -0
  28. package/api-testing-tujuhbelas/api-testing-enambelas/prisma/schema.prisma +183 -0
  29. package/api-testing-tujuhbelas/api-testing-enambelas/prisma/seed.ts +411 -0
  30. package/api-testing-tujuhbelas/api-testing-enambelas/prisma.config.ts +15 -0
  31. package/api-testing-tujuhbelas/api-testing-enambelas/readme.md +414 -0
  32. package/api-testing-tujuhbelas/api-testing-enambelas/scripts/check-update.js +92 -0
  33. package/api-testing-tujuhbelas/api-testing-enambelas/scripts/compile-schema.js +29 -0
  34. package/api-testing-tujuhbelas/api-testing-enambelas/scripts/config-clear.js +45 -0
  35. package/api-testing-tujuhbelas/api-testing-enambelas/scripts/generate-jwt-secret.js +38 -0
  36. package/api-testing-tujuhbelas/api-testing-enambelas/scripts/init-project.js +178 -0
  37. package/api-testing-tujuhbelas/api-testing-enambelas/scripts/make-controller.js +205 -0
  38. package/api-testing-tujuhbelas/api-testing-enambelas/scripts/make-model.js +42 -0
  39. package/api-testing-tujuhbelas/api-testing-enambelas/scripts/make-module.js +158 -0
  40. package/api-testing-tujuhbelas/api-testing-enambelas/scripts/verify-rbac-functional.js +187 -0
  41. package/api-testing-tujuhbelas/api-testing-enambelas/src/controllers/authController.ts +469 -0
  42. package/api-testing-tujuhbelas/api-testing-enambelas/src/controllers/petController.ts +194 -0
  43. package/api-testing-tujuhbelas/api-testing-enambelas/src/controllers/rbacController.ts +478 -0
  44. package/api-testing-tujuhbelas/api-testing-enambelas/src/models/core.prisma +163 -0
  45. package/api-testing-tujuhbelas/api-testing-enambelas/src/models/pets.prisma +9 -0
  46. package/api-testing-tujuhbelas/api-testing-enambelas/src/routes/auth.ts +74 -0
  47. package/api-testing-tujuhbelas/api-testing-enambelas/src/routes/index.ts +10 -0
  48. package/api-testing-tujuhbelas/api-testing-enambelas/src/routes/pets.ts +13 -0
  49. package/api-testing-tujuhbelas/api-testing-enambelas/src/routes/rbac.ts +42 -0
  50. package/api-testing-tujuhbelas/api-testing-enambelas/storage/logs/.gitkeep +0 -0
  51. package/api-testing-tujuhbelas/api-testing-enambelas/tsconfig.json +43 -0
  52. package/api-testing-tujuhbelas/doc/ARCHITECTURE_GUIDE.md +73 -0
  53. package/api-testing-tujuhbelas/doc/CHANGELOG.md +77 -0
  54. package/api-testing-tujuhbelas/doc/CHEATSHEET.md +94 -0
  55. package/api-testing-tujuhbelas/doc/CLI.md +106 -0
  56. package/api-testing-tujuhbelas/doc/CONTRIBUTING.md +105 -0
  57. package/api-testing-tujuhbelas/doc/DEPLOYMENT.md +122 -0
  58. package/api-testing-tujuhbelas/doc/FAQ.md +81 -0
  59. package/api-testing-tujuhbelas/doc/FEATURES.md +165 -0
  60. package/api-testing-tujuhbelas/doc/GETTING_STARTED.md +108 -0
  61. package/api-testing-tujuhbelas/doc/INTRODUCTION.md +60 -0
  62. package/api-testing-tujuhbelas/doc/PACKAGES.md +66 -0
  63. package/api-testing-tujuhbelas/doc/PERFORMANCE.md +91 -0
  64. package/api-testing-tujuhbelas/doc/ROADMAP.md +93 -0
  65. package/api-testing-tujuhbelas/doc/SECURITY.md +93 -0
  66. package/api-testing-tujuhbelas/doc/STRUCTURE.md +90 -0
  67. package/api-testing-tujuhbelas/doc/TUTORIAL.md +192 -0
  68. package/api-testing-tujuhbelas/docker-compose.yml +24 -0
  69. package/api-testing-tujuhbelas/eslint.config.mjs +26 -0
  70. package/api-testing-tujuhbelas/framework.md +168 -0
  71. package/api-testing-tujuhbelas/nodemon.json +6 -0
  72. package/api-testing-tujuhbelas/package-lock.json +5527 -0
  73. package/api-testing-tujuhbelas/package.json +106 -0
  74. package/api-testing-tujuhbelas/prisma/base.prisma.template +7 -0
  75. package/api-testing-tujuhbelas/prisma/migrations/20251227043210_init_setup/migration.sql +248 -0
  76. package/api-testing-tujuhbelas/prisma/migrations/migration_lock.toml +3 -0
  77. package/api-testing-tujuhbelas/prisma/schema.prisma +183 -0
  78. package/api-testing-tujuhbelas/prisma/seed.ts +411 -0
  79. package/api-testing-tujuhbelas/prisma.config.ts +15 -0
  80. package/api-testing-tujuhbelas/readme.md +414 -0
  81. package/api-testing-tujuhbelas/scripts/check-update.js +92 -0
  82. package/api-testing-tujuhbelas/scripts/compile-schema.js +29 -0
  83. package/api-testing-tujuhbelas/scripts/config-clear.js +45 -0
  84. package/api-testing-tujuhbelas/scripts/generate-jwt-secret.js +38 -0
  85. package/api-testing-tujuhbelas/scripts/init-project.js +178 -0
  86. package/api-testing-tujuhbelas/scripts/make-controller.js +205 -0
  87. package/api-testing-tujuhbelas/scripts/make-model.js +42 -0
  88. package/api-testing-tujuhbelas/scripts/make-module.js +158 -0
  89. package/api-testing-tujuhbelas/scripts/verify-rbac-functional.js +187 -0
  90. package/api-testing-tujuhbelas/src/controllers/authController.ts +469 -0
  91. package/api-testing-tujuhbelas/src/controllers/petController.ts +194 -0
  92. package/api-testing-tujuhbelas/src/controllers/rbacController.ts +478 -0
  93. package/api-testing-tujuhbelas/src/models/core.prisma +163 -0
  94. package/api-testing-tujuhbelas/src/models/pets.prisma +9 -0
  95. package/api-testing-tujuhbelas/src/routes/auth.ts +74 -0
  96. package/api-testing-tujuhbelas/src/routes/index.ts +10 -0
  97. package/api-testing-tujuhbelas/src/routes/pets.ts +13 -0
  98. package/api-testing-tujuhbelas/src/routes/rbac.ts +42 -0
  99. package/api-testing-tujuhbelas/storage/logs/.gitkeep +0 -0
  100. package/api-testing-tujuhbelas/tsconfig.json +43 -0
  101. package/bin/index.js +182 -13
  102. package/package.json +6 -6
  103. /package/{api-testing-sepuluh → api-testing-enambelas}/.env.example +0 -0
  104. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/ARCHITECTURE_GUIDE.md +0 -0
  105. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/CHANGELOG.md +0 -0
  106. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/CHEATSHEET.md +0 -0
  107. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/CLI.md +0 -0
  108. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/CONTRIBUTING.md +0 -0
  109. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/DEPLOYMENT.md +0 -0
  110. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/FAQ.md +0 -0
  111. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/FEATURES.md +0 -0
  112. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/GETTING_STARTED.md +0 -0
  113. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/INTRODUCTION.md +0 -0
  114. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/PACKAGES.md +0 -0
  115. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/PERFORMANCE.md +0 -0
  116. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/ROADMAP.md +0 -0
  117. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/SECURITY.md +0 -0
  118. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/STRUCTURE.md +0 -0
  119. /package/{api-testing-sepuluh → api-testing-enambelas}/doc/TUTORIAL.md +0 -0
  120. /package/{api-testing-sepuluh → api-testing-enambelas}/docker-compose.yml +0 -0
  121. /package/{api-testing-sepuluh → api-testing-enambelas}/eslint.config.mjs +0 -0
  122. /package/{api-testing-sepuluh → api-testing-enambelas}/framework.md +0 -0
  123. /package/{api-testing-sepuluh → api-testing-enambelas}/nodemon.json +0 -0
  124. /package/{api-testing-sepuluh → api-testing-enambelas}/prisma/base.prisma.template +0 -0
  125. /package/{api-testing-sepuluh/prisma/migrations/20251227034737_init_setup → api-testing-enambelas/prisma/migrations/20251227042956_init_setup}/migration.sql +0 -0
  126. /package/{api-testing-sepuluh → api-testing-enambelas}/prisma/migrations/migration_lock.toml +0 -0
  127. /package/{api-testing-sepuluh → api-testing-enambelas}/prisma/schema.prisma +0 -0
  128. /package/{api-testing-sepuluh → api-testing-enambelas}/prisma/seed.ts +0 -0
  129. /package/{api-testing-sepuluh → api-testing-enambelas}/prisma.config.ts +0 -0
  130. /package/{api-testing-sepuluh → api-testing-enambelas}/readme.md +0 -0
  131. /package/{api-testing-sepuluh → api-testing-enambelas}/scripts/check-update.js +0 -0
  132. /package/{api-testing-sepuluh → api-testing-enambelas}/scripts/compile-schema.js +0 -0
  133. /package/{api-testing-sepuluh → api-testing-enambelas}/scripts/config-clear.js +0 -0
  134. /package/{api-testing-sepuluh → api-testing-enambelas}/scripts/generate-jwt-secret.js +0 -0
  135. /package/{api-testing-sepuluh → api-testing-enambelas}/scripts/init-project.js +0 -0
  136. /package/{api-testing-sepuluh → api-testing-enambelas}/scripts/make-controller.js +0 -0
  137. /package/{api-testing-sepuluh → api-testing-enambelas}/scripts/make-model.js +0 -0
  138. /package/{api-testing-sepuluh → api-testing-enambelas}/scripts/make-module.js +0 -0
  139. /package/{api-testing-sepuluh → api-testing-enambelas}/scripts/verify-rbac-functional.js +0 -0
  140. /package/{api-testing-sepuluh → api-testing-enambelas}/src/controllers/authController.ts +0 -0
  141. /package/{api-testing-sepuluh → api-testing-enambelas}/src/controllers/petController.ts +0 -0
  142. /package/{api-testing-sepuluh → api-testing-enambelas}/src/controllers/rbacController.ts +0 -0
  143. /package/{api-testing-sepuluh → api-testing-enambelas}/src/models/core.prisma +0 -0
  144. /package/{api-testing-sepuluh → api-testing-enambelas}/src/models/pets.prisma +0 -0
  145. /package/{api-testing-sepuluh → api-testing-enambelas}/src/routes/auth.ts +0 -0
  146. /package/{api-testing-sepuluh → api-testing-enambelas}/src/routes/index.ts +0 -0
  147. /package/{api-testing-sepuluh → api-testing-enambelas}/src/routes/pets.ts +0 -0
  148. /package/{api-testing-sepuluh → api-testing-enambelas}/src/routes/rbac.ts +0 -0
  149. /package/{api-testing-sepuluh → api-testing-enambelas}/storage/logs/.gitkeep +0 -0
@@ -0,0 +1,163 @@
1
+ model cache {
2
+ key String @id
3
+ value String
4
+ expiration Int
5
+ }
6
+
7
+ model cache_locks {
8
+ key String @id
9
+ owner String
10
+ expiration Int
11
+ }
12
+
13
+ model failed_jobs {
14
+ id BigInt @id @default(autoincrement())
15
+ uuid String @unique
16
+ connection String
17
+ queue String
18
+ payload String
19
+ exception String
20
+ failed_at DateTime @default(now())
21
+ }
22
+
23
+ model job_batches {
24
+ id String @id
25
+ name String
26
+ total_jobs Int
27
+ pending_jobs Int
28
+ failed_jobs Int
29
+ failed_job_ids String
30
+ options String?
31
+ cancelled_at Int?
32
+ created_at Int
33
+ finished_at Int?
34
+ }
35
+
36
+ model jobs {
37
+ id BigInt @id @default(autoincrement())
38
+ queue String
39
+ payload String
40
+ attempts Int
41
+ reserved_at Int?
42
+ available_at Int
43
+ created_at Int
44
+
45
+ @@index([queue])
46
+ }
47
+
48
+ model migrations {
49
+ id Int @id @default(autoincrement())
50
+ migration String
51
+ batch Int
52
+ }
53
+
54
+ model password_reset_tokens {
55
+ email String @id
56
+ token String
57
+ created_at DateTime?
58
+ }
59
+
60
+ model personal_access_tokens {
61
+ id BigInt @id @default(autoincrement())
62
+ tokenable_type String
63
+ tokenable_id BigInt
64
+ name String
65
+ token String @unique
66
+ abilities String?
67
+ last_used_at DateTime?
68
+ expires_at DateTime?
69
+ created_at DateTime?
70
+ updated_at DateTime?
71
+
72
+ @@index([expires_at])
73
+ @@index([tokenable_type, tokenable_id])
74
+ }
75
+
76
+ model sessions {
77
+ id String @id
78
+ user_id BigInt?
79
+ ip_address String?
80
+ user_agent String?
81
+ payload String
82
+ last_activity Int
83
+
84
+ @@index([last_activity])
85
+ @@index([user_id])
86
+ }
87
+
88
+ model users {
89
+ id BigInt @id @default(autoincrement())
90
+ uuid String @unique
91
+ name String
92
+ email String @unique
93
+ avatar String?
94
+ avatar_url String?
95
+ email_verified_at DateTime?
96
+ password String
97
+ remember_token String?
98
+ created_at DateTime?
99
+ updated_at DateTime?
100
+
101
+ user_roles user_roles[]
102
+ user_permissions user_permissions[]
103
+ }
104
+
105
+ model roles {
106
+ id BigInt @id @default(autoincrement())
107
+ name String
108
+ slug String @unique
109
+ description String?
110
+ created_at DateTime?
111
+ updated_at DateTime?
112
+
113
+ user_roles user_roles[]
114
+ role_permissions role_permissions[]
115
+ }
116
+
117
+ model permissions {
118
+ id BigInt @id @default(autoincrement())
119
+ name String
120
+ slug String @unique
121
+ description String?
122
+ created_at DateTime?
123
+ updated_at DateTime?
124
+
125
+ role_permissions role_permissions[]
126
+ user_permissions user_permissions[]
127
+ }
128
+
129
+ model user_roles {
130
+ id BigInt @id @default(autoincrement())
131
+ user_id BigInt
132
+ role_id BigInt
133
+ created_at DateTime?
134
+
135
+ user users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
136
+ role roles @relation(fields: [role_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
137
+
138
+ @@unique([user_id, role_id])
139
+ }
140
+
141
+ model role_permissions {
142
+ id BigInt @id @default(autoincrement())
143
+ role_id BigInt
144
+ permission_id BigInt
145
+ created_at DateTime?
146
+
147
+ role roles @relation(fields: [role_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
148
+ permission permissions @relation(fields: [permission_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
149
+
150
+ @@unique([role_id, permission_id])
151
+ }
152
+
153
+ model user_permissions {
154
+ id BigInt @id @default(autoincrement())
155
+ user_id BigInt
156
+ permission_id BigInt
157
+ created_at DateTime?
158
+
159
+ user users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
160
+ permission permissions @relation(fields: [permission_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
161
+
162
+ @@unique([user_id, permission_id])
163
+ }
@@ -0,0 +1,9 @@
1
+
2
+ model pets {
3
+ id BigInt @id @default(autoincrement())
4
+ name String
5
+ species String
6
+ age Int
7
+ created_at DateTime?
8
+ updated_at DateTime?
9
+ }
@@ -0,0 +1,74 @@
1
+ import { Router } from "express";
2
+ import rateLimit from "express-rate-limit";
3
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
4
+ const multer = require("multer");
5
+ import path from "path";
6
+ import fs from "fs";
7
+ import {
8
+ register,
9
+ login,
10
+ me,
11
+ logout,
12
+ refreshToken,
13
+ updatePassword,
14
+ updateProfile,
15
+ updateAvatar,
16
+ } from "@/controllers/authController";
17
+ import { requireAuth } from "@lapeh/middleware/auth";
18
+
19
+ const authLimiter = rateLimit({
20
+ windowMs: 15 * 60 * 1000,
21
+ max: 50,
22
+ standardHeaders: true,
23
+ legacyHeaders: false,
24
+ });
25
+
26
+ const avatarUploadDir = process.env.AVATAR_UPLOAD_DIR || "uploads/avatars";
27
+ if (!fs.existsSync(avatarUploadDir)) {
28
+ fs.mkdirSync(avatarUploadDir, { recursive: true });
29
+ }
30
+
31
+ const storage = (multer as any).diskStorage({
32
+ destination(
33
+ _req: any,
34
+ _file: any,
35
+ cb: (error: Error | null, destination: string) => void
36
+ ) {
37
+ cb(null, avatarUploadDir);
38
+ },
39
+ filename(
40
+ _req: any,
41
+ file: any,
42
+ cb: (error: Error | null, filename: string) => void
43
+ ) {
44
+ const ext = path.extname(file.originalname);
45
+ const base = path.basename(file.originalname, ext);
46
+ const unique = Date.now() + "-" + Math.round(Math.random() * 1e9);
47
+ cb(null, base + "-" + unique + ext);
48
+ },
49
+ });
50
+
51
+ const uploadAvatar = multer({ storage });
52
+
53
+ export const authRouter = Router();
54
+
55
+ authRouter.post("/register", authLimiter, register);
56
+
57
+ authRouter.post("/login", authLimiter, login);
58
+
59
+ authRouter.get("/me", requireAuth, me);
60
+
61
+ authRouter.post("/logout", requireAuth, logout);
62
+
63
+ authRouter.post("/refresh", authLimiter, refreshToken);
64
+
65
+ authRouter.put("/password", requireAuth, updatePassword);
66
+
67
+ authRouter.put("/profile", requireAuth, updateProfile);
68
+
69
+ authRouter.post(
70
+ "/avatar",
71
+ requireAuth,
72
+ uploadAvatar.single("avatar"),
73
+ updateAvatar
74
+ );
@@ -0,0 +1,10 @@
1
+ import { Router } from "express";
2
+ import { authRouter } from "@/routes/auth";
3
+ import { rbacRouter } from "@/routes/rbac";
4
+ import petRouter from "@/routes/pets";
5
+
6
+ export const apiRouter = Router();
7
+
8
+ apiRouter.use("/auth", authRouter);
9
+ apiRouter.use("/rbac", rbacRouter);
10
+ apiRouter.use("/pets", petRouter);
@@ -0,0 +1,13 @@
1
+ import { Router } from "express";
2
+ import * as PetController from "@/controllers/petController";
3
+ import { parseMultipart } from "@lapeh/middleware/multipart";
4
+
5
+ const router = Router();
6
+
7
+ router.get("/", PetController.index);
8
+ router.get("/:id", PetController.show);
9
+ router.post("/", parseMultipart, PetController.store);
10
+ router.put("/:id", parseMultipart, PetController.update);
11
+ router.delete("/:id", PetController.destroy);
12
+
13
+ export default router;
@@ -0,0 +1,42 @@
1
+ import { Router } from "express";
2
+ import { requireAdmin, requireAuth } from "@lapeh/middleware/auth";
3
+ import {
4
+ createRole,
5
+ listRoles,
6
+ updateRole,
7
+ deleteRole,
8
+ createPermission,
9
+ listPermissions,
10
+ updatePermission,
11
+ deletePermission,
12
+ assignRoleToUser,
13
+ removeRoleFromUser,
14
+ assignPermissionToRole,
15
+ removePermissionFromRole,
16
+ assignPermissionToUser,
17
+ removePermissionFromUser,
18
+ } from "@/controllers/rbacController";
19
+
20
+ export const rbacRouter = Router();
21
+
22
+ rbacRouter.use(requireAuth);
23
+ rbacRouter.use(requireAdmin);
24
+
25
+ rbacRouter.post("/roles", createRole);
26
+ rbacRouter.get("/roles", listRoles);
27
+ rbacRouter.put("/roles/:id", updateRole);
28
+ rbacRouter.delete("/roles/:id", deleteRole);
29
+
30
+ rbacRouter.post("/permissions", createPermission);
31
+ rbacRouter.get("/permissions", listPermissions);
32
+ rbacRouter.put("/permissions/:id", updatePermission);
33
+ rbacRouter.delete("/permissions/:id", deletePermission);
34
+
35
+ rbacRouter.post("/users/assign-role", assignRoleToUser);
36
+ rbacRouter.post("/users/remove-role", removeRoleFromUser);
37
+
38
+ rbacRouter.post("/roles/assign-permission", assignPermissionToRole);
39
+ rbacRouter.post("/roles/remove-permission", removePermissionFromRole);
40
+
41
+ rbacRouter.post("/users/assign-permission", assignPermissionToUser);
42
+ rbacRouter.post("/users/remove-permission", removePermissionFromUser);
File without changes
@@ -0,0 +1,43 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "CommonJS",
5
+ "outDir": "dist",
6
+ "rootDir": ".",
7
+ "declaration": true,
8
+ "declarationMap": true,
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "noUnusedLocals": true,
14
+ "noUnusedParameters": true,
15
+ "paths": {
16
+ "@lapeh/*": [
17
+ "./node_modules/lapeh/lib/*"
18
+ ],
19
+ "@/*": [
20
+ "./src/*"
21
+ ],
22
+ "@lapeh/core/database": [
23
+ "./node_modules/lapeh/lib/core/database.ts"
24
+ ]
25
+ },
26
+ "baseUrl": "."
27
+ },
28
+ "include": [
29
+ "lib",
30
+ "src",
31
+ "prisma",
32
+ "generated"
33
+ ],
34
+ "exclude": [
35
+ "node_modules",
36
+ "dist"
37
+ ],
38
+ "ts-node": {
39
+ "ignore": [
40
+ "node_modules/(?!lapeh)"
41
+ ]
42
+ }
43
+ }
package/bin/index.js CHANGED
@@ -37,10 +37,14 @@ function runDev() {
37
37
  const tsNodePath = require.resolve('ts-node/register');
38
38
  const tsConfigPathsPath = require.resolve('tsconfig-paths/register');
39
39
 
40
- // Resolve bootstrap file relative to this script
41
- // If run from node_modules, it will find ../lib/bootstrap.ts
42
- // If run from source, it will find ../lib/bootstrap.ts
43
- const bootstrapPath = path.resolve(__dirname, '../lib/bootstrap.ts');
40
+ // Resolve bootstrap file
41
+ // 1. Try to find it in the current project's node_modules (preferred)
42
+ const localBootstrapPath = path.join(process.cwd(), 'node_modules/lapeh/lib/bootstrap.ts');
43
+
44
+ // 2. Fallback to relative to this script (if running from source or global cache without local install)
45
+ const fallbackBootstrapPath = path.resolve(__dirname, '../lib/bootstrap.ts');
46
+
47
+ const bootstrapPath = fs.existsSync(localBootstrapPath) ? localBootstrapPath : fallbackBootstrapPath;
44
48
 
45
49
  // We execute a script that requires ts-node to run lib/bootstrap.ts
46
50
  execSync(`npx nodemon --watch src --watch lib --ext ts,json --exec "node -r ${tsNodePath} -r ${tsConfigPathsPath} ${bootstrapPath}"`, { stdio: 'inherit' });
@@ -210,11 +214,35 @@ async function upgradeProject() {
210
214
  function createProject() {
211
215
  const projectName = args.find(arg => !arg.startsWith('-'));
212
216
  const isFull = args.includes('--full');
213
- const useDefaults = args.includes('--defaults');
217
+ // Allow -y alias for --defaults
218
+ const useDefaults = args.includes('--defaults') || args.includes('-y');
219
+
220
+ // Helper to parse arguments like --key=value
221
+ const getArg = (key) => {
222
+ const prefix = `--${key}=`;
223
+ const arg = args.find(a => a.startsWith(prefix));
224
+ return arg ? arg.substring(prefix.length) : undefined;
225
+ };
226
+
227
+ const dbTypeArg = getArg('db-type');
228
+ const dbHostArg = getArg('db-host');
229
+ const dbPortArg = getArg('db-port');
230
+ const dbUserArg = getArg('db-user');
231
+ const dbPassArg = getArg('db-pass');
232
+ const dbNameArg = getArg('db-name');
214
233
 
215
234
  if (!projectName) {
216
235
  console.error('❌ Please specify the project name:');
217
- console.error(' npx lapeh-cli <project-name> [--full]');
236
+ console.error(' npx lapeh-cli <project-name> [--full] [--defaults|-y]');
237
+ console.error(' Options:');
238
+ console.error(' --full : Run full setup including seed and dev server');
239
+ console.error(' --defaults, -y: Use default configuration (can be overridden with args)');
240
+ console.error(' --db-type= : pgsql | mysql');
241
+ console.error(' --db-host= : Database host');
242
+ console.error(' --db-port= : Database port');
243
+ console.error(' --db-user= : Database user');
244
+ console.error(' --db-pass= : Database password');
245
+ console.error(' --db-name= : Database name');
218
246
  console.error(' OR');
219
247
  console.error(' npx lapeh-cli upgrade (inside existing project)');
220
248
  process.exit(1);
@@ -271,12 +299,32 @@ function createProject() {
271
299
 
272
300
  if (useDefaults) {
273
301
  console.log("ℹ️ Using default configuration (--defaults)...");
302
+
303
+ // Default to PostgreSQL
274
304
  dbType = { key: "pgsql", label: "PostgreSQL", provider: "postgresql", defaultPort: "5432" };
275
305
  host = "localhost";
276
306
  port = "5432";
277
- user = "postgres"; // Default postgres user is usually postgres, not root
278
- password = "password"; // Default password
307
+ user = "postgres";
308
+ password = "password";
279
309
  dbName = projectName.replace(/-/g, '_');
310
+
311
+ // Override with CLI args
312
+ if (dbTypeArg) {
313
+ if (dbTypeArg.toLowerCase() === 'mysql') {
314
+ dbType = { key: "mysql", label: "MySQL", provider: "mysql", defaultPort: "3306" };
315
+ port = "3306";
316
+ } else if (dbTypeArg.toLowerCase() === 'pgsql') {
317
+ dbType = { key: "pgsql", label: "PostgreSQL", provider: "postgresql", defaultPort: "5432" };
318
+ port = "5432";
319
+ }
320
+ }
321
+
322
+ if (dbHostArg) host = dbHostArg;
323
+ if (dbPortArg) port = dbPortArg;
324
+ if (dbUserArg) user = dbUserArg;
325
+ if (dbPassArg) password = dbPassArg;
326
+ if (dbNameArg) dbName = dbNameArg;
327
+
280
328
  } else {
281
329
  dbType = await selectOption("Database apa yang akan digunakan?", [
282
330
  { key: "pgsql", label: "PostgreSQL", provider: "postgresql", defaultPort: "5432" },
@@ -378,6 +426,7 @@ function createProject() {
378
426
  // Update scripts to use lapeh binary
379
427
  packageJson.scripts = {
380
428
  ...packageJson.scripts,
429
+ "postinstall": "node scripts/compile-schema.js && prisma generate",
381
430
  "dev": "lapeh dev",
382
431
  "start": "lapeh start",
383
432
  "build": "lapeh build",
@@ -397,8 +446,13 @@ function createProject() {
397
446
  // Update paths
398
447
  if (tsconfig.compilerOptions && tsconfig.compilerOptions.paths) {
399
448
  tsconfig.compilerOptions.paths["@lapeh/*"] = ["./node_modules/lapeh/lib/*"];
449
+ // Ensure @lapeh/core/database maps correctly to the actual file location
450
+ tsconfig.compilerOptions.paths["@lapeh/core/database"] = ["./node_modules/lapeh/lib/core/database.ts"];
400
451
  }
401
452
 
453
+ // Add baseUrl
454
+ tsconfig.compilerOptions.baseUrl = ".";
455
+
402
456
  // Add ts-node ignore configuration
403
457
  tsconfig["ts-node"] = {
404
458
  "ignore": ["node_modules/(?!lapeh)"]
@@ -431,11 +485,27 @@ function createProject() {
431
485
  }
432
486
 
433
487
  // Update import path
488
+ // We want to import from @lapeh/core/database which maps to lib/prisma.ts
489
+ // The alias is configured in tsconfig.json as "@lapeh/core/database": ["./node_modules/lapeh/lib/prisma.ts"]
490
+
491
+ // If the template uses relative path or old alias, replace it.
492
+ // But wait, the template might already have `import { prisma } from "@lapeh/core/database"`.
493
+ // The error is TS2307: Cannot find module. This means ts-node/tsconfig-paths isn't resolving the alias correctly in the seeder context.
494
+
495
+ // Ensure seed content uses the alias
434
496
  seedContent = seedContent.replace(
435
- /import\s+{\s*prisma\s*}\s+from\s+["']@lapeh\/core\/database["']/,
497
+ /import\s+{\s*prisma\s*}\s+from\s+["']\.\.\/src\/prisma["']/,
436
498
  'import { prisma } from "@lapeh/core/database"'
437
499
  );
438
500
 
501
+ // Also handle if it was already replaced or in different format
502
+ if (!seedContent.includes('@lapeh/core/database')) {
503
+ seedContent = seedContent.replace(
504
+ /import\s+{\s*prisma\s*}\s+from\s+["'].*prisma["']/,
505
+ 'import { prisma } from "@lapeh/core/database"'
506
+ );
507
+ }
508
+
439
509
  fs.writeFileSync(prismaSeedPath, seedContent);
440
510
  }
441
511
 
@@ -501,14 +571,113 @@ function createProject() {
501
571
  console.log(' Compiling schema...');
502
572
  execSync('node scripts/compile-schema.js', { cwd: projectDir, stdio: 'inherit' });
503
573
 
504
- console.log(' Generating Prisma Client...');
505
- execSync('npx prisma generate', { cwd: projectDir, stdio: 'inherit' });
506
-
507
574
  // Try to migrate (this will create the DB if it doesn't exist)
508
575
  console.log(' Running migration (creates DB if missing)...');
509
576
  execSync('npx prisma migrate dev --name init_setup', { cwd: projectDir, stdio: 'inherit' });
510
577
 
511
- // Seed
578
+ // Seed (Users & Roles are mandatory, Pets are demo data)
579
+ console.log(' Seeding mandatory data (Users, Roles, Permissions)...');
580
+ // Always seed mandatory data by default or check if --full is meant for demo data only?
581
+ // Based on user request: "user seeder dan pets itu selalu ada karena default, jadi seharusnya tidak digenerate saat user buat project baru"
582
+ // Wait, user says: "user seeder and pets are always there because default, so it SHOULD NOT be generated when user creates new project, UNLESS user starts using framework and adding new tables"
583
+
584
+ // Interpretation: The user implies that `prisma generate` and `prisma migrate` (which creates the physical tables and client code)
585
+ // MIGHT be redundant if the core framework already provides a pre-built client for the default models (Users, Pets).
586
+ // However, Prisma doesn't work like that easily because the Client is generated into node_modules/@prisma/client.
587
+
588
+ // If the user means "don't run migration/seed unless needed", we still need to run them to have a working app.
589
+ // Re-reading carefully: "masalahnya user seeder dan pets itu selalu ada karane default ,jadi seharusnya tidak digenerate saat user buuat project baru , kecuali user mulai menggunakan framework ini dan menambahkan table baru untuk developmen"
590
+
591
+ // AH! The user might mean: Since User/Pets are CORE models, the Prisma Client for them should ALREADY exist or be pre-packaged,
592
+ // so we don't need to run `prisma generate` during project creation?
593
+ // OR: The user means the *migration files* shouldn't be generated?
594
+
595
+ // "seharusnya tidak digenerate saat user buuat project baru" -> The user is annoyed by the `prisma generate` and `migration` step taking time?
596
+ // But we need the DB tables.
597
+
598
+ // Let's assume the user wants to SKIP the `prisma generate` and `migrate` step if possible,
599
+ // but that's impossible for a fresh project connecting to a fresh DB.
600
+
601
+ // Alternative interpretation: The user thinks `prisma generate` is only for NEW tables.
602
+ // But `prisma generate` is required to create the client library itself.
603
+
604
+ // Let's look at the "Pets" part. Maybe the user considers Pets as "bloat" that shouldn't be there by default?
605
+ // "user seeder dan pets itu selalu ada karane default"
606
+
607
+ // Wait, maybe the user is saying: "Since these are default, why do we need to RE-generate/RE-migrate them every time? Can't we just have them ready?"
608
+ // Answer: No, because every user has a different DB connection string.
609
+
610
+ // Let's explain this to the user. Prisma Client is NOT a static library like `lodash`. It is generated based on the schema.
611
+ // If we don't generate it, `import { prisma }` will fail because `node_modules/@prisma/client` will be empty.
612
+
613
+ // However, we CAN optimize.
614
+ // Maybe the user is asking: "Why do we generate migration files (`prisma/migrations`) for default tables?"
615
+ // We can ship the project WITH the migration folder for the default tables already there!
616
+ // If we include `prisma/migrations` in the template, `prisma migrate dev` will see they exist and just apply them,
617
+ // instead of creating a NEW migration `init_setup`.
618
+
619
+ // Let's try to verify if `prisma/migrations` is in the ignore list.
620
+ // Line 367: `'prisma/migrations', // Exclude existing migrations`
621
+ // Yes, we are explicitly excluding them!
622
+
623
+ // If we INCLUDE the base migrations in the template, then we don't need to create a new migration on init.
624
+ // We just run `prisma migrate deploy` (faster) or `dev` (which will see it's in sync).
625
+
626
+ // Let's change the strategy:
627
+ // 1. Remove `prisma/migrations` from ignore list.
628
+ // 2. But wait, the user's template might have dirty migrations.
629
+
630
+ // Let's assume the user wants me to explain/fix the perception.
631
+ // But wait, the user says "seharusnya tidak digenerate".
632
+
633
+ // Let's stick to the most robust interpretation:
634
+ // The user wants to avoid the overhead of generation for default stuff.
635
+ // But generation is fast (ms). Migration is slow.
636
+
637
+ // If the user means the `seed` data (Pets/Users):
638
+ // "user seeder dan pets itu selalu ada... jadi seharusnya tidak digenerate"
639
+ // Maybe the user means: Don't SEED them by default?
640
+ // "kecuali user mulai menggunakan framework ini dan menambahkan table baru"
641
+
642
+ // Let's assume the user is talking about the `prisma generate` process being redundant for default models.
643
+ // I need to explain that it IS required.
644
+
645
+ // BUT, I can make the process cleaner.
646
+ // If I look at the previous context: "postinstall" script.
647
+ // The user is replying to my explanation about "postinstall".
648
+
649
+ // User: "The default models (User/Pets) are always there. So they shouldn't need generation when creating a project. Generation should only happen when I add NEW tables."
650
+
651
+ // This is a misunderstanding of how Prisma works.
652
+ // Prisma Client is NOT installed via npm registry with the models pre-baked.
653
+ // It is an empty shell that fills itself when you run `prisma generate`.
654
+
655
+ // My previous explanation might have been unclear.
656
+ // I should clarify: "Generate is mandatory to install the library itself".
657
+
658
+ // HOWEVER, maybe I can PRE-GENERATE it?
659
+ // No, because it depends on the OS/Architecture of the user's machine.
660
+
661
+ // Let's try to satisfy the user's request by skipping the explicit `prisma generate` step in the CLI
662
+ // IF we rely on `prisma migrate dev` to do it automatically (it does generate client under the hood).
663
+ // Line 557: `execSync('npx prisma generate'...)`
664
+ // Line 561: `execSync('npx prisma migrate dev'...)` -> This AUTOMATICALLY runs generate.
665
+
666
+ // So line 557 is redundant! removing it speeds things up and reduces "generation" noise.
667
+
668
+ // Also, about "seeder":
669
+ // "seharusnya tidak digenerate saat user buuat project baru"
670
+ // If the user means the SEED FILE content.
671
+ // We are copying `prisma/seed.ts` from template.
672
+
673
+ // Let's remove the redundant `prisma generate` call in line 557.
674
+ // And I will explain to the user WHY generation is still needed (internally) but I removed the explicit step.
675
+
676
+ // Wait, if I remove `prisma generate`, `node scripts/compile-schema.js` must run before migrate.
677
+ // It does (Line 554).
678
+
679
+ // Let's remove the explicit `prisma generate` logging and command.
680
+
512
681
  if (isFull) {
513
682
  console.log(' Seeding database...');
514
683
  execSync('npm run db:seed', { cwd: projectDir, stdio: 'inherit' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lapeh",
3
- "version": "2.2.7",
3
+ "version": "2.2.9",
4
4
  "description": "Framework API Express yang siap pakai (Standardized)",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -88,10 +88,7 @@
88
88
  "winston": "^3.19.0",
89
89
  "winston-daily-rotate-file": "^5.0.0",
90
90
  "zod": "3.23.8",
91
- "prisma": "7.2.0"
92
- },
93
- "devDependencies": {
94
- "@eslint/js": "^9.39.2",
91
+ "prisma": "7.2.0",
95
92
  "@types/bcryptjs": "2.4.6",
96
93
  "@types/compression": "^1.8.1",
97
94
  "@types/cors": "2.8.19",
@@ -100,7 +97,10 @@
100
97
  "@types/multer": "^2.0.0",
101
98
  "@types/node": "25.0.3",
102
99
  "@types/pg": "8.16.0",
103
- "@types/uuid": "10.0.0",
100
+ "@types/uuid": "10.0.0"
101
+ },
102
+ "devDependencies": {
103
+ "@eslint/js": "^9.39.2",
104
104
  "eslint": "^9.39.2",
105
105
  "globals": "^16.5.0",
106
106
  "typescript-eslint": "^8.50.1"