lapeh 2.2.7 → 2.2.8

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 (52) hide show
  1. package/bin/index.js +164 -13
  2. package/package.json +6 -6
  3. package/api-testing-sepuluh/.env.example +0 -19
  4. package/api-testing-sepuluh/doc/ARCHITECTURE_GUIDE.md +0 -73
  5. package/api-testing-sepuluh/doc/CHANGELOG.md +0 -77
  6. package/api-testing-sepuluh/doc/CHEATSHEET.md +0 -94
  7. package/api-testing-sepuluh/doc/CLI.md +0 -106
  8. package/api-testing-sepuluh/doc/CONTRIBUTING.md +0 -105
  9. package/api-testing-sepuluh/doc/DEPLOYMENT.md +0 -122
  10. package/api-testing-sepuluh/doc/FAQ.md +0 -81
  11. package/api-testing-sepuluh/doc/FEATURES.md +0 -165
  12. package/api-testing-sepuluh/doc/GETTING_STARTED.md +0 -108
  13. package/api-testing-sepuluh/doc/INTRODUCTION.md +0 -60
  14. package/api-testing-sepuluh/doc/PACKAGES.md +0 -66
  15. package/api-testing-sepuluh/doc/PERFORMANCE.md +0 -91
  16. package/api-testing-sepuluh/doc/ROADMAP.md +0 -93
  17. package/api-testing-sepuluh/doc/SECURITY.md +0 -93
  18. package/api-testing-sepuluh/doc/STRUCTURE.md +0 -90
  19. package/api-testing-sepuluh/doc/TUTORIAL.md +0 -192
  20. package/api-testing-sepuluh/docker-compose.yml +0 -24
  21. package/api-testing-sepuluh/eslint.config.mjs +0 -26
  22. package/api-testing-sepuluh/framework.md +0 -168
  23. package/api-testing-sepuluh/nodemon.json +0 -6
  24. package/api-testing-sepuluh/package-lock.json +0 -5539
  25. package/api-testing-sepuluh/package.json +0 -103
  26. package/api-testing-sepuluh/prisma/base.prisma.template +0 -7
  27. package/api-testing-sepuluh/prisma/migrations/20251227034737_init_setup/migration.sql +0 -248
  28. package/api-testing-sepuluh/prisma/migrations/migration_lock.toml +0 -3
  29. package/api-testing-sepuluh/prisma/schema.prisma +0 -183
  30. package/api-testing-sepuluh/prisma/seed.ts +0 -411
  31. package/api-testing-sepuluh/prisma.config.ts +0 -15
  32. package/api-testing-sepuluh/readme.md +0 -414
  33. package/api-testing-sepuluh/scripts/check-update.js +0 -92
  34. package/api-testing-sepuluh/scripts/compile-schema.js +0 -29
  35. package/api-testing-sepuluh/scripts/config-clear.js +0 -45
  36. package/api-testing-sepuluh/scripts/generate-jwt-secret.js +0 -38
  37. package/api-testing-sepuluh/scripts/init-project.js +0 -178
  38. package/api-testing-sepuluh/scripts/make-controller.js +0 -205
  39. package/api-testing-sepuluh/scripts/make-model.js +0 -42
  40. package/api-testing-sepuluh/scripts/make-module.js +0 -158
  41. package/api-testing-sepuluh/scripts/verify-rbac-functional.js +0 -187
  42. package/api-testing-sepuluh/src/controllers/authController.ts +0 -469
  43. package/api-testing-sepuluh/src/controllers/petController.ts +0 -194
  44. package/api-testing-sepuluh/src/controllers/rbacController.ts +0 -478
  45. package/api-testing-sepuluh/src/models/core.prisma +0 -163
  46. package/api-testing-sepuluh/src/models/pets.prisma +0 -9
  47. package/api-testing-sepuluh/src/routes/auth.ts +0 -74
  48. package/api-testing-sepuluh/src/routes/index.ts +0 -10
  49. package/api-testing-sepuluh/src/routes/pets.ts +0 -13
  50. package/api-testing-sepuluh/src/routes/rbac.ts +0 -42
  51. package/api-testing-sepuluh/storage/logs/.gitkeep +0 -0
  52. package/api-testing-sepuluh/tsconfig.json +0 -39
