@igniter-js/cli 0.1.4 → 0.1.6

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 (36) hide show
  1. package/dist/index.js +373 -191
  2. package/dist/index.js.map +1 -0
  3. package/dist/templates/express.server.hbs +33 -0
  4. package/dist/templates/feature.controller.hbs +14 -4
  5. package/dist/templates/feature.interface.hbs +27 -5
  6. package/dist/templates/feature.procedure.hbs +12 -7
  7. package/dist/templates/globals.hbs +7 -82
  8. package/dist/templates/igniter.context.hbs +1 -1
  9. package/dist/templates/layout.hbs +6 -14
  10. package/dist/templates/page.hbs +4 -37
  11. package/dist/templates/readme.hbs +25 -42
  12. package/dist/utils/analyze.js +8 -10
  13. package/dist/utils/analyze.js.map +1 -0
  14. package/dist/utils/cli-style.d.ts +55 -0
  15. package/dist/utils/cli-style.js +171 -0
  16. package/dist/utils/cli-style.js.map +1 -0
  17. package/dist/utils/consts.d.ts +4 -9
  18. package/dist/utils/consts.js +5 -13
  19. package/dist/utils/consts.js.map +1 -0
  20. package/dist/utils/handlebars-helpers.js +18 -5
  21. package/dist/utils/handlebars-helpers.js.map +1 -0
  22. package/dist/utils/helpers.d.ts +2 -1
  23. package/dist/utils/helpers.js +44 -17
  24. package/dist/utils/helpers.js.map +1 -0
  25. package/dist/utils/platform-utils.d.ts +46 -0
  26. package/dist/utils/platform-utils.js +95 -0
  27. package/dist/utils/platform-utils.js.map +1 -0
  28. package/dist/utils/prisma-schema-parser.js +11 -16
  29. package/dist/utils/prisma-schema-parser.js.map +1 -0
  30. package/dist/utils/project-utils.d.ts +32 -0
  31. package/dist/utils/project-utils.js +123 -0
  32. package/dist/utils/project-utils.js.map +1 -0
  33. package/dist/utils/template-handler.js +4 -5
  34. package/dist/utils/template-handler.js.map +1 -0
  35. package/package.json +3 -1
  36. package/readme.md +23 -1
package/dist/index.js CHANGED
@@ -1,25 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
3
  Object.defineProperty(exports, "__esModule", { value: true });
7
- const inquirer_1 = __importDefault(require("inquirer"));
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const ora_1 = __importDefault(require("ora"));
10
- const path_1 = __importDefault(require("path"));
4
+ const tslib_1 = require("tslib");
5
+ const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
6
+ const path_1 = tslib_1.__importDefault(require("path"));
7
+ const fs_1 = tslib_1.__importDefault(require("fs"));
11
8
  const commander_1 = require("commander");
12
- const helpers_1 = require("./utils/helpers");
13
9
  const consts_1 = require("./utils/consts");
10
+ const helpers_1 = require("./utils/helpers");
14
11
  const template_handler_1 = require("./utils/template-handler");
15
12
  const handlebars_helpers_1 = require("./utils/handlebars-helpers");
16
13
  const prisma_schema_parser_1 = require("./utils/prisma-schema-parser");
17
14
  const analyze_1 = require("./utils/analyze");
