lapeh 2.2.8 → 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.
- package/api-testing-enambelas/.env.example +19 -0
- package/api-testing-enambelas/doc/ARCHITECTURE_GUIDE.md +73 -0
- package/api-testing-enambelas/doc/CHANGELOG.md +77 -0
- package/api-testing-enambelas/doc/CHEATSHEET.md +94 -0
- package/api-testing-enambelas/doc/CLI.md +106 -0
- package/api-testing-enambelas/doc/CONTRIBUTING.md +105 -0
- package/api-testing-enambelas/doc/DEPLOYMENT.md +122 -0
- package/api-testing-enambelas/doc/FAQ.md +81 -0
- package/api-testing-enambelas/doc/FEATURES.md +165 -0
- package/api-testing-enambelas/doc/GETTING_STARTED.md +108 -0
- package/api-testing-enambelas/doc/INTRODUCTION.md +60 -0
- package/api-testing-enambelas/doc/PACKAGES.md +66 -0
- package/api-testing-enambelas/doc/PERFORMANCE.md +91 -0
- package/api-testing-enambelas/doc/ROADMAP.md +93 -0
- package/api-testing-enambelas/doc/SECURITY.md +93 -0
- package/api-testing-enambelas/doc/STRUCTURE.md +90 -0
- package/api-testing-enambelas/doc/TUTORIAL.md +192 -0
- package/api-testing-enambelas/docker-compose.yml +24 -0
- package/api-testing-enambelas/eslint.config.mjs +26 -0
- package/api-testing-enambelas/framework.md +168 -0
- package/api-testing-enambelas/nodemon.json +6 -0
- package/api-testing-enambelas/package-lock.json +5527 -0
- package/api-testing-enambelas/package.json +106 -0
- package/api-testing-enambelas/prisma/base.prisma.template +7 -0
- package/api-testing-enambelas/prisma/migrations/20251227042956_init_setup/migration.sql +248 -0
- package/api-testing-enambelas/prisma/migrations/migration_lock.toml +3 -0
- package/api-testing-enambelas/prisma/schema.prisma +183 -0
- package/api-testing-enambelas/prisma/seed.ts +411 -0
- package/api-testing-enambelas/prisma.config.ts +15 -0
- package/api-testing-enambelas/readme.md +414 -0
- package/api-testing-enambelas/scripts/check-update.js +92 -0
- package/api-testing-enambelas/scripts/compile-schema.js +29 -0
- package/api-testing-enambelas/scripts/config-clear.js +45 -0
- package/api-testing-enambelas/scripts/generate-jwt-secret.js +38 -0
- package/api-testing-enambelas/scripts/init-project.js +178 -0
- package/api-testing-enambelas/scripts/make-controller.js +205 -0
- package/api-testing-enambelas/scripts/make-model.js +42 -0
- package/api-testing-enambelas/scripts/make-module.js +158 -0
- package/api-testing-enambelas/scripts/verify-rbac-functional.js +187 -0
- package/api-testing-enambelas/src/controllers/authController.ts +469 -0
- package/api-testing-enambelas/src/controllers/petController.ts +194 -0
- package/api-testing-enambelas/src/controllers/rbacController.ts +478 -0
- package/api-testing-enambelas/src/models/core.prisma +163 -0
- package/api-testing-enambelas/src/models/pets.prisma +9 -0
- package/api-testing-enambelas/src/routes/auth.ts +74 -0
- package/api-testing-enambelas/src/routes/index.ts +10 -0
- package/api-testing-enambelas/src/routes/pets.ts +13 -0
- package/api-testing-enambelas/src/routes/rbac.ts +42 -0
- package/api-testing-enambelas/storage/logs/.gitkeep +0 -0
- package/api-testing-enambelas/tsconfig.json +43 -0
- package/api-testing-tujuhbelas/.env.example +19 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/.env.example +19 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/ARCHITECTURE_GUIDE.md +73 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/CHANGELOG.md +77 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/CHEATSHEET.md +94 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/CLI.md +106 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/CONTRIBUTING.md +105 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/DEPLOYMENT.md +122 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/FAQ.md +81 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/FEATURES.md +165 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/GETTING_STARTED.md +108 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/INTRODUCTION.md +60 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/PACKAGES.md +66 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/PERFORMANCE.md +91 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/ROADMAP.md +93 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/SECURITY.md +93 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/STRUCTURE.md +90 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/doc/TUTORIAL.md +192 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/docker-compose.yml +24 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/eslint.config.mjs +26 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/framework.md +168 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/nodemon.json +6 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/package.json +106 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/prisma/base.prisma.template +7 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/prisma/schema.prisma +183 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/prisma/seed.ts +411 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/prisma.config.ts +15 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/readme.md +414 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/scripts/check-update.js +92 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/scripts/compile-schema.js +29 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/scripts/config-clear.js +45 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/scripts/generate-jwt-secret.js +38 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/scripts/init-project.js +178 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/scripts/make-controller.js +205 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/scripts/make-model.js +42 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/scripts/make-module.js +158 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/scripts/verify-rbac-functional.js +187 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/src/controllers/authController.ts +469 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/src/controllers/petController.ts +194 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/src/controllers/rbacController.ts +478 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/src/models/core.prisma +163 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/src/models/pets.prisma +9 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/src/routes/auth.ts +74 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/src/routes/index.ts +10 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/src/routes/pets.ts +13 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/src/routes/rbac.ts +42 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/storage/logs/.gitkeep +0 -0
- package/api-testing-tujuhbelas/api-testing-enambelas/tsconfig.json +43 -0
- package/api-testing-tujuhbelas/doc/ARCHITECTURE_GUIDE.md +73 -0
- package/api-testing-tujuhbelas/doc/CHANGELOG.md +77 -0
- package/api-testing-tujuhbelas/doc/CHEATSHEET.md +94 -0
- package/api-testing-tujuhbelas/doc/CLI.md +106 -0
- package/api-testing-tujuhbelas/doc/CONTRIBUTING.md +105 -0
- package/api-testing-tujuhbelas/doc/DEPLOYMENT.md +122 -0
- package/api-testing-tujuhbelas/doc/FAQ.md +81 -0
- package/api-testing-tujuhbelas/doc/FEATURES.md +165 -0
- package/api-testing-tujuhbelas/doc/GETTING_STARTED.md +108 -0
- package/api-testing-tujuhbelas/doc/INTRODUCTION.md +60 -0
- package/api-testing-tujuhbelas/doc/PACKAGES.md +66 -0
- package/api-testing-tujuhbelas/doc/PERFORMANCE.md +91 -0
- package/api-testing-tujuhbelas/doc/ROADMAP.md +93 -0
- package/api-testing-tujuhbelas/doc/SECURITY.md +93 -0
- package/api-testing-tujuhbelas/doc/STRUCTURE.md +90 -0
- package/api-testing-tujuhbelas/doc/TUTORIAL.md +192 -0
- package/api-testing-tujuhbelas/docker-compose.yml +24 -0
- package/api-testing-tujuhbelas/eslint.config.mjs +26 -0
- package/api-testing-tujuhbelas/framework.md +168 -0
- package/api-testing-tujuhbelas/nodemon.json +6 -0
- package/api-testing-tujuhbelas/package-lock.json +5527 -0
- package/api-testing-tujuhbelas/package.json +106 -0
- package/api-testing-tujuhbelas/prisma/base.prisma.template +7 -0
- package/api-testing-tujuhbelas/prisma/migrations/20251227043210_init_setup/migration.sql +248 -0
- package/api-testing-tujuhbelas/prisma/migrations/migration_lock.toml +3 -0
- package/api-testing-tujuhbelas/prisma/schema.prisma +183 -0
- package/api-testing-tujuhbelas/prisma/seed.ts +411 -0
- package/api-testing-tujuhbelas/prisma.config.ts +15 -0
- package/api-testing-tujuhbelas/readme.md +414 -0
- package/api-testing-tujuhbelas/scripts/check-update.js +92 -0
- package/api-testing-tujuhbelas/scripts/compile-schema.js +29 -0
- package/api-testing-tujuhbelas/scripts/config-clear.js +45 -0
- package/api-testing-tujuhbelas/scripts/generate-jwt-secret.js +38 -0
- package/api-testing-tujuhbelas/scripts/init-project.js +178 -0
- package/api-testing-tujuhbelas/scripts/make-controller.js +205 -0
- package/api-testing-tujuhbelas/scripts/make-model.js +42 -0
- package/api-testing-tujuhbelas/scripts/make-module.js +158 -0
- package/api-testing-tujuhbelas/scripts/verify-rbac-functional.js +187 -0
- package/api-testing-tujuhbelas/src/controllers/authController.ts +469 -0
- package/api-testing-tujuhbelas/src/controllers/petController.ts +194 -0
- package/api-testing-tujuhbelas/src/controllers/rbacController.ts +478 -0
- package/api-testing-tujuhbelas/src/models/core.prisma +163 -0
- package/api-testing-tujuhbelas/src/models/pets.prisma +9 -0
- package/api-testing-tujuhbelas/src/routes/auth.ts +74 -0
- package/api-testing-tujuhbelas/src/routes/index.ts +10 -0
- package/api-testing-tujuhbelas/src/routes/pets.ts +13 -0
- package/api-testing-tujuhbelas/src/routes/rbac.ts +42 -0
- package/api-testing-tujuhbelas/storage/logs/.gitkeep +0 -0
- package/api-testing-tujuhbelas/tsconfig.json +43 -0
- package/bin/index.js +20 -2
- package/package.json +1 -1
|
@@ -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,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/prisma.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
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Panduan Arsitektur: Menuju "Framework as a Dependency" (Next.js Style)
|
|
2
|
+
|
|
3
|
+
Saat ini, Lapeh menggunakan pendekatan **Boilerplate** (seperti Laravel), di mana pengguna mendapatkan seluruh kode sumber (`src/`) dan bertanggung jawab atas `express`, `prisma`, dll.
|
|
4
|
+
|
|
5
|
+
Untuk mengubahnya menjadi seperti **Next.js** (di mana pengguna hanya menginstall `lapeh` dan `package.json` mereka bersih), kita perlu mengubah arsitektur menjadi **Library**.
|
|
6
|
+
|
|
7
|
+
## 1. Perbedaan Utama
|
|
8
|
+
|
|
9
|
+
| Fitur | Boilerplate (Lapeh Saat Ini) | Library (Next.js Style) |
|
|
10
|
+
| :--- | :--- | :--- |
|
|
11
|
+
| **Instalasi** | `git clone` / `npx create-lapeh` | `npm install lapeh` |
|
|
12
|
+
| **package.json** | Banyak dependency (`express`, `cors`, dll) | Sedikit (`lapeh`, `react`) |
|
|
13
|
+
| **Scripts** | Panjang (`nodemon src/index.ts`) | Pendek (`lapeh dev`) |
|
|
14
|
+
| **Core Code** | Terbuka di `src/core/` | Tersembunyi di `node_modules/lapeh` |
|
|
15
|
+
| **Update** | Susah (harus merge manual) | Mudah (`npm update lapeh`) |
|
|
16
|
+
|
|
17
|
+
## 2. Langkah Implementasi
|
|
18
|
+
|
|
19
|
+
Saya telah memulai langkah pertama dengan menambahkan **CLI Runner** di `bin/index.js`.
|
|
20
|
+
|
|
21
|
+
### A. Update CLI (`bin/index.js`) ✅ (Sudah Dilakukan)
|
|
22
|
+
Saya sudah menambahkan command `dev`, `start`, dan `build` ke dalam CLI Lapeh. Ini memungkinkan pengguna menjalankan server tanpa tahu perintah aslinya.
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
// Contoh penggunaan nanti:
|
|
26
|
+
"scripts": {
|
|
27
|
+
"dev": "lapeh dev",
|
|
28
|
+
"build": "lapeh build",
|
|
29
|
+
"start": "lapeh start"
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### B. Struktur Project Pengguna (Target)
|
|
34
|
+
Nantinya, project pengguna Lapeh hanya akan berisi file bisnis mereka:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
my-app/
|
|
38
|
+
├── src/
|
|
39
|
+
│ ├── controllers/
|
|
40
|
+
│ ├── routes/
|
|
41
|
+
│ └── models/
|
|
42
|
+
├── lapeh.config.ts <-- Konfigurasi framework (pengganti edit core)
|
|
43
|
+
└── package.json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Dan `package.json` mereka akan terlihat seperti ini:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"name": "my-app",
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"lapeh": "^2.0.0"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"dev": "lapeh dev",
|
|
56
|
+
"build": "lapeh build",
|
|
57
|
+
"start": "lapeh start"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### C. Apa yang Harus Dilakukan Selanjutnya?
|
|
63
|
+
|
|
64
|
+
1. **Publish Package**: Anda perlu mempublish folder framework ini ke NPM (atau private registry).
|
|
65
|
+
* Pastikan `express`, `cors`, `helmet`, dll ada di `dependencies` (bukan `devDependencies`).
|
|
66
|
+
2. **Abstraksi `src/index.ts`**:
|
|
67
|
+
* Saat ini `src/index.ts` adalah entry point yang diedit user.
|
|
68
|
+
* Ubah agar `lapeh dev` menjalankan server internal yang **mengimpor** routes/controller user secara dinamis (seperti Next.js pages router).
|
|
69
|
+
3. **Config Loader**:
|
|
70
|
+
* Buat sistem pembacaan `lapeh.config.ts` untuk mengatur Port, Database URL, dll tanpa mengedit kode core.
|
|
71
|
+
|
|
72
|
+
## 3. Kesimpulan
|
|
73
|
+
Perubahan yang saya lakukan di `bin/index.js` adalah fondasi untuk CLI style. Untuk mencapai "Clean package.json" sepenuhnya, Anda harus memisahkan **Framework Core** (repo ini) dengan **User Project** (repo baru yang menginstall framework ini).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Dokumentasi Perubahan Lapeh Framework
|
|
2
|
+
|
|
3
|
+
File ini mencatat semua perubahan, pembaruan, dan perbaikan yang dilakukan pada framework Lapeh, diurutkan berdasarkan tanggal.
|
|
4
|
+
|
|
5
|
+
## [2025-12-27] - Code Quality & Standardization Update
|
|
6
|
+
|
|
7
|
+
### 🚀 Fitur & Standarisasi
|
|
8
|
+
|
|
9
|
+
- **Standardized Import Paths**:
|
|
10
|
+
- Implementasi path alias `@/` untuk import yang lebih bersih (e.g., `import { prisma } from "@/core/database"`).
|
|
11
|
+
- Penghapusan penggunaan relative paths yang dalam (`../../../`).
|
|
12
|
+
- Konfigurasi `tsconfig.json` tanpa `baseUrl` (mengikuti standar TypeScript 6.0+).
|
|
13
|
+
- **Strict Linting & Code Quality**:
|
|
14
|
+
- Implementasi aturan **ESLint** ketat untuk mencegah "Dead Code".
|
|
15
|
+
- Error otomatis untuk variabel, parameter, dan import yang tidak digunakan (`no-unused-vars`).
|
|
16
|
+
- Script `npm run lint` dan `npm run lint:fix` untuk pembersihan kode otomatis.
|
|
17
|
+
- **Fastify-Style Standardization**:
|
|
18
|
+
- Penerapan standar respon cepat (`sendFastSuccess`) di seluruh controller (`AuthController`, `RbacController`, `PetController`).
|
|
19
|
+
- Penggunaan **Schema-based Serialization** untuk performa JSON maksimal.
|
|
20
|
+
- Konversi otomatis `BigInt` ke `string` dalam respon JSON.
|
|
21
|
+
|
|
22
|
+
## [2025-12-27] - High Performance & Scalability Update
|
|
23
|
+
|
|
24
|
+
### 🚀 Fitur Baru
|
|
25
|
+
|
|
26
|
+
- **High Performance Serialization (Fastify-Style)**:
|
|
27
|
+
- Implementasi `fast-json-stringify` untuk serialisasi JSON super cepat (2x-3x lebih cepat dari `JSON.stringify`).
|
|
28
|
+
- Helper `sendFastSuccess` di `src/utils/response.ts` untuk mem-bypass overhead Express.
|
|
29
|
+
- Caching schema serializer otomatis di `src/core/serializer.ts`.
|
|
30
|
+
- **Scalability & Clustering**:
|
|
31
|
+
- Dukungan **Load Balancing** dengan Nginx.
|
|
32
|
+
- Dukungan **Redis Clustering** untuk Rate Limiter (`rate-limit-redis`).
|
|
33
|
+
- File konfigurasi `docker-compose.cluster.yml` untuk simulasi cluster lokal (1 Nginx + 2 App Instances + 1 Redis).
|
|
34
|
+
- **Smart Error Handling**:
|
|
35
|
+
- Deteksi otomatis port bentrok (`EADDRINUSE`) saat startup.
|
|
36
|
+
- Memberikan saran command _copy-paste_ untuk mematikan process yang memblokir port (support Windows, Mac, Linux).
|
|
37
|
+
- **SEO Optimization**:
|
|
38
|
+
- Update metadata `package.json` dan `README.md` agar framework lebih mudah ditemukan di Google/NPM.
|
|
39
|
+
|
|
40
|
+
## [2025-12-27] - Pembaruan Struktur & Validasi
|
|
41
|
+
|
|
42
|
+
### 🚀 Fitur Baru
|
|
43
|
+
|
|
44
|
+
- **Laravel-style Validator**:
|
|
45
|
+
- Implementasi utility `Validator` baru di `src/utils/validator.ts` yang meniru gaya validasi Laravel.
|
|
46
|
+
- Mendukung rule string seperti `required|string|min:3|email`.
|
|
47
|
+
- Penambahan rule `unique` untuk pengecekan database otomatis (Prisma).
|
|
48
|
+
- Penambahan rule `mimes`, `image`, `max` (file size) untuk validasi upload file.
|
|
49
|
+
- Penambahan rule `sometimes` untuk field opsional.
|
|
50
|
+
- **Framework Hardening (Keamanan & Stabilitas)**:
|
|
51
|
+
- **Rate Limiting**: Middleware anti-spam/brute-force di `src/middleware/rateLimit.ts`.
|
|
52
|
+
- **Request Logger**: Pencatatan log request masuk di `src/middleware/requestLogger.ts`.
|
|
53
|
+
- **Health Check**: Endpoint `/` kini mengembalikan status kesehatan server.
|
|
54
|
+
- **Graceful Shutdown**: Penanganan penutupan koneksi Database dan Redis yang aman saat server berhenti (`SIGTERM`/`SIGINT`).
|
|
55
|
+
- **Environment Validation**: Validasi variabel `.env` wajib (seperti `DATABASE_URL`, `JWT_SECRET`) saat startup.
|
|
56
|
+
- **Struktur Folder Baru**:
|
|
57
|
+
- Pemisahan konfigurasi inti ke `src/core/` (`server.ts`, `database.ts`, `redis.ts`, `realtime.ts`) agar folder `src` lebih bersih.
|
|
58
|
+
- Sentralisasi route di `src/routes/index.ts` (WIP).
|
|
59
|
+
- **CLI Improvements**:
|
|
60
|
+
- `npx lapeh <project-name> --full` kini otomatis menjalankan server dev setelah instalasi selesai, sehingga user bisa langsung melihat hasil tanpa mengetik perintah tambahan.
|
|
61
|
+
|
|
62
|
+
### 🛠️ Perbaikan & Refactoring
|
|
63
|
+
|
|
64
|
+
- **Controller Refactoring**:
|
|
65
|
+
- `AuthController`: Migrasi ke `Validator` baru, termasuk validasi upload avatar.
|
|
66
|
+
- `PetController`: Migrasi ke `Validator` baru.
|
|
67
|
+
- `RbacController`: Migrasi sebagian ke `Validator` baru.
|
|
68
|
+
- **Pembersihan**:
|
|
69
|
+
- Penghapusan folder `src/schema/` (Zod schema lama) karena sudah digantikan oleh `Validator` utility.
|
|
70
|
+
- Penghapusan file duplikat/lama di root `src/` setelah migrasi ke `src/core/`.
|
|
71
|
+
|
|
72
|
+
### 📝 Catatan Teknis
|
|
73
|
+
|
|
74
|
+
- **Validator Async**: Method `fails()`, `passes()`, dan `validated()` kini bersifat `async` untuk mendukung pengecekan database (`unique`).
|
|
75
|
+
- **Type Safety**: Semua perubahan telah diverifikasi dengan `npm run typecheck`.
|
|
76
|
+
|
|
77
|
+
---
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Lapeh Framework Cheatsheet
|
|
2
|
+
|
|
3
|
+
Referensi cepat untuk perintah dan kode yang sering digunakan.
|
|
4
|
+
|
|
5
|
+
## 💻 CLI Commands
|
|
6
|
+
|
|
7
|
+
| Perintah | Fungsi |
|
|
8
|
+
| :----------------------------------- | :------------------------------------------- |
|
|
9
|
+
| **`npm run dev`** | Menjalankan server development (hot-reload). |
|
|
10
|
+
| **`npm run typecheck`** | Cek error TypeScript (tanpa compile). |
|
|
11
|
+
| **`npm run lint`** | Cek kode kotor/variabel tidak terpakai. |
|
|
12
|
+
| **`npm run lint:fix`** | Perbaiki kode kotor otomatis. |
|
|
13
|
+
| **`npm run make:module <Name>`** | Buat Controller, Route, & Model sekaligus. |
|
|
14
|
+
| **`npm run make:controller <Name>`** | Buat Controller saja. |
|
|
15
|
+
| **`npm run make:model <Name>`** | Buat Model Prisma saja. |
|
|
16
|
+
| **`npm run prisma:migrate`** | Apply perubahan schema ke DB lokal. |
|
|
17
|
+
| **`npm run db:studio`** | Buka GUI Database. |
|
|
18
|
+
| **`npm run db:seed`** | Isi data dummy. |
|
|
19
|
+
| **`npm run db:reset`** | Hapus DB & mulai dari nol. |
|
|
20
|
+
|
|
21
|
+
## 🛡️ Validator Rules (Laravel-Style)
|
|
22
|
+
|
|
23
|
+
Gunakan di `Validator.make(data, rules)`.
|
|
24
|
+
|
|
25
|
+
| Rule | Deskripsi | Contoh |
|
|
26
|
+
| :----------------- | :---------------------- | :---------------------------------- | -------- |
|
|
27
|
+
| `required` | Wajib ada & tidak null. | `"required"` |
|
|
28
|
+
| `string` | Harus text. | `"required | string"` |
|
|
29
|
+
| `number` | Harus angka. | `"required | number"` |
|
|
30
|
+
| `email` | Format email valid. | `"required | email"` |
|
|
31
|
+
| `min:X` | Min panjang/nilai. | `"min:8"` (pass), `"min:18"` (umur) |
|
|
32
|
+
| `max:X` | Max panjang/nilai. | `"max:255"` |
|
|
33
|
+
| `unique:table,col` | Cek unik di DB. | `"unique:users,email"` |
|
|
34
|
+
| `exists:table,col` | Cek exist di DB. | `"exists:roles,id"` |
|
|
35
|
+
| `image` | File harus gambar. | `"required | image"` |
|
|
36
|
+
| `mimes:types` | File extension. | `"mimes:pdf,docx"` |
|
|
37
|
+
|
|
38
|
+
## 🔑 Authentication
|
|
39
|
+
|
|
40
|
+
**Middleware di Route:**
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { requireAuth, requireAdmin } from "@/middleware/auth";
|
|
44
|
+
|
|
45
|
+
router.get("/profile", requireAuth, getProfile); // Login User
|
|
46
|
+
router.delete("/user", requireAuth, requireAdmin, del); // Admin Only
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Akses User di Controller:**
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// (req as any).user tersedia setelah requireAuth
|
|
53
|
+
const userId = (req as any).user.userId;
|
|
54
|
+
const role = (req as any).user.role;
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## ⚡ Fast Response (Serializer)
|
|
58
|
+
|
|
59
|
+
**1. Schema:**
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
const schema = {
|
|
63
|
+
type: "object",
|
|
64
|
+
properties: {
|
|
65
|
+
id: { type: "string" },
|
|
66
|
+
name: { type: "string" },
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**2. Serializer:**
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
const serializer = getSerializer("key-name", createResponseSchema(schema));
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**3. Send:**
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
sendFastSuccess(res, 200, serializer, { ...data });
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## 📦 Redis (Cache)
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { redis } from "@lapeh/core/redis";
|
|
87
|
+
|
|
88
|
+
// Set Cache (Key, Value, Mode, Detik)
|
|
89
|
+
await redis.set("profile:1", JSON.stringify(data), "EX", 3600);
|
|
90
|
+
|
|
91
|
+
// Get Cache
|
|
92
|
+
const cached = await redis.get("profile:1");
|
|
93
|
+
if (cached) return JSON.parse(cached);
|
|
94
|
+
```
|