@intrig/core 0.0.15-15 → 0.0.15-16

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 (2) hide show
  1. package/main.js +191 -38
  2. package/package.json +2 -1
package/main.js CHANGED
@@ -901,6 +901,10 @@ class SpecManagementService {
901
901
  external_fs_namespaceObject.mkdirSync(this.specsDir, {
902
902
  recursive: true
903
903
  });
904
+ // Create the file if it doesn't exist (proper-lockfile requires the file to exist)
905
+ if (!external_fs_namespaceObject.existsSync(filePath)) {
906
+ external_fs_namespaceObject.writeFileSync(filePath, '', 'utf-8');
907
+ }
904
908
  // Acquire lock for the file
905
909
  release = await external_proper_lockfile_namespaceObject.lock(filePath, {
906
910
  retries: {
@@ -984,6 +988,10 @@ class SpecManagementService {
984
988
  if (external_fs_namespaceObject.existsSync(specPath)) {
985
989
  try {
986
990
  const content = external_fs_namespaceObject.readFileSync(specPath, 'utf-8');
991
+ // Handle empty files (created for locking purposes)
992
+ if (!content || content.trim() === '') {
993
+ return undefined;
994
+ }
987
995
  return JSON.parse(content);
988
996
  } catch (error) {
989
997
  this.logger.error(`Failed to parse JSON for ${apiName}: ${error.message}`);
@@ -5296,6 +5304,9 @@ class SourcesAddCommand extends external_nest_commander_namespaceObject.CommandR
5296
5304
  constructor(pm, httpService, lazyPluginService, configService){
5297
5305
  super(), this.pm = pm, this.httpService = httpService, this.lazyPluginService = lazyPluginService, this.configService = configService;
5298
5306
  }
5307
+ parseIdOption(val) {
5308
+ return val;
5309
+ }
5299
5310
  async run(passedParams, options) {
5300
5311
  const metadata = await this.pm.getMetadata();
5301
5312
  if (!metadata) {
@@ -5327,15 +5338,27 @@ class SourcesAddCommand extends external_nest_commander_namespaceObject.CommandR
5327
5338
  console.log(external_chalk_default().bold.cyan('\nSource details:'));
5328
5339
  console.log(`${external_chalk_default().green('Name:')} ${external_chalk_default().white(source.name ?? 'N/A')}`);
5329
5340
  console.log(`${external_chalk_default().green('Spec:')} ${external_chalk_default().white(source.specUrl ?? 'N/A')}`);
5330
- // 6) Ask for ID
5331
- const { id } = await external_inquirer_default().prompt([
5332
- {
5333
- type: 'input',
5334
- name: 'id',
5335
- message: external_chalk_default().yellow('Enter an ID for this source (letters/numbers/-/_):'),
5336
- validate: (v)=>/^[\w-]+$/.test(v) || 'ID must contain only letters, numbers, hyphens, or underscores'
5341
+ // 6) Get ID from option or prompt
5342
+ let id;
5343
+ if (options?.id) {
5344
+ // Validate the provided ID
5345
+ if (!/^[\w-]+$/.test(options.id)) {
5346
+ console.error(external_chalk_default().red.bold('Error:'), external_chalk_default().red('ID must contain only letters, numbers, hyphens, or underscores'));
5347
+ process.exit(1);
5337
5348
  }
5338
- ]);
5349
+ id = options.id;
5350
+ console.log(external_chalk_default().blue(`ℹ️ Using provided ID: ${id}`));
5351
+ } else {
5352
+ const { id: promptedId } = await external_inquirer_default().prompt([
5353
+ {
5354
+ type: 'input',
5355
+ name: 'id',
5356
+ message: external_chalk_default().yellow('Enter an ID for this source (letters/numbers/-/_):'),
5357
+ validate: (v)=>/^[\w-]+$/.test(v) || 'ID must contain only letters, numbers, hyphens, or underscores'
5358
+ }
5359
+ ]);
5360
+ id = promptedId;
5361
+ }
5339
5362
  source.id = id;
5340
5363
  // 7) Add endpoint
5341
5364
  const addUrl = `${metadata.url}/api/config/sources/add`;
@@ -5368,6 +5391,17 @@ class SourcesAddCommand extends external_nest_commander_namespaceObject.CommandR
5368
5391
  }
5369
5392
  }
5370
5393
  }
5394
+ sources_command_ts_decorate([
5395
+ (0,external_nest_commander_namespaceObject.Option)({
5396
+ flags: '--id <id>',
5397
+ description: 'Specify source ID directly (letters/numbers/-/_)'
5398
+ }),
5399
+ sources_command_ts_metadata("design:type", Function),
5400
+ sources_command_ts_metadata("design:paramtypes", [
5401
+ String
5402
+ ]),
5403
+ sources_command_ts_metadata("design:returntype", String)
5404
+ ], SourcesAddCommand.prototype, "parseIdOption", null);
5371
5405
  SourcesAddCommand = sources_command_ts_decorate([
5372
5406
  (0,external_nest_commander_namespaceObject.SubCommand)({
5373
5407
  name: 'add',
@@ -5426,6 +5460,12 @@ class SourceRemoveCommand extends external_nest_commander_namespaceObject.Comman
5426
5460
  constructor(pm, httpService, lazyPluginService, configService){
5427
5461
  super(), this.pm = pm, this.httpService = httpService, this.lazyPluginService = lazyPluginService, this.configService = configService;
5428
5462
  }
5463
+ parseIdOption(val) {
5464
+ return val;
5465
+ }
5466
+ parseYesOption() {
5467
+ return true;
5468
+ }
5429
5469
  async run(passedParams, options) {
5430
5470
  // 1) fetch metadata
5431
5471
  const metadata = await this.pm.getMetadata();
@@ -5444,33 +5484,54 @@ class SourceRemoveCommand extends external_nest_commander_namespaceObject.Comman
5444
5484
  console.log(external_chalk_default().yellow('No sources found.'));
5445
5485
  return;
5446
5486
  }
5447
- // 3) prompt user to choose one
5448
- const choices = sources.map((src)=>({
5449
- name: `${src.id} — ${src.name ?? 'N/A'} (${src.specUrl})`,
5450
- value: src.id
5451
- }));
5452
- const { id } = await external_inquirer_default().prompt([
5453
- {
5454
- type: 'list',
5455
- name: 'id',
5456
- message: external_chalk_default().yellow('Select a source to remove:'),
5457
- choices
5487
+ // 3) Get source ID from option or prompt
5488
+ let id;
5489
+ if (options?.id) {
5490
+ // Validate the ID exists in sources
5491
+ const sourceExists = sources.some((src)=>src.id === options.id);
5492
+ if (!sourceExists) {
5493
+ console.error(external_chalk_default().red.bold('Error:'), external_chalk_default().red(`Source with ID "${options.id}" not found.`));
5494
+ console.log(external_chalk_default().yellow('Available sources:'));
5495
+ sources.forEach((src)=>{
5496
+ console.log(` - ${src.id}`);
5497
+ });
5498
+ process.exit(1);
5458
5499
  }
5459
- ]);
5500
+ id = options.id;
5501
+ console.log(external_chalk_default().blue(`ℹ️ Using provided ID: ${id}`));
5502
+ } else {
5503
+ const choices = sources.map((src)=>({
5504
+ name: `${src.id} — ${src.name ?? 'N/A'} (${src.specUrl})`,
5505
+ value: src.id
5506
+ }));
5507
+ const { id: promptedId } = await external_inquirer_default().prompt([
5508
+ {
5509
+ type: 'list',
5510
+ name: 'id',
5511
+ message: external_chalk_default().yellow('Select a source to remove:'),
5512
+ choices
5513
+ }
5514
+ ]);
5515
+ id = promptedId;
5516
+ }
5460
5517
  // Store the source details before deletion for lifecycle method
5461
5518
  const selectedSource = sources.find((src)=>src.id === id);
5462
- // 4) confirm deletion
5463
- const { confirm } = await external_inquirer_default().prompt([
5464
- {
5465
- type: 'confirm',
5466
- name: 'confirm',
5467
- message: external_chalk_default().red(`Are you sure you want to delete "${id}"?`),
5468
- default: false
5519
+ // 4) Confirm deletion (skip if --yes flag is set)
5520
+ if (!options?.yes) {
5521
+ const { confirm } = await external_inquirer_default().prompt([
5522
+ {
5523
+ type: 'confirm',
5524
+ name: 'confirm',
5525
+ message: external_chalk_default().red(`Are you sure you want to delete "${id}"?`),
5526
+ default: false
5527
+ }
5528
+ ]);
5529
+ if (!confirm) {
5530
+ console.log(external_chalk_default().gray('Aborted.'));
5531
+ return;
5469
5532
  }
5470
- ]);
5471
- if (!confirm) {
5472
- console.log(external_chalk_default().gray('Aborted.'));
5473
- return;
5533
+ } else {
5534
+ console.log(external_chalk_default().blue(`ℹ️ Skipping confirmation (--yes flag set)`));
5474
5535
  }
5475
5536
  // 5) call DELETE /remove/:id
5476
5537
  const removeUrl = `${metadata.url}/api/config/sources/remove/${encodeURIComponent(id)}`;
@@ -5497,6 +5558,26 @@ class SourceRemoveCommand extends external_nest_commander_namespaceObject.Comman
5497
5558
  }
5498
5559
  }
5499
5560
  }
5561
+ sources_command_ts_decorate([
5562
+ (0,external_nest_commander_namespaceObject.Option)({
5563
+ flags: '--id <id>',
5564
+ description: 'Specify source ID to remove directly'
5565
+ }),
5566
+ sources_command_ts_metadata("design:type", Function),
5567
+ sources_command_ts_metadata("design:paramtypes", [
5568
+ String
5569
+ ]),
5570
+ sources_command_ts_metadata("design:returntype", String)
5571
+ ], SourceRemoveCommand.prototype, "parseIdOption", null);
5572
+ sources_command_ts_decorate([
5573
+ (0,external_nest_commander_namespaceObject.Option)({
5574
+ flags: '-y, --yes',
5575
+ description: 'Skip confirmation prompt'
5576
+ }),
5577
+ sources_command_ts_metadata("design:type", Function),
5578
+ sources_command_ts_metadata("design:paramtypes", []),
5579
+ sources_command_ts_metadata("design:returntype", Boolean)
5580
+ ], SourceRemoveCommand.prototype, "parseYesOption", null);
5500
5581
  SourceRemoveCommand = sources_command_ts_decorate([
5501
5582
  (0,external_nest_commander_namespaceObject.SubCommand)({
5502
5583
  name: 'rm',
@@ -8118,6 +8199,9 @@ function init_command_ts_decorate(decorators, target, key, desc) {
8118
8199
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
8119
8200
  return c > 3 && r && Object.defineProperty(target, key, r), r;
8120
8201
  }
8202
+ function init_command_ts_metadata(k, v) {
8203
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
8204
+ }
8121
8205
 
8122
8206
 
8123
8207
 
@@ -8129,6 +8213,12 @@ function init_command_ts_decorate(decorators, target, key, desc) {
8129
8213
 
8130
8214
 
8131
8215
  class InitCommand extends external_nest_commander_namespaceObject.CommandRunner {
8216
+ parsePluginOption(val) {
8217
+ return val;
8218
+ }
8219
+ parseYesOption() {
8220
+ return true;
8221
+ }
8132
8222
  async run(passedParams, options) {
8133
8223
  console.log(external_chalk_default().blue('🚀 Initializing Intrig setup...'));
8134
8224
  const rootDir = process.cwd();
@@ -8143,17 +8233,49 @@ class InitCommand extends external_nest_commander_namespaceObject.CommandRunner
8143
8233
  // Check for existing plugin dependency matching the plugin regex format
8144
8234
  const existingPlugin = this.checkForExistingPlugin(packageJson);
8145
8235
  let selectedPlugin;
8146
- if (existingPlugin) {
8236
+ // Priority: 1. CLI --plugin option, 2. Existing plugin in package.json, 3. Interactive prompt (or best match with --yes)
8237
+ if (options?.plugin) {
8238
+ console.log(external_chalk_default().blue(`ℹ️ Using plugin from CLI option: ${options.plugin}`));
8239
+ selectedPlugin = {
8240
+ type: 'generator',
8241
+ generator: 'custom',
8242
+ name: options.plugin,
8243
+ compat: {
8244
+ latest: {
8245
+ dependencies: {}
8246
+ }
8247
+ }
8248
+ };
8249
+ } else if (existingPlugin) {
8147
8250
  console.log(external_chalk_default().green(`✅ Found existing plugin dependency: ${existingPlugin.name}`));
8148
8251
  selectedPlugin = existingPlugin;
8149
8252
  } else {
8150
8253
  // Fetch approved plugins from GitHub
8151
8254
  const approvedPlugins = await this.fetchApprovedPlugins();
8152
- // Prompt user to select plugin (show all plugins with best match as default)
8153
- selectedPlugin = await this.promptUserForPlugin(approvedPlugins, packageJson);
8255
+ // If --yes flag is set, use the best matching plugin automatically
8256
+ if (options?.yes) {
8257
+ const projectDependencies = {
8258
+ ...packageJson.dependencies,
8259
+ ...packageJson.devDependencies
8260
+ };
8261
+ const pluginsWithScores = approvedPlugins.map((plugin)=>({
8262
+ plugin,
8263
+ score: this.calculateCompatibilityScore(plugin, projectDependencies)
8264
+ })).sort((a, b)=>b.score - a.score);
8265
+ const bestMatch = pluginsWithScores[0]?.plugin;
8266
+ if (bestMatch) {
8267
+ console.log(external_chalk_default().blue(`ℹ️ Auto-selecting best matching plugin: ${bestMatch.name} (score: ${pluginsWithScores[0].score})`));
8268
+ selectedPlugin = bestMatch;
8269
+ } else {
8270
+ throw new Error('No plugins available and --yes flag was set. Please specify a plugin with --plugin option.');
8271
+ }
8272
+ } else {
8273
+ // Prompt user to select plugin (show all plugins with best match as default)
8274
+ selectedPlugin = await this.promptUserForPlugin(approvedPlugins, packageJson);
8275
+ }
8154
8276
  }
8155
8277
  // Load and initialize the selected plugin
8156
- const { pluginInstance, generatorOptions, postInitFunction } = await this.loadAndInitializePlugin(selectedPlugin);
8278
+ const { pluginInstance, generatorOptions, postInitFunction } = await this.loadAndInitializePlugin(selectedPlugin, options?.yes);
8157
8279
  // Check if plugin loading failed
8158
8280
  if (!pluginInstance) {
8159
8281
  throw new Error(`Failed to load and initialize plugin ${selectedPlugin.name}. Please check the plugin installation and try again.`);
@@ -8352,7 +8474,7 @@ class InitCommand extends external_nest_commander_namespaceObject.CommandRunner
8352
8474
  }
8353
8475
  return selectedPlugin;
8354
8476
  }
8355
- async loadAndInitializePlugin(plugin) {
8477
+ async loadAndInitializePlugin(plugin, skipPrompts) {
8356
8478
  const installSpinner = external_ora_default()(`Installing plugin: ${plugin.name}`).start();
8357
8479
  try {
8358
8480
  const rootDir = process.cwd();
@@ -8397,7 +8519,7 @@ class InitCommand extends external_nest_commander_namespaceObject.CommandRunner
8397
8519
  loadSpinner.text = 'Collecting generator configuration...';
8398
8520
  // Stop the spinner before collecting interactive input to prevent interference
8399
8521
  loadSpinner.stop();
8400
- generatorOptions = await this.collectGeneratorOptions(pluginInstance.$generatorSchema, plugin.name);
8522
+ generatorOptions = await this.collectGeneratorOptions(pluginInstance.$generatorSchema, plugin.name, skipPrompts);
8401
8523
  console.log("Generator options", generatorOptions);
8402
8524
  // Restart the spinner if we have more work to do
8403
8525
  loadSpinner.start();
@@ -8460,7 +8582,7 @@ class InitCommand extends external_nest_commander_namespaceObject.CommandRunner
8460
8582
  throw new Error(`Plugin "${pluginName}" does not export a factory function. ` + `Expected "createPlugin()" or a default function export. ` + `Available exports: ${Object.keys(mod || {}).join(', ')}`);
8461
8583
  }
8462
8584
  }
8463
- async collectGeneratorOptions(generatorSchema, pluginName) {
8585
+ async collectGeneratorOptions(generatorSchema, pluginName, skipPrompts) {
8464
8586
  const options = {};
8465
8587
  if (!generatorSchema.properties) {
8466
8588
  return options;
@@ -8468,6 +8590,17 @@ class InitCommand extends external_nest_commander_namespaceObject.CommandRunner
8468
8590
  // Use schinquirer to generate questions from schema
8469
8591
  if (generatorSchema.properties && Object.keys(generatorSchema.properties).length > 0) {
8470
8592
  try {
8593
+ // If --yes flag is set, use defaults from schema
8594
+ if (skipPrompts) {
8595
+ console.log(external_chalk_default().blue(`ℹ️ Using default generator options (--yes flag set)`));
8596
+ for (const [key, prop] of Object.entries(generatorSchema.properties)){
8597
+ if (prop.default !== undefined) {
8598
+ options[key] = prop.default;
8599
+ }
8600
+ }
8601
+ console.log(external_chalk_default().blue(`ℹ️ You can configure generator options later in intrig.config.json`));
8602
+ return options;
8603
+ }
8471
8604
  // Check if we're in a non-interactive environment
8472
8605
  if (!process.stdin.isTTY) {
8473
8606
  console.log(external_chalk_default().yellow(`⚠️ Non-interactive environment detected. Skipping generator configuration for plugin ${pluginName}.`));
@@ -8535,6 +8668,26 @@ class InitCommand extends external_nest_commander_namespaceObject.CommandRunner
8535
8668
  }
8536
8669
  }
8537
8670
  }
8671
+ init_command_ts_decorate([
8672
+ (0,external_nest_commander_namespaceObject.Option)({
8673
+ flags: '-p, --plugin <plugin>',
8674
+ description: 'Specify plugin name directly (e.g., @intrig/plugin-react)'
8675
+ }),
8676
+ init_command_ts_metadata("design:type", Function),
8677
+ init_command_ts_metadata("design:paramtypes", [
8678
+ String
8679
+ ]),
8680
+ init_command_ts_metadata("design:returntype", String)
8681
+ ], InitCommand.prototype, "parsePluginOption", null);
8682
+ init_command_ts_decorate([
8683
+ (0,external_nest_commander_namespaceObject.Option)({
8684
+ flags: '-y, --yes',
8685
+ description: 'Accept defaults and skip interactive prompts'
8686
+ }),
8687
+ init_command_ts_metadata("design:type", Function),
8688
+ init_command_ts_metadata("design:paramtypes", []),
8689
+ init_command_ts_metadata("design:returntype", Boolean)
8690
+ ], InitCommand.prototype, "parseYesOption", null);
8538
8691
  InitCommand = init_command_ts_decorate([
8539
8692
  (0,external_nest_commander_namespaceObject.Command)({
8540
8693
  name: 'init',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intrig/core",
3
- "version": "0.0.15-15",
3
+ "version": "0.0.15-16",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,6 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@apidevtools/json-schema-ref-parser": "12.0.2",
14
+ "@intrig/plugin-sdk": "^0.0.15-16",
14
15
  "@nestjs/axios": "4.0.1",
15
16
  "@nestjs/common": "10.4.20",
16
17
  "@nestjs/config": "4.0.2",