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.
- package/.env.example +1 -6
- package/README.md +19 -85
- package/bin/index.js +84 -180
- package/dist/lib/bootstrap.d.ts.map +1 -1
- package/dist/lib/bootstrap.js +17 -16
- package/dist/lib/core/store.d.ts +55 -0
- package/dist/lib/core/store.d.ts.map +1 -0
- package/dist/lib/core/store.js +66 -0
- package/dist/lib/middleware/error.d.ts.map +1 -1
- package/dist/lib/middleware/error.js +1 -20
- package/dist/lib/utils/validator.d.ts.map +1 -1
- package/dist/lib/utils/validator.js +3 -32
- package/dist/src/modules/Auth/auth.controller.d.ts.map +1 -1
- package/dist/src/modules/Auth/auth.controller.js +118 -105
- package/dist/src/modules/Rbac/rbac.controller.d.ts.map +1 -1
- package/dist/src/modules/Rbac/rbac.controller.js +141 -140
- package/dist/src/routes/index.d.ts.map +1 -1
- package/dist/src/routes/index.js +0 -5
- package/doc/en/CHEATSHEET.md +3 -7
- package/doc/en/CLI.md +16 -41
- package/doc/en/DEPLOYMENT.md +171 -245
- package/doc/en/GETTING_STARTED.md +1 -25
- package/doc/en/PACKAGES.md +2 -3
- package/doc/en/STRUCTURE.md +1 -11
- package/doc/en/TUTORIAL.md +61 -119
- package/doc/id/CHANGELOG.md +16 -0
- package/doc/id/CHEATSHEET.md +0 -4
- package/doc/id/CLI.md +19 -54
- package/doc/id/DEPLOYMENT.md +171 -245
- package/doc/id/GETTING_STARTED.md +91 -115
- package/doc/id/PACKAGES.md +0 -1
- package/doc/id/STRUCTURE.md +1 -11
- package/doc/id/TUTORIAL.md +51 -109
- package/gitignore.template +0 -10
- package/lib/bootstrap.ts +39 -38
- package/lib/core/store.ts +116 -0
- package/lib/middleware/error.ts +1 -21
- package/lib/utils/validator.ts +3 -39
- package/package.json +4 -18
- package/scripts/init-project.js +2 -108
- package/scripts/make-module.js +1 -12
- package/scripts/seed-json.js +158 -0
- package/src/modules/Auth/auth.controller.ts +156 -106
- package/src/modules/Rbac/rbac.controller.ts +193 -138
- package/src/routes/index.ts +0 -3
- package/src/routes/rbac.ts +42 -42
- package/storage/logs/.0337f5062fe676994d1dc340156e089444e3d6e0-audit.json +5 -10
- package/storage/logs/lapeh-2025-12-30.log +1093 -0
- package/tsconfig.build.json +1 -3
- package/tsconfig.json +0 -1
- package/lib/core/database.ts +0 -5
- package/prisma/base.prisma.template +0 -8
- package/prisma/migrations/20251225163737_init/migration.sql +0 -236
- package/prisma/migrations/20251226000329_create_pets_table/migration.sql +0 -11
- package/prisma/migrations/20251226001249_create_pets_table/migration.sql +0 -82
- package/prisma/migrations/20251226001717_restore_core_models/migration.sql +0 -236
- package/prisma/migrations/migration_lock.toml +0 -3
- package/prisma/schema.prisma +0 -197
- package/prisma/seed.ts +0 -411
- package/scripts/compile-schema.js +0 -64
- package/src/modules/Auth/auth.prisma +0 -106
- package/src/modules/Pets/pets.controller.ts +0 -238
- package/src/modules/Pets/pets.prisma +0 -9
- package/src/modules/Rbac/rbac.prisma +0 -68
- package/src/routes/pets.ts +0 -13
- package/storage/logs/lapeh-2025-12-26.log +0 -88
- package/storage/logs/lapeh-2025-12-27.log +0 -217
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lapeh",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "Framework API Express yang siap pakai (Standardized)",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0",
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"bin",
|
|
24
24
|
"dist",
|
|
25
25
|
"lib",
|
|
26
|
-
"prisma",
|
|
27
26
|
"scripts",
|
|
28
27
|
"src",
|
|
29
28
|
"storage",
|
|
@@ -42,23 +41,13 @@
|
|
|
42
41
|
"scripts": {
|
|
43
42
|
"dev": "node bin/index.js dev",
|
|
44
43
|
"first": "node scripts/init-project.js",
|
|
45
|
-
"prebuild": "npm run prisma:generate",
|
|
46
44
|
"build": "node bin/index.js build",
|
|
47
|
-
"prestart": "npm run prisma:generate",
|
|
48
45
|
"start": "node bin/index.js start",
|
|
49
|
-
"prestart:prod": "npm run prisma:generate",
|
|
50
46
|
"start:prod": "node bin/index.js start",
|
|
51
47
|
"typecheck": "tsc --noEmit",
|
|
52
48
|
"lint": "eslint .",
|
|
53
49
|
"lint:fix": "eslint . --fix",
|
|
54
50
|
"test": "jest",
|
|
55
|
-
"prisma:generate": "node scripts/compile-schema.js && prisma generate",
|
|
56
|
-
"prisma:migrate": "node scripts/compile-schema.js && prisma migrate dev",
|
|
57
|
-
"prisma:deploy": "node scripts/compile-schema.js && prisma migrate deploy",
|
|
58
|
-
"db:seed": "prisma db seed",
|
|
59
|
-
"db:reset": "prisma migrate reset",
|
|
60
|
-
"db:rs": "prisma migrate reset --force && prisma db seed",
|
|
61
|
-
"db:studio": "prisma studio",
|
|
62
51
|
"generate:jwt": "node scripts/generate-jwt-secret.js",
|
|
63
52
|
"make:module": "node scripts/make-module.js",
|
|
64
53
|
"make:modul": "node scripts/make-module.js",
|
|
@@ -71,7 +60,6 @@
|
|
|
71
60
|
"express-framework",
|
|
72
61
|
"backend-framework",
|
|
73
62
|
"rest-api",
|
|
74
|
-
"prisma-orm",
|
|
75
63
|
"production-ready",
|
|
76
64
|
"api-generator",
|
|
77
65
|
"boilerplate",
|
|
@@ -87,9 +75,7 @@
|
|
|
87
75
|
"author": "robyajo <robyfull.dev@gmail.com>",
|
|
88
76
|
"license": "MIT",
|
|
89
77
|
"type": "commonjs",
|
|
90
|
-
"peerDependencies": {
|
|
91
|
-
"@prisma/client": "^6.0.0"
|
|
92
|
-
},
|
|
78
|
+
"peerDependencies": {},
|
|
93
79
|
"dependencies": {
|
|
94
80
|
"@types/bcryptjs": "2.4.6",
|
|
95
81
|
"@types/compression": "^1.8.1",
|
|
@@ -100,7 +86,7 @@
|
|
|
100
86
|
"@types/node": "25.0.3",
|
|
101
87
|
"@types/pg": "8.16.0",
|
|
102
88
|
"@types/uuid": "10.0.0",
|
|
103
|
-
"bcryptjs": "
|
|
89
|
+
"bcryptjs": "^2.4.3",
|
|
104
90
|
"compression": "^1.8.1",
|
|
105
91
|
"cors": "2.8.5",
|
|
106
92
|
"dotenv": "17.2.3",
|
|
@@ -126,13 +112,13 @@
|
|
|
126
112
|
},
|
|
127
113
|
"devDependencies": {
|
|
128
114
|
"@eslint/js": "^9.39.2",
|
|
115
|
+
"@types/bcrypt": "^5.0.2",
|
|
129
116
|
"@types/jest": "^30.0.0",
|
|
130
117
|
"@types/module-alias": "^2.0.4",
|
|
131
118
|
"@types/supertest": "^6.0.3",
|
|
132
119
|
"eslint": "^9.39.2",
|
|
133
120
|
"globals": "^16.5.0",
|
|
134
121
|
"jest": "^30.2.0",
|
|
135
|
-
"prisma": "^6.0.0",
|
|
136
122
|
"supertest": "^7.1.4",
|
|
137
123
|
"ts-jest": "^29.4.6",
|
|
138
124
|
"typescript-eslint": "^8.50.1"
|
package/scripts/init-project.js
CHANGED
|
@@ -6,7 +6,6 @@ const readline = require("readline");
|
|
|
6
6
|
const rootDir = path.join(__dirname, "..");
|
|
7
7
|
const envExample = path.join(rootDir, ".env.example");
|
|
8
8
|
const envFile = path.join(rootDir, ".env");
|
|
9
|
-
const prismaBaseFile = path.join(rootDir, "prisma", "base.prisma.template");
|
|
10
9
|
|
|
11
10
|
const rl = readline.createInterface({
|
|
12
11
|
input: process.stdin,
|
|
@@ -44,32 +43,6 @@ const selectOption = async (query, options) => {
|
|
|
44
43
|
console.log("🚀 Starting project initialization...");
|
|
45
44
|
|
|
46
45
|
try {
|
|
47
|
-
// --- DATABASE SELECTION ---
|
|
48
|
-
console.log("\n--- Database Configuration ---");
|
|
49
|
-
const dbType = await selectOption("Database apa yang akan digunakan?", [
|
|
50
|
-
{ key: "pgsql", label: "PostgreSQL", provider: "postgresql", defaultPort: "5432" },
|
|
51
|
-
{ key: "mysql", label: "MySQL", provider: "mysql", defaultPort: "3306" },
|
|
52
|
-
{ key: "mongo", label: "MongoDB", provider: "mongodb", defaultPort: "27017" },
|
|
53
|
-
]);
|
|
54
|
-
|
|
55
|
-
let dbUrl = "";
|
|
56
|
-
let dbProvider = dbType.provider;
|
|
57
|
-
|
|
58
|
-
const host = await ask("Database Host", "localhost");
|
|
59
|
-
const port = await ask("Database Port", dbType.defaultPort);
|
|
60
|
-
const user = await ask("Database User", dbType.key === "mongo" ? "" : "root");
|
|
61
|
-
const password = await ask("Database Password", "");
|
|
62
|
-
const dbName = await ask("Database Name", "lapeh");
|
|
63
|
-
|
|
64
|
-
if (dbType.key === "pgsql") {
|
|
65
|
-
dbUrl = `postgresql://${user}:${password}@${host}:${port}/${dbName}?schema=public`;
|
|
66
|
-
} else if (dbType.key === "mysql") {
|
|
67
|
-
dbUrl = `mysql://${user}:${password}@${host}:${port}/${dbName}`;
|
|
68
|
-
} else if (dbType.key === "mongo") {
|
|
69
|
-
const auth = user ? `${user}:${password}@` : "";
|
|
70
|
-
dbUrl = `mongodb://${auth}${host}:${port}/${dbName}?authSource=admin`;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
46
|
// Close readline as we are done with input
|
|
74
47
|
rl.close();
|
|
75
48
|
|
|
@@ -80,65 +53,16 @@ const selectOption = async (query, options) => {
|
|
|
80
53
|
envContent = fs.readFileSync(envExample, "utf8");
|
|
81
54
|
} else {
|
|
82
55
|
// Fallback minimal env if example missing
|
|
83
|
-
envContent = `PORT=4000\
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Replace DATABASE_URL and DATABASE_PROVIDER
|
|
87
|
-
// Regex to replace existing values or append if missing (simplified)
|
|
88
|
-
if (envContent.includes("DATABASE_URL=")) {
|
|
89
|
-
envContent = envContent.replace(/DATABASE_URL=".+"/g, `DATABASE_URL="${dbUrl}"`);
|
|
90
|
-
envContent = envContent.replace(/DATABASE_URL=.+/g, `DATABASE_URL="${dbUrl}"`); // Handle unquoted
|
|
91
|
-
} else {
|
|
92
|
-
envContent += `\nDATABASE_URL="${dbUrl}"`;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (envContent.includes("DATABASE_PROVIDER=")) {
|
|
96
|
-
envContent = envContent.replace(/DATABASE_PROVIDER=".+"/g, `DATABASE_PROVIDER="${dbProvider}"`);
|
|
97
|
-
envContent = envContent.replace(/DATABASE_PROVIDER=.+/g, `DATABASE_PROVIDER="${dbProvider}"`);
|
|
98
|
-
} else {
|
|
99
|
-
envContent += `\nDATABASE_PROVIDER="${dbProvider}"`;
|
|
56
|
+
envContent = `PORT=4000\nJWT_SECRET="replace_this"\n`;
|
|
100
57
|
}
|
|
101
58
|
|
|
102
59
|
fs.writeFileSync(envFile, envContent);
|
|
103
|
-
console.log("✅ .env
|
|
104
|
-
|
|
105
|
-
// Update base.prisma.template with the correct provider
|
|
106
|
-
console.log("\n�️ Updating Prisma configuration...");
|
|
107
|
-
if (fs.existsSync(prismaBaseFile)) {
|
|
108
|
-
let prismaContent = fs.readFileSync(prismaBaseFile, "utf8");
|
|
109
|
-
|
|
110
|
-
// Replace provider in datasource block
|
|
111
|
-
// Matches: provider = "..." inside datasource db { ... }
|
|
112
|
-
prismaContent = prismaContent.replace(
|
|
113
|
-
/(datasource\s+db\s+\{[\s\S]*?provider\s*=\s*")[^"]+(")/,
|
|
114
|
-
`$1${dbProvider}$2`
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
fs.writeFileSync(prismaBaseFile, prismaContent);
|
|
118
|
-
console.log(`✅ prisma/base.prisma.template updated to use ${dbProvider}.`);
|
|
119
|
-
} else {
|
|
120
|
-
console.warn("⚠️ prisma/base.prisma.template not found. Skipping prisma update.");
|
|
121
|
-
}
|
|
60
|
+
console.log("✅ .env created.");
|
|
122
61
|
|
|
123
62
|
// 3. Install dependencies
|
|
124
63
|
console.log("\n📦 Installing dependencies...");
|
|
125
64
|
execSync("npm install", { stdio: "inherit", cwd: rootDir });
|
|
126
65
|
|
|
127
|
-
// 4. Create .vscode/settings.json
|
|
128
|
-
console.log("\n🛠️ Configuring VS Code...");
|
|
129
|
-
const vscodeDir = path.join(rootDir, ".vscode");
|
|
130
|
-
if (!fs.existsSync(vscodeDir)) {
|
|
131
|
-
fs.mkdirSync(vscodeDir, { recursive: true });
|
|
132
|
-
}
|
|
133
|
-
const settingsFile = path.join(vscodeDir, "settings.json");
|
|
134
|
-
const settingsContent = {
|
|
135
|
-
"files.associations": {
|
|
136
|
-
"*.model": "prisma"
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
fs.writeFileSync(settingsFile, JSON.stringify(settingsContent, null, 2));
|
|
140
|
-
console.log("✅ VS Code configured (.model support added).");
|
|
141
|
-
|
|
142
66
|
// 5. Generate JWT Secret
|
|
143
67
|
console.log("\n🔑 Generating JWT Secret...");
|
|
144
68
|
try {
|
|
@@ -150,41 +74,11 @@ const selectOption = async (query, options) => {
|
|
|
150
74
|
console.warn("⚠️ Failed to generate JWT secret automatically.");
|
|
151
75
|
}
|
|
152
76
|
|
|
153
|
-
// 5. Setup Database (Migrate)
|
|
154
|
-
console.log("\n🗄️ Setting up database...");
|
|
155
|
-
try {
|
|
156
|
-
execSync("node scripts/compile-schema.js", { stdio: "inherit", cwd: rootDir });
|
|
157
|
-
console.log("⚙️ Generating Prisma Client...");
|
|
158
|
-
execSync("npx prisma generate", { stdio: "inherit", cwd: rootDir });
|
|
159
|
-
|
|
160
|
-
console.log("🚀 Running Migration...");
|
|
161
|
-
if (dbProvider === 'mongodb') {
|
|
162
|
-
execSync("npx prisma db push", { stdio: "inherit", cwd: rootDir });
|
|
163
|
-
} else {
|
|
164
|
-
execSync("npx prisma migrate dev --name init_setup", { stdio: "inherit", cwd: rootDir });
|
|
165
|
-
}
|
|
166
|
-
} catch (error) {
|
|
167
|
-
console.warn(
|
|
168
|
-
'⚠️ Database migration had an issue. Please check your database connection in .env and run "npm run prisma:migrate" manually.'
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// 6. Seed Database
|
|
173
|
-
console.log("\n🌱 Seeding database...");
|
|
174
|
-
try {
|
|
175
|
-
execSync("npm run db:seed", { stdio: "inherit", cwd: rootDir });
|
|
176
|
-
} catch (error) {
|
|
177
|
-
console.warn(
|
|
178
|
-
'⚠️ Database seeding had an issue. You might need to run "npm run db:seed" manually.'
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
77
|
console.log("\n✅ Setup complete! You can now run:");
|
|
183
78
|
console.log(" npm run dev");
|
|
184
79
|
|
|
185
80
|
} catch (error) {
|
|
186
81
|
console.error("\n❌ Setup failed:", error.message);
|
|
187
|
-
rl.close();
|
|
188
82
|
process.exit(1);
|
|
189
83
|
}
|
|
190
84
|
})();
|
package/scripts/make-module.js
CHANGED
|
@@ -55,8 +55,7 @@ export async function destroy(req: Request, res: Response) {
|
|
|
55
55
|
fs.writeFileSync(path.join(moduleDir, `${lowerName}.controller.ts`), controllerContent);
|
|
56
56
|
|
|
57
57
|
// Service (Optional but good for NestJS style)
|
|
58
|
-
const serviceContent =
|
|
59
|
-
|
|
58
|
+
const serviceContent = `
|
|
60
59
|
export async function findAll() {
|
|
61
60
|
return [];
|
|
62
61
|
}
|
|
@@ -83,18 +82,8 @@ export default router;
|
|
|
83
82
|
`;
|
|
84
83
|
fs.writeFileSync(path.join(moduleDir, `${lowerName}.routes.ts`), routeContent);
|
|
85
84
|
|
|
86
|
-
// Prisma Model
|
|
87
|
-
const prismaContent = `model ${name} {
|
|
88
|
-
id String @id @default(uuid())
|
|
89
|
-
createdAt DateTime @default(now())
|
|
90
|
-
updatedAt DateTime @updatedAt
|
|
91
|
-
}
|
|
92
|
-
`;
|
|
93
|
-
fs.writeFileSync(path.join(moduleDir, `${lowerName}.prisma`), prismaContent);
|
|
94
|
-
|
|
95
85
|
console.log(`✅ Module ${name} created successfully at src/modules/${name}`);
|
|
96
86
|
console.log(` - ${lowerName}.controller.ts`);
|
|
97
87
|
console.log(` - ${lowerName}.service.ts`);
|
|
98
88
|
console.log(` - ${lowerName}.routes.ts`);
|
|
99
|
-
console.log(` - ${lowerName}.prisma`);
|
|
100
89
|
console.log(`\n👉 Don't forget to register the route in src/routes/index.ts!`);
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const bcrypt = require('bcryptjs');
|
|
5
|
+
const { v4: uuidv4 } = require('uuid');
|
|
6
|
+
|
|
7
|
+
const DB_PATH = path.join(__dirname, '../database.json');
|
|
8
|
+
|
|
9
|
+
async function seed() {
|
|
10
|
+
console.log('🌱 Seeding database.json...');
|
|
11
|
+
|
|
12
|
+
let store = {
|
|
13
|
+
users: [],
|
|
14
|
+
roles: [],
|
|
15
|
+
permissions: [],
|
|
16
|
+
user_roles: [],
|
|
17
|
+
role_permissions: [],
|
|
18
|
+
user_permissions: []
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Load existing if any (optional, but we'll overwrite for seed)
|
|
22
|
+
// if (fs.existsSync(DB_PATH)) {
|
|
23
|
+
// store = JSON.parse(fs.readFileSync(DB_PATH, 'utf-8'));
|
|
24
|
+
// }
|
|
25
|
+
|
|
26
|
+
const passwordHash = await bcrypt.hash('password123', 10);
|
|
27
|
+
|
|
28
|
+
// 1. Seed Users
|
|
29
|
+
const usersData = [
|
|
30
|
+
{ name: "Super Admin", email: "sa@sa.com", roleSlug: "super_admin" },
|
|
31
|
+
{ name: "Admin User", email: "a@a.com", roleSlug: "admin" },
|
|
32
|
+
{ name: "Regular User", email: "u@u.com", roleSlug: "user" }
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
for (const u of usersData) {
|
|
36
|
+
const user = {
|
|
37
|
+
id: (store.users.length + 1).toString(),
|
|
38
|
+
uuid: uuidv4(),
|
|
39
|
+
name: u.name,
|
|
40
|
+
email: u.email,
|
|
41
|
+
password: passwordHash,
|
|
42
|
+
created_at: new Date(),
|
|
43
|
+
updated_at: new Date(),
|
|
44
|
+
avatar: null,
|
|
45
|
+
avatar_url: null,
|
|
46
|
+
email_verified_at: null,
|
|
47
|
+
remember_token: null
|
|
48
|
+
};
|
|
49
|
+
store.users.push(user);
|
|
50
|
+
console.log(`Created user: ${user.name}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 2. Seed Roles
|
|
54
|
+
const rolesData = [
|
|
55
|
+
{ name: "Super Admin", slug: "super_admin", description: "Full access to all resources" },
|
|
56
|
+
{ name: "Admin", slug: "admin", description: "Administrator" },
|
|
57
|
+
{ name: "User", slug: "user", description: "Regular user" }
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
for (const r of rolesData) {
|
|
61
|
+
const role = {
|
|
62
|
+
id: (store.roles.length + 1).toString(),
|
|
63
|
+
name: r.name,
|
|
64
|
+
slug: r.slug,
|
|
65
|
+
description: r.description,
|
|
66
|
+
created_at: new Date(),
|
|
67
|
+
updated_at: new Date()
|
|
68
|
+
};
|
|
69
|
+
store.roles.push(role);
|
|
70
|
+
console.log(`Created role: ${role.name}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 3. Seed Permissions
|
|
74
|
+
const permissionsData = [
|
|
75
|
+
{ name: "Manage Users", slug: "users.manage", description: "Create, update, and delete users" },
|
|
76
|
+
{ name: "Create Users", slug: "users.create", description: "Create users" },
|
|
77
|
+
{ name: "View Users", slug: "users.view", description: "View users" },
|
|
78
|
+
{ name: "Update Users", slug: "users.update", description: "Update users" },
|
|
79
|
+
{ name: "Delete Users", slug: "users.delete", description: "Delete users" },
|
|
80
|
+
{ name: "Manage Roles", slug: "roles.manage", description: "Create, update, and delete roles" },
|
|
81
|
+
{ name: "Manage Permissions", slug: "permissions.manage", description: "Create, update, and delete permissions" },
|
|
82
|
+
{ name: "Manage Profiles", slug: "profiles.manage", description: "Manage user profiles" }
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
for (const p of permissionsData) {
|
|
86
|
+
const perm = {
|
|
87
|
+
id: (store.permissions.length + 1).toString(),
|
|
88
|
+
name: p.name,
|
|
89
|
+
slug: p.slug,
|
|
90
|
+
description: p.description,
|
|
91
|
+
created_at: new Date(),
|
|
92
|
+
updated_at: new Date()
|
|
93
|
+
};
|
|
94
|
+
store.permissions.push(perm);
|
|
95
|
+
}
|
|
96
|
+
console.log(`Seeded ${store.permissions.length} permissions`);
|
|
97
|
+
|
|
98
|
+
// 4. Link Users to Roles
|
|
99
|
+
for (const u of usersData) {
|
|
100
|
+
const user = store.users.find(x => x.email === u.email);
|
|
101
|
+
const role = store.roles.find(x => x.slug === u.roleSlug);
|
|
102
|
+
if (user && role) {
|
|
103
|
+
store.user_roles.push({
|
|
104
|
+
id: (store.user_roles.length + 1).toString(),
|
|
105
|
+
user_id: user.id,
|
|
106
|
+
role_id: role.id,
|
|
107
|
+
created_at: new Date()
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 5. Link Roles to Permissions
|
|
113
|
+
// Super Admin -> All Permissions
|
|
114
|
+
const superAdminRole = store.roles.find(r => r.slug === 'super_admin');
|
|
115
|
+
if (superAdminRole) {
|
|
116
|
+
for (const p of store.permissions) {
|
|
117
|
+
store.role_permissions.push({
|
|
118
|
+
id: (store.role_permissions.length + 1).toString(),
|
|
119
|
+
role_id: superAdminRole.id,
|
|
120
|
+
permission_id: p.id,
|
|
121
|
+
created_at: new Date()
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Admin -> Users.*
|
|
127
|
+
const adminRole = store.roles.find(r => r.slug === 'admin');
|
|
128
|
+
if (adminRole) {
|
|
129
|
+
const adminPerms = store.permissions.filter(p => p.slug.startsWith('users.'));
|
|
130
|
+
for (const p of adminPerms) {
|
|
131
|
+
store.role_permissions.push({
|
|
132
|
+
id: (store.role_permissions.length + 1).toString(),
|
|
133
|
+
role_id: adminRole.id,
|
|
134
|
+
permission_id: p.id,
|
|
135
|
+
created_at: new Date()
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// User -> profiles.manage
|
|
141
|
+
const userRole = store.roles.find(r => r.slug === 'user');
|
|
142
|
+
if (userRole) {
|
|
143
|
+
const userPerms = store.permissions.filter(p => p.slug === 'profiles.manage');
|
|
144
|
+
for (const p of userPerms) {
|
|
145
|
+
store.role_permissions.push({
|
|
146
|
+
id: (store.role_permissions.length + 1).toString(),
|
|
147
|
+
role_id: userRole.id,
|
|
148
|
+
permission_id: p.id,
|
|
149
|
+
created_at: new Date()
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
fs.writeFileSync(DB_PATH, JSON.stringify(store, null, 2));
|
|
155
|
+
console.log('✅ Database seeded successfully!');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
seed().catch(console.error);
|