@zapier/zapier-sdk-cli 0.15.1 → 0.15.3

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,20 @@
1
1
  # @zapier/zapier-sdk-cli
2
2
 
3
+ ## 0.15.3
4
+
5
+ ### Patch Changes
6
+
7
+ - f7e552e: Add synchronous customuser_id and account_id retrieval to event emission plugin
8
+ - Updated dependencies [f7e552e]
9
+ - @zapier/zapier-sdk@0.15.4
10
+ - @zapier/zapier-sdk-mcp@0.3.28
11
+
12
+ ## 0.15.2
13
+
14
+ ### Patch Changes
15
+
16
+ - a4aee2e: Enhanced param resolver to fully resolve dynamic input fields and dynamic choices.
17
+
3
18
  ## 0.15.1
4
19
 
5
20
  ### Patch Changes
package/dist/cli.cjs CHANGED
@@ -396,7 +396,8 @@ var SchemaParameterResolver = class {
396
396
  inputs,
397
397
  processedFieldKeys,
398
398
  [],
399
- iteration
399
+ iteration,
400
+ updatedContext
400
401
  );
401
402
  if (fieldStats.newRequired === 0 && fieldStats.newOptional === 0) {
402
403
  break;
@@ -419,7 +420,7 @@ var SchemaParameterResolver = class {
419
420
  * Recursively processes fieldsets and their fields, maintaining natural structure
420
421
  * and creating nested inputs as needed (e.g., fieldset "foo" becomes inputs.foo = [{}])
421
422
  */
422
- async processFieldItems(items, targetInputs, processedFieldKeys, fieldsetPath = [], iteration = 1) {
423
+ async processFieldItems(items, targetInputs, processedFieldKeys, fieldsetPath = [], iteration = 1, context) {
423
424
  let newRequiredCount = 0;
424
425
  let newOptionalCount = 0;
425
426
  let optionalSkipped = false;
@@ -444,7 +445,8 @@ var SchemaParameterResolver = class {
444
445
  fieldsetTarget,
445
446
  processedFieldKeys,
446
447
  nestedPath,
447
- iteration
448
+ iteration,
449
+ context
448
450
  );
449
451
  newRequiredCount += nestedStats.newRequired;
450
452
  newOptionalCount += nestedStats.newOptional;
@@ -466,7 +468,7 @@ var SchemaParameterResolver = class {
466
468
  )
467
469
  );
468
470
  }
469
- await this.promptForField(typedItem, targetInputs);
471
+ await this.promptForField(typedItem, targetInputs, context);
470
472
  processedFieldKeys.add(typedItem.key);
471
473
  } else {
472
474
  newOptionalCount++;
@@ -499,7 +501,7 @@ There are ${optionalFields.length} ${iteration === 1 ? "" : "additional "}option
499
501
  console.log(chalk3__default.default.cyan(`
500
502
  Optional fields${pathContext}:`));
501
503
  for (const field of optionalFields) {
502
- await this.promptForField(field, targetInputs);
504
+ await this.promptForField(field, targetInputs, context);
503
505
  const typedField = field;
504
506
  processedFieldKeys.add(typedField.key);
505
507
  }
@@ -542,38 +544,171 @@ Optional fields${pathContext}:`));
542
544
  }, obj);
543
545
  parent[lastKey] = value;
544
546
  }
545
- async promptForField(field, inputs) {
547
+ /**
548
+ * Extract and normalize field metadata from raw field object
549
+ */
550
+ extractFieldMetadata(field) {
546
551
  const fieldObj = field;
547
- const fieldPrompt = {
548
- type: fieldObj.type === "boolean" ? "confirm" : "input",
549
- name: fieldObj.key,
550
- message: `${fieldObj.label || fieldObj.key}${fieldObj.is_required ? " (required)" : " (optional)"}:`
552
+ const valueType = fieldObj.value_type || "string";
553
+ return {
554
+ key: fieldObj.key,
555
+ title: fieldObj.title || fieldObj.label || fieldObj.key,
556
+ description: fieldObj.description || fieldObj.helpText,
557
+ isRequired: fieldObj.is_required || false,
558
+ defaultValue: fieldObj.default_value ?? fieldObj.default,
559
+ valueType,
560
+ hasDropdown: fieldObj.format === "SELECT",
561
+ isMultiSelect: Boolean(
562
+ valueType === "array" || fieldObj.items && fieldObj.items.type !== void 0
563
+ )
551
564
  };
552
- if (fieldObj.helpText) {
553
- fieldPrompt.prefix = chalk3__default.default.gray(`\u2139 ${fieldObj.helpText}
554
- `);
565
+ }
566
+ /**
567
+ * Fetch a page of choices for a dropdown field
568
+ */
569
+ async fetchChoices(fieldMeta, inputs, context, cursor) {
570
+ try {
571
+ console.log(
572
+ chalk3__default.default.gray(
573
+ cursor ? ` Fetching more choices...` : ` Fetching choices for ${fieldMeta.title}...`
574
+ )
575
+ );
576
+ const page = await context.sdk.listInputFieldChoices({
577
+ appKey: context.resolvedParams.appKey,
578
+ actionKey: context.resolvedParams.actionKey,
579
+ actionType: context.resolvedParams.actionType,
580
+ authenticationId: context.resolvedParams.authenticationId,
581
+ inputFieldKey: fieldMeta.key,
582
+ inputs,
583
+ ...cursor && { cursor }
584
+ });
585
+ const choices = page.data.map((choice) => ({
586
+ label: choice.label || choice.key || String(choice.value),
587
+ value: choice.value ?? choice.key
588
+ }));
589
+ if (choices.length === 0 && !cursor) {
590
+ console.log(
591
+ chalk3__default.default.yellow(` No choices available for ${fieldMeta.title}`)
592
+ );
593
+ }
594
+ return {
595
+ choices,
596
+ nextCursor: page.nextCursor
597
+ };
598
+ } catch (error) {
599
+ console.warn(
600
+ chalk3__default.default.yellow(` \u26A0\uFE0F Failed to fetch choices for ${fieldMeta.title}:`),
601
+ error
602
+ );
603
+ return { choices: [] };
555
604
  }
556
- if (fieldObj.default !== void 0) {
557
- fieldPrompt.default = fieldObj.default;
558
- }
559
- if (fieldObj.choices && fieldObj.choices.length > 0) {
560
- fieldPrompt.type = "list";
561
- fieldPrompt.choices = fieldObj.choices.map(
562
- (choice) => {
563
- const choiceObj = choice;
564
- return {
565
- name: choiceObj.label || choiceObj.value,
566
- value: choiceObj.value
567
- };
605
+ }
606
+ /**
607
+ * Prompt user with choices (handles both single and multi-select with pagination)
608
+ */
609
+ async promptWithChoices({
610
+ fieldMeta,
611
+ choices: initialChoices,
612
+ nextCursor: initialCursor,
613
+ inputs,
614
+ context
615
+ }) {
616
+ const choices = [...initialChoices];
617
+ let nextCursor = initialCursor;
618
+ const LOAD_MORE_SENTINEL = Symbol("LOAD_MORE");
619
+ while (true) {
620
+ const promptChoices = choices.map((choice) => ({
621
+ name: choice.label,
622
+ value: choice.value
623
+ }));
624
+ if (nextCursor) {
625
+ promptChoices.push({
626
+ name: chalk3__default.default.dim("(Load more...)"),
627
+ value: LOAD_MORE_SENTINEL
628
+ });
629
+ }
630
+ if (!fieldMeta.isRequired && !fieldMeta.isMultiSelect) {
631
+ promptChoices.push({ name: "(Skip)", value: void 0 });
632
+ }
633
+ const promptConfig = {
634
+ type: fieldMeta.isMultiSelect ? "checkbox" : "list",
635
+ name: fieldMeta.key,
636
+ message: `${fieldMeta.title}${fieldMeta.isRequired ? " (required)" : " (optional)"}:`,
637
+ choices: promptChoices,
638
+ ...fieldMeta.isMultiSelect && {
639
+ validate: (input) => {
640
+ if (fieldMeta.isRequired && (!input || input.length === 0)) {
641
+ return "At least one selection is required";
642
+ }
643
+ return true;
644
+ }
568
645
  }
569
- );
646
+ };
647
+ const answer = await inquirer__default.default.prompt([promptConfig]);
648
+ let selectedValue = answer[fieldMeta.key];
649
+ const wantsMore = fieldMeta.isMultiSelect ? Array.isArray(selectedValue) && selectedValue.includes(LOAD_MORE_SENTINEL) : selectedValue === LOAD_MORE_SENTINEL;
650
+ if (wantsMore && nextCursor && context) {
651
+ if (fieldMeta.isMultiSelect && Array.isArray(selectedValue)) {
652
+ selectedValue = selectedValue.filter((v) => v !== LOAD_MORE_SENTINEL);
653
+ }
654
+ const result = await this.fetchChoices(
655
+ fieldMeta,
656
+ inputs,
657
+ context,
658
+ nextCursor
659
+ );
660
+ choices.push(...result.choices);
661
+ nextCursor = result.nextCursor;
662
+ continue;
663
+ }
664
+ return selectedValue;
665
+ }
666
+ }
667
+ /**
668
+ * Prompt user for free-form input (text or boolean)
669
+ */
670
+ async promptFreeForm(fieldMeta) {
671
+ const promptConfig = {
672
+ name: fieldMeta.key,
673
+ message: `${fieldMeta.title}${fieldMeta.isRequired ? " (required)" : " (optional)"}:`
674
+ };
675
+ if (fieldMeta.valueType === "boolean") {
676
+ promptConfig.type = "confirm";
677
+ promptConfig.default = fieldMeta.defaultValue !== void 0 ? Boolean(fieldMeta.defaultValue) : void 0;
678
+ } else {
679
+ promptConfig.type = "input";
680
+ promptConfig.default = fieldMeta.defaultValue;
681
+ promptConfig.validate = (input) => {
682
+ if (fieldMeta.isRequired && !input) {
683
+ return "This field is required";
684
+ }
685
+ return true;
686
+ };
687
+ }
688
+ if (fieldMeta.description) {
689
+ promptConfig.prefix = chalk3__default.default.gray(`\u2139 ${fieldMeta.description}
690
+ `);
570
691
  }
571
692
  try {
572
- const answer = await inquirer__default.default.prompt([fieldPrompt]);
573
- if (answer[fieldObj.key] !== void 0 && answer[fieldObj.key] !== "") {
574
- inputs[fieldObj.key] = answer[fieldObj.key];
575
- } else if (fieldObj.is_required) {
576
- throw new Error(`Required field ${fieldObj.key} cannot be empty`);
693
+ const answer = await inquirer__default.default.prompt([promptConfig]);
694
+ return answer[fieldMeta.key];
695
+ } catch (error) {
696
+ if (this.isUserCancellation(error)) {
697
+ console.log(chalk3__default.default.yellow("\n\nOperation cancelled by user"));
698
+ throw new ZapierCliUserCancellationError();
699
+ }
700
+ throw error;
701
+ }
702
+ }
703
+ /**
704
+ * Store field value in inputs object with validation
705
+ */
706
+ storeFieldValue(inputs, key, value, isRequired) {
707
+ try {
708
+ if (value !== void 0 && value !== "") {
709
+ inputs[key] = value;
710
+ } else if (isRequired) {
711
+ throw new Error(`Required field ${key} cannot be empty`);
577
712
  }
578
713
  } catch (error) {
579
714
  if (this.isUserCancellation(error)) {
@@ -583,6 +718,34 @@ Optional fields${pathContext}:`));
583
718
  throw error;
