frontend-hamroun 1.2.16 → 1.2.17

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 (158) hide show
  1. package/README.md +4 -0
  2. package/bin/cli.js +673 -0
  3. package/dist/component.d.ts +1 -1
  4. package/dist/context.d.ts +4 -3
  5. package/dist/index.client.d.ts +11 -0
  6. package/dist/index.d.ts +9 -89
  7. package/dist/index.js +396 -67
  8. package/dist/index.js.map +1 -0
  9. package/dist/index.mjs +392 -0
  10. package/dist/index.mjs.map +1 -0
  11. package/dist/jsx-runtime/jsx-runtime.d.ts +0 -1
  12. package/dist/jsx-runtime.d.ts +1 -1
  13. package/dist/renderer.d.ts +0 -10
  14. package/dist/server-renderer.d.ts +0 -3
  15. package/dist/server-types.d.ts +42 -0
  16. package/package.json +69 -41
  17. package/templates/basic-app/index.html +6 -6
  18. package/templates/basic-app/package.json +18 -7
  19. package/templates/basic-app/postcss.config.js +0 -1
  20. package/templates/basic-app/src/main.tsx +1 -10
  21. package/templates/basic-app/tailwind.config.js +2 -23
  22. package/templates/basic-app/tsconfig.json +4 -17
  23. package/templates/basic-app/vite.config.ts +3 -54
  24. package/templates/fullstack-app/api/hello.ts +18 -0
  25. package/templates/fullstack-app/api/users/[id].ts +73 -0
  26. package/templates/fullstack-app/api/users/index.ts +32 -0
  27. package/templates/fullstack-app/package.json +31 -0
  28. package/templates/fullstack-app/server.ts +46 -0
  29. package/templates/fullstack-app/src/pages/index.tsx +59 -0
  30. package/templates/ssr-template/vite.config.ts +1 -11
  31. package/bin/cli.cjs +0 -16
  32. package/bin/cli.mjs +0 -237
  33. package/dist/backend/api-utils.d.ts +0 -38
  34. package/dist/backend/api-utils.js +0 -135
  35. package/dist/backend/auth.d.ts +0 -134
  36. package/dist/backend/auth.js +0 -387
  37. package/dist/backend/database.d.ts +0 -27
  38. package/dist/backend/database.js +0 -91
  39. package/dist/backend/model.d.ts +0 -43
  40. package/dist/backend/model.js +0 -178
  41. package/dist/backend/router.d.ts +0 -27
  42. package/dist/backend/router.js +0 -137
  43. package/dist/backend/server.d.ts +0 -19
  44. package/dist/backend/server.js +0 -268
  45. package/dist/backend/types.d.ts +0 -217
  46. package/dist/backend/types.js +0 -1
  47. package/dist/batch.js +0 -22
  48. package/dist/cli/index.d.ts +0 -2
  49. package/dist/cli/index.js +0 -215
  50. package/dist/component.js +0 -84
  51. package/dist/components/Counter.js +0 -2
  52. package/dist/context.js +0 -18
  53. package/dist/frontend-hamroun.es.js +0 -1378
  54. package/dist/frontend-hamroun.umd.js +0 -66
  55. package/dist/hooks.js +0 -164
  56. package/dist/jsx-runtime/index.d.ts +0 -11
  57. package/dist/jsx-runtime/index.js +0 -19
  58. package/dist/jsx-runtime/jsx-dev-runtime.js +0 -1
  59. package/dist/jsx-runtime/jsx-runtime.js +0 -95
  60. package/dist/jsx-runtime.js +0 -192
  61. package/dist/renderer.js +0 -51
  62. package/dist/server-renderer.js +0 -102
  63. package/dist/types.js +0 -1
  64. package/dist/vdom.js +0 -27
  65. package/scripts/build-cli.js +0 -1199
  66. package/scripts/generate.js +0 -134
  67. package/src/backend/api-utils.ts +0 -178
  68. package/src/backend/auth.ts +0 -544
  69. package/src/backend/database.ts +0 -104
  70. package/src/backend/model.ts +0 -198
  71. package/src/backend/router.ts +0 -176
  72. package/src/backend/server.ts +0 -330
  73. package/src/backend/types.ts +0 -257
  74. package/src/batch.ts +0 -24
  75. package/src/cli/index.js +0 -554
  76. package/src/cli/index.ts +0 -257
  77. package/src/component.ts +0 -98
  78. package/src/components/Counter.tsx +0 -4
  79. package/src/context.ts +0 -29
  80. package/src/hooks.ts +0 -211
  81. package/src/index.ts +0 -144
  82. package/src/jsx-runtime/index.ts +0 -27
  83. package/src/jsx-runtime/jsx-dev-runtime.ts +0 -0
  84. package/src/jsx-runtime/jsx-runtime.ts +0 -104
  85. package/src/jsx-runtime.ts +0 -226
  86. package/src/renderer.ts +0 -55
  87. package/src/server-renderer.ts +0 -114
  88. package/src/shims.d.ts +0 -20
  89. package/src/types/bcrypt.d.ts +0 -30
  90. package/src/types/jsonwebtoken.d.ts +0 -55
  91. package/src/types.d.ts +0 -26
  92. package/src/types.ts +0 -21
  93. package/src/vdom.ts +0 -34
  94. package/templates/basic/.eslintignore +0 -5
  95. package/templates/basic/.eslintrc.json +0 -25
  96. package/templates/basic/docs/rapport_pfe.aux +0 -27
  97. package/templates/basic/docs/rapport_pfe.log +0 -399
  98. package/templates/basic/docs/rapport_pfe.out +0 -10
  99. package/templates/basic/docs/rapport_pfe.pdf +0 -0
  100. package/templates/basic/docs/rapport_pfe.tex +0 -68
  101. package/templates/basic/docs/rapport_pfe.toc +0 -14
  102. package/templates/basic/index.html +0 -12
  103. package/templates/basic/jsconfig.json +0 -14
  104. package/templates/basic/package.json +0 -18
  105. package/templates/basic/postcss.config.js +0 -7
  106. package/templates/basic/src/App.js +0 -105
  107. package/templates/basic/src/App.tsx +0 -65
  108. package/templates/basic/src/api.ts +0 -58
  109. package/templates/basic/src/components/Counter.tsx +0 -26
  110. package/templates/basic/src/components/Header.tsx +0 -9
  111. package/templates/basic/src/components/TodoList.tsx +0 -90
  112. package/templates/basic/src/main.css +0 -3
  113. package/templates/basic/src/main.js +0 -11
  114. package/templates/basic/src/main.ts +0 -20
  115. package/templates/basic/src/main.tsx +0 -144
  116. package/templates/basic/src/server.ts +0 -99
  117. package/templates/basic/tailwind.config.js +0 -32
  118. package/templates/basic/tsconfig.json +0 -20
  119. package/templates/basic/tsconfig.node.json +0 -10
  120. package/templates/basic/vite.config.js +0 -18
  121. package/templates/basic/vite.config.ts +0 -86
  122. package/templates/basic-app/src/App.js +0 -105
  123. package/templates/basic-app/src/App.tsx +0 -143
  124. package/templates/basic-app/src/api.ts +0 -58
  125. package/templates/basic-app/src/components/Counter.tsx +0 -26
  126. package/templates/basic-app/src/components/Header.tsx +0 -9
  127. package/templates/basic-app/src/components/TodoList.tsx +0 -90
  128. package/templates/basic-app/src/main.js +0 -10
  129. package/templates/basic-app/src/main.ts +0 -21
  130. package/templates/basic-app/src/react/index.ts +0 -35
  131. package/templates/basic-app/src/react/jsx-dev-runtime.ts +0 -13
  132. package/templates/basic-app/src/react/jsx-runtime.ts +0 -12
  133. package/templates/basic-app/src/server.ts +0 -99
  134. package/templates/basic-app/src/shims.ts +0 -9
  135. package/templates/basic-app/tsconfig.node.json +0 -10
  136. package/templates/basic-app/vite.config.js +0 -22
  137. package/templates/full-stack/.env.example +0 -11
  138. package/templates/full-stack/README.md +0 -51
  139. package/templates/full-stack/index.html +0 -12
  140. package/templates/full-stack/jsconfig.json +0 -14
  141. package/templates/full-stack/package.json +0 -21
  142. package/templates/full-stack/src/App.js +0 -105
  143. package/templates/full-stack/src/client/App.tsx +0 -50
  144. package/templates/full-stack/src/client/components/Header.tsx +0 -42
  145. package/templates/full-stack/src/client/components/UserList.tsx +0 -29
  146. package/templates/full-stack/src/client/main.tsx +0 -5
  147. package/templates/full-stack/src/main.css +0 -3
  148. package/templates/full-stack/src/main.js +0 -11
  149. package/templates/full-stack/src/main.ts +0 -20
  150. package/templates/full-stack/src/server/index.ts +0 -99
  151. package/templates/full-stack/src/server/routes/auth.ts +0 -39
  152. package/templates/full-stack/src/server/routes/users.ts +0 -48
  153. package/templates/full-stack/src/shims.ts +0 -9
  154. package/templates/full-stack/tsconfig.json +0 -20
  155. package/templates/full-stack/tsconfig.node.json +0 -10
  156. package/templates/full-stack/tsconfig.server.json +0 -15
  157. package/templates/full-stack/vite.config.js +0 -18
  158. package/templates/full-stack/vite.config.ts +0 -85
