@chimerai/cli 0.2.73

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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +293 -0
  3. package/dist/cli.d.ts +7 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +317 -0
  6. package/dist/commands/add.d.ts +11 -0
  7. package/dist/commands/add.d.ts.map +1 -0
  8. package/dist/commands/add.js +2126 -0
  9. package/dist/commands/create.d.ts +12 -0
  10. package/dist/commands/create.d.ts.map +1 -0
  11. package/dist/commands/create.js +1703 -0
  12. package/dist/commands/deploy.d.ts +11 -0
  13. package/dist/commands/deploy.d.ts.map +1 -0
  14. package/dist/commands/deploy.js +219 -0
  15. package/dist/commands/dev.d.ts +17 -0
  16. package/dist/commands/dev.d.ts.map +1 -0
  17. package/dist/commands/dev.js +206 -0
  18. package/dist/commands/doctor.d.ts +11 -0
  19. package/dist/commands/doctor.d.ts.map +1 -0
  20. package/dist/commands/doctor.js +728 -0
  21. package/dist/commands/generate.d.ts +19 -0
  22. package/dist/commands/generate.d.ts.map +1 -0
  23. package/dist/commands/generate.js +429 -0
  24. package/dist/commands/init.d.ts +11 -0
  25. package/dist/commands/init.d.ts.map +1 -0
  26. package/dist/commands/init.js +269 -0
  27. package/dist/commands/list.d.ts +12 -0
  28. package/dist/commands/list.d.ts.map +1 -0
  29. package/dist/commands/list.js +328 -0
  30. package/dist/commands/migrate.d.ts +14 -0
  31. package/dist/commands/migrate.d.ts.map +1 -0
  32. package/dist/commands/migrate.js +197 -0
  33. package/dist/commands/plugin.d.ts +10 -0
  34. package/dist/commands/plugin.d.ts.map +1 -0
  35. package/dist/commands/plugin.js +239 -0
  36. package/dist/commands/remove.d.ts +11 -0
  37. package/dist/commands/remove.d.ts.map +1 -0
  38. package/dist/commands/remove.js +472 -0
  39. package/dist/commands/secret.d.ts +12 -0
  40. package/dist/commands/secret.d.ts.map +1 -0
  41. package/dist/commands/secret.js +102 -0
  42. package/dist/commands/setup.d.ts +9 -0
  43. package/dist/commands/setup.d.ts.map +1 -0
  44. package/dist/commands/setup.js +788 -0
  45. package/dist/commands/update.d.ts +14 -0
  46. package/dist/commands/update.d.ts.map +1 -0
  47. package/dist/commands/update.js +211 -0
  48. package/dist/commands/use.d.ts +9 -0
  49. package/dist/commands/use.d.ts.map +1 -0
  50. package/dist/commands/use.js +51 -0
  51. package/dist/index.d.ts +22 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +45 -0
  54. package/dist/license.d.ts +55 -0
  55. package/dist/license.d.ts.map +1 -0
  56. package/dist/license.js +258 -0
  57. package/dist/scanner.d.ts +31 -0
  58. package/dist/scanner.d.ts.map +1 -0
  59. package/dist/scanner.js +113 -0
  60. package/dist/schema-manager.d.ts +26 -0
  61. package/dist/schema-manager.d.ts.map +1 -0
  62. package/dist/schema-manager.js +132 -0
  63. package/dist/templates/admin.d.ts +49 -0
  64. package/dist/templates/admin.d.ts.map +1 -0
  65. package/dist/templates/admin.js +1358 -0
  66. package/dist/templates/ai-routes.d.ts +17 -0
  67. package/dist/templates/ai-routes.d.ts.map +1 -0
  68. package/dist/templates/ai-routes.js +1130 -0
  69. package/dist/templates/ai-service-tools.d.ts +22 -0
  70. package/dist/templates/ai-service-tools.d.ts.map +1 -0
  71. package/dist/templates/ai-service-tools.js +1424 -0
  72. package/dist/templates/ai-service.d.ts +66 -0
  73. package/dist/templates/ai-service.d.ts.map +1 -0
  74. package/dist/templates/ai-service.js +2202 -0
  75. package/dist/templates/api-routes.d.ts +108 -0
  76. package/dist/templates/api-routes.d.ts.map +1 -0
  77. package/dist/templates/api-routes.js +1219 -0
  78. package/dist/templates/auth.d.ts +48 -0
  79. package/dist/templates/auth.d.ts.map +1 -0
  80. package/dist/templates/auth.js +381 -0
  81. package/dist/templates/billing.d.ts +44 -0
  82. package/dist/templates/billing.d.ts.map +1 -0
  83. package/dist/templates/billing.js +551 -0
  84. package/dist/templates/chat.d.ts +63 -0
  85. package/dist/templates/chat.d.ts.map +1 -0
  86. package/dist/templates/chat.js +1979 -0
  87. package/dist/templates/components.d.ts +22 -0
  88. package/dist/templates/components.d.ts.map +1 -0
  89. package/dist/templates/components.js +672 -0
  90. package/dist/templates/config.d.ts +6 -0
  91. package/dist/templates/config.d.ts.map +1 -0
  92. package/dist/templates/config.js +86 -0
  93. package/dist/templates/docker.d.ts +25 -0
  94. package/dist/templates/docker.d.ts.map +1 -0
  95. package/dist/templates/docker.js +165 -0
  96. package/dist/templates/gdpr.d.ts +16 -0
  97. package/dist/templates/gdpr.d.ts.map +1 -0
  98. package/dist/templates/gdpr.js +259 -0
  99. package/dist/templates/index.d.ts +77 -0
  100. package/dist/templates/index.d.ts.map +1 -0
  101. package/dist/templates/index.js +339 -0
  102. package/dist/templates/layout.d.ts +67 -0
  103. package/dist/templates/layout.d.ts.map +1 -0
  104. package/dist/templates/layout.js +670 -0
  105. package/dist/templates/mfa.d.ts +23 -0
  106. package/dist/templates/mfa.d.ts.map +1 -0
  107. package/dist/templates/mfa.js +353 -0
  108. package/dist/templates/middleware.d.ts +12 -0
  109. package/dist/templates/middleware.d.ts.map +1 -0
  110. package/dist/templates/middleware.js +116 -0
  111. package/dist/templates/prisma.d.ts +35 -0
  112. package/dist/templates/prisma.d.ts.map +1 -0
  113. package/dist/templates/prisma.js +724 -0
  114. package/dist/templates/provider-routes.d.ts +21 -0
  115. package/dist/templates/provider-routes.d.ts.map +1 -0
  116. package/dist/templates/provider-routes.js +1203 -0
  117. package/dist/templates/rag.d.ts +48 -0
  118. package/dist/templates/rag.d.ts.map +1 -0
  119. package/dist/templates/rag.js +532 -0
  120. package/dist/templates/widget.d.ts +64 -0
  121. package/dist/templates/widget.d.ts.map +1 -0
  122. package/dist/templates/widget.js +1360 -0
  123. package/dist/utils/provider-db.d.ts +63 -0
  124. package/dist/utils/provider-db.d.ts.map +1 -0
  125. package/dist/utils/provider-db.js +300 -0
  126. package/dist/utils.d.ts +78 -0
  127. package/dist/utils.d.ts.map +1 -0
  128. package/dist/utils.js +330 -0
  129. package/package.json +60 -0
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Generate Command - PHASE 3.4
3
+ * Code generation scaffolding for models, API routes, pages, components, and hooks
4
+ * Automatically generates Prisma models, CRUD API routes, and TypeScript scaffolding
5
+ */
6
+ export interface GenerateOptions {
7
+ dir: string;
8
+ force: boolean;
9
+ }
10
+ type GeneratorType = 'model' | 'api' | 'page' | 'component' | 'hook';
11
+ /**
12
+ * Main generate command - routes to specific generators
13
+ * @param type - Generator type (model, api, page, component, hook)
14
+ * @param name - Name of what to generate (e.g., "user-profile", "post")
15
+ * @param options - Generate options
16
+ */
17
+ export declare function generateCommand(type: GeneratorType, name: string, options: GenerateOptions): Promise<void>;
18
+ export {};
19
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,KAAK,aAAa,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;AAErE;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CA6Bf"}
@@ -0,0 +1,429 @@
1
+ "use strict";
2
+ /**
3
+ * Generate Command - PHASE 3.4
4
+ * Code generation scaffolding for models, API routes, pages, components, and hooks
5
+ * Automatically generates Prisma models, CRUD API routes, and TypeScript scaffolding
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.generateCommand = generateCommand;
12
+ const chalk_1 = __importDefault(require("chalk"));
13
+ const path_1 = __importDefault(require("path"));
14
+ const fs_extra_1 = __importDefault(require("fs-extra"));
15
+ const scanner_js_1 = require("../scanner.js");
16
+ const schema_manager_js_1 = require("../schema-manager.js");
17
+ const utils_js_1 = require("../utils.js");
18
+ /**
19
+ * Main generate command - routes to specific generators
20
+ * @param type - Generator type (model, api, page, component, hook)
21
+ * @param name - Name of what to generate (e.g., "user-profile", "post")
22
+ * @param options - Generate options
23
+ */
24
+ async function generateCommand(type, name, options) {
25
+ const targetDir = (0, utils_js_1.resolveTargetDir)(options.dir || '.');
26
+ const project = await (0, scanner_js_1.scanProject)(targetDir);
27
+ if (!project.hasPackageJson) {
28
+ (0, utils_js_1.handleCliError)('No package.json found. Run: chimerai create <name>');
29
+ }
30
+ switch (type) {
31
+ case 'model':
32
+ await generateModel(name, targetDir, project, options.force);
33
+ break;
34
+ case 'api':
35
+ await generateApiRoute(name, targetDir, project, options.force);
36
+ break;
37
+ case 'page':
38
+ await generatePage(name, targetDir, project, options.force);
39
+ break;
40
+ case 'component':
41
+ await generateComponent(name, targetDir, project, options.force);
42
+ break;
43
+ case 'hook':
44
+ await generateHook(name, targetDir, project, options.force);
45
+ break;
46
+ default:
47
+ (0, utils_js_1.handleCliError)(`Unknown generator type: ${type}. Available types: model, api, page, component, hook`);
48
+ }
49
+ }
50
+ /**
51
+ * Normalize names: "user-profile" → { pascal: "UserProfile", camel: "userProfile", kebab: "user-profile" }
52
+ */
53
+ function normalizeName(name) {
54
+ const kebab = name
55
+ .toLowerCase()
56
+ .replace(/([A-Z])/g, '-$1')
57
+ .toLowerCase();
58
+ const pascal = kebab
59
+ .split('-')
60
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
61
+ .join('');
62
+ const camel = pascal.charAt(0).toLowerCase() + pascal.slice(1);
63
+ const snake = kebab.replace(/-/g, '_');
64
+ return { pascal, camel, kebab, snake };
65
+ }
66
+ /**
67
+ * Extract hook name - removes 'use' prefix if present
68
+ * e.g., 'use-auth' -> 'Auth', 'useAuth' -> 'Auth', 'auth' -> 'Auth'
69
+ */
70
+ function extractHookName(name) {
71
+ // Remove 'use' prefix if present (case-insensitive)
72
+ let cleaned = name.replace(/^use-?/i, '');
73
+ // Ensure it starts with uppercase
74
+ return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);
75
+ }
76
+ /**
77
+ * Generate Prisma model with CRUD API routes
78
+ */
79
+ async function generateModel(name, targetDir, project, force) {
80
+ if (!project.hasPrisma) {
81
+ (0, utils_js_1.handleCliError)('Prisma not configured in this project. Run: chimerai init and select RBAC');
82
+ }
83
+ // Preserve original casing for model name (just ensure first char is uppercase)
84
+ const modelName = name.charAt(0).toUpperCase() + name.slice(1);
85
+ const { kebab, camel } = normalizeName(name);
86
+ console.log(chalk_1.default.blue(`\n 📦 Generating model: ${chalk_1.default.bold(modelName)}\n`));
87
+ // 1. Add Prisma model
88
+ const schemaPath = path_1.default.join(targetDir, 'prisma', 'schema.prisma');
89
+ const prismaModel = `
90
+ model ${modelName} {
91
+ id String @id @default(cuid())
92
+ // TODO: Add your fields here
93
+ createdAt DateTime @default(now())
94
+ updatedAt DateTime @updatedAt
95
+
96
+ @@map("${kebab}")
97
+ }
98
+ `;
99
+ try {
100
+ await (0, schema_manager_js_1.extendPrismaSchema)(schemaPath, prismaModel);
101
+ console.log(chalk_1.default.green(` ✓ prisma/schema.prisma (${modelName} model)`));
102
+ }
103
+ catch (error) {
104
+ (0, utils_js_1.handleCliError)(`Failed to add Prisma model: ${error.message}`);
105
+ }
106
+ // 2. Generate GET/POST API route
107
+ const apiRoute = generateCrudRoute(modelName, camel);
108
+ const apiPath = path_1.default.join(targetDir, 'app', 'api', kebab, 'route.ts');
109
+ if (await fs_extra_1.default.pathExists(apiPath)) {
110
+ if (!force) {
111
+ console.log(chalk_1.default.yellow(` ⊘ app/api/${kebab}/route.ts already exists (use --force to overwrite)`));
112
+ return;
113
+ }
114
+ }
115
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(apiPath));
116
+ await fs_extra_1.default.writeFile(apiPath, apiRoute);
117
+ console.log(chalk_1.default.green(` ✓ app/api/${kebab}/route.ts (GET, POST)`));
118
+ // 3. Generate GET/PUT/DELETE API route for [id]
119
+ const apiIdRoute = generateCrudByIdRoute(modelName, camel);
120
+ const apiIdPath = path_1.default.join(targetDir, 'app', 'api', kebab, '[id]', 'route.ts');
121
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(apiIdPath));
122
+ await fs_extra_1.default.writeFile(apiIdPath, apiIdRoute);
123
+ console.log(chalk_1.default.green(` ✓ app/api/${kebab}/[id]/route.ts (GET, PUT, DELETE)`));
124
+ // Summary
125
+ console.log(chalk_1.default.cyan('\n 📋 Next steps:'));
126
+ console.log(chalk_1.default.gray(` 1. Edit prisma/schema.prisma to add fields to ${modelName}`));
127
+ console.log(chalk_1.default.gray(` 2. Run: npx prisma db push`));
128
+ console.log(chalk_1.default.gray(` 3. Your API is ready at /api/${kebab}\n`));
129
+ }
130
+ /**
131
+ * Generate standalone API route
132
+ */
133
+ async function generateApiRoute(name, targetDir, _project, force) {
134
+ const { kebab } = normalizeName(name);
135
+ console.log(chalk_1.default.blue(`\n 🔌 Generating API route: ${chalk_1.default.bold(`/api/${kebab}`)}\n`));
136
+ const apiRoute = `import { NextRequest, NextResponse } from 'next/server';
137
+
138
+ export async function GET(request: NextRequest) {
139
+ try {
140
+ // TODO: Implement GET logic
141
+ return NextResponse.json({ data: [] });
142
+ } catch (error) {
143
+ console.error('GET error:', error);
144
+ return NextResponse.json(
145
+ { error: { code: 'INTERNAL_ERROR', message: 'Internal server error' } },
146
+ { status: 500 }
147
+ );
148
+ }
149
+ }
150
+
151
+ export async function POST(request: NextRequest) {
152
+ try {
153
+ const body = await request.json();
154
+ // TODO: Implement POST logic
155
+ return NextResponse.json({ data: body }, { status: 201 });
156
+ } catch (error) {
157
+ console.error('POST error:', error);
158
+ return NextResponse.json(
159
+ { error: { code: 'INTERNAL_ERROR', message: 'Internal server error' } },
160
+ { status: 500 }
161
+ );
162
+ }
163
+ }
164
+ `;
165
+ const apiPath = path_1.default.join(targetDir, 'app', 'api', kebab, 'route.ts');
166
+ if (await fs_extra_1.default.pathExists(apiPath)) {
167
+ if (!force) {
168
+ console.log(chalk_1.default.yellow(` ⊘ app/api/${kebab}/route.ts already exists (use --force to overwrite)`));
169
+ return;
170
+ }
171
+ }
172
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(apiPath));
173
+ await fs_extra_1.default.writeFile(apiPath, apiRoute);
174
+ console.log(chalk_1.default.green(` ✓ app/api/${kebab}/route.ts\n`));
175
+ }
176
+ /**
177
+ * Generate page component
178
+ */
179
+ async function generatePage(name, targetDir, _project, force) {
180
+ const { pascal, kebab } = normalizeName(name);
181
+ console.log(chalk_1.default.blue(`\n 📄 Generating page: ${chalk_1.default.bold(`/${kebab}`)}\n`));
182
+ const page = `'use client';
183
+
184
+ import { useState, useEffect } from 'react';
185
+
186
+ export default function ${pascal}Page() {
187
+ const [data, setData] = useState(null);
188
+ const [loading, setLoading] = useState(true);
189
+
190
+ useEffect(() => {
191
+ // TODO: Fetch data
192
+ setLoading(false);
193
+ }, []);
194
+
195
+ if (loading) return <div>Loading...</div>;
196
+
197
+ return (
198
+ <div className="p-6">
199
+ <h1 className="text-3xl font-bold">${pascal}</h1>
200
+ {/* TODO: Add content */}
201
+ </div>
202
+ );
203
+ }
204
+ `;
205
+ const pagePath = path_1.default.join(targetDir, 'app', kebab, 'page.tsx');
206
+ if (await fs_extra_1.default.pathExists(pagePath)) {
207
+ if (!force) {
208
+ console.log(chalk_1.default.yellow(` ⊘ app/${kebab}/page.tsx already exists (use --force to overwrite)`));
209
+ return;
210
+ }
211
+ }
212
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(pagePath));
213
+ await fs_extra_1.default.writeFile(pagePath, page);
214
+ console.log(chalk_1.default.green(` ✓ app/${kebab}/page.tsx\n`));
215
+ }
216
+ /**
217
+ * Generate React component
218
+ */
219
+ async function generateComponent(name, targetDir, _project, force) {
220
+ const { pascal } = normalizeName(name);
221
+ console.log(chalk_1.default.blue(`\n ⚛️ Generating component: ${chalk_1.default.bold(pascal)}\n`));
222
+ const component = `import React from 'react';
223
+
224
+ interface ${pascal}Props {
225
+ // TODO: Define props
226
+ }
227
+
228
+ export function ${pascal}({ }: ${pascal}Props) {
229
+ return (
230
+ <div>
231
+ {/* TODO: Add JSX */}
232
+ </div>
233
+ );
234
+ }
235
+ `;
236
+ const componentPath = path_1.default.join(targetDir, 'components', `${pascal}.tsx`);
237
+ if (await fs_extra_1.default.pathExists(componentPath)) {
238
+ if (!force) {
239
+ console.log(chalk_1.default.yellow(` ⊘ components/${pascal}.tsx already exists (use --force to overwrite)`));
240
+ return;
241
+ }
242
+ }
243
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(componentPath));
244
+ await fs_extra_1.default.writeFile(componentPath, component);
245
+ console.log(chalk_1.default.green(` ✓ components/${pascal}.tsx\n`));
246
+ }
247
+ /**
248
+ * Generate custom hook
249
+ */
250
+ async function generateHook(name, targetDir, _project, force) {
251
+ const hookName = extractHookName(name);
252
+ console.log(chalk_1.default.blue(`\n 🪝 Generating hook: ${chalk_1.default.bold(`use${hookName}`)}\n`));
253
+ const hook = `'use client';
254
+
255
+ import { useState, useEffect } from 'react';
256
+
257
+ export function use${hookName}() {
258
+ const [state, setState] = useState(null);
259
+ const [loading, setLoading] = useState(false);
260
+ const [error, setError] = useState<Error | null>(null);
261
+
262
+ useEffect(() => {
263
+ // TODO: Implement hook logic
264
+ }, []);
265
+
266
+ return { state, loading, error };
267
+ }
268
+ `;
269
+ const hookPath = path_1.default.join(targetDir, 'hooks', `use${hookName}.ts`);
270
+ if (await fs_extra_1.default.pathExists(hookPath)) {
271
+ if (!force) {
272
+ console.log(chalk_1.default.yellow(` ⊘ hooks/use${hookName}.ts already exists (use --force to overwrite)`));
273
+ return;
274
+ }
275
+ }
276
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(hookPath));
277
+ await fs_extra_1.default.writeFile(hookPath, hook);
278
+ console.log(chalk_1.default.green(` ✓ hooks/use${hookName}.ts\n`));
279
+ }
280
+ /**
281
+ * Generate CRUD API route (GET list, POST create)
282
+ */
283
+ function generateCrudRoute(modelName, varName) {
284
+ return `import { NextRequest, NextResponse } from 'next/server';
285
+ import { prisma } from '@/lib/prisma';
286
+
287
+ /**
288
+ * GET /api/${varName.toLowerCase()}s
289
+ * List all ${varName} records with pagination
290
+ */
291
+ export async function GET(request: NextRequest) {
292
+ try {
293
+ const { searchParams } = new URL(request.url);
294
+ const page = Math.max(1, parseInt(searchParams.get('page') || '1', 10));
295
+ const limit = Math.min(100, Math.max(1, parseInt(searchParams.get('limit') || '20', 10)));
296
+ const skip = (page - 1) * limit;
297
+
298
+ const [items, total] = await Promise.all([
299
+ prisma.${varName}.findMany({
300
+ skip,
301
+ take: limit,
302
+ orderBy: { createdAt: 'desc' },
303
+ }),
304
+ prisma.${varName}.count(),
305
+ ]);
306
+
307
+ return NextResponse.json({
308
+ data: items,
309
+ pagination: {
310
+ page,
311
+ limit,
312
+ total,
313
+ totalPages: Math.ceil(total / limit),
314
+ },
315
+ });
316
+ } catch (error) {
317
+ console.error('Failed to fetch ${varName} records:', error);
318
+ return NextResponse.json(
319
+ { error: { code: 'INTERNAL_ERROR', message: 'Failed to fetch records' } },
320
+ { status: 500 }
321
+ );
322
+ }
323
+ }
324
+
325
+ /**
326
+ * POST /api/${varName.toLowerCase()}s
327
+ * Create a new ${varName}
328
+ */
329
+ export async function POST(request: NextRequest) {
330
+ try {
331
+ const body = await request.json();
332
+
333
+ const item = await prisma.${varName}.create({
334
+ data: body,
335
+ });
336
+
337
+ return NextResponse.json({ data: item }, { status: 201 });
338
+ } catch (error) {
339
+ console.error('Failed to create ${varName}:', error);
340
+ return NextResponse.json(
341
+ { error: { code: 'INTERNAL_ERROR', message: 'Failed to create record' } },
342
+ { status: 500 }
343
+ );
344
+ }
345
+ }
346
+ `;
347
+ }
348
+ /**
349
+ * Generate CRUD API route for [id] (GET, PUT, DELETE)
350
+ */
351
+ function generateCrudByIdRoute(modelName, varName) {
352
+ return `import { NextRequest, NextResponse } from 'next/server';
353
+ import { prisma } from '@/lib/prisma';
354
+
355
+ interface Params {
356
+ params: { id: string };
357
+ }
358
+
359
+ /**
360
+ * GET /api/${varName.toLowerCase()}s/:id
361
+ * Get a single ${varName}
362
+ */
363
+ export async function GET(request: NextRequest, { params }: Params) {
364
+ try {
365
+ const item = await prisma.${varName}.findUnique({
366
+ where: { id: params.id },
367
+ });
368
+
369
+ if (!item) {
370
+ return NextResponse.json(
371
+ { error: { code: 'NOT_FOUND', message: '${modelName} not found' } },
372
+ { status: 404 }
373
+ );
374
+ }
375
+
376
+ return NextResponse.json({ data: item });
377
+ } catch (error) {
378
+ console.error('Failed to fetch ${varName}:', error);
379
+ return NextResponse.json(
380
+ { error: { code: 'INTERNAL_ERROR', message: 'Failed to fetch record' } },
381
+ { status: 500 }
382
+ );
383
+ }
384
+ }
385
+
386
+ /**
387
+ * PUT /api/${varName.toLowerCase()}s/:id
388
+ * Update a ${varName}
389
+ */
390
+ export async function PUT(request: NextRequest, { params }: Params) {
391
+ try {
392
+ const body = await request.json();
393
+
394
+ const item = await prisma.${varName}.update({
395
+ where: { id: params.id },
396
+ data: body,
397
+ });
398
+
399
+ return NextResponse.json({ data: item });
400
+ } catch (error) {
401
+ console.error('Failed to update ${varName}:', error);
402
+ return NextResponse.json(
403
+ { error: { code: 'INTERNAL_ERROR', message: 'Failed to update record' } },
404
+ { status: 500 }
405
+ );
406
+ }
407
+ }
408
+
409
+ /**
410
+ * DELETE /api/${varName.toLowerCase()}s/:id
411
+ * Delete a ${varName}
412
+ */
413
+ export async function DELETE(request: NextRequest, { params }: Params) {
414
+ try {
415
+ await prisma.${varName}.delete({
416
+ where: { id: params.id },
417
+ });
418
+
419
+ return NextResponse.json({ success: true });
420
+ } catch (error) {
421
+ console.error('Failed to delete ${varName}:', error);
422
+ return NextResponse.json(
423
+ { error: { code: 'INTERNAL_ERROR', message: 'Failed to delete record' } },
424
+ { status: 500 }
425
+ );
426
+ }
427
+ }
428
+ `;
429
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Init Command - Initialize RBAC or complete project
3
+ * REFACTORED: Uses generic installFeature() instead of individual install functions (PHASE 2.1)
4
+ */
5
+ interface InitOptions {
6
+ dir: string;
7
+ yes: boolean;
8
+ }
9
+ export declare function initCommand(feature: string, options: InitOptions): Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,UAAU,WAAW;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,OAAO,CAAC;CACd;AAyND,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,iBAiDtE"}