@@ -1,178 +0,0 @@
1
- const fs = require("fs");
2
- const path = require("path");
3
- const { execSync } = require("child_process");
4
- const readline = require("readline");
5
-
6
- const rootDir = path.join(__dirname, "..");
7
- const envExample = path.join(rootDir, ".env.example");
8
- const envFile = path.join(rootDir, ".env");
9
- const prismaBaseFile = path.join(rootDir, "prisma", "base.prisma.template");
10
-
11
- const rl = readline.createInterface({
12
- input: process.stdin,
13
- output: process.stdout,
14
- });
15
-
16
- const ask = (query, defaultVal) => {
17
- return new Promise((resolve) => {
18
- rl.question(`${query} ${defaultVal ? `[${defaultVal}]` : ""}: `, (answer) => {
19
- resolve(answer.trim() || defaultVal);
20
- });
21
- });
22
- };
23
-
24
- const selectOption = async (query, options) => {
25
- console.log(query);
26
- options.forEach((opt, idx) => {
27
- console.log(` [${opt.key}] ${opt.label}`);
28
- });
29
-
30
- while (true) {
31
- const answer = await ask(">", options[0].key); // Default to first option
32
- const selected = options.find(o => o.key.toLowerCase() === answer.toLowerCase());
33
- if (selected) return selected;
34
-
35
- // Check if user entered the full name or label
36
- const byLabel = options.find(o => o.label.toLowerCase().includes(answer.toLowerCase()));
37
- if (byLabel) return byLabel;
38
-
39
- console.log("Pilihan tidak valid. Silakan coba lagi.");
40
- }
41
- };
42
-
43
- (async () => {
44
- console.log("šŸš€ Starting project initialization...");
45
-
46
- 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
- ]);
53
-
54
- let dbUrl = "";
55
- let dbProvider = dbType.provider;
56
-
57
- const host = await ask("Database Host", "localhost");
58
- const port = await ask("Database Port", dbType.defaultPort);
59
- const user = await ask("Database User", "root");
60
- const password = await ask("Database Password", "");
61
- const dbName = await ask("Database Name", "lapeh");
62
-
63
- if (dbType.key === "pgsql") {
64
- dbUrl = `postgresql://${user}:${password}@${host}:${port}/${dbName}?schema=public`;
65
- } else {
66
- dbUrl = `mysql://${user}:${password}@${host}:${port}/${dbName}`;
67
- }
68
-
69
- // Close readline as we are done with input
70
- rl.close();
71
-
72
- // 1. Setup .env
73
- console.log("\nšŸ“„ Setting up .env...");
74
- let envContent = "";
75
- if (fs.existsSync(envExample)) {
76
- envContent = fs.readFileSync(envExample, "utf8");
77
- } else {
78
- // Fallback minimal env if example missing
79
- envContent = `PORT=4000\nDATABASE_PROVIDER="postgresql"\nDATABASE_URL=""\nJWT_SECRET="replace_this"\n`;
80
- }
81
-
82
- // Replace DATABASE_URL and DATABASE_PROVIDER
83
- // Regex to replace existing values or append if missing (simplified)
84
- if (envContent.includes("DATABASE_URL=")) {
85
- envContent = envContent.replace(/DATABASE_URL=".+"/g, `DATABASE_URL="${dbUrl}"`);
86
- envContent = envContent.replace(/DATABASE_URL=.+/g, `DATABASE_URL="${dbUrl}"`); // Handle unquoted
87
- } else {
88
- envContent += `\nDATABASE_URL="${dbUrl}"`;
89
- }
90
-
91
- if (envContent.includes("DATABASE_PROVIDER=")) {
92
- envContent = envContent.replace(/DATABASE_PROVIDER=".+"/g, `DATABASE_PROVIDER="${dbProvider}"`);
93
- envContent = envContent.replace(/DATABASE_PROVIDER=.+/g, `DATABASE_PROVIDER="${dbProvider}"`);
94
- } else {
95
- envContent += `\nDATABASE_PROVIDER="${dbProvider}"`;
96
- }
97
-
98
- fs.writeFileSync(envFile, envContent);
99
- console.log("āœ… .env updated with database configuration.");
100
-
101
- // 2. Update prisma/base.prisma.template
102
- console.log("šŸ“„ Updating prisma/base.prisma.template...");
103
- if (fs.existsSync(prismaBaseFile)) {
104
- let baseContent = fs.readFileSync(prismaBaseFile, "utf8");
105
- // Replace provider in datasource block
106
- baseContent = baseContent.replace(
107
- /(datasource\s+db\s+\{[\s\S]*?provider\s*=\s*")([^"]+)(")/,
108
- `$1${dbProvider}$3`
109
- );
110
- fs.writeFileSync(prismaBaseFile, baseContent);
111
- } else {
112
- console.warn("āš ļø prisma/base.prisma.template not found. Skipping.");
113
- }
114
-
115
- // 3. Install dependencies
116
- console.log("\nšŸ“¦ Installing dependencies...");
117
- execSync("npm install", { stdio: "inherit", cwd: rootDir });
118
-
119
- // 4. Create .vscode/settings.json
120
- console.log("\nšŸ› ļø Configuring VS Code...");
121
- const vscodeDir = path.join(rootDir, ".vscode");
122
- if (!fs.existsSync(vscodeDir)) {
123
- fs.mkdirSync(vscodeDir, { recursive: true });
124
- }
125
- const settingsFile = path.join(vscodeDir, "settings.json");
126
- const settingsContent = {
127
- "files.associations": {
128
- "*.model": "prisma"
129
- }
130
- };
131
- fs.writeFileSync(settingsFile, JSON.stringify(settingsContent, null, 2));
132
- console.log("āœ… VS Code configured (.model support added).");
133
-
134
- // 5. Generate JWT Secret
135
- console.log("\nšŸ”‘ Generating JWT Secret...");
136
- try {
137
- execSync("node scripts/generate-jwt-secret.js", {
138
- stdio: "inherit",
139
- cwd: rootDir,
140
- });
141
- } catch (e) {
142
- console.warn("āš ļø Failed to generate JWT secret automatically.");
143
- }
144
-
145
- // 5. Setup Database (Migrate)
146
- console.log("\nšŸ—„ļø Setting up database...");
147
- try {
148
- execSync("node scripts/compile-schema.js", { stdio: "inherit", cwd: rootDir });
149
- console.log("āš™ļø Generating Prisma Client...");
150
- execSync("npx prisma generate", { stdio: "inherit", cwd: rootDir });
151
-
152
- console.log("šŸš€ Running Migration...");
153
- execSync("npx prisma migrate dev --name init_setup", { stdio: "inherit", cwd: rootDir });
154
- } catch (error) {
155
- console.warn(
156
- 'āš ļø Database migration had an issue. Please check your database connection in .env and run "npm run prisma:migrate" manually.'
157
- );
158
- }
159
-
160
- // 6. Seed Database
161
- console.log("\n🌱 Seeding database...");
162
- try {
163
- execSync("npm run db:seed", { stdio: "inherit", cwd: rootDir });
164
- } catch (error) {
165
- console.warn(
166
- 'āš ļø Database seeding had an issue. You might need to run "npm run db:seed" manually.'
167
- );
168
- }
169
-
170
- console.log("\nāœ… Setup complete! You can now run:");
171
- console.log(" npm run dev");
172
-
173
- } catch (error) {
174
- console.error("\nāŒ Setup failed:", error.message);
175
- rl.close();
176
- process.exit(1);
177
- }
178
- })();
@@ -1,205 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- const args = process.argv.slice(2);
5
- const controllerName = args[0];
6
- const isResource = args.includes('-r') || args.includes('--resource');
7
-
8
- if (!controllerName || controllerName.startsWith('-')) {
9
- console.error('āŒ Please specify the controller name.');
10
- console.error(' Usage: npm run make:controller <ControllerName> [-r]');
11
- console.error(' Example: npm run make:controller TestController -r');
12
- process.exit(1);
13
- }
14
-
15
- const controllersDir = path.join(__dirname, '..', 'src', 'controllers');
16
-
17
- // Ensure controllers directory exists
18
- if (!fs.existsSync(controllersDir)) {
19
- fs.mkdirSync(controllersDir, { recursive: true });
20
- }
21
-
22
- let fileName = controllerName;
23
- if (!fileName.endsWith('.ts')) {
24
- fileName += '.ts';
25
- }
26
-
27
- // Capitalize first letter if convention is needed, but usually users provide PascalCase
28
- // We will just use what user provided but ensure .ts extension
29
- const filePath = path.join(controllersDir, fileName);
30
-
31
- if (fs.existsSync(filePath)) {
32
- console.error(`āŒ Controller ${fileName} already exists at ${filePath}`);
33
- process.exit(1);
34
- }
35
-
36
- let content = '';
37
-
38
- if (isResource) {
39
- content = `import { Request, Response } from "express";
40
- import { prisma } from "../core/database";
41
- import { sendSuccess, sendError } from "../utils/response";
42
- import { getPagination, buildPaginationMeta } from "../utils/pagination";
43
-
44
- /**
45
- * Display a listing of the resource.
46
- */
47
- export async function index(req: Request, res: Response) {
48
- const { page, perPage, skip, take } = getPagination(req.query);
49
-
50
- // TODO: Add search logic
51
- const where: any = {};
52
-
53
- // TODO: Replace 'model' with your actual model name
54
- /*
55
- const [data, total] = await Promise.all([
56
- prisma.model.findMany({
57
- where,
58
- skip,
59
- take,
60
- orderBy: { created_at: "desc" },
61
- }),
62
- prisma.model.count({ where }),
63
- ]);
64
-
65
- const serialized = data.map((item: any) => ({
66
- ...item,
67
- id: item.id.toString(),
68
- }));
69
-
70
- const meta = buildPaginationMeta(page, perPage, total);
71
-
72
- sendSuccess(res, 200, "Data retrieved successfully", {
73
- data: serialized,
74
- meta,
75
- });
76
- */
77
-
78
- sendSuccess(res, 200, "Index method", { message: "Implement me" });
79
- }
80
-
81
- /**
82
- * Display the specified resource.
83
- */
84
- export async function show(req: Request, res: Response) {
85
- const { id } = req.params;
86
-
87
- // TODO: Replace 'model' with your actual model name
88
- /*
89
- const item = await prisma.model.findUnique({
90
- where: { id: BigInt(id) },
91
- });
92
-
93
- if (!item) {
94
- sendError(res, 404, "Data not found");
95
- return;
96
- }
97
-
98
- sendSuccess(res, 200, "Data retrieved successfully", {
99
- ...item,
100
- id: item.id.toString(),
101
- });
102
- */
103
- sendSuccess(res, 200, "Show method", { id, message: "Implement me" });
104
- }
105
-
106
- /**
107
- * Store a newly created resource in storage.
108
- */
109
- export async function store(req: Request, res: Response) {
110
- // TODO: Add validation
111
- // const parsed = createSchema.safeParse(req.body);
112
- // if (!parsed.success) { ... }
113
-
114
- // TODO: Replace 'model' with your actual model name
115
- /*
116
- const item = await prisma.model.create({
117
- data: {
118
- ...req.body,
119
- created_at: new Date(),
120
- updated_at: new Date(),
121
- },
122
- });
123
-
124
- sendSuccess(res, 201, "Data created successfully", {
125
- ...item,
126
- id: item.id.toString(),
127
- });
128
- */
129
- sendSuccess(res, 201, "Store method", { message: "Implement me" });
130
- }
131
-
132
- /**
133
- * Update the specified resource in storage.
134
- */
135
- export async function update(req: Request, res: Response) {
136
- const { id } = req.params;
137
-
138
- // TODO: Add validation
139
- // const parsed = updateSchema.safeParse(req.body);
140
-
141
- // TODO: Replace 'model' with your actual model name
142
- /*
143
- const existing = await prisma.model.findUnique({
144
- where: { id: BigInt(id) },
145
- });
146
-
147
- if (!existing) {
148
- sendError(res, 404, "Data not found");
149
- return;
150
- }
151
-
152
- const updated = await prisma.model.update({
153
- where: { id: BigInt(id) },
154
- data: {
155
- ...req.body,
156
- updated_at: new Date(),
157
- },
158
- });
159
-
160
- sendSuccess(res, 200, "Data updated successfully", {
161
- ...updated,
162
- id: updated.id.toString(),
163
- });
164
- */
165
- sendSuccess(res, 200, "Update method", { id, message: "Implement me" });
166
- }
167
-
168
- /**
169
- * Remove the specified resource from storage.
170
- */
171
- export async function destroy(req: Request, res: Response) {
172
- const { id } = req.params;
173
-
174
- // TODO: Replace 'model' with your actual model name
175
- /*
176
- const existing = await prisma.model.findUnique({
177
- where: { id: BigInt(id) },
178
- });
179
-
180
- if (!existing) {
181
- sendError(res, 404, "Data not found");
182
- return;
183
- }
184
-
185
- await prisma.model.delete({
186
- where: { id: BigInt(id) },
187
- });
188
- */
189
-
190
- sendSuccess(res, 200, "Data deleted successfully", null);
191
- }
192
- `;
193
- } else {
194
- content = `import { Request, Response } from "express";
195
- import { sendSuccess, sendError } from "../utils/response";
196
-
197
- export async function index(req: Request, res: Response) {
198
- sendSuccess(res, 200, "Hello from ${controllerName}", null);
199
- }
200
- `;
201
- }
202
-
203
- fs.writeFileSync(filePath, content);
204
-
205
- console.log(`āœ… Controller created: src/controllers/${fileName}`);
@@ -1,42 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- const modelName = process.argv[2];
5
-
6
- if (!modelName) {
7
- console.error('āŒ Please specify the model name.');
8
- console.error(' Usage: npm run make:model <ModelName>');
9
- console.error(' Example: npm run make:model Product');
10
- process.exit(1);
11
- }
12
-
13
- const PascalCaseName = modelName.charAt(0).toUpperCase() + modelName.slice(1);
14
- const tableName = modelName.toLowerCase() + 's'; // simple pluralization
15
-
16
- const modelsDir = path.join(__dirname, '..', 'src', 'models');
17
- const modelPath = path.join(modelsDir, `${PascalCaseName}.prisma`);
18
-
19
- if (fs.existsSync(modelPath)) {
20
- console.error(`āŒ Model ${PascalCaseName} already exists at ${modelPath}`);
21
- process.exit(1);
22
- }
23
-
24
- // Ensure models directory exists
25
- if (!fs.existsSync(modelsDir)) {
26
- fs.mkdirSync(modelsDir, { recursive: true });
27
- }
28
-
29
- const content = `model ${tableName} {
30
- id BigInt @id @default(autoincrement())
31
- name String
32
- createdAt DateTime? @default(now())
33
- updatedAt DateTime? @updatedAt
34
- }
35
- `;
36
-
37
- fs.writeFileSync(modelPath, content);
38
-
39
- console.log(`āœ… Model created: src/models/${PascalCaseName}.prisma`);
40
- console.log(`\nNext steps:`);
41
- console.log(`1. Edit the model file.`);
42
- console.log(`2. Run 'npm run prisma:migrate' to update the database.`);
@@ -1,158 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- const moduleName = process.argv[2];
5
-
6
- if (!moduleName) {
7
- console.error('āŒ Please specify the module name.');
8
- console.error(' Usage: npm run make:module <name>');
9
- console.error(' Example: npm run make:module product');
10
- process.exit(1);
11
- }
12
-
13
- // Convert "product" -> "Product" (PascalCase) for Class names
14
- const PascalCaseName = moduleName.charAt(0).toUpperCase() + moduleName.slice(1);
15
- // Convert "product" -> "product" (camelCase) for variables/files
16
- const camelCaseName = moduleName.toLowerCase();
17
-
18
- const srcDir = path.join(__dirname, '..', 'src');
19
-
20
- // 1. Create Controller
21
- const controllerContent = `import { Request, Response } from 'express';
22
- import { ${PascalCaseName}Service } from '../services/${camelCaseName}Service';
23
- import { successResponse, errorResponse } from '../utils/response';
24
-
25
- export const ${PascalCaseName}Controller = {
26
- async getAll(req: Request, res: Response) {
27
- try {
28
- const data = await ${PascalCaseName}Service.getAll();
29
- return successResponse(res, data, '${PascalCaseName}s retrieved successfully');
30
- } catch (error) {
31
- return errorResponse(res, error as Error);
32
- }
33
- },
34
-
35
- async getById(req: Request, res: Response) {
36
- try {
37
- const { id } = req.params;
38
- const data = await ${PascalCaseName}Service.getById(id);
39
- if (!data) return errorResponse(res, new Error('${PascalCaseName} not found'), 404);
40
- return successResponse(res, data, '${PascalCaseName} retrieved successfully');
41
- } catch (error) {
42
- return errorResponse(res, error as Error);
43
- }
44
- },
45
-
46
- async create(req: Request, res: Response) {
47
- try {
48
- const data = await ${PascalCaseName}Service.create(req.body);
49
- return successResponse(res, data, '${PascalCaseName} created successfully', 201);
50
- } catch (error) {
51
- return errorResponse(res, error as Error);
52
- }
53
- },
54
-
55
- async update(req: Request, res: Response) {
56
- try {
57
- const { id } = req.params;
58
- const data = await ${PascalCaseName}Service.update(id, req.body);
59
- return successResponse(res, data, '${PascalCaseName} updated successfully');
60
- } catch (error) {
61
- return errorResponse(res, error as Error);
62
- }
63
- },
64
-
65
- async delete(req: Request, res: Response) {
66
- try {
67
- const { id } = req.params;
68
- await ${PascalCaseName}Service.delete(id);
69
- return successResponse(res, null, '${PascalCaseName} deleted successfully');
70
- } catch (error) {
71
- return errorResponse(res, error as Error);
72
- }
73
- }
74
- };
75
- `;
76
-
77
- // 2. Create Service
78
- const serviceContent = `// import prisma from '../prisma'; // Uncomment this line if you use Prisma
79
-
80
- export const ${PascalCaseName}Service = {
81
- async getAll() {
82
- // return prisma.${camelCaseName}.findMany();
83
- return [{ id: 1, name: 'Sample ${PascalCaseName}' }]; // Placeholder
84
- },
85
-
86
- async getById(id: string) {
87
- // return prisma.${camelCaseName}.findUnique({ where: { id } });
88
- return { id, name: 'Sample ${PascalCaseName}' }; // Placeholder
89
- },
90
-
91
- async create(data: any) {
92
- // return prisma.${camelCaseName}.create({ data });
93
- return { id: Date.now(), ...data }; // Placeholder
94
- },
95
-
96
- async update(id: string, data: any) {
97
- // return prisma.${camelCaseName}.update({ where: { id }, data });
98
- return { id, ...data }; // Placeholder
99
- },
100
-
101
- async delete(id: string) {
102
- // return prisma.${camelCaseName}.delete({ where: { id } });
103
- return true; // Placeholder
104
- }
105
- };
106
- `;
107
-
108
- // 3. Create Route
109
- const routeContent = `import { Router } from 'express';
110
- import { ${PascalCaseName}Controller } from '../controllers/${camelCaseName}Controller';
111
- import { authenticateToken } from '../middleware/auth';
112
-
113
- const router = Router();
114
-
115
- router.get('/', authenticateToken, ${PascalCaseName}Controller.getAll);
116
- router.get('/:id', authenticateToken, ${PascalCaseName}Controller.getById);
117
- router.post('/', authenticateToken, ${PascalCaseName}Controller.create);
118
- router.put('/:id', authenticateToken, ${PascalCaseName}Controller.update);
119
- router.delete('/:id', authenticateToken, ${PascalCaseName}Controller.delete);
120
-
121
- export default router;
122
- `;
123
-
124
- const paths = {
125
- controller: path.join(srcDir, 'controllers', `${camelCaseName}Controller.ts`),
126
- service: path.join(srcDir, 'services', `${camelCaseName}Service.ts`),
127
- route: path.join(srcDir, 'routes', `${camelCaseName}.ts`),
128
- };
129
-
130
- // Helper to create directory if not exists
131
- function ensureDir(filePath) {
132
- const dirname = path.dirname(filePath);
133
- if (!fs.existsSync(dirname)) {
134
- fs.mkdirSync(dirname, { recursive: true });
135
- }
136
- }
137
-
138
- try {
139
- ensureDir(paths.controller);
140
- fs.writeFileSync(paths.controller, controllerContent);
141
- console.log(`āœ… Created Controller: src/controllers/${camelCaseName}Controller.ts`);
142
-
143
- ensureDir(paths.service);
144
- fs.writeFileSync(paths.service, serviceContent);
145
- console.log(`āœ… Created Service: src/services/${camelCaseName}Service.ts`);
146
-
147
- ensureDir(paths.route);
148
- fs.writeFileSync(paths.route, routeContent);
149
- console.log(`āœ… Created Route: src/routes/${camelCaseName}.ts`);
150
-
151
- console.log('\nāš ļø Don\'t forget to register the new route in src/index.ts or src/server.ts!');
152
- console.log(` import ${camelCaseName}Routes from './routes/${camelCaseName}';`);
153
- console.log(` app.use('/${camelCaseName}s', ${camelCaseName}Routes);`);
154
-
155
- } catch (error) {
156
- console.error('āŒ Error creating module:', error);
157
- process.exit(1);
158
- }