584
719
  }
585
720
  }
721
+ async promptForField(field, inputs, context) {
722
+ const fieldMeta = this.extractFieldMetadata(field);
723
+ let choices = [];
724
+ let nextCursor;
725
+ if (fieldMeta.hasDropdown && context) {
726
+ const result = await this.fetchChoices(fieldMeta, inputs, context);
727
+ choices = result.choices;
728
+ nextCursor = result.nextCursor;
729
+ }
730
+ let selectedValue;
731
+ if (choices.length > 0) {
732
+ selectedValue = await this.promptWithChoices({
733
+ fieldMeta,
734
+ choices,
735
+ nextCursor,
736
+ inputs,
737
+ context
738
+ });
739
+ } else {
740
+ selectedValue = await this.promptFreeForm(fieldMeta);
741
+ }
742
+ this.storeFieldValue(
743
+ inputs,
744
+ fieldMeta.key,
745
+ selectedValue,
746
+ fieldMeta.isRequired
747
+ );
748
+ }
586
749
  isUserCancellation(error) {
587
750
  const errorObj = error;
588
751
  return errorObj?.name === "ExitPromptError" || errorObj?.message?.includes("User force closed") || errorObj?.isTTYError === true;
@@ -1462,7 +1625,7 @@ var LoginSchema = zod.z.object({
1462
1625
 
1463
1626
  // package.json
1464
1627
  var package_default = {
1465
- version: "0.15.1"};
1628
+ version: "0.15.3"};
1466
1629
 
1467
1630
  // src/telemetry/builders.ts
1468
1631
  function createCliBaseEvent(context = {}) {
@@ -1541,6 +1704,8 @@ var loginPlugin = ({ context }) => {
1541
1704
  const startTime = Date.now();
1542
1705
  let success = false;
1543
1706
  let errorMessage = null;
1707
+ let accountId = null;
1708
+ let customUserId = null;
1544
1709
  try {
1545
1710
  await loginWithSdk({
1546
1711
  ...options,
@@ -1549,6 +1714,10 @@ var loginPlugin = ({ context }) => {
1549
1714
  authClientId: context.options?.authClientId
1550
1715
  });
1551
1716
  success = true;
1717
+ try {
1718
+ ({ accountId, customUserId } = await zapierSdkCliLogin.getLoggedInUser());
1719
+ } catch {
1720
+ }
1552
1721
  } catch (error) {
1553
1722
  success = false;
1554
1723
  errorMessage = error instanceof Error ? error.message : "Login failed";
@@ -1572,7 +1741,9 @@ var loginPlugin = ({ context }) => {
1572
1741
  session_id: context.session_id,
1573
1742
  selected_api: context.selected_api,
1574
1743
  app_id: context.app_id,
1575
- app_version_id: context.app_version_id
1744
+ app_version_id: context.app_version_id,
1745
+ customuser_id: customUserId,
1746
+ account_id: accountId
1576
1747
  },
1577
1748
  cliVersion: package_default.version
1578
1749
  });
@@ -2734,7 +2905,7 @@ function createZapierCliSdk(options = {}) {
2734
2905
  // package.json with { type: 'json' }
2735
2906
  var package_default2 = {
2736
2907
  name: "@zapier/zapier-sdk-cli",
2737
- version: "0.15.1"};
2908
+ version: "0.15.3"};
2738
2909
  function detectPackageManager(cwd = process.cwd()) {
2739
2910
  const ua = process.env.npm_config_user_agent;
2740
2911
  if (ua) {
package/dist/cli.mjs CHANGED
@@ -360,7 +360,8 @@ var SchemaParameterResolver = class {
360
360
  inputs,
361
361
  processedFieldKeys,
362
362
  [],
363
- iteration
363
+ iteration,
364
+ updatedContext
364
365
  );
365
366
  if (fieldStats.newRequired === 0 && fieldStats.newOptional === 0) {
366
367
  break;
@@ -383,7 +384,7 @@ var SchemaParameterResolver = class {
383
384
  * Recursively processes fieldsets and their fields, maintaining natural structure
384
385
  * and creating nested inputs as needed (e.g., fieldset "foo" becomes inputs.foo = [{}])
385
386
  */
386
- async processFieldItems(items, targetInputs, processedFieldKeys, fieldsetPath = [], iteration = 1) {
387
+ async processFieldItems(items, targetInputs, processedFieldKeys, fieldsetPath = [], iteration = 1, context) {
387
388
  let newRequiredCount = 0;
388
389
  let newOptionalCount = 0;
389
390
  let optionalSkipped = false;
@@ -408,7 +409,8 @@ var SchemaParameterResolver = class {
408
409
  fieldsetTarget,
409
410
  processedFieldKeys,
410
411
  nestedPath,
411
- iteration
412
+ iteration,
413
+ context
412
414
  );
413
415
  newRequiredCount += nestedStats.newRequired;
414
416
  newOptionalCount += nestedStats.newOptional;
@@ -430,7 +432,7 @@ var SchemaParameterResolver = class {
430
432
  )
431
433
  );
432
434
  }
433
- await this.promptForField(typedItem, targetInputs);
435
+ await this.promptForField(typedItem, targetInputs, context);
434
436
  processedFieldKeys.add(typedItem.key);
435
437
  } else {
436
438
  newOptionalCount++;
@@ -463,7 +465,7 @@ There are ${optionalFields.length} ${iteration === 1 ? "" : "additional "}option
463
465
  console.log(chalk3.cyan(`
464
466
  Optional fields${pathContext}:`));
465
467
  for (const field of optionalFields) {
466
- await this.promptForField(field, targetInputs);
468
+ await this.promptForField(field, targetInputs, context);
467
469
  const typedField = field;
468
470
  processedFieldKeys.add(typedField.key);
469
471
  }
@@ -506,38 +508,171 @@ Optional fields${pathContext}:`));
506
508
  }, obj);
507
509
  parent[lastKey] = value;
508
510
  }
509
- async promptForField(field, inputs) {
511
+ /**
512
+ * Extract and normalize field metadata from raw field object
513
+ */
514
+ extractFieldMetadata(field) {
510
515
  const fieldObj = field;
511
- const fieldPrompt = {
512
- type: fieldObj.type === "boolean" ? "confirm" : "input",
513
- name: fieldObj.key,
514
- message: `${fieldObj.label || fieldObj.key}${fieldObj.is_required ? " (required)" : " (optional)"}:`
516
+ const valueType = fieldObj.value_type || "string";
517
+ return {
518
+ key: fieldObj.key,
519
+ title: fieldObj.title || fieldObj.label || fieldObj.key,
520
+ description: fieldObj.description || fieldObj.helpText,
521
+ isRequired: fieldObj.is_required || false,
522
+ defaultValue: fieldObj.default_value ?? fieldObj.default,
523
+ valueType,
524
+ hasDropdown: fieldObj.format === "SELECT",
525
+ isMultiSelect: Boolean(
526
+ valueType === "array" || fieldObj.items && fieldObj.items.type !== void 0
527
+ )
515
528
  };
516
- if (fieldObj.helpText) {
517
- fieldPrompt.prefix = chalk3.gray(`\u2139 ${fieldObj.helpText}
518
- `);
529
+ }
530
+ /**
531
+ * Fetch a page of choices for a dropdown field
532
+ */
533
+ async fetchChoices(fieldMeta, inputs, context, cursor) {
534
+ try {
535
+ console.log(
536
+ chalk3.gray(
537
+ cursor ? ` Fetching more choices...` : ` Fetching choices for ${fieldMeta.title}...`
538
+ )
539
+ );
540
+ const page = await context.sdk.listInputFieldChoices({
541
+ appKey: context.resolvedParams.appKey,
542
+ actionKey: context.resolvedParams.actionKey,
543
+ actionType: context.resolvedParams.actionType,
544
+ authenticationId: context.resolvedParams.authenticationId,
545
+ inputFieldKey: fieldMeta.key,
546
+ inputs,
547
+ ...cursor && { cursor }
548
+ });
549
+ const choices = page.data.map((choice) => ({
550
+ label: choice.label || choice.key || String(choice.value),
551
+ value: choice.value ?? choice.key
552
+ }));
553
+ if (choices.length === 0 && !cursor) {
554
+ console.log(
555
+ chalk3.yellow(` No choices available for ${fieldMeta.title}`)
556
+ );
557
+ }
558
+ return {
559
+ choices,
560
+ nextCursor: page.nextCursor
561
+ };
562
+ } catch (error) {
563
+ console.warn(
564
+ chalk3.yellow(` \u26A0\uFE0F Failed to fetch choices for ${fieldMeta.title}:`),
565
+ error
566
+ );
567
+ return { choices: [] };
519
568
  }
520
- if (fieldObj.default !== void 0) {
521
- fieldPrompt.default = fieldObj.default;
522
- }
523
- if (fieldObj.choices && fieldObj.choices.length > 0) {
524
- fieldPrompt.type = "list";
525
- fieldPrompt.choices = fieldObj.choices.map(
526
- (choice) => {
527
- const choiceObj = choice;
528
- return {
529
- name: choiceObj.label || choiceObj.value,
530
- value: choiceObj.value
531
- };
569
+ }
570
+ /**
571
+ * Prompt user with choices (handles both single and multi-select with pagination)
572
+ */
573
+ async promptWithChoices({
574
+ fieldMeta,
575
+ choices: initialChoices,
576
+ nextCursor: initialCursor,
577
+ inputs,
578
+ context
579
+ }) {
580
+ const choices = [...initialChoices];
581
+ let nextCursor = initialCursor;
582
+ const LOAD_MORE_SENTINEL = Symbol("LOAD_MORE");
583
+ while (true) {
584
+ const promptChoices = choices.map((choice) => ({
585
+ name: choice.label,
586
+ value: choice.value
587
+ }));
588
+ if (nextCursor) {
589
+ promptChoices.push({
590
+ name: chalk3.dim("(Load more...)"),
591
+ value: LOAD_MORE_SENTINEL
592
+ });
593
+ }
594
+ if (!fieldMeta.isRequired && !fieldMeta.isMultiSelect) {
595
+ promptChoices.push({ name: "(Skip)", value: void 0 });
596
+ }
597
+ const promptConfig = {
598
+ type: fieldMeta.isMultiSelect ? "checkbox" : "list",
599
+ name: fieldMeta.key,
600
+ message: `${fieldMeta.title}${fieldMeta.isRequired ? " (required)" : " (optional)"}:`,
601
+ choices: promptChoices,
602
+ ...fieldMeta.isMultiSelect && {
603
+ validate: (input) => {
604
+ if (fieldMeta.isRequired && (!input || input.length === 0)) {
605
+ return "At least one selection is required";
606
+ }
607
+ return true;
608
+ }
532
609
  }
533
- );
610
+ };
611
+ const answer = await inquirer.prompt([promptConfig]);
612
+ let selectedValue = answer[fieldMeta.key];
613
+ const wantsMore = fieldMeta.isMultiSelect ? Array.isArray(selectedValue) && selectedValue.includes(LOAD_MORE_SENTINEL) : selectedValue === LOAD_MORE_SENTINEL;
614
+ if (wantsMore && nextCursor && context) {
615
+ if (fieldMeta.isMultiSelect && Array.isArray(selectedValue)) {
616
+ selectedValue = selectedValue.filter((v) => v !== LOAD_MORE_SENTINEL);
617
+ }
618
+ const result = await this.fetchChoices(
619
+ fieldMeta,
620
+ inputs,
621
+ context,
622
+ nextCursor
623
+ );
624
+ choices.push(...result.choices);
625
+ nextCursor = result.nextCursor;
626
+ continue;
627
+ }
628
+ return selectedValue;
629
+ }
630
+ }
631
+ /**
632
+ * Prompt user for free-form input (text or boolean)
633
+ */
634
+ async promptFreeForm(fieldMeta) {
635
+ const promptConfig = {
636
+ name: fieldMeta.key,
637
+ message: `${fieldMeta.title}${fieldMeta.isRequired ? " (required)" : " (optional)"}:`
638
+ };
639
+ if (fieldMeta.valueType === "boolean") {
640
+ promptConfig.type = "confirm";
641
+ promptConfig.default = fieldMeta.defaultValue !== void 0 ? Boolean(fieldMeta.defaultValue) : void 0;
642
+ } else {
643
+ promptConfig.type = "input";
644
+ promptConfig.default = fieldMeta.defaultValue;
645
+ promptConfig.validate = (input) => {
646
+ if (fieldMeta.isRequired && !input) {
647
+ return "This field is required";
648
+ }
649
+ return true;
650
+ };
651
+ }
652
+ if (fieldMeta.description) {
653
+ promptConfig.prefix = chalk3.gray(`\u2139 ${fieldMeta.description}
654
+ `);
534
655
  }
535
656
  try {
536
- const answer = await inquirer.prompt([fieldPrompt]);
537
- if (answer[fieldObj.key] !== void 0 && answer[fieldObj.key] !== "") {
538
- inputs[fieldObj.key] = answer[fieldObj.key];
539
- } else if (fieldObj.is_required) {
540
- throw new Error(`Required field ${fieldObj.key} cannot be empty`);
657
+ const answer = await inquirer.prompt([promptConfig]);
658
+ return answer[fieldMeta.key];
659
+ } catch (error) {
660
+ if (this.isUserCancellation(error)) {
661
+ console.log(chalk3.yellow("\n\nOperation cancelled by user"));
662
+ throw new ZapierCliUserCancellationError();
663
+ }
664
+ throw error;
665
+ }
666
+ }
667
+ /**
668
+ * Store field value in inputs object with validation
669
+ */
670
+ storeFieldValue(inputs, key, value, isRequired) {
671
+ try {
672
+ if (value !== void 0 && value !== "") {
673
+ inputs[key] = value;
674
+ } else if (isRequired) {
675
+ throw new Error(`Required field ${key} cannot be empty`);
541
676
  }
542
677
  } catch (error) {
543
678
  if (this.isUserCancellation(error)) {
@@ -547,6 +682,34 @@ Optional fields${pathContext}:`));
547
682
  throw error;
548
683
  }
549
684
  }
685
+ async promptForField(field, inputs, context) {
686
+ const fieldMeta = this.extractFieldMetadata(field);
687
+ let choices = [];
688
+ let nextCursor;
689
+ if (fieldMeta.hasDropdown && context) {
690
+ const result = await this.fetchChoices(fieldMeta, inputs, context);
691
+ choices = result.choices;
692
+ nextCursor = result.nextCursor;
693
+ }
694
+ let selectedValue;
695
+ if (choices.length > 0) {
696
+ selectedValue = await this.promptWithChoices({
697
+ fieldMeta,
698
+ choices,
699
+ nextCursor,
700
+ inputs,
701
+ context
702
+ });
703
+ } else {
704
+ selectedValue = await this.promptFreeForm(fieldMeta);
705
+ }
706
+ this.storeFieldValue(
707
+ inputs,
708
+ fieldMeta.key,
709
+ selectedValue,
710
+ fieldMeta.isRequired
711
+ );
712
+ }
550
713
  isUserCancellation(error) {
551
714
  const errorObj = error;
552
715
  return errorObj?.name === "ExitPromptError" || errorObj?.message?.includes("User force closed") || errorObj?.isTTYError === true;
@@ -1426,7 +1589,7 @@ var LoginSchema = z.object({
1426
1589
 
1427
1590
  // package.json
1428
1591
  var package_default = {
1429
- version: "0.15.1"};
1592
+ version: "0.15.3"};
1430
1593
 
1431
1594
  // src/telemetry/builders.ts
1432
1595
  function createCliBaseEvent(context = {}) {
@@ -1505,6 +1668,8 @@ var loginPlugin = ({ context }) => {
1505
1668
  const startTime = Date.now();
1506
1669
  let success = false;
1507
1670
  let errorMessage = null;
1671
+ let accountId = null;
1672
+ let customUserId = null;
1508
1673
  try {
1509
1674
  await loginWithSdk({
1510
1675
  ...options,
@@ -1513,6 +1678,10 @@ var loginPlugin = ({ context }) => {
1513
1678
  authClientId: context.options?.authClientId
1514
1679
  });
1515
1680
  success = true;
1681
+ try {
1682
+ ({ accountId, customUserId } = await getLoggedInUser());
1683
+ } catch {
1684
+ }
1516
1685
  } catch (error) {
1517
1686
  success = false;
1518
1687
  errorMessage = error instanceof Error ? error.message : "Login failed";
@@ -1536,7 +1705,9 @@ var loginPlugin = ({ context }) => {
1536
1705
  session_id: context.session_id,
1537
1706
  selected_api: context.selected_api,
1538
1707
  app_id: context.app_id,
1539
- app_version_id: context.app_version_id
1708
+ app_version_id: context.app_version_id,
1709
+ customuser_id: customUserId,
1710
+ account_id: accountId
1540
1711
  },
1541
1712
  cliVersion: package_default.version
1542
1713
  });
@@ -2698,7 +2869,7 @@ function createZapierCliSdk(options = {}) {
2698
2869
  // package.json with { type: 'json' }
2699
2870
  var package_default2 = {
2700
2871
  name: "@zapier/zapier-sdk-cli",
2701
- version: "0.15.1"};
2872
+ version: "0.15.3"};
2702
2873
  function detectPackageManager(cwd = process.cwd()) {
2703
2874
  const ua = process.env.npm_config_user_agent;
2704
2875
  if (ua) {