@zapier/zapier-sdk-cli 0.0.2 → 0.1.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.
@@ -7,6 +7,7 @@ exports.SchemaParameterResolver = void 0;
7
7
  const inquirer_1 = __importDefault(require("inquirer"));
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
9
  const zod_1 = require("zod");
10
+ const zapier_sdk_1 = require("@zapier/zapier-sdk");
10
11
  // ============================================================================
11
12
  // Schema Parameter Resolver
12
13
  // ============================================================================
@@ -14,55 +15,106 @@ class SchemaParameterResolver {
14
15
  async resolveParameters(schema, providedParams, sdk) {
15
16
  // 1. Try to parse with current parameters
16
17
  const parseResult = schema.safeParse(providedParams);
17
- // Even if parsing succeeds, check if we should resolve optional but important parameters
18
- const allResolvable = this.findAllResolvableParameters(schema);
19
- const shouldResolveAnyway = allResolvable.filter((param) => {
18
+ // Get all schema parameters to check which ones have resolvers
19
+ const allParams = this.extractParametersFromSchema(schema);
20
+ const resolvableParams = allParams.filter((param) => (0, zapier_sdk_1.hasResolver)(param.name));
21
+ // Get all missing parameters that have resolvers
22
+ const missingResolvable = resolvableParams.filter((param) => {
20
23
  const hasValue = this.getNestedValue(providedParams, param.path) !== undefined;
21
- // Resolve any parameters with resolvers even if optional, unless explicitly provided
22
- return !hasValue && param.resolverMeta?.resolver;
24
+ return !hasValue;
23
25
  });
24
- if (parseResult.success && shouldResolveAnyway.length === 0) {
26
+ // Determine which parameters are "functionally required" vs truly optional
27
+ // For run-action: appKey, actionType, actionKey are schema-required
28
+ // authenticationId and inputs are schema-optional but functionally needed
29
+ const functionallyRequired = missingResolvable.filter((param) => {
30
+ // Schema-required parameters are always functionally required
31
+ if (param.isRequired)
32
+ return true;
33
+ // For run-action, inputs and authenticationId are functionally required
34
+ // even though schema-optional
35
+ if (param.name === "inputs" || param.name === "authenticationId") {
36
+ return true;
37
+ }
38
+ return false;
39
+ });
40
+ const trulyOptional = missingResolvable.filter((param) => !functionallyRequired.includes(param));
41
+ if (parseResult.success && functionallyRequired.length === 0) {
25
42
  return parseResult.data;
26
43
  }
27
- // 2. Analyze what's missing and can be resolved
28
- let missingResolvable;
29
- if (!parseResult.success) {
30
- missingResolvable = this.findResolvableParameters(schema, parseResult.error, providedParams);
31
- }
32
- else {
33
- // Schema parsing succeeded, but we want to resolve optional important parameters
34
- missingResolvable = shouldResolveAnyway;
35
- }
36
- if (missingResolvable.length === 0) {
37
- // No resolvable parameters, throw original error
38
- throw parseResult.error;
44
+ if (functionallyRequired.length === 0) {
45
+ // No functionally required parameters missing, but check if we can parse
46
+ if (!parseResult.success) {
47
+ throw parseResult.error;
48
+ }
49
+ return parseResult.data;
39
50
  }
40
- // 3. Resolve missing parameters interactively
51
+ // 2. Resolve functionally required parameters first
41
52
  const resolvedParams = { ...providedParams };
42
53
  const context = {
43
54
  sdk,
44
55
  currentParams: providedParams,
45
56
  resolvedParams,
46
57
  };
47
- // Sort by dependency order (parameters that depend on others go last)
48
- const sortedMissing = this.sortByDependencies(missingResolvable);
49
- for (const missing of sortedMissing) {
50
- try {
51
- const value = await this.resolveParameter(missing, context);
52
- this.setNestedValue(resolvedParams, missing.path, value);
53
- // Update context with newly resolved value
54
- context.resolvedParams = resolvedParams;
58
+ if (functionallyRequired.length > 0) {
59
+ const requiredParamNames = functionallyRequired.map((p) => p.name);
60
+ const requiredResolutionOrder = (0, zapier_sdk_1.getResolutionOrderForParams)(requiredParamNames);
61
+ const orderedRequiredParams = requiredResolutionOrder
62
+ .map((paramName) => functionallyRequired.find((p) => p.name === paramName))
63
+ .filter((param) => param !== undefined);
64
+ for (const param of orderedRequiredParams) {
65
+ try {
66
+ const value = await this.resolveParameter(param, context);
67
+ this.setNestedValue(resolvedParams, param.path, value);
68
+ // Update context with newly resolved value
69
+ context.resolvedParams = resolvedParams;
70
+ }
71
+ catch (error) {
72
+ if (this.isUserCancellation(error)) {
73
+ console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
74
+ process.exit(0);
75
+ }
76
+ console.error(chalk_1.default.red(`Failed to resolve ${param.name}:`), error);
77
+ throw error;
78
+ }
55
79
  }
56
- catch (error) {
57
- if (this.isUserCancellation(error)) {
58
- console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
59
- process.exit(0);
80
+ }
81
+ // 3. Ask user if they want to resolve truly optional parameters
82
+ if (trulyOptional.length > 0) {
83
+ const optionalNames = trulyOptional.map((p) => p.name).join(", ");
84
+ const shouldResolveOptional = await inquirer_1.default.prompt([
85
+ {
86
+ type: "confirm",
87
+ name: "resolveOptional",
88
+ message: `Would you like to be prompted for optional parameters (${optionalNames})?`,
89
+ default: false,
90
+ },
91
+ ]);
92
+ if (shouldResolveOptional.resolveOptional) {
93
+ // Resolve optional parameters using their resolvers
94
+ const optionalParamNames = trulyOptional.map((p) => p.name);
95
+ const optionalResolutionOrder = (0, zapier_sdk_1.getResolutionOrderForParams)(optionalParamNames);
96
+ const orderedOptionalParams = optionalResolutionOrder
97
+ .map((paramName) => trulyOptional.find((p) => p.name === paramName))
98
+ .filter((param) => param !== undefined);
99
+ for (const param of orderedOptionalParams) {
100
+ try {
101
+ const value = await this.resolveParameter(param, context);
102
+ this.setNestedValue(resolvedParams, param.path, value);
103
+ // Update context with newly resolved value
104
+ context.resolvedParams = resolvedParams;
105
+ }
106
+ catch (error) {
107
+ if (this.isUserCancellation(error)) {
108
+ console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
109
+ process.exit(0);
110
+ }
111
+ console.error(chalk_1.default.red(`Failed to resolve ${param.name}:`), error);
112
+ throw error;
113
+ }
60
114
  }
61
- console.error(chalk_1.default.red(`Failed to resolve ${missing.name}:`), error);
62
- throw error;
63
115
  }
64
116
  }
65
- // 4. Validate final parameters
117
+ // 3. Validate final parameters
66
118
  const finalResult = schema.safeParse(resolvedParams);
67
119
  if (!finalResult.success) {
68
120
  console.error(chalk_1.default.red("❌ Parameter validation failed after resolution:"));
@@ -70,294 +122,173 @@ class SchemaParameterResolver {
70
122
  }
71
123
  return finalResult.data;
72
124
  }
73
- findAllResolvableParameters(schema) {
74
- const resolvable = [];
75
- this.analyzeSchema(schema, [], resolvable);
76
- return resolvable;
77
- }
78
- findResolvableParameters(schema, error, providedParams) {
79
- const resolvable = this.findAllResolvableParameters(schema);
80
- // Filter to only include parameters that are actually missing/invalid
81
- const errorPaths = new Set(error.issues.map((issue) => issue.path.join(".")));
82
- return resolvable.filter((param) => {
83
- const paramPath = param.path.join(".");
84
- const isErrorPath = errorPaths.has(paramPath);
85
- const hasValue = this.getNestedValue(providedParams, param.path) !== undefined;
86
- // Include if there's an error for this path or if it's required and missing
87
- // Also include optional parameters that have resolvers and aren't provided
88
- const shouldResolve = isErrorPath ||
89
- (param.isRequired && !hasValue) ||
90
- (!param.isRequired && !hasValue && param.resolverMeta?.resolver);
91
- return shouldResolve;
92
- });
93
- }
94
- analyzeSchema(schema, currentPath, resolvable) {
95
- // Handle different Zod types
125
+ extractParametersFromSchema(schema) {
126
+ const parameters = [];
127
+ // Only handle ZodObject at the top level
96
128
  if (schema instanceof zod_1.z.ZodObject) {
97
129
  const shape = schema.shape;
98
- Object.entries(shape).forEach(([key, fieldSchema]) => {
99
- const fieldPath = [...currentPath, key];
100
- this.analyzeSchemaField(key, fieldSchema, fieldPath, resolvable);
101
- });
102
- }
103
- else if (schema instanceof zod_1.z.ZodOptional) {
104
- this.analyzeSchema(schema.unwrap(), currentPath, resolvable);
105
- }
106
- else if (schema instanceof zod_1.z.ZodDefault) {
107
- this.analyzeSchema(schema.removeDefault(), currentPath, resolvable);
130
+ for (const [key, fieldSchema] of Object.entries(shape)) {
131
+ const param = this.analyzeFieldSchema(key, fieldSchema);
132
+ if (param) {
133
+ parameters.push(param);
134
+ }
135
+ }
108
136
  }
137
+ return parameters;
109
138
  }
110
- analyzeSchemaField(name, schema, path, resolvable) {
111
- const resolverMeta = schema._def.resolverMeta;
112
- if (resolverMeta?.resolver) {
113
- resolvable.push({
114
- name,
115
- path,
116
- schema,
117
- description: schema.description,
118
- resolverMeta,
119
- isRequired: !schema.isOptional(),
120
- });
121
- }
122
- // Recursively analyze nested objects
123
- if (schema instanceof zod_1.z.ZodObject) {
124
- this.analyzeSchema(schema, path, resolvable);
125
- }
126
- else if (schema instanceof zod_1.z.ZodOptional) {
127
- this.analyzeSchemaField(name, schema.unwrap(), path, resolvable);
128
- }
129
- else if (schema instanceof zod_1.z.ZodDefault) {
130
- this.analyzeSchemaField(name, schema.removeDefault(), path, resolvable);
131
- }
139
+ analyzeFieldSchema(fieldName, fieldSchema) {
140
+ let baseSchema = fieldSchema;
141
+ let isRequired = true;
142
+ // Check if field is optional or has default
143
+ if (baseSchema instanceof zod_1.z.ZodOptional) {
144
+ isRequired = false;
145
+ baseSchema = baseSchema._def.innerType;
146
+ }
147
+ if (baseSchema instanceof zod_1.z.ZodDefault) {
148
+ isRequired = false;
149
+ baseSchema = baseSchema._def.innerType;
150
+ }
151
+ return this.createResolvableParameter([fieldName], baseSchema, isRequired);
132
152
  }
133
- sortByDependencies(parameters) {
134
- // Simple topological sort based on 'depends' field
135
- const sorted = [];
136
- const remaining = [...parameters];
137
- while (remaining.length > 0) {
138
- const canResolve = remaining.filter((param) => {
139
- const depends = param.resolverMeta?.resolver?.depends || [];
140
- return depends.every((dep) => sorted.some((resolved) => resolved.name === dep));
141
- });
142
- if (canResolve.length === 0) {
143
- // No more resolvable parameters, add remaining ones (circular dependency or no dependencies)
144
- sorted.push(...remaining);
145
- break;
146
- }
147
- sorted.push(...canResolve);
148
- canResolve.forEach((param) => {
149
- const index = remaining.indexOf(param);
150
- remaining.splice(index, 1);
151
- });
152
- }
153
- return sorted;
153
+ createResolvableParameter(path, schema, isRequired) {
154
+ if (path.length === 0)
155
+ return null;
156
+ const name = path[path.length - 1];
157
+ return {
158
+ name,
159
+ path,
160
+ schema,
161
+ description: schema.description,
162
+ isRequired,
163
+ };
154
164
  }
155
- async resolveParameter(paramInfo, context) {
156
- const resolver = paramInfo.resolverMeta?.resolver;
165
+ async resolveParameter(param, context) {
166
+ const resolver = (0, zapier_sdk_1.getResolver)(param.name);
157
167
  if (!resolver) {
158
- return await this.promptStaticInput(paramInfo);
168
+ throw new Error(`No resolver found for parameter: ${param.name}`);
159
169
  }
170
+ console.log(chalk_1.default.blue(`\n🔍 Resolving ${param.name}...`));
160
171
  if (resolver.type === "static") {
161
- return await this.promptStaticInput(paramInfo, resolver);
162
- }
163
- if (resolver.type === "dynamic") {
164
- return await this.resolveDynamicParameter(paramInfo, resolver, context);
165
- }
166
- if (resolver.type === "fields") {
167
- return await this.resolveFieldsParameter(paramInfo, resolver, context);
168
- }
169
- throw new Error(`Unknown resolver type: ${resolver.type}`);
170
- }
171
- async promptStaticInput(paramInfo, resolver) {
172
- const promptConfig = {
173
- type: resolver?.inputType === "editor"
174
- ? "input"
175
- : resolver?.inputType || "input",
176
- name: "value",
177
- message: `Enter ${paramInfo.description || paramInfo.name}${paramInfo.isRequired ? "" : " (optional)"}:`,
178
- };
179
- // Only use placeholder as default for required parameters
180
- if (resolver?.placeholder && paramInfo.isRequired) {
181
- promptConfig.default = resolver.placeholder;
182
- }
183
- // Add validation for required parameters
184
- if (paramInfo.isRequired) {
185
- promptConfig.validate = (input) => {
186
- if (!input || (typeof input === "string" && input.trim() === "")) {
187
- return "This field is required. Please enter a value.";
188
- }
189
- return true;
172
+ // Static resolver - just prompt for input
173
+ const promptConfig = {
174
+ type: resolver.inputType === "password" ? "password" : "input",
175
+ name: param.name,
176
+ message: `Enter ${param.name}:`,
177
+ ...(resolver.placeholder && { default: resolver.placeholder }),
190
178
  };
179
+ const answers = await inquirer_1.default.prompt([promptConfig]);
180
+ return answers[param.name];
191
181
  }
192
- // For editor-like prompts, provide helpful instructions
193
- if (resolver?.inputType === "editor") {
194
- promptConfig.message += " (JSON format)";
195
- }
196
- try {
197
- const result = await inquirer_1.default.prompt([promptConfig]);
198
- // For optional parameters, treat empty input as undefined
199
- if (!paramInfo.isRequired &&
200
- (!result.value || result.value.trim() === "")) {
201
- return undefined;
202
- }
203
- // Try to parse JSON if it looks like JSON
204
- if (typeof result.value === "string" &&
205
- result.value.trim().startsWith("{")) {
206
- try {
207
- return JSON.parse(result.value);
208
- }
209
- catch {
210
- console.warn(chalk_1.default.yellow("Warning: Could not parse as JSON, using as string"));
211
- return result.value;
212
- }
213
- }
214
- return result.value;
215
- }
216
- catch (error) {
217
- if (this.isUserCancellation(error)) {
218
- console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
219
- process.exit(0);
220
- }
221
- throw error;
222
- }
223
- }
224
- async resolveDynamicParameter(paramInfo, resolver, context) {
225
- console.log(chalk_1.default.gray(`Fetching options for ${paramInfo.name}...`));
226
- try {
227
- // Use the new fetch function approach
228
- const options = await resolver.fetch(context.sdk, context.resolvedParams);
229
- if (options.length === 0) {
230
- console.log(chalk_1.default.yellow(`No options available for ${paramInfo.name}`));
231
- return await this.promptStaticInput(paramInfo);
232
- }
233
- // Generate prompt configuration
234
- const promptConfig = resolver.prompt(options, context.resolvedParams);
235
- // Execute the prompt
236
- let result;
182
+ else if (resolver.type === "dynamic") {
183
+ // Dynamic resolver - fetch options and prompt for selection
237
184
  try {
238
- result = await inquirer_1.default.prompt([promptConfig]);
185
+ console.log(chalk_1.default.gray(`Fetching options for ${param.name}...`));
186
+ const items = await resolver.fetch(context.sdk, context.resolvedParams);
187
+ if (!items || items.length === 0) {
188
+ throw new Error(`No options available for ${param.name}`);
189
+ }
190
+ const promptConfig = resolver.prompt(items, context.resolvedParams);
191
+ const answers = await inquirer_1.default.prompt([promptConfig]);
192
+ return answers[param.name];
239
193
  }
240
194
  catch (error) {
241
- if (this.isUserCancellation(error)) {
242
- console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
243
- process.exit(0);
244
- }
195
+ console.error(chalk_1.default.red(`Failed to fetch options for ${param.name}:`), error instanceof Error ? error.message : error);
245
196
  throw error;
246
197
  }
247
- let value = result[promptConfig.name || "value"];
248
- // Handle JSON parsing if the value looks like JSON
249
- if (typeof value === "string" && value.trim().startsWith("{")) {
250
- try {
251
- value = JSON.parse(value);
252
- }
253
- catch {
254
- console.warn(chalk_1.default.yellow("Warning: Could not parse as JSON, using as string"));
255
- }
256
- }
257
- return value;
258
198
  }
259
- catch (error) {
260
- if (this.isUserCancellation(error)) {
261
- console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
262
- process.exit(0);
263
- }
264
- if (error instanceof Error && error.message.includes("401")) {
265
- console.log(chalk_1.default.yellow(`⚠️ Invalid auth token, falling back to manual input for ${paramInfo.name}`));
266
- }
267
- else {
268
- console.error(chalk_1.default.red(`Failed to fetch options for ${paramInfo.name}:`), error);
269
- console.log(chalk_1.default.yellow("Falling back to manual input..."));
270
- }
271
- return await this.promptStaticInput(paramInfo);
272
- }
273
- }
274
- async resolveFieldsParameter(paramInfo, resolver, context) {
275
- console.log(chalk_1.default.gray(`Fetching field definitions for ${paramInfo.name}...`));
276
- try {
277
- // Fetch field definitions using the resolver's fetch function
278
- const fields = await resolver.fetch(context.sdk, context.resolvedParams);
279
- if (fields.length === 0) {
280
- console.log(chalk_1.default.yellow(`No input fields required for this action`));
281
- return {};
282
- }
283
- console.log(chalk_1.default.blue(`\nConfiguring inputs for ${context.resolvedParams.app} ${context.resolvedParams.type} ${context.resolvedParams.action}:`));
284
- const inputs = {};
285
- // Separate required and optional fields
286
- const requiredFields = fields.filter((field) => field.required);
287
- const optionalFields = fields.filter((field) => !field.required);
288
- // First, prompt for all required fields
289
- if (requiredFields.length > 0) {
290
- console.log(chalk_1.default.cyan(`\nRequired fields (${requiredFields.length}):`));
291
- for (const field of requiredFields) {
292
- await this.promptForField(field, inputs);
293
- }
294
- }
295
- // Then ask if user wants to configure optional fields
296
- if (optionalFields.length > 0) {
297
- console.log(chalk_1.default.gray(`\nThere are ${optionalFields.length} optional field(s) available.`));
298
- let shouldConfigureOptional;
299
- try {
300
- shouldConfigureOptional = await inquirer_1.default.prompt([
301
- {
302
- type: "confirm",
303
- name: "configure",
304
- message: "Would you like to configure optional fields?",
305
- default: false,
306
- },
307
- ]);
199
+ else if (resolver.type === "fields") {
200
+ // Fields resolver - fetch field definitions and prompt for each input
201
+ try {
202
+ console.log(chalk_1.default.gray(`Fetching input fields for ${param.name}...`));
203
+ const fields = await resolver.fetch(context.sdk, context.resolvedParams);
204
+ if (!fields || fields.length === 0) {
205
+ console.log(chalk_1.default.yellow(`No input fields required for this action.`));
206
+ return {};
308
207
  }
309
- catch (error) {
310
- if (this.isUserCancellation(error)) {
311
- console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
312
- process.exit(0);
208
+ const inputs = {};
209
+ // Separate required and optional fields
210
+ const requiredFields = fields.filter((field) => field.required);
211
+ const optionalFields = fields.filter((field) => !field.required);
212
+ // First, prompt for all required fields
213
+ if (requiredFields.length > 0) {
214
+ console.log(chalk_1.default.blue(`\n📝 Please provide values for the following input fields:`));
215
+ for (const field of requiredFields) {
216
+ await this.promptForField(field, inputs);
313
217
  }
314
- throw error;
315
218
  }
316
- if (shouldConfigureOptional.configure) {
317
- console.log(chalk_1.default.cyan(`\nOptional fields:`));
318
- for (const field of optionalFields) {
319
- await this.promptForField(field, inputs);
219
+ // Then ask if user wants to configure optional fields
220
+ if (optionalFields.length > 0) {
221
+ console.log(chalk_1.default.gray(`\nThere are ${optionalFields.length} optional field(s) available.`));
222
+ let shouldConfigureOptional;
223
+ try {
224
+ shouldConfigureOptional = await inquirer_1.default.prompt([
225
+ {
226
+ type: "confirm",
227
+ name: "configure",
228
+ message: "Would you like to configure optional fields?",
229
+ default: false,
230
+ },
231
+ ]);
232
+ }
233
+ catch (error) {
234
+ if (this.isUserCancellation(error)) {
235
+ console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
236
+ process.exit(0);
237
+ }
238
+ throw error;
239
+ }
240
+ if (shouldConfigureOptional.configure) {
241
+ console.log(chalk_1.default.cyan(`\nOptional fields:`));
242
+ for (const field of optionalFields) {
243
+ await this.promptForField(field, inputs);
244
+ }
320
245
  }
321
246
  }
247
+ return inputs;
322
248
  }
323
- return inputs;
324
- }
325
- catch (error) {
326
- if (this.isUserCancellation(error)) {
327
- console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
328
- process.exit(0);
249
+ catch (error) {
250
+ console.error(chalk_1.default.red(`Failed to fetch fields for ${param.name}:`), error instanceof Error ? error.message : error);
251
+ throw error;
329
252
  }
330
- console.error(chalk_1.default.red(`Failed to fetch field definitions for ${paramInfo.name}:`), error);
331
- console.log(chalk_1.default.yellow("Falling back to manual JSON input..."));
332
- return await this.promptStaticInput(paramInfo);
333
253
  }
254
+ throw new Error(`Unknown resolver type for ${param.name}`);
255
+ }
256
+ getNestedValue(obj, path) {
257
+ return path.reduce((current, key) => current?.[key], obj);
258
+ }
259
+ setNestedValue(obj, path, value) {
260
+ const lastKey = path[path.length - 1];
261
+ const parent = path.slice(0, -1).reduce((current, key) => {
262
+ if (!(key in current)) {
263
+ current[key] = {};
264
+ }
265
+ return current[key];
266
+ }, obj);
267
+ parent[lastKey] = value;
334
268
  }
335
269
  async promptForField(field, inputs) {
336
270
  const fieldPrompt = {
337
- type: "input",
271
+ type: field.type === "boolean" ? "confirm" : "input",
338
272
  name: field.key,
339
273
  message: `${field.label || field.key}${field.required ? " (required)" : " (optional)"}:`,
274
+ ...(field.helpText && { prefix: chalk_1.default.gray(`ℹ ${field.helpText}\n`) }),
275
+ ...(field.default && { default: field.default }),
340
276
  };
341
- // Add description/help text if available
342
- if (field.help_text || field.description) {
343
- fieldPrompt.message += `\n ${chalk_1.default.dim(field.help_text || field.description)}`;
344
- }
345
- // Set default value
346
- if (field.default !== undefined) {
347
- fieldPrompt.default = field.default;
348
- }
349
- // Add validation for required fields
350
- if (field.required) {
351
- fieldPrompt.validate = (input) => {
352
- if (!input || (typeof input === "string" && input.trim() === "")) {
353
- return "This field is required. Please enter a value.";
354
- }
355
- return true;
356
- };
277
+ if (field.choices && field.choices.length > 0) {
278
+ fieldPrompt.type = "list";
279
+ fieldPrompt.choices = field.choices.map((choice) => ({
280
+ name: choice.label || choice.value,
281
+ value: choice.value,
282
+ }));
357
283
  }
358
- let result;
359
284
  try {
360
- result = await inquirer_1.default.prompt([fieldPrompt]);
285
+ const answer = await inquirer_1.default.prompt([fieldPrompt]);
286
+ if (answer[field.key] !== undefined && answer[field.key] !== "") {
287
+ inputs[field.key] = answer[field.key];
288
+ }
289
+ else if (field.required) {
290
+ throw new Error(`Required field ${field.key} cannot be empty`);
291
+ }
361
292
  }
362
293
  catch (error) {
363
294
  if (this.isUserCancellation(error)) {
@@ -366,48 +297,11 @@ class SchemaParameterResolver {
366
297
  }
367
298
  throw error;
368
299
  }
369
- // Only include non-empty values
370
- if (result[field.key] !== undefined && result[field.key] !== "") {
371
- let value = result[field.key];
372
- // Try to parse as appropriate type
373
- if (field.type === "integer" && typeof value === "string") {
374
- const parsed = parseInt(value, 10);
375
- if (!isNaN(parsed))
376
- value = parsed;
377
- }
378
- else if (field.type === "number" && typeof value === "string") {
379
- const parsed = parseFloat(value);
380
- if (!isNaN(parsed))
381
- value = parsed;
382
- }
383
- else if (field.type === "boolean" && typeof value === "string") {
384
- value = value.toLowerCase() === "true" || value === "1";
385
- }
386
- inputs[field.key] = value;
387
- }
388
- }
389
- getNestedValue(obj, path) {
390
- return path.reduce((current, key) => current?.[key], obj);
391
- }
392
- setNestedValue(obj, path, value) {
393
- const lastKey = path[path.length - 1];
394
- const parentPath = path.slice(0, -1);
395
- const parent = parentPath.reduce((current, key) => {
396
- if (!current[key]) {
397
- current[key] = {};
398
- }
399
- return current[key];
400
- }, obj);
401
- parent[lastKey] = value;
402
300
  }
403
301
  isUserCancellation(error) {
404
- // Check for various ways user cancellation can be detected
405
- return (error &&
406
- (error.name === "ExitPromptError" ||
407
- error.message?.includes("User force closed the prompt") ||
408
- error.message?.includes("SIGINT") ||
409
- error.code === "SIGINT" ||
410
- error.signal === "SIGINT"));
302
+ return (error?.name === "ExitPromptError" ||
303
+ error?.message?.includes("User force closed") ||
304
+ error?.isTTYError);
411
305
  }
412
306
  }
413
307
  exports.SchemaParameterResolver = SchemaParameterResolver;
@@ -5,19 +5,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.formatItemsFromSchema = formatItemsFromSchema;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
- const zapier_sdk_1 = require("@zapier/zapier-sdk");
8
+ function getFormatMetadata(schema) {
9
+ return schema?._def?.formatMeta;
10
+ }
11
+ function getOutputSchema(schema) {
12
+ return schema?._def?.outputSchema;
13
+ }
9
14
  // ============================================================================
10
15
  // Generic Schema-Driven Formatter
11
16
  // ============================================================================
12
17
  function formatItemsFromSchema(inputSchema, items) {
13
18
  // Get the output schema and its format metadata
14
- const outputSchema = (0, zapier_sdk_1.getOutputSchema)(inputSchema);
19
+ const outputSchema = getOutputSchema(inputSchema);
15
20
  if (!outputSchema) {
16
21
  // Fallback to generic formatting if no output schema
17
22
  formatItemsGeneric(items);
18
23
  return;
19
24
  }
20
- const formatMeta = (0, zapier_sdk_1.getFormatMetadata)(outputSchema);
25
+ const formatMeta = getFormatMetadata(outputSchema);
21
26
  if (!formatMeta) {
22
27
  // Fallback to generic formatting if no format metadata
23
28
  formatItemsGeneric(items);