@igniter-js/cli 0.1.4 → 0.1.5

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