package/src/cli/index.js DELETED
@@ -1,554 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import fs from 'fs';
4
- import path from 'path';
5
- import readline from 'readline';
6
- import { exec } from 'child_process';
7
- import { promisify } from 'util';
8
-
9
- // Promisify fs functions
10
- const mkdir = promisify(fs.mkdir);
11
- const readdir = promisify(fs.readdir);
12
- const writeFile = promisify(fs.writeFile);
13
- const readFile = promisify(fs.readFile);
14
- const copyFile = promisify(fs.copyFile);
15
- const access = promisify(fs.access);
16
- const execPromise = promisify(exec);
17
-
18
- // Find the templates directory
19
- const TEMPLATES_DIR = path.join(path.dirname(new URL(import.meta.url).pathname), '..', 'templates');
20
-
21
- // Create readline interface
22
- const rl = readline.createInterface({
23
- input: process.stdin,
24
- output: process.stdout
25
- });
26
-
27
- // Promisify question
28
- const question = (query) => new Promise((resolve) => rl.question(query, resolve));
29
-
30
- // Simple logger
31
- const log = {
32
- info: (msg) => console.log(`\x1b[36minfo\x1b[0m: ${msg}`),
33
- success: (msg) => console.log(`\x1b[32msuccess\x1b[0m: ${msg}`),
34
- warn: (msg) => console.log(`\x1b[33mwarning\x1b[0m: ${msg}`),
35
- error: (msg) => console.log(`\x1b[31merror\x1b[0m: ${msg}`),
36
- title: (msg) => console.log(`\n\x1b[1m${msg}\x1b[0m\n`)
37
- };
38
-
39
- // Rest of the CLI functionality...
40
- /**
41
- * Copy directory recursively
42
- */
43
- async function copyDir(src, dest) {
44
- // Create destination directory if it doesn't exist
45
- await mkdir(dest, { recursive: true });
46
-
47
- // Read the contents of the source directory
48
- const entries = await readdir(src, { withFileTypes: true });
49
-
50
- // Process each file/directory
51
- for (const entry of entries) {
52
- const srcPath = path.join(src, entry.name);
53
- const destPath = path.join(dest, entry.name);
54
-
55
- if (entry.isDirectory()) {
56
- // Recursively copy directories
57
- await copyDir(srcPath, destPath);
58
- } else {
59
- // Copy files
60
- await copyFile(srcPath, destPath);
61
- }
62
- }
63
- }
64
-
65
- /**
66
- * Check if directory exists
67
- */
68
- async function directoryExists(path) {
69
- try {
70
- await access(path, fs.constants.F_OK);
71
- return true;
72
- } catch (error) {
73
- return false;
74
- }
75
- }
76
-
77
- /**
78
- * Replace placeholders in file content
79
- */
80
- async function processTemplateFile(filePath, replacements) {
81
- try {
82
- // Read file content
83
- let content = await readFile(filePath, 'utf8');
84
-
85
- // Replace each placeholder
86
- for (const [key, value] of Object.entries(replacements)) {
87
- content = content.replace(new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, 'g'), value);
88
- }
89
-
90
- // Write back to file
91
- await writeFile(filePath, content, 'utf8');
92
- } catch (error) {
93
- log.error(`Failed to process template file ${filePath}: ${error.message}`);
94
- }
95
- }
96
-
97
- /**
98
- * Process all template files in a directory
99
- */
100
- async function processTemplateDir(dir, replacements) {
101
- try {
102
- const entries = await readdir(dir, { withFileTypes: true });
103
-
104
- for (const entry of entries) {
105
- const fullPath = path.join(dir, entry.name);
106
-
107
- if (entry.isDirectory()) {
108
- await processTemplateDir(fullPath, replacements);
109
- } else if (entry.isFile() &&
110
- (entry.name.endsWith('.js') ||
111
- entry.name.endsWith('.ts') ||
112
- entry.name.endsWith('.json') ||
113
- entry.name.endsWith('.tsx') ||
114
- entry.name.endsWith('.md') ||
115
- entry.name.endsWith('.html'))) {
116
- await processTemplateFile(fullPath, replacements);
117
- }
118
- }
119
- } catch (error) {
120
- log.error(`Failed to process template directory ${dir}: ${error.message}`);
121
- }
122
- }
123
-
124
- /**
125
- * Create a new Hamroun project
126
- */
127
- async function createProject(projectName, templateName) {
128
- const targetDir = path.resolve(process.cwd(), projectName);
129
-
130
- // Check if directory already exists
131
- if (await directoryExists(targetDir)) {
132
- const overwrite = await question(`Directory ${projectName} already exists. Continue and overwrite? (y/N): `);
133
- if (overwrite.toLowerCase() !== 'y') {
134
- log.info('Project creation cancelled.');
135
- rl.close();
136
- return;
137
- }
138
- }
139
-
140
- // Check if template exists
141
- const templateDir = path.join(TEMPLATES_DIR, templateName);
142
- if (!(await directoryExists(templateDir))) {
143
- log.error(`Template "${templateName}" not found.`);
144
- rl.close();
145
- return;
146
- }
147
-
148
- try {
149
- log.title(`Creating new Hamroun project: ${projectName}`);
150
-
151
- // Create project directory
152
- await mkdir(targetDir, { recursive: true });
153
-
154
- // Copy template files
155
- log.info(`Copying template files from ${templateName}...`);
156
- await copyDir(templateDir, targetDir);
157
-
158
- // Get template customization values
159
- const appName = await question('Application name: ') || projectName;
160
- const description = await question('Description: ') || `A Hamroun application`;
161
- const author = await question('Author: ') || '';
162
-
163
- // Replace placeholders in template files
164
- log.info('Processing template files...');
165
- await processTemplateDir(targetDir, {
166
- projectName,
167
- appName,
168
- description,
169
- author,
170
- creationDate: new Date().toISOString().split('T')[0]
171
- });
172
-
173
- // Install dependencies
174
- log.info('Installing dependencies (this may take a while)...');
175
- try {
176
- await execPromise('npm install', { cwd: targetDir });
177
- log.success('Dependencies installed successfully.');
178
- } catch (error) {
179
- log.warn(`Failed to install dependencies: ${error.message}`);
180
- log.info('You can install them later by running "npm install" in the project directory.');
181
- }
182
-
183
- log.success(`Project ${projectName} created successfully!`);
184
- log.info(`\nTo get started:\n`);
185
- log.info(` cd ${projectName}`);
186
- log.info(` npm run dev\n`);
187
-
188
- } catch (error) {
189
- log.error(`Failed to create project: ${error.message}`);
190
- } finally {
191
- rl.close();
192
- }
193
- }
194
-
195
- /**
196
- * Generate a component
197
- */
198
- async function generateComponent(componentName, options = {}) {
199
- try {
200
- const { type = 'functional', directory = 'components' } = options;
201
- const targetDir = path.resolve(process.cwd(), directory);
202
-
203
- // Create directory if it doesn't exist
204
- await mkdir(targetDir, { recursive: true });
205
-
206
- // Determine file path and content
207
- const componentFileName = `${componentName}.tsx`;
208
- const componentFilePath = path.join(targetDir, componentFileName);
209
-
210
- // Check if file already exists
211
- if (fs.existsSync(componentFilePath)) {
212
- const overwrite = await question(`Component ${componentName} already exists. Overwrite? (y/N): `);
213
- if (overwrite.toLowerCase() !== 'y') {
214
- log.info('Component generation cancelled.');
215
- rl.close();
216
- return;
217
- }
218
- }
219
-
220
- // Generate component content based on type
221
- let content = '';
222
- if (type === 'functional') {
223
- content = `import { useState, useEffect } from 'frontend-hamroun';
224
-
225
- interface ${componentName}Props {
226
- title?: string;
227
- }
228
-
229
- export function ${componentName}({ title = 'Default Title' }: ${componentName}Props) {
230
- const [count, setCount] = useState(0);
231
-
232
- useEffect(() => {
233
- // Component mounted
234
- console.log('${componentName} mounted');
235
-
236
- return () => {
237
- // Component will unmount
238
- console.log('${componentName} will unmount');
239
- };
240
- }, []);
241
-
242
- return (
243
- <div className="${componentName.toLowerCase()}">
244
- <h2>{title}</h2>
245
- <p>Count: {count}</p>
246
- <button onClick={() => setCount(count + 1)}>Increment</button>
247
- </div>
248
- );
249
- }
250
- `;
251
- } else if (type === 'class') {
252
- content = `import { Component } from 'frontend-hamroun';
253
-
254
- interface ${componentName}Props {
255
- title?: string;
256
- }
257
-
258
- interface ${componentName}State {
259
- count: number;
260
- }
261
-
262
- export class ${componentName} extends Component<${componentName}Props, ${componentName}State> {
263
- constructor(props: ${componentName}Props) {
264
- super(props);
265
- this.state = {
266
- count: 0
267
- };
268
- }
269
-
270
- componentDidMount() {
271
- console.log('${componentName} mounted');
272
- }
273
-
274
- componentWillUnmount() {
275
- console.log('${componentName} will unmount');
276
- }
277
-
278
- increment = () => {
279
- this.setState({ count: this.state.count + 1 });
280
- }
281
-
282
- render() {
283
- const { title = 'Default Title' } = this.props;
284
-
285
- return (
286
- <div className="${componentName.toLowerCase()}">
287
- <h2>{title}</h2>
288
- <p>Count: {this.state.count}</p>
289
- <button onClick={this.increment}>Increment</button>
290
- </div>
291
- );
292
- }
293
- }
294
- `;
295
- }
296
-
297
- // Write component file
298
- await writeFile(componentFilePath, content, 'utf8');
299
-
300
- log.success(`Component ${componentName} created at ${componentFilePath}`);
301
- } catch (error) {
302
- log.error(`Failed to generate component: ${error.message}`);
303
- } finally {
304
- rl.close();
305
- }
306
- }
307
-
308
- /**
309
- * Generate a model
310
- */
311
- async function generateModel(modelName, options = {}) {
312
- try {
313
- const { directory = 'models' } = options;
314
- const targetDir = path.resolve(process.cwd(), directory);
315
-
316
- // Create directory if it doesn't exist
317
- await mkdir(targetDir, { recursive: true });
318
-
319
- // Determine file path and content
320
- const modelFileName = `${modelName}.ts`;
321
- const modelFilePath = path.join(targetDir, modelFileName);
322
-
323
- // Check if file already exists
324
- if (fs.existsSync(modelFilePath)) {
325
- const overwrite = await question(`Model ${modelName} already exists. Overwrite? (y/N): `);
326
- if (overwrite.toLowerCase() !== 'y') {
327
- log.info('Model generation cancelled.');
328
- rl.close();
329
- return;
330
- }
331
- }
332
-
333
- // Generate model content
334
- const content = `import { Schema } from 'mongoose';
335
- import { createModel, FieldTypes } from 'frontend-hamroun';
336
-
337
- // Define the model interface
338
- export interface ${modelName} {
339
- _id?: string;
340
- name: string;
341
- description?: string;
342
- createdAt: Date;
343
- updatedAt: Date;
344
- }
345
-
346
- // Define the schema
347
- const ${modelName.toLowerCase()}Schema = new Schema<${modelName}>({
348
- name: FieldTypes.Required(FieldTypes.String),
349
- description: FieldTypes.String,
350
- createdAt: FieldTypes.Default(FieldTypes.Date, Date.now),
351
- updatedAt: FieldTypes.Default(FieldTypes.Date, Date.now)
352
- }, {
353
- timestamps: true
354
- });
355
-
356
- // Create and export the model
357
- export const ${modelName}Model = createModel<${modelName}>('${modelName}', ${modelName.toLowerCase()}Schema);
358
- `;
359
-
360
- // Write model file
361
- await writeFile(modelFilePath, content, 'utf8');
362
-
363
- log.success(`Model ${modelName} created at ${modelFilePath}`);
364
- } catch (error) {
365
- log.error(`Failed to generate model: ${error.message}`);
366
- } finally {
367
- rl.close();
368
- }
369
- }
370
-
371
- /**
372
- * Generate an API route
373
- */
374
- async function generateRoute(routeName, options = {}) {
375
- try {
376
- const { directory = 'routes', model = null } = options;
377
- const targetDir = path.resolve(process.cwd(), directory);
378
-
379
- // Create directory if it doesn't exist
380
- await mkdir(targetDir, { recursive: true });
381
-
382
- // Determine file path and content
383
- const routeFileName = `${routeName}.ts`;
384
- const routeFilePath = path.join(targetDir, routeFileName);
385
-
386
- // Check if file already exists
387
- if (fs.existsSync(routeFilePath)) {
388
- const overwrite = await question(`Route ${routeName} already exists. Overwrite? (y/N): `);
389
- if (overwrite.toLowerCase() !== 'y') {
390
- log.info('Route generation cancelled.');
391
- rl.close();
392
- return;
393
- }
394
- }
395
-
396
- // Generate route content based on whether a model is specified
397
- let content = '';
398
- if (model) {
399
- content = `import { Router } from 'express';
400
- import { createRestEndpoints, asyncHandler, sendSuccess, sendError } from 'frontend-hamroun';
401
- import { ${model}Model } from '../models/${model}';
402
-
403
- // Create router with standard CRUD endpoints
404
- const router = createRestEndpoints(${model}Model);
405
-
406
- // Add custom endpoints
407
- router.get('/count', asyncHandler(async (req, res) => {
408
- const count = await ${model}Model.count();
409
- sendSuccess(res, { count });
410
- }));
411
-
412
- export default router;
413
- `;
414
- } else {
415
- content = `import { Router } from 'express';
416
- import { asyncHandler, sendSuccess, sendError } from 'frontend-hamroun';
417
-
418
- const router = Router();
419
-
420
- // Define routes
421
- router.get('/', asyncHandler(async (req, res) => {
422
- sendSuccess(res, { message: 'Welcome to the ${routeName} API' });
423
- }));
424
-
425
- router.post('/', asyncHandler(async (req, res) => {
426
- const { name } = req.body;
427
-
428
- if (!name) {
429
- return sendError(res, 'Name is required', 400);
430
- }
431
-
432
- sendSuccess(res, { name }, 'Resource created', 201);
433
- }));
434
-
435
- router.get('/:id', asyncHandler(async (req, res) => {
436
- const { id } = req.params;
437
-
438
- // Implement your logic here
439
-
440
- sendSuccess(res, { id, name: 'Sample Item' });
441
- }));
442
-
443
- export default router;
444
- `;
445
- }
446
-
447
- // Write route file
448
- await writeFile(routeFilePath, content, 'utf8');
449
-
450
- log.success(`Route ${routeName} created at ${routeFilePath}`);
451
- } catch (error) {
452
- log.error(`Failed to generate route: ${error.message}`);
453
- } finally {
454
- rl.close();
455
- }
456
- }
457
-
458
- /**
459
- * Print usage instructions
460
- */
461
- function printHelp() {
462
- log.title('Hamroun CLI Tool');
463
- console.log('Usage: hamroun <command> [options]\n');
464
-
465
- console.log('Commands:');
466
- console.log(' create <project-name> [template] Create a new Hamroun project');
467
- console.log(' generate <type> <name> Generate a component, model, or route');
468
- console.log(' help Show this help message\n');
469
-
470
- console.log('Examples:');
471
- console.log(' hamroun create my-app full-stack Create a new full-stack project');
472
- console.log(' hamroun generate component Button Generate a new component');
473
- console.log(' hamroun generate model User Generate a new model');
474
- console.log(' hamroun generate route users Generate a new API route\n');
475
-
476
- console.log('Available templates:');
477
- console.log(' full-stack Full-stack application with API and frontend');
478
- console.log(' frontend Frontend-only application');
479
- console.log(' api API-only application');
480
- console.log(' minimal Minimal starter with essential files only\n');
481
-
482
- rl.close();
483
- }
484
-
485
- /**
486
- * Main CLI function
487
- */
488
- async function main() {
489
- const args = process.argv.slice(2);
490
- const command = args[0];
491
-
492
- if (!command || command === 'help') {
493
- printHelp();
494
- return;
495
- }
496
-
497
- switch (command) {
498
- case 'create':
499
- const projectName = args[1];
500
- const templateName = args[2] || 'full-stack';
501
-
502
- if (!projectName) {
503
- log.error('Project name is required.');
504
- printHelp();
505
- return;
506
- }
507
-
508
- await createProject(projectName, templateName);
509
- break;
510
-
511
- case 'generate':
512
- const type = args[1];
513
- const name = args[2];
514
-
515
- if (!type || !name) {
516
- log.error('Type and name are required.');
517
- printHelp();
518
- return;
519
- }
520
-
521
- switch (type) {
522
- case 'component':
523
- await generateComponent(name, {
524
- type: args[3] || 'functional'
525
- });
526
- break;
527
-
528
- case 'model':
529
- await generateModel(name);
530
- break;
531
-
532
- case 'route':
533
- await generateRoute(name, {
534
- model: args[3]
535
- });
536
- break;
537
-
538
- default:
539
- log.error(`Unknown generator type: ${type}`);
540
- printHelp();
541
- }
542
- break;
543
-
544
- default:
545
- log.error(`Unknown command: ${command}`);
546
- printHelp();
547
- }
548
- }
549
-
550
- // Run CLI
551
- main().catch(error => {
552
- log.error(`An error occurred: ${error.message}`);
553
- rl.close();
554
- });