15
+ const cli_style_1 = require("./utils/cli-style");
16
+ const project_utils_1 = require("./utils/project-utils");
17
+ const platform_utils_1 = require("./utils/platform-utils");
18
18
  class IgniterCLI extends helpers_1.CLIHelper {
19
19
  constructor() {
20
20
  super();
21
21
  this.program = new commander_1.Command();
22
- this.spinner = (0, ora_1.default)();
23
22
  this.schemaParser = new prisma_schema_parser_1.PrismaSchemaParser();
24
23
  this.analyze = new analyze_1.AnalyzeCommand();
25
24
  this.setupCLI();
@@ -33,9 +32,10 @@ class IgniterCLI extends helpers_1.CLIHelper {
33
32
  .version('1.0.0');
34
33
  this.program
35
34
  .command('init')
36
- .description('Initialize a new Next.js project with Igniter Framework')
37
- .action(async () => {
38
- await this.init();
35
+ .description('Initialize a new Next.js project with Igniter.js')
36
+ .option('-d, --dir <directory>', 'Directory to initialize the project in')
37
+ .action(async (options) => {
38
+ await this.init(options.dir);
39
39
  });
40
40
  this.program
41
41
  .command('analyze')
@@ -47,50 +47,180 @@ class IgniterCLI extends helpers_1.CLIHelper {
47
47
  .command('generate feature')
48
48
  .alias('g')
49
49
  .description('Generate a new feature')
50
- .option('-n, --name [name]', 'Feature name')
50
+ .option('-n, --name <name>', 'Feature name')
51
51
  .option('-f, --fields <fields...>', 'Fields for the feature (format: name:type)')
52
- .action(async (name, options) => {
53
- if (!options.name) {
52
+ .option('-y, --yes', 'Automatically confirm creation if model is not found')
53
+ .action(async (options, params) => {
54
+ console.log(options, params);
55
+ if (!params.name) {
54
56
  await this.generateAllFeatures();
55
57
  return;
56
58
  }
57
- await this.generateFeature(name, options.fields || []);
59
+ await this.generateFeature(params.name, params.fields || [], params.yes);
58
60
  });
59
61
  this.program.parse();
60
62
  }
61
- async init() {
63
+ async init(targetDir) {
62
64
  console.clear();
63
- console.log(chalk_1.default.bold.cyan('\n🚀 Welcome to Igniter Framework!\n'));
64
- console.log(chalk_1.default.gray('Let\'s set up your new project. This may take a few minutes...\n'));
65
+ cli_style_1.CLIStyle.startSequence('Welcome to Igniter.js CLI');
66
+ cli_style_1.CLIStyle.logInfo('Let\'s configure your new project together. I\'ll guide you through each step.');
65
67
  try {
66
- // Check dependencies
67
- this.spinner.start('Checking required dependencies...');
68
+ // Se um diretório foi especificado, criar e navegar até ele
69
+ if (targetDir) {
70
+ cli_style_1.CLIStyle.logInfo(`Creating project in directory: ${targetDir}`);
71
+ // Normalizar o caminho do diretório
72
+ const normalizedPath = (0, platform_utils_1.normalizePath)(targetDir);
73
+ // Criar diretório se não existir
74
+ if (!fs_1.default.existsSync(normalizedPath)) {
75
+ fs_1.default.mkdirSync(normalizedPath, { recursive: true });
76
+ cli_style_1.CLIStyle.logSuccess(`Directory created: ${normalizedPath}`);
77
+ }
78
+ // Navegar para o diretório
79
+ process.chdir(normalizedPath);
80
+ cli_style_1.CLIStyle.logSuccess(`Changed to directory: ${process.cwd()}`);
81
+ }
82
+ const spinner = cli_style_1.CLIStyle.createSpinner('Checking required dependencies...');
83
+ spinner.start();
68
84
  this.checkDependencies(consts_1.DEPENDENCIES.required);
69
- this.spinner.succeed();
70
- // Setup project
71
- await this.setupProject();
85
+ spinner.succeed('All required dependencies are installed');
86
+ const preferences = await this.gatherUserPreferences();
87
+ await this.setupProject(preferences);
72
88
  }
73
89
  catch (error) {
74
- this.spinner.fail(chalk_1.default.red('Project initialization failed'));
75
- console.error('\n' + chalk_1.default.red('Error details:'));
76
- console.error(chalk_1.default.red(error));
90
+ cli_style_1.CLIStyle.logError('Project initialization failed', error);
77
91
  process.exit(1);
78
92
  }
79
93
  }
80
- async generateFeature(name, fields = []) {
94
+ async gatherUserPreferences() {
95
+ cli_style_1.CLIStyle.startSequence('Project Configuration');
96
+ const isNextProject = (0, project_utils_1.isNextJSProject)();
97
+ const packageManager = await inquirer_1.default.prompt({
98
+ type: 'list',
99
+ name: 'value',
100
+ message: 'Which package manager do you prefer?',
101
+ choices: [
102
+ { name: 'bun', value: 'bun' },
103
+ { name: 'npm', value: 'npm' },
104
+ { name: 'yarn', value: 'yarn' },
105
+ { name: 'pnpm', value: 'pnpm' }
106
+ ],
107
+ default: 'npm'
108
+ });
109
+ let projectType = { value: 'nextjs' };
110
+ if (!isNextProject) {
111
+ projectType = await inquirer_1.default.prompt({
112
+ type: 'list',
113
+ name: 'value',
114
+ message: 'What type of project are you creating?',
115
+ choices: [
116
+ {
117
+ name: 'Fullstack (Igniter.js, Next.js, Zod and Prisma)',
118
+ value: 'nextjs',
119
+ },
120
+ {
121
+ name: 'Rest API (Igniter.js, Express, Zod and Prisma)',
122
+ value: 'express',
123
+ },
124
+ {
125
+ name: 'Only setup Igniter.js',
126
+ value: 'igniter',
127
+ }
128
+ ]
129
+ });
130
+ }
131
+ const database = await inquirer_1.default.prompt({
132
+ type: 'list',
133
+ name: 'value',
134
+ message: 'Would you like to set up Prisma ORM?',
135
+ choices: [
136
+ {
137
+ name: 'Yes, set up Prisma',
138
+ value: 'prisma',
139
+ },
140
+ {
141
+ name: 'No, skip database setup',
142
+ value: 'none',
143
+ }
144
+ ],
145
+ default: 'prisma'
146
+ });
147
+ // Display confirmation of selections
148
+ console.log('\n');
149
+ cli_style_1.CLIStyle.logInfo('Configuration summary:');
150
+ cli_style_1.CLIStyle.logInfo(`Package Manager: ${packageManager.value}`);
151
+ if (!isNextProject)
152
+ cli_style_1.CLIStyle.logInfo(`Project Type: ${projectType.value}`);
153
+ cli_style_1.CLIStyle.logInfo(`Database: ${database.value === 'prisma' ? 'Prisma ORM' : 'None'}`);
154
+ if (database.value === 'prisma') {
155
+ console.log('\n');
156
+ cli_style_1.CLIStyle.logInfo(`Note: With Prisma enabled, you can use the igniter generate feature command to automatically create features based on your Prisma schema models.`);
157
+ }
158
+ const confirm = await inquirer_1.default.prompt({
159
+ type: 'confirm',
160
+ name: 'value',
161
+ message: 'Ready to proceed with the installation?',
162
+ default: true
163
+ });
164
+ if (!confirm.value) {
165
+ cli_style_1.CLIStyle.logWarning('Installation cancelled by the user');
166
+ process.exit(0);
167
+ }
168
+ cli_style_1.CLIStyle.endSequence();
169
+ return {
170
+ 'package-manager': packageManager.value,
171
+ 'project-type': projectType.value,
172
+ 'database': database.value,
173
+ };
174
+ }
175
+ async generateFeature(name, fields = [], autoConfirm = false) {
81
176
  console.clear();
82
- console.log(chalk_1.default.bold.cyan(`\n🏗️ Generating feature: ${chalk_1.default.white(name)}\n`));
177
+ cli_style_1.CLIStyle.startSequence(`Generating Feature: ${name}`);
83
178
  try {
179
+ // Check if model exists in Prisma
180
+ const spinner = cli_style_1.CLIStyle.createSpinner('Parsing Prisma schema...');
181
+ spinner.start();
182
+ const modelExists = this.schemaParser.hasModel(name);
183
+ if (!modelExists) {
184
+ spinner.warn(`Model "${name}" not found in Prisma schema`);
185
+ // Ask user if they want to create a feature without a model
186
+ let createFeature = autoConfirm;
187
+ if (!autoConfirm) {
188
+ cli_style_1.CLIStyle.logInfo("The model doesn't exist in your Prisma schema");
189
+ console.log(cli_style_1.CLIStyle.getVerticalLine());
190
+ const answer = await inquirer_1.default.prompt({
191
+ type: 'confirm',
192
+ name: 'createFeature',
193
+ message: cli_style_1.CLIStyle.logPrompt(`Would you like to create a basic feature for "${name}" anyway?`),
194
+ default: true
195
+ });
196
+ createFeature = answer.createFeature;
197
+ }
198
+ if (!createFeature) {
199
+ cli_style_1.CLIStyle.logWarning('Feature generation cancelled');
200
+ cli_style_1.CLIStyle.endSequence();
201
+ return;
202
+ }
203
+ cli_style_1.CLIStyle.logInfo(`Creating basic feature for "${name}" without database model`);
204
+ }
84
205
  // Parse fields from Prisma schema
85
- this.spinner.start('Parsing Prisma schema...');
86
- let parsedFields = this.schemaParser.getModelFields(name);
87
- // If no fields found in schema, use provided fields as fallback
88
- if (parsedFields.length === 0 && fields.length > 0) {
206
+ let parsedFields = [];
207
+ if (modelExists) {
208
+ parsedFields = this.schemaParser.getModelFields(name);
209
+ // Transform parsed fields to include relationship info
210
+ parsedFields = parsedFields.map(field => ({
211
+ ...field,
212
+ isRelation: !!field.relations,
213
+ isList: field.isList || (field.relations?.type === 'one-to-many' || field.relations?.type === 'many-to-many'),
214
+ isOptional: field.hasDefault || field.isOptional
215
+ }));
216
+ }
217
+ else if (fields.length > 0) {
218
+ // Use provided fields as fallback
89
219
  parsedFields = fields.map(field => {
90
220
  const [name, type] = field.split(':');
91
221
  return {
92
222
  name,
93
- type,
223
+ type: type || 'String',
94
224
  zodType: 'z.string()',
95
225
  description: `${name} field`,
96
226
  isOptional: false,
@@ -101,21 +231,9 @@ class IgniterCLI extends helpers_1.CLIHelper {
101
231
  };
102
232
  });
103
233
  }
104
- else {
105
- // Transform parsed fields to include relationship info
106
- parsedFields = parsedFields.map(field => {
107
- var _a, _b;
108
- return ({
109
- ...field,
110
- isRelation: !!field.relations,
111
- isList: field.isList || (((_a = field.relations) === null || _a === void 0 ? void 0 : _a.type) === 'one-to-many' || ((_b = field.relations) === null || _b === void 0 ? void 0 : _b.type) === 'many-to-many'),
112
- isOptional: field.hasDefault || field.isOptional
113
- });
114
- });
115
- }
116
- this.spinner.succeed();
234
+ spinner.succeed('Schema analysis completed');
117
235
  // Create feature directory
118
- this.spinner.start('Creating feature directory structure...');
236
+ cli_style_1.CLIStyle.startStep('Creating directory structure');
119
237
  const featurePath = path_1.default.join('src/features', name.toLowerCase());
120
238
  this.createDir(featurePath);
121
239
  // Create presentation directory and its subdirectories
@@ -140,13 +258,15 @@ class IgniterCLI extends helpers_1.CLIHelper {
140
258
  for (const dir of featureDirs) {
141
259
  this.createDir(path_1.default.join(featurePath, dir));
142
260
  }
143
- this.spinner.succeed();
261
+ cli_style_1.CLIStyle.endStep();
144
262
  // Generate files from templates
263
+ cli_style_1.CLIStyle.startStep('Generating feature files');
145
264
  const templateData = {
146
265
  name,
147
- fields: parsedFields
266
+ fields: parsedFields,
267
+ hasFields: parsedFields.length > 0,
268
+ noModel: !modelExists
148
269
  };
149
- this.spinner.start('Generating feature files...');
150
270
  const templates = {
151
271
  'feature.index': 'index.ts',
152
272
  'feature.interface': `${name.toLowerCase()}.interface.ts`,
@@ -157,19 +277,31 @@ class IgniterCLI extends helpers_1.CLIHelper {
157
277
  const content = template_handler_1.TemplateHandler.render(template, templateData);
158
278
  this.createFile(path_1.default.join(featurePath, filePath), content);
159
279
  }
160
- this.spinner.succeed();
161
- console.log('\n' + chalk_1.default.bold.green(`✨ Feature ${chalk_1.default.white(name)} generated successfully! ✨\n`));
280
+ cli_style_1.CLIStyle.endStep();
281
+ cli_style_1.CLIStyle.endSequence();
282
+ cli_style_1.CLIStyle.logSuccess(`Feature ${name} generated successfully!`);
283
+ if (modelExists && parsedFields.length > 0) {
284
+ cli_style_1.CLIStyle.logInfo(`Created ${Object.keys(templates).length} files with ${parsedFields.length} fields from Prisma model`);
285
+ }
286
+ else if (!modelExists && parsedFields.length > 0) {
287
+ cli_style_1.CLIStyle.logInfo(`Created ${Object.keys(templates).length} files with ${parsedFields.length} custom fields`);
288
+ }
289
+ else if (!modelExists) {
290
+ cli_style_1.CLIStyle.logInfo(`Created basic feature template without fields`);
291
+ }
292
+ else {
293
+ cli_style_1.CLIStyle.logWarning(`No fields were found in the Prisma schema for model ${name}`);
294
+ }
295
+ console.log('\n');
162
296
  }
163
297
  catch (error) {
164
- this.spinner.fail(chalk_1.default.red('Feature generation failed'));
165
- console.error('\n' + chalk_1.default.red('Error details:'));
166
- console.error(chalk_1.default.red(error));
298
+ cli_style_1.CLIStyle.logError('Feature generation failed', error);
167
299
  process.exit(1);
168
300
  }
169
301
  }
170
302
  async generateAllFeatures() {
171
303
  console.clear();
172
- console.log(chalk_1.default.bold.cyan('\n🏗️ Generating features for all Prisma models\n'));
304
+ cli_style_1.CLIStyle.startSequence('Batch Feature Generation');
173
305
  try {
174
306
  // Get all models from schema
175
307
  const schemaContent = this.schemaParser.getSchemaContent();
@@ -180,15 +312,16 @@ class IgniterCLI extends helpers_1.CLIHelper {
180
312
  models.push(match[1]);
181
313
  }
182
314
  if (models.length === 0) {
183
- console.log('\n' + chalk_1.default.yellow('⚠️ No models found in your Prisma schema.'));
184
- console.log(chalk_1.default.gray('\nTip: Add some models to your schema.prisma file first.'));
315
+ cli_style_1.CLIStyle.logWarning('No models found in your Prisma schema');
316
+ cli_style_1.CLIStyle.logInfo('Tip: Add some models to your schema.prisma file first');
317
+ cli_style_1.CLIStyle.endSequence();
185
318
  return;
186
319
  }
187
320
  // Let user select models
188
321
  const { selectedModels } = await inquirer_1.default.prompt([{
189
322
  type: 'checkbox',
190
323
  name: 'selectedModels',
191
- message: chalk_1.default.yellow('\n🎯 Select which models to generate features for:'),
324
+ message: cli_style_1.CLIStyle.logPrompt('Select which models to generate features for:'),
192
325
  choices: models.map(model => ({
193
326
  name: model,
194
327
  value: model,
@@ -196,171 +329,220 @@ class IgniterCLI extends helpers_1.CLIHelper {
196
329
  }))
197
330
  }]);
198
331
  if (selectedModels.length === 0) {
199
- console.log(chalk_1.default.gray('\nNo models selected. Operation cancelled.'));
332
+ cli_style_1.CLIStyle.logWarning('No models selected. Operation cancelled.');
333
+ cli_style_1.CLIStyle.endSequence();
200
334
  return;
201
335
  }
336
+ cli_style_1.CLIStyle.startStep(`Generating ${selectedModels.length} features`);
202
337
  // Track progress
203
338
  let completed = 0;
204
339
  const total = selectedModels.length;
205
340
  const failed = [];
206
341
  for (const model of selectedModels) {
207
- this.spinner.start(chalk_1.default.white(`Generating feature for ${chalk_1.default.cyan(model)} [${completed + 1}/${total}]`));
342
+ const spinner = cli_style_1.CLIStyle.createSpinner(`Processing model ${model} [${completed + 1}/${total}]`);
343
+ spinner.start();
208
344
  try {
209
- await this.generateFeature(model);
345
+ // Create a feature without displaying all the normal output
346
+ const featurePath = path_1.default.join('src/features', model.toLowerCase());
347
+ this.createDir(featurePath);
348
+ // Create subdirectories
349
+ const presentationPath = path_1.default.join(featurePath, 'presentation');
350
+ this.createDir(presentationPath);
351
+ for (const dir of ['components', 'hooks', 'contexts', 'utils']) {
352
+ const dirPath = path_1.default.join(presentationPath, dir);
353
+ this.createDir(dirPath);
354
+ this.createFile(path_1.default.join(dirPath, '.gitkeep'), '');
355
+ }
356
+ for (const dir of ['controllers', 'procedures']) {
357
+ this.createDir(path_1.default.join(featurePath, dir));
358
+ }
359
+ // Parse fields and generate templates
360
+ let parsedFields = this.schemaParser.getModelFields(model);
361
+ parsedFields = parsedFields.map(field => ({
362
+ ...field,
363
+ isRelation: !!field.relations,
364
+ isList: field.isList || (field.relations?.type === 'one-to-many' || field.relations?.type === 'many-to-many'),
365
+ isOptional: field.hasDefault || field.isOptional
366
+ }));
367
+ const templateData = { name: model, fields: parsedFields };
368
+ const templates = {
369
+ 'feature.index': 'index.ts',
370
+ 'feature.interface': `${model.toLowerCase()}.interface.ts`,
371
+ 'feature.controller': `controllers/${model.toLowerCase()}.controller.ts`,
372
+ 'feature.procedure': `procedures/${model.toLowerCase()}.procedure.ts`
373
+ };
374
+ for (const [template, filePath] of Object.entries(templates)) {
375
+ const content = template_handler_1.TemplateHandler.render(template, templateData);
376
+ this.createFile(path_1.default.join(featurePath, filePath), content);
377
+ }
210
378
  completed++;
211
- this.spinner.succeed(chalk_1.default.green(`✓ Generated feature for ${chalk_1.default.cyan(model)}`));
379
+ spinner.succeed(`Generated feature for ${model}`);
212
380
  }
213
381
  catch (error) {
214
382
  failed.push(model);
215
- this.spinner.fail(chalk_1.default.red(`✗ Failed to generate feature for ${chalk_1.default.cyan(model)}`));
216
- console.log(chalk_1.default.gray(` Error: ${error}`));
383
+ spinner.fail(`Failed to generate feature for ${model}`);
384
+ cli_style_1.CLIStyle.logInfo(`Error: ${error}`);
217
385
  }
218
- // Show progress bar
386
+ // Show progress
219
387
  const progress = completed / total * 100;
220
- console.log(chalk_1.default.gray(` Progress: ${chalk_1.default.cyan(`${Math.round(progress)}%`)} [${'='.repeat(Math.floor(progress / 5))}${' '.repeat(20 - Math.floor(progress / 5))}]`));
221
- console.log('');
388
+ cli_style_1.CLIStyle.logInfo(`Progress: ${Math.round(progress)}% [${'='.repeat(Math.floor(progress / 5))}${' '.repeat(20 - Math.floor(progress / 5))}]`);
222
389
  }
390
+ cli_style_1.CLIStyle.endStep();
391
+ cli_style_1.CLIStyle.endSequence();
223
392
  // Final summary
224
- console.log(chalk_1.default.bold.white('\n📊 Generation Summary:'));
225
- console.log(chalk_1.default.green(`Successfully generated: ${completed}/${total} features`));
393
+ cli_style_1.CLIStyle.logInfo(`Generation summary:`);
394
+ cli_style_1.CLIStyle.logSuccess(`Successfully generated: ${completed}/${total} features`);
226
395
  if (failed.length > 0) {
227
- console.log(chalk_1.default.red(`Failed to generate: ${failed.length} features`));
228
- console.log(chalk_1.default.gray('\nFailed models:'));
229
- failed.forEach(model => console.log(chalk_1.default.red(` - ${model}`)));
230
- }
231
- if (completed === total) {
232
- console.log('\n' + chalk_1.default.bold.green('✨ All features generated successfully! ✨'));
233
- }
234
- else {
235
- console.log('\n' + chalk_1.default.yellow('⚠️ Some features could not be generated.'));
236
- console.log(chalk_1.default.gray(' Check the errors above and try again.'));
396
+ cli_style_1.CLIStyle.logWarning(`Failed to generate: ${failed.length} features`);
397
+ cli_style_1.CLIStyle.logInfo('Failed models:');
398
+ failed.forEach(model => cli_style_1.CLIStyle.logInfo(`- ${model}`));
237
399
  }
238
- console.log('');
239
400
  }
240
401
  catch (error) {
241
- this.spinner.fail(chalk_1.default.red('Failed to generate features'));
242
- console.error('\n' + chalk_1.default.red('Error details:'));
243
- console.error(chalk_1.default.gray(error));
402
+ cli_style_1.CLIStyle.logError('Failed to generate features', error);
244
403
  process.exit(1);
245
404
  }
246
405
  }
247
- async setupProject() {
248
- console.log(chalk_1.default.cyan('\n📦 Project Setup Progress\n'));
249
- // Next.js setup
250
- this.spinner.start('Creating Next.js application...');
251
- await this.delay(1000); // Pequena pausa para melhor visualização
252
- this.execCommand('npx create-next-app@canary --ts --turbopack --import-alias "@/*" --src-dir --tailwind --eslint --typescript --app .');
253
- this.spinner.succeed('Next.js application created successfully');
406
+ async setupProject(preferences) {
407
+ cli_style_1.CLIStyle.startSequence('Project Setup');
408
+ cli_style_1.CLIStyle.logInfo('Setting up your Igniter project. This might take a few minutes...');
254
409
  // Project structure
255
- await this.delay(1000);
256
- this.spinner.start('Creating project structure...');
410
+ cli_style_1.CLIStyle.startStep('Setting up project structure');
411
+ const spinner2 = cli_style_1.CLIStyle.createSpinner('Creating directories...');
412
+ spinner2.start();
413
+ const packageManager = preferences['package-manager'];
414
+ const isNextProject = (0, project_utils_1.isNextJSProject)();
415
+ if (isNextProject) {
416
+ this.createDir('src/app/api/[[...all]]');
417
+ this.createFile('src/app/api/[[...all]]/route.ts', template_handler_1.TemplateHandler.render('route.hbs', {}));
418
+ this.createFile('src/hooks/use-form-with-zod.ts', template_handler_1.TemplateHandler.render('use-form-with-zod', {}));
419
+ }
420
+ if (!isNextProject) {
421
+ if (preferences['project-type'] === 'express') {
422
+ this.execCommand(`${packageManager} init -y`);
423
+ this.execCommand(`${packageManager} install express`);
424
+ this.execCommand(`${packageManager} install --save-dev typescript ts-node @types/node @types/express`);
425
+ const packageJson = this.loadJSON('package.json');
426
+ packageJson.name = path_1.default.basename(process.cwd());
427
+ packageJson.version = '1.0.0';
428
+ packageJson.legacyPeerDeps = true;
429
+ packageJson.scripts = {};
430
+ packageJson.scripts['build'] = 'tsc';
431
+ packageJson.scripts['start'] = 'node dist/server.js';
432
+ packageJson.scripts['dev'] = 'ts-node src/server.ts';
433
+ this.saveJSON('package.json', packageJson);
434
+ this.createFile('src/server.ts', template_handler_1.TemplateHandler.render('express.server.hbs', {}));
435
+ this.createFile('README.md', template_handler_1.TemplateHandler.render('readme.hbs', {}));
436
+ this.createFile('eslintrc.json', template_handler_1.TemplateHandler.render('eslintrc.hbs', {}));
437
+ this.createFile('docker-compose.yml', template_handler_1.TemplateHandler.render('docker-compose.hbs', {}));
438
+ }
439
+ if (preferences['project-type'] === 'nextjs') {
440
+ this.execCommand(`npx create-next-app@latest --ts --tailwind --eslint --app --src-dir --turbopack --import-alias="@/*" --use-${packageManager} .`);
441
+ const packageJson = this.loadJSON('package.json');
442
+ packageJson.name = path_1.default.basename(process.cwd());
443
+ packageJson.version = '1.0.0';
444
+ packageJson.legacyPeerDeps = true;
445
+ this.saveJSON('package.json', packageJson);
446
+ this.createFile('.github/copilot.next.instructions.md', template_handler_1.TemplateHandler.render('copilot.next.instructions.hbs', {}));
447
+ this.createFile('.github/copilot.form.instructions.md', template_handler_1.TemplateHandler.render('copilot.form.instructions.hbs', {}));
448
+ this.createFile('src/app/page.tsx', template_handler_1.TemplateHandler.render('page.hbs', {}));
449
+ this.createFile('src/app/layout.tsx', template_handler_1.TemplateHandler.render('layout.hbs', {}));
450
+ this.createFile('src/app/globals.css', template_handler_1.TemplateHandler.render('globals.hbs', {}));
451
+ this.createDir('src/app/api/[[...all]]');
452
+ this.createFile('src/app/api/[[...all]]/route.ts', template_handler_1.TemplateHandler.render('route.hbs', {}));
453
+ this.createFile('src/hooks/use-form-with-zod.ts', template_handler_1.TemplateHandler.render('use-form-with-zod', {}));
454
+ this.createFile('README.md', template_handler_1.TemplateHandler.render('readme.hbs', {}));
455
+ this.createFile('eslintrc.json', template_handler_1.TemplateHandler.render('eslintrc.hbs', {}));
456
+ this.createFile('docker-compose.yml', template_handler_1.TemplateHandler.render('docker-compose.hbs', {}));
457
+ const runner = (0, project_utils_1.getPackageManagerRunner)(packageManager);
458
+ if (!runner) {
459
+ cli_style_1.CLIStyle.logError('Unsupported package manager. Please use npm, yarn, pnpm or bun.');
460
+ process.exit(1);
461
+ }
462
+ console.log(runner);
463
+ this.execCommand(`${runner} shadcn@latest init -y -f --src-dir --css-variables --base-color zinc`);
464
+ this.execCommand(`${runner} shadcn@latest add -y -a`);
465
+ }
466
+ }
257
467
  this.createDirectoryStructure(consts_1.PROJECT_STRUCTURE);
258
- this.spinner.succeed('Project structure created successfully');
259
- // Prisma setup
260
- await this.delay(1000);
261
- this.spinner.start('Initializing Prisma...');
262
- this.execCommand('npx prisma init');
263
- this.execCommand('rm ./.env');
264
- const prismaFile = template_handler_1.TemplateHandler.render('prisma', {});
265
- this.createFile('src/core/providers/prisma.ts', prismaFile);
266
- this.spinner.succeed('Prisma initialized successfully');
267
- // Testing environment
268
- await this.delay(1000);
269
- this.spinner.start('Setting up testing environment...');
270
- this.execCommand('npm install --save-dev vitest');
271
- this.execCommand('npm install --save-dev @vitejs/plugin-react');
272
- this.execCommand('npm install --save-dev vite-tsconfig-paths');
273
- this.spinner.succeed('Testing environment setup completed');
468
+ spinner2.succeed('Directory structure created');
469
+ cli_style_1.CLIStyle.endStep();
470
+ // Prisma setup (conditional)
471
+ if (preferences.database === 'prisma') {
472
+ cli_style_1.CLIStyle.startStep('Setting up Prisma ORM');
473
+ const spinner3 = cli_style_1.CLIStyle.createSpinner('Initializing Prisma...');
474
+ spinner3.start();
475
+ this.execCommand('npx prisma init');
476
+ this.execCommand('rm ./.env');
477
+ const prismaFile = template_handler_1.TemplateHandler.render('prisma', {});
478
+ this.createFile('src/providers/prisma.ts', prismaFile);
479
+ spinner3.succeed('Prisma initialized');
480
+ cli_style_1.CLIStyle.endStep();
481
+ }
482
+ else {
483
+ cli_style_1.CLIStyle.logInfo('Skipping Prisma setup as per your preference');
484
+ }
274
485
  // Core dependencies
275
- await this.delay(1000);
276
- this.spinner.start('Installing core dependencies...');
277
- this.execCommand('npm install --save @igniter-js/eslint-config');
278
- this.execCommand('npm install --save @igniter-js/core');
279
- this.spinner.succeed('Core dependencies installed successfully');
280
- // Shadcn/UI setup
281
- await this.delay(1000);
282
- this.spinner.start('Setting up Shadcn/UI...');
283
- this.execCommand('npm config set legacy-peer-deps true');
284
- this.execCommand('npx shadcn@canary init -d -y');
285
- const content = template_handler_1.TemplateHandler.render('components.json', {});
286
- this.updateFile('components.json', content);
287
- this.execCommand('npx shadcn@canary add --all');
288
- this.spinner.succeed('Shadcn/UI setup completed');
289
- // Environment files
290
- await this.delay(1000);
291
- this.spinner.start('Creating environment files...');
486
+ cli_style_1.CLIStyle.startStep('Installing Igniter.js and updating environment files');
487
+ const spinner5 = cli_style_1.CLIStyle.createSpinner('Installing packages...');
488
+ spinner5.start();
489
+ this.execCommand(`${packageManager} install @igniter-js/eslint-config`);
490
+ this.execCommand(`${packageManager} install @igniter-js/core`);
292
491
  const envContent = template_handler_1.TemplateHandler.render('env.hbs', {});
293
492
  this.createFile('.env', envContent);
294
- this.spinner.succeed('Environment files created successfully');
295
- // Project files configuration
296
- await this.delay(1000);
297
- this.spinner.start('Configuring project files...');
298
- this.execCommand('mv ./src/lib/utils.ts ./src/core/utils/cn.ts');
299
- this.execCommand('rm -rf ./src/lib');
300
- const pageContent = template_handler_1.TemplateHandler.render('page.hbs', {});
301
- this.updateFile('src/app/page.tsx', pageContent);
302
- const layoutContent = template_handler_1.TemplateHandler.render('layout.hbs', {});
303
- this.updateFile('src/app/layout.tsx', layoutContent);
304
- const globalsContent = template_handler_1.TemplateHandler.render('globals.hbs', {});
305
- this.updateFile('src/app/globals.css', globalsContent);
306
- this.spinner.succeed('Project files configured successfully');
307
- // Package configuration
308
- await this.delay(1000);
309
- this.spinner.start('Updating package configuration...');
310
- const packageJson = this.loadJSON('package.json');
311
- for (const config of consts_1.CONFIG_FILES) {
312
- const content = template_handler_1.TemplateHandler.render(config.template, {});
313
- this.createFile(config.name, content);
314
- }
315
- this.spinner.succeed('Package configuration updated successfully');
493
+ this.createFile('src/igniter.client.ts', template_handler_1.TemplateHandler.render('igniter.client', {}));
494
+ this.createFile('src/igniter.context.ts', template_handler_1.TemplateHandler.render('igniter.context', {}));
495
+ this.createFile('src/igniter.router.ts', template_handler_1.TemplateHandler.render('igniter.router', {}));
496
+ this.createFile('src/igniter.ts', template_handler_1.TemplateHandler.render('igniter', {}));
497
+ spinner5.succeed('Igniter.js installed and environment files updated');
498
+ cli_style_1.CLIStyle.endStep();
316
499
  // Lia files
317
- await this.delay(1000);
318
- this.spinner.start('Creating Lia files...');
500
+ cli_style_1.CLIStyle.startStep('Creating Lia assistant files for GitHub Copilot');
501
+ const spinner10 = cli_style_1.CLIStyle.createSpinner('Setting up Lia...');
502
+ spinner10.start();
319
503
  for (const file of consts_1.LIA_FILES) {
320
504
  const content = template_handler_1.TemplateHandler.render(file.template, {});
321
505
  this.createFile(file.name, content);
322
506
  }
323
- this.spinner.succeed('Lia files created successfully');
324
- this.spinner.start('Creating igniter files...');
325
- const igniterClientFile = template_handler_1.TemplateHandler.render('igniter.client', {});
326
- const igniterContextFile = template_handler_1.TemplateHandler.render('igniter.context', {});
327
- const igniterRouterFile = template_handler_1.TemplateHandler.render('igniter.router', {});
328
- const igniterRouteHandlerFile = template_handler_1.TemplateHandler.render('route', {});
329
- const useFormFile = template_handler_1.TemplateHandler.render('use-form-with-zod', {});
330
- const igniterFile = template_handler_1.TemplateHandler.render('igniter', {});
331
- this.createFile('src/igniter.client.ts', igniterClientFile);
332
- this.createFile('src/igniter.context.ts', igniterContextFile);
333
- this.createFile('src/igniter.router.ts', igniterRouterFile);
334
- this.createFile('src/core/hooks/use-form-with-zod.ts', useFormFile);
335
- this.createFile('src/app/api/[[...all]]/route.ts', igniterRouteHandlerFile);
336
- this.createFile('src/igniter.ts', igniterFile);
337
- this.spinner.succeed('Igniter files created successfully');
338
- packageJson.name = path_1.default.basename(process.cwd());
339
- packageJson.version = '1.0.0';
340
- packageJson.legacyPeerDeps = true;
341
- packageJson.scripts['igniter'] = 'npx @igniter-js/cli';
342
- this.saveJSON('package.json', packageJson);
343
- this.spinner.succeed('Package configuration updated successfully');
344
- console.log('\n' + chalk_1.default.bold.cyan('🎉 Setup Complete!\n'));
345
- console.log(chalk_1.default.bold('Next Steps:'));
346
- console.log(`
347
- ${chalk_1.default.cyan('1.')} Start development server:
348
- ${chalk_1.default.gray('$')} ${chalk_1.default.white('npm run dev')}
349
-
350
- ${chalk_1.default.cyan('2.')} Start Docker services:
351
- ${chalk_1.default.gray('$')} ${chalk_1.default.white('docker compose up -d')}
352
-
353
- ${chalk_1.default.cyan('3.')} Run Prisma migrations client:
354
- ${chalk_1.default.gray('$')} ${chalk_1.default.white('npx prisma migrate dev')}
355
-
356
- ${chalk_1.default.cyan('4.')} Create your first feature:
357
- ${chalk_1.default.gray('$')} ${chalk_1.default.white('npx @igniter-js/cli generate feature')}
358
-
359
- ${chalk_1.default.cyan('📚')} Documentation: ${chalk_1.default.blue('https://github.com/felipebarcelospro/igniter-js')}
360
- ${chalk_1.default.cyan('💡')} Need help? ${chalk_1.default.blue('https://github.com/felipebarcelospro/igniter-js/issues')}
361
- `);
362
- console.log(chalk_1.default.bold.green('\n✨ Happy coding! ✨\n'));
507
+ spinner10.succeed('Lia assistant configured');
508
+ cli_style_1.CLIStyle.endStep();
509
+ cli_style_1.CLIStyle.endSequence();
510
+ cli_style_1.CLIStyle.logSuccess('Your Igniter project is ready!');
511
+ console.log('\n' + '🎯 Next Steps:\n');
512
+ console.log(` 1. Start development server:`);
513
+ console.log(` $ npm run dev`);
514
+ console.log('');
515
+ if (preferences.database === 'prisma') {
516
+ console.log(` 2. Start Docker services for database:`);
517
+ console.log(` $ docker compose up -d`);
518
+ console.log('');
519
+ console.log(` 3. Run Prisma migrations:`);
520
+ console.log(` $ npx prisma migrate dev`);
521
+ console.log('');
522
+ console.log(` 4. Generate features from your database models:`);
523
+ console.log(` $ npx @igniter-js/cli generate feature`);
524
+ console.log('');
525
+ }
526
+ console.log('\n' + '🎯 Next Steps:\n');
527
+ console.log(` 1. Start development server:`);
528
+ console.log(` $ npm run dev`);
529
+ console.log('');
530
+ if (preferences.database === 'prisma') {
531
+ console.log(` 2. Start Docker services for database:`);
532
+ console.log(` $ docker compose up -d`);
533
+ console.log('');
534
+ console.log(` 3. Run Prisma migrations:`);
535
+ console.log(` $ npx prisma migrate dev`);
536
+ console.log('');
537
+ console.log(` 4. Generate features from your database models:`);
538
+ console.log(` $ npx @igniter-js/cli generate feature`);
539
+ console.log('');
540
+ }
541
+ console.log(` 📚 Documentation: https://github.com/felipebarcelospro/igniter-js`);
542
+ console.log(` 💡 Need help? https://github.com/felipebarcelospro/igniter-js/issues`);
543
+ console.log('\n' + '✨ Happy coding with Igniter! ✨\n');
363
544
  }
364
545
  }
365
546
  // Start CLI
366
547
  new IgniterCLI();
548
+ //# sourceMappingURL=index.js.map