@zapier/zapier-sdk-cli 0.10.0 → 0.11.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @zapier/zapier-sdk-cli
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 12c6d3d: Return nested fields with fieldsets instead of flat fields. Also have CLI properly create line items from fieldsets for run-action.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [12c6d3d]
12
+ - @zapier/zapier-sdk@0.11.0
13
+ - @zapier/zapier-sdk-mcp@0.3.8
14
+
3
15
  ## 0.10.0
4
16
 
5
17
  ### Minor Changes
package/dist/cli.cjs CHANGED
@@ -336,7 +336,7 @@ var SchemaParameterResolver = class {
336
336
  const inputs = {};
337
337
  let processedFieldKeys = /* @__PURE__ */ new Set();
338
338
  let iteration = 0;
339
- const maxIterations = 5;
339
+ const maxIterations = 10;
340
340
  while (iteration < maxIterations) {
341
341
  iteration++;
342
342
  const updatedContext = {
@@ -351,11 +351,11 @@ var SchemaParameterResolver = class {
351
351
  `Fetching input fields for ${param.name}${iteration > 1 ? ` (iteration ${iteration})` : ""}...`
352
352
  )
353
353
  );
354
- const fields = await typedResolver.fetch(
354
+ const rootFieldItems = await typedResolver.fetch(
355
355
  updatedContext.sdk,
356
356
  updatedContext.resolvedParams
357
357
  );
358
- if (!fields || fields.length === 0) {
358
+ if (!rootFieldItems || rootFieldItems.length === 0) {
359
359
  if (iteration === 1) {
360
360
  console.log(
361
361
  chalk3__default.default.yellow(`No input fields required for this action.`)
@@ -363,47 +363,125 @@ var SchemaParameterResolver = class {
363
363
  }
364
364
  break;
365
365
  }
366
- const newFields = fields.filter(
367
- (field) => !(field.key && processedFieldKeys.has(field.key))
366
+ const fieldStats = await this.processFieldItems(
367
+ rootFieldItems,
368
+ inputs,
369
+ processedFieldKeys,
370
+ [],
371
+ iteration
368
372
  );
369
- if (newFields.length === 0) {
373
+ if (fieldStats.newRequired === 0 && fieldStats.newOptional === 0) {
370
374
  break;
371
375
  }
372
- const newRequiredFields = newFields.filter(
373
- (field) => field.is_required
374
- );
375
- const newOptionalFields = newFields.filter(
376
- (field) => !field.is_required
376
+ if (fieldStats.newRequired === 0 && fieldStats.optionalSkipped) {
377
+ break;
378
+ }
379
+ }
380
+ if (iteration >= maxIterations) {
381
+ console.log(
382
+ chalk3__default.default.yellow(
383
+ `
384
+ \u26A0\uFE0F Maximum field resolution iterations reached. Some dynamic fields may not have been discovered.`
385
+ )
377
386
  );
378
- if (newRequiredFields.length > 0) {
387
+ }
388
+ return inputs;
389
+ }
390
+ /**
391
+ * Recursively processes fieldsets and their fields, maintaining natural structure
392
+ * and creating nested inputs as needed (e.g., fieldset "foo" becomes inputs.foo = [{}])
393
+ */
394
+ async processFieldItems(items, targetInputs, processedFieldKeys, fieldsetPath = [], iteration = 1) {
395
+ let newRequiredCount = 0;
396
+ let newOptionalCount = 0;
397
+ let optionalSkipped = false;
398
+ for (const item of items) {
399
+ const typedItem = item;
400
+ if (typedItem.type === "fieldset" && typedItem.fields && typedItem.key) {
401
+ const fieldsetTitle = typedItem.title || typedItem.key;
402
+ const pathDisplay = fieldsetPath.length > 0 ? ` (in ${fieldsetPath.join(" > ")})` : "";
379
403
  console.log(
380
- chalk3__default.default.blue(
404
+ chalk3__default.default.cyan(
381
405
  `
382
- \u{1F4DD} Please provide values for the following ${iteration === 1 ? "" : "additional "}input fields:`
406
+ \u{1F4C1} Processing fieldset: ${fieldsetTitle}${pathDisplay}`
383
407
  )
384
408
  );
385
- for (const field of newRequiredFields) {
386
- await this.promptForField(field, inputs);
387
- processedFieldKeys.add(field.key);
409
+ if (!targetInputs[typedItem.key]) {
410
+ targetInputs[typedItem.key] = [{}];
411
+ }
412
+ const fieldsetTarget = targetInputs[typedItem.key][0];
413
+ const nestedPath = [...fieldsetPath, fieldsetTitle];
414
+ const nestedStats = await this.processFieldItems(
415
+ typedItem.fields,
416
+ fieldsetTarget,
417
+ processedFieldKeys,
418
+ nestedPath,
419
+ iteration
420
+ );
421
+ newRequiredCount += nestedStats.newRequired;
422
+ newOptionalCount += nestedStats.newOptional;
423
+ if (nestedStats.optionalSkipped) {
424
+ optionalSkipped = true;
425
+ }
426
+ } else if (typedItem.type === "input_field" && typedItem.key) {
427
+ if (processedFieldKeys.has(typedItem.key)) {
428
+ continue;
429
+ }
430
+ const isRequired = typedItem.is_required || false;
431
+ if (isRequired) {
432
+ newRequiredCount++;
433
+ if (newRequiredCount === 1 && fieldsetPath.length === 0) {
434
+ console.log(
435
+ chalk3__default.default.blue(
436
+ `
437
+ \u{1F4DD} Please provide values for the following ${iteration === 1 ? "" : "additional "}input fields:`
438
+ )
439
+ );
440
+ }
441
+ await this.promptForField(typedItem, targetInputs);
442
+ processedFieldKeys.add(typedItem.key);
443
+ } else {
444
+ newOptionalCount++;
388
445
  }
389
446
  }
390
- let shouldConfigureOptional = { configure: false };
391
- if (newOptionalFields.length > 0) {
447
+ }
448
+ if (newOptionalCount > 0) {
449
+ const optionalFields = items.filter((item) => {
450
+ const typedItem = item;
451
+ return typedItem.type === "input_field" && typedItem.key && !typedItem.is_required && !processedFieldKeys.has(typedItem.key);
452
+ });
453
+ if (optionalFields.length > 0) {
454
+ const pathContext = fieldsetPath.length > 0 ? ` in ${fieldsetPath.join(" > ")}` : "";
392
455
  console.log(
393
456
  chalk3__default.default.gray(
394
457
  `
395
- There are ${newOptionalFields.length} ${iteration === 1 ? "" : "additional "}optional field(s) available.`
458
+ There are ${optionalFields.length} ${iteration === 1 ? "" : "additional "}optional field(s) available${pathContext}.`
396
459
  )
397
460
  );
398
461
  try {
399
- shouldConfigureOptional = await inquirer__default.default.prompt([
462
+ const shouldConfigureOptional = await inquirer__default.default.prompt([
400
463
  {
401
464
  type: "confirm",
402
465
  name: "configure",
403
- message: `Would you like to configure ${iteration === 1 ? "" : "these additional "}optional fields?`,
466
+ message: `Would you like to configure ${iteration === 1 ? "" : "these additional "}optional fields${pathContext}?`,
404
467
  default: false
405
468
  }
406
469
  ]);
470
+ if (shouldConfigureOptional.configure) {
471
+ console.log(chalk3__default.default.cyan(`
472
+ Optional fields${pathContext}:`));
473
+ for (const field of optionalFields) {
474
+ await this.promptForField(field, targetInputs);
475
+ const typedField = field;
476
+ processedFieldKeys.add(typedField.key);
477
+ }
478
+ } else {
479
+ optionalSkipped = true;
480
+ optionalFields.forEach((field) => {
481
+ const typedField = field;
482
+ processedFieldKeys.add(typedField.key);
483
+ });
484
+ }
407
485
  } catch (error) {
408
486
  if (this.isUserCancellation(error)) {
409
487
  console.log(chalk3__default.default.yellow("\n\nOperation cancelled by user"));
@@ -411,32 +489,13 @@ There are ${newOptionalFields.length} ${iteration === 1 ? "" : "additional "}opt
411
489
  }
412
490
  throw error;
413
491
  }
414
- if (shouldConfigureOptional.configure) {
415
- console.log(chalk3__default.default.cyan(`
416
- Optional fields:`));
417
- for (const field of newOptionalFields) {
418
- await this.promptForField(field, inputs);
419
- processedFieldKeys.add(field.key);
420
- }
421
- } else {
422
- newOptionalFields.forEach(
423
- (field) => processedFieldKeys.add(field.key)
424
- );
425
- }
426
492
  }
427
- if (newRequiredFields.length === 0 && (!newOptionalFields.length || !shouldConfigureOptional.configure)) {
428
- break;
429
- }
430
- }
431
- if (iteration >= maxIterations) {
432
- console.log(
433
- chalk3__default.default.yellow(
434
- `
435
- \u26A0\uFE0F Maximum field resolution iterations reached. Some dynamic fields may not have been discovered.`
436
- )
437
- );
438
493
  }
439
- return inputs;
494
+ return {
495
+ newRequired: newRequiredCount,
496
+ newOptional: newOptionalCount,
497
+ optionalSkipped
498
+ };
440
499
  }
441
500
  getNestedValue(obj, path2) {
442
501
  return path2.reduce(
@@ -2228,7 +2287,7 @@ function createZapierCliSdk(options = {}) {
2228
2287
 
2229
2288
  // package.json
2230
2289
  var package_default = {
2231
- version: "0.10.0"};
2290
+ version: "0.11.0"};
2232
2291
 
2233
2292
  // src/cli.ts
2234
2293
  var program = new commander.Command();
package/dist/cli.mjs CHANGED
@@ -303,7 +303,7 @@ var SchemaParameterResolver = class {
303
303
  const inputs = {};
304
304
  let processedFieldKeys = /* @__PURE__ */ new Set();
305
305
  let iteration = 0;
306
- const maxIterations = 5;
306
+ const maxIterations = 10;
307
307
  while (iteration < maxIterations) {
308
308
  iteration++;
309
309
  const updatedContext = {
@@ -318,11 +318,11 @@ var SchemaParameterResolver = class {
318
318
  `Fetching input fields for ${param.name}${iteration > 1 ? ` (iteration ${iteration})` : ""}...`
319
319
  )
320
320
  );
321
- const fields = await typedResolver.fetch(
321
+ const rootFieldItems = await typedResolver.fetch(
322
322
  updatedContext.sdk,
323
323
  updatedContext.resolvedParams
324
324
  );
325
- if (!fields || fields.length === 0) {
325
+ if (!rootFieldItems || rootFieldItems.length === 0) {
326
326
  if (iteration === 1) {
327
327
  console.log(
328
328
  chalk3.yellow(`No input fields required for this action.`)
@@ -330,47 +330,125 @@ var SchemaParameterResolver = class {
330
330
  }
331
331
  break;
332
332
  }
333
- const newFields = fields.filter(
334
- (field) => !(field.key && processedFieldKeys.has(field.key))
333
+ const fieldStats = await this.processFieldItems(
334
+ rootFieldItems,
335
+ inputs,
336
+ processedFieldKeys,
337
+ [],
338
+ iteration
335
339
  );
336
- if (newFields.length === 0) {
340
+ if (fieldStats.newRequired === 0 && fieldStats.newOptional === 0) {
337
341
  break;
338
342
  }
339
- const newRequiredFields = newFields.filter(
340
- (field) => field.is_required
341
- );
342
- const newOptionalFields = newFields.filter(
343
- (field) => !field.is_required
343
+ if (fieldStats.newRequired === 0 && fieldStats.optionalSkipped) {
344
+ break;
345
+ }
346
+ }
347
+ if (iteration >= maxIterations) {
348
+ console.log(
349
+ chalk3.yellow(
350
+ `
351
+ \u26A0\uFE0F Maximum field resolution iterations reached. Some dynamic fields may not have been discovered.`
352
+ )
344
353
  );
345
- if (newRequiredFields.length > 0) {
354
+ }
355
+ return inputs;
356
+ }
357
+ /**
358
+ * Recursively processes fieldsets and their fields, maintaining natural structure
359
+ * and creating nested inputs as needed (e.g., fieldset "foo" becomes inputs.foo = [{}])
360
+ */
361
+ async processFieldItems(items, targetInputs, processedFieldKeys, fieldsetPath = [], iteration = 1) {
362
+ let newRequiredCount = 0;
363
+ let newOptionalCount = 0;
364
+ let optionalSkipped = false;
365
+ for (const item of items) {
366
+ const typedItem = item;
367
+ if (typedItem.type === "fieldset" && typedItem.fields && typedItem.key) {
368
+ const fieldsetTitle = typedItem.title || typedItem.key;
369
+ const pathDisplay = fieldsetPath.length > 0 ? ` (in ${fieldsetPath.join(" > ")})` : "";
346
370
  console.log(
347
- chalk3.blue(
371
+ chalk3.cyan(
348
372
  `
349
- \u{1F4DD} Please provide values for the following ${iteration === 1 ? "" : "additional "}input fields:`
373
+ \u{1F4C1} Processing fieldset: ${fieldsetTitle}${pathDisplay}`
350
374
  )
351
375
  );
352
- for (const field of newRequiredFields) {
353
- await this.promptForField(field, inputs);
354
- processedFieldKeys.add(field.key);
376
+ if (!targetInputs[typedItem.key]) {
377
+ targetInputs[typedItem.key] = [{}];
378
+ }
379
+ const fieldsetTarget = targetInputs[typedItem.key][0];
380
+ const nestedPath = [...fieldsetPath, fieldsetTitle];
381
+ const nestedStats = await this.processFieldItems(
382
+ typedItem.fields,
383
+ fieldsetTarget,
384
+ processedFieldKeys,
385
+ nestedPath,
386
+ iteration
387
+ );
388
+ newRequiredCount += nestedStats.newRequired;
389
+ newOptionalCount += nestedStats.newOptional;
390
+ if (nestedStats.optionalSkipped) {
391
+ optionalSkipped = true;
392
+ }
393
+ } else if (typedItem.type === "input_field" && typedItem.key) {
394
+ if (processedFieldKeys.has(typedItem.key)) {
395
+ continue;
396
+ }
397
+ const isRequired = typedItem.is_required || false;
398
+ if (isRequired) {
399
+ newRequiredCount++;
400
+ if (newRequiredCount === 1 && fieldsetPath.length === 0) {
401
+ console.log(
402
+ chalk3.blue(
403
+ `
404
+ \u{1F4DD} Please provide values for the following ${iteration === 1 ? "" : "additional "}input fields:`
405
+ )
406
+ );
407
+ }
408
+ await this.promptForField(typedItem, targetInputs);
409
+ processedFieldKeys.add(typedItem.key);
410
+ } else {
411
+ newOptionalCount++;
355
412
  }
356
413
  }
357
- let shouldConfigureOptional = { configure: false };
358
- if (newOptionalFields.length > 0) {
414
+ }
415
+ if (newOptionalCount > 0) {
416
+ const optionalFields = items.filter((item) => {
417
+ const typedItem = item;
418
+ return typedItem.type === "input_field" && typedItem.key && !typedItem.is_required && !processedFieldKeys.has(typedItem.key);
419
+ });
420
+ if (optionalFields.length > 0) {
421
+ const pathContext = fieldsetPath.length > 0 ? ` in ${fieldsetPath.join(" > ")}` : "";
359
422
  console.log(
360
423
  chalk3.gray(
361
424
  `
362
- There are ${newOptionalFields.length} ${iteration === 1 ? "" : "additional "}optional field(s) available.`
425
+ There are ${optionalFields.length} ${iteration === 1 ? "" : "additional "}optional field(s) available${pathContext}.`
363
426
  )
364
427
  );
365
428
  try {
366
- shouldConfigureOptional = await inquirer.prompt([
429
+ const shouldConfigureOptional = await inquirer.prompt([
367
430
  {
368
431
  type: "confirm",
369
432
  name: "configure",
370
- message: `Would you like to configure ${iteration === 1 ? "" : "these additional "}optional fields?`,
433
+ message: `Would you like to configure ${iteration === 1 ? "" : "these additional "}optional fields${pathContext}?`,
371
434
  default: false
372
435
  }
373
436
  ]);
437
+ if (shouldConfigureOptional.configure) {
438
+ console.log(chalk3.cyan(`
439
+ Optional fields${pathContext}:`));
440
+ for (const field of optionalFields) {
441
+ await this.promptForField(field, targetInputs);
442
+ const typedField = field;
443
+ processedFieldKeys.add(typedField.key);
444
+ }
445
+ } else {
446
+ optionalSkipped = true;
447
+ optionalFields.forEach((field) => {
448
+ const typedField = field;
449
+ processedFieldKeys.add(typedField.key);
450
+ });
451
+ }
374
452
  } catch (error) {
375
453
  if (this.isUserCancellation(error)) {
376
454
  console.log(chalk3.yellow("\n\nOperation cancelled by user"));
@@ -378,32 +456,13 @@ There are ${newOptionalFields.length} ${iteration === 1 ? "" : "additional "}opt
378
456
  }
379
457
  throw error;
380
458
  }
381
- if (shouldConfigureOptional.configure) {
382
- console.log(chalk3.cyan(`
383
- Optional fields:`));
384
- for (const field of newOptionalFields) {
385
- await this.promptForField(field, inputs);
386
- processedFieldKeys.add(field.key);
387
- }
388
- } else {
389
- newOptionalFields.forEach(
390
- (field) => processedFieldKeys.add(field.key)
391
- );
392
- }
393
459
  }
394
- if (newRequiredFields.length === 0 && (!newOptionalFields.length || !shouldConfigureOptional.configure)) {
395
- break;
396
- }
397
- }
398
- if (iteration >= maxIterations) {
399
- console.log(
400
- chalk3.yellow(
401
- `
402
- \u26A0\uFE0F Maximum field resolution iterations reached. Some dynamic fields may not have been discovered.`
403
- )
404
- );
405
460
  }
406
- return inputs;
461
+ return {
462
+ newRequired: newRequiredCount,
463
+ newOptional: newOptionalCount,
464
+ optionalSkipped
465
+ };
407
466
  }
408
467
  getNestedValue(obj, path2) {
409
468
  return path2.reduce(
@@ -2195,7 +2254,7 @@ function createZapierCliSdk(options = {}) {
2195
2254
 
2196
2255
  // package.json
2197
2256
  var package_default = {
2198
- version: "0.10.0"};
2257
+ version: "0.11.0"};
2199
2258
 
2200
2259
  // src/cli.ts
2201
2260
  var program = new Command();
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zapier/zapier-sdk-cli",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Command line interface for Zapier SDK",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
@@ -7,6 +7,11 @@ export declare class SchemaParameterResolver {
7
7
  private createResolvableParameter;
8
8
  private resolveParameter;
9
9
  private resolveFieldsRecursively;
10
+ /**
11
+ * Recursively processes fieldsets and their fields, maintaining natural structure
12
+ * and creating nested inputs as needed (e.g., fieldset "foo" becomes inputs.foo = [{}])
13
+ */
14
+ private processFieldItems;
10
15
  private getNestedValue;
11
16
  private setNestedValue;
12
17
  private promptForField;
@@ -303,7 +303,7 @@ export class SchemaParameterResolver {
303
303
  const inputs = {};
304
304
  let processedFieldKeys = new Set();
305
305
  let iteration = 0;
306
- const maxIterations = 5; // Prevent infinite loops
306
+ const maxIterations = 10; // Prevent infinite loops
307
307
  while (iteration < maxIterations) {
308
308
  iteration++;
309
309
  // Update context with current inputs so they're passed to listInputFields
@@ -315,44 +315,118 @@ export class SchemaParameterResolver {
315
315
  },
316
316
  };
317
317
  console.log(chalk.gray(`Fetching input fields for ${param.name}${iteration > 1 ? ` (iteration ${iteration})` : ""}...`));
318
- const fields = await typedResolver.fetch(updatedContext.sdk, updatedContext.resolvedParams);
319
- if (!fields || fields.length === 0) {
318
+ const rootFieldItems = await typedResolver.fetch(updatedContext.sdk, updatedContext.resolvedParams);
319
+ if (!rootFieldItems || rootFieldItems.length === 0) {
320
320
  if (iteration === 1) {
321
321
  console.log(chalk.yellow(`No input fields required for this action.`));
322
322
  }
323
323
  break;
324
324
  }
325
- // Find new fields that we haven't processed yet
326
- const newFields = fields.filter((field) => !(field.key &&
327
- processedFieldKeys.has(field.key)));
328
- if (newFields.length === 0) {
329
- // No new fields, we're done
325
+ // Process fields recursively, maintaining fieldset structure
326
+ const fieldStats = await this.processFieldItems(rootFieldItems, inputs, processedFieldKeys, [], iteration);
327
+ // If no new fields were processed, we're done
328
+ if (fieldStats.newRequired === 0 && fieldStats.newOptional === 0) {
330
329
  break;
331
330
  }
332
- // Separate new required and optional fields
333
- const newRequiredFields = newFields.filter((field) => field.is_required);
334
- const newOptionalFields = newFields.filter((field) => !field.is_required);
335
- // Prompt for new required fields
336
- if (newRequiredFields.length > 0) {
337
- console.log(chalk.blue(`\nšŸ“ Please provide values for the following ${iteration === 1 ? "" : "additional "}input fields:`));
338
- for (const field of newRequiredFields) {
339
- await this.promptForField(field, inputs);
340
- processedFieldKeys.add(field.key);
331
+ // If we only processed optional fields and skipped them, no need to re-fetch
332
+ if (fieldStats.newRequired === 0 && fieldStats.optionalSkipped) {
333
+ break;
334
+ }
335
+ }
336
+ if (iteration >= maxIterations) {
337
+ console.log(chalk.yellow(`\nāš ļø Maximum field resolution iterations reached. Some dynamic fields may not have been discovered.`));
338
+ }
339
+ return inputs;
340
+ }
341
+ /**
342
+ * Recursively processes fieldsets and their fields, maintaining natural structure
343
+ * and creating nested inputs as needed (e.g., fieldset "foo" becomes inputs.foo = [{}])
344
+ */
345
+ async processFieldItems(items, targetInputs, processedFieldKeys, fieldsetPath = [], iteration = 1) {
346
+ let newRequiredCount = 0;
347
+ let newOptionalCount = 0;
348
+ let optionalSkipped = false;
349
+ for (const item of items) {
350
+ const typedItem = item;
351
+ if (typedItem.type === "fieldset" && typedItem.fields && typedItem.key) {
352
+ // Show fieldset context to user
353
+ const fieldsetTitle = typedItem.title || typedItem.key;
354
+ const pathDisplay = fieldsetPath.length > 0 ? ` (in ${fieldsetPath.join(" > ")})` : "";
355
+ console.log(chalk.cyan(`\nšŸ“ Processing fieldset: ${fieldsetTitle}${pathDisplay}`));
356
+ // Create fieldset array in target inputs if it doesn't exist
357
+ if (!targetInputs[typedItem.key]) {
358
+ targetInputs[typedItem.key] = [{}];
359
+ }
360
+ // Process fields within this fieldset recursively
361
+ const fieldsetTarget = targetInputs[typedItem.key][0];
362
+ const nestedPath = [...fieldsetPath, fieldsetTitle];
363
+ const nestedStats = await this.processFieldItems(typedItem.fields, fieldsetTarget, processedFieldKeys, nestedPath, iteration);
364
+ newRequiredCount += nestedStats.newRequired;
365
+ newOptionalCount += nestedStats.newOptional;
366
+ if (nestedStats.optionalSkipped) {
367
+ optionalSkipped = true;
368
+ }
369
+ }
370
+ else if (typedItem.type === "input_field" && typedItem.key) {
371
+ // Skip if already processed
372
+ if (processedFieldKeys.has(typedItem.key)) {
373
+ continue;
374
+ }
375
+ const isRequired = typedItem.is_required || false;
376
+ if (isRequired) {
377
+ // Process required field immediately
378
+ newRequiredCount++;
379
+ if (newRequiredCount === 1 && fieldsetPath.length === 0) {
380
+ // Only show this message once at root level
381
+ console.log(chalk.blue(`\nšŸ“ Please provide values for the following ${iteration === 1 ? "" : "additional "}input fields:`));
382
+ }
383
+ await this.promptForField(typedItem, targetInputs);
384
+ processedFieldKeys.add(typedItem.key);
385
+ }
386
+ else {
387
+ // Collect optional fields for batch processing
388
+ newOptionalCount++;
341
389
  }
342
390
  }
343
- // Ask about optional fields
344
- let shouldConfigureOptional = { configure: false };
345
- if (newOptionalFields.length > 0) {
346
- console.log(chalk.gray(`\nThere are ${newOptionalFields.length} ${iteration === 1 ? "" : "additional "}optional field(s) available.`));
391
+ // Skip info fields - they're for display only
392
+ }
393
+ // Handle optional fields after processing all required fields
394
+ if (newOptionalCount > 0) {
395
+ const optionalFields = items.filter((item) => {
396
+ const typedItem = item;
397
+ return (typedItem.type === "input_field" &&
398
+ typedItem.key &&
399
+ !typedItem.is_required &&
400
+ !processedFieldKeys.has(typedItem.key));
401
+ });
402
+ if (optionalFields.length > 0) {
403
+ const pathContext = fieldsetPath.length > 0 ? ` in ${fieldsetPath.join(" > ")}` : "";
404
+ console.log(chalk.gray(`\nThere are ${optionalFields.length} ${iteration === 1 ? "" : "additional "}optional field(s) available${pathContext}.`));
347
405
  try {
348
- shouldConfigureOptional = await inquirer.prompt([
406
+ const shouldConfigureOptional = await inquirer.prompt([
349
407
  {
350
408
  type: "confirm",
351
409
  name: "configure",
352
- message: `Would you like to configure ${iteration === 1 ? "" : "these additional "}optional fields?`,
410
+ message: `Would you like to configure ${iteration === 1 ? "" : "these additional "}optional fields${pathContext}?`,
353
411
  default: false,
354
412
  },
355
413
  ]);
414
+ if (shouldConfigureOptional.configure) {
415
+ console.log(chalk.cyan(`\nOptional fields${pathContext}:`));
416
+ for (const field of optionalFields) {
417
+ await this.promptForField(field, targetInputs);
418
+ const typedField = field;
419
+ processedFieldKeys.add(typedField.key);
420
+ }
421
+ }
422
+ else {
423
+ optionalSkipped = true;
424
+ // Mark these fields as processed even if skipped to avoid re-asking
425
+ optionalFields.forEach((field) => {
426
+ const typedField = field;
427
+ processedFieldKeys.add(typedField.key);
428
+ });
429
+ }
356
430
  }
357
431
  catch (error) {
358
432
  if (this.isUserCancellation(error)) {
@@ -361,28 +435,13 @@ export class SchemaParameterResolver {
361
435
  }
362
436
  throw error;
363
437
  }
364
- if (shouldConfigureOptional.configure) {
365
- console.log(chalk.cyan(`\nOptional fields:`));
366
- for (const field of newOptionalFields) {
367
- await this.promptForField(field, inputs);
368
- processedFieldKeys.add(field.key);
369
- }
370
- }
371
- else {
372
- // Mark these fields as processed even if skipped to avoid re-asking
373
- newOptionalFields.forEach((field) => processedFieldKeys.add(field.key));
374
- }
375
438
  }
376
- // If we only processed optional fields and skipped them, no need to re-fetch
377
- if (newRequiredFields.length === 0 &&
378
- (!newOptionalFields.length || !shouldConfigureOptional.configure)) {
379
- break;
380
- }
381
- }
382
- if (iteration >= maxIterations) {
383
- console.log(chalk.yellow(`\nāš ļø Maximum field resolution iterations reached. Some dynamic fields may not have been discovered.`));
384
439
  }
385
- return inputs;
440
+ return {
441
+ newRequired: newRequiredCount,
442
+ newOptional: newOptionalCount,
443
+ optionalSkipped,
444
+ };
386
445
  }
387
446
  getNestedValue(obj, path) {
388
447
  return path.reduce((current, key) => current?.[key], obj);