@zapier/zapier-sdk-cli 0.8.4 → 0.10.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +35 -51
  3. package/dist/cli.cjs +950 -433
  4. package/dist/cli.mjs +951 -434
  5. package/dist/index.cjs +729 -336
  6. package/dist/index.mjs +730 -337
  7. package/dist/package.json +1 -1
  8. package/dist/src/plugins/add/ast-generator.d.ts +37 -0
  9. package/dist/src/plugins/add/ast-generator.js +403 -0
  10. package/dist/src/plugins/add/index.d.ts +13 -0
  11. package/dist/src/plugins/add/index.js +120 -0
  12. package/dist/src/plugins/add/schemas.d.ts +18 -0
  13. package/dist/src/plugins/add/schemas.js +19 -0
  14. package/dist/src/plugins/getLoginConfigPath/index.d.ts +15 -0
  15. package/dist/src/plugins/getLoginConfigPath/index.js +19 -0
  16. package/dist/src/plugins/getLoginConfigPath/schemas.d.ts +3 -0
  17. package/dist/src/plugins/getLoginConfigPath/schemas.js +5 -0
  18. package/dist/src/plugins/index.d.ts +2 -2
  19. package/dist/src/plugins/index.js +2 -2
  20. package/dist/src/sdk.js +3 -3
  21. package/dist/src/utils/cli-generator-utils.d.ts +2 -1
  22. package/dist/src/utils/cli-generator-utils.js +11 -5
  23. package/dist/src/utils/cli-generator.js +65 -65
  24. package/dist/src/utils/parameter-resolver.d.ts +4 -1
  25. package/dist/src/utils/parameter-resolver.js +92 -15
  26. package/dist/src/utils/schema-formatter.d.ts +5 -1
  27. package/dist/src/utils/schema-formatter.js +48 -18
  28. package/dist/tsconfig.tsbuildinfo +1 -1
  29. package/package.json +4 -4
  30. package/src/plugins/add/ast-generator.ts +777 -0
  31. package/src/plugins/add/index.test.ts +58 -0
  32. package/src/plugins/add/index.ts +187 -0
  33. package/src/plugins/add/schemas.ts +26 -0
  34. package/src/plugins/getLoginConfigPath/index.ts +45 -0
  35. package/src/plugins/getLoginConfigPath/schemas.ts +10 -0
  36. package/src/plugins/index.ts +2 -2
  37. package/src/sdk.ts +4 -4
  38. package/src/utils/cli-generator-utils.ts +17 -5
  39. package/src/utils/cli-generator.ts +90 -79
  40. package/src/utils/parameter-resolver.ts +155 -21
  41. package/src/utils/schema-formatter.ts +68 -33
  42. package/tsup.config.ts +1 -1
  43. package/dist/src/plugins/generateTypes/index.d.ts +0 -21
  44. package/dist/src/plugins/generateTypes/index.js +0 -312
  45. package/dist/src/plugins/generateTypes/schemas.d.ts +0 -18
  46. package/dist/src/plugins/generateTypes/schemas.js +0 -14
  47. package/dist/src/plugins/getConfigPath/index.d.ts +0 -15
  48. package/dist/src/plugins/getConfigPath/index.js +0 -19
  49. package/dist/src/plugins/getConfigPath/schemas.d.ts +0 -3
  50. package/dist/src/plugins/getConfigPath/schemas.js +0 -5
  51. package/src/plugins/generateTypes/index.ts +0 -444
  52. package/src/plugins/generateTypes/schemas.ts +0 -23
  53. package/src/plugins/getConfigPath/index.ts +0 -42
  54. package/src/plugins/getConfigPath/schemas.ts +0 -8
@@ -1,6 +1,6 @@
1
1
  export { loginPlugin } from "./login";
2
2
  export { logoutPlugin } from "./logout";
3
3
  export { mcpPlugin } from "./mcp";
4
- export { generateTypesPlugin } from "./generateTypes";
5
4
  export { bundleCodePlugin } from "./bundleCode";
6
- export { getConfigPathPlugin } from "./getConfigPath";
5
+ export { getLoginConfigPathPlugin } from "./getLoginConfigPath";
6
+ export { addPlugin } from "./add";
@@ -1,6 +1,6 @@
1
1
  export { loginPlugin } from "./login";
2
2
  export { logoutPlugin } from "./logout";
3
3
  export { mcpPlugin } from "./mcp";
4
- export { generateTypesPlugin } from "./generateTypes";
5
4
  export { bundleCodePlugin } from "./bundleCode";
6
- export { getConfigPathPlugin } from "./getConfigPath";
5
+ export { getLoginConfigPathPlugin } from "./getLoginConfigPath";
6
+ export { addPlugin } from "./add";
package/dist/src/sdk.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createZapierSdkWithoutRegistry, registryPlugin, } from "@zapier/zapier-sdk";
2
- import { loginPlugin, logoutPlugin, mcpPlugin, generateTypesPlugin, bundleCodePlugin, getConfigPathPlugin, } from "./plugins/index";
2
+ import { loginPlugin, logoutPlugin, mcpPlugin, bundleCodePlugin, getLoginConfigPathPlugin, addPlugin, } from "./plugins/index";
3
3
  /**
4
4
  * Create a Zapier SDK instance configured specifically for the CLI
5
5
  * Includes all CLI-specific plugins in addition to the standard SDK functionality
@@ -10,9 +10,9 @@ export function createZapierCliSdk(options = {}) {
10
10
  debug: options.debug,
11
11
  });
12
12
  // Add CLI-specific plugins before registry
13
- sdk = sdk.addPlugin(generateTypesPlugin);
14
13
  sdk = sdk.addPlugin(bundleCodePlugin);
15
- sdk = sdk.addPlugin(getConfigPathPlugin);
14
+ sdk = sdk.addPlugin(getLoginConfigPathPlugin);
15
+ sdk = sdk.addPlugin(addPlugin);
16
16
  sdk = sdk.addPlugin(mcpPlugin);
17
17
  sdk = sdk.addPlugin(loginPlugin);
18
18
  sdk = sdk.addPlugin(logoutPlugin);
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { type FunctionRegistryEntry } from "@zapier/zapier-sdk";
2
3
  export interface CliParameter {
3
4
  name: string;
4
5
  type: "string" | "number" | "boolean" | "array";
@@ -9,5 +10,5 @@ export interface CliParameter {
9
10
  hasResolver?: boolean;
10
11
  isPositional?: boolean;
11
12
  }
12
- export declare function analyzeZodSchema(schema: z.ZodSchema): CliParameter[];
13
+ export declare function analyzeZodSchema(schema: z.ZodSchema, functionInfo?: FunctionRegistryEntry): CliParameter[];
13
14
  export declare function convertCliArgsToSdkParams(parameters: CliParameter[], positionalArgs: unknown[], options: Record<string, unknown>): Record<string, unknown>;
@@ -1,14 +1,14 @@
1
1
  import { z } from "zod";
2
- import { hasResolver, isPositional } from "@zapier/zapier-sdk";
2
+ import { isPositional } from "@zapier/zapier-sdk";
3
3
  // ============================================================================
4
4
  // Schema Analysis
5
5
  // ============================================================================
6
- export function analyzeZodSchema(schema) {
6
+ export function analyzeZodSchema(schema, functionInfo) {
7
7
  const parameters = [];
8
8
  if (schema instanceof z.ZodObject) {
9
9
  const shape = schema.shape;
10
10
  for (const [key, fieldSchema] of Object.entries(shape)) {
11
- const param = analyzeZodField(key, fieldSchema);
11
+ const param = analyzeZodField(key, fieldSchema, functionInfo);
12
12
  if (param) {
13
13
  parameters.push(param);
14
14
  }
@@ -16,7 +16,7 @@ export function analyzeZodSchema(schema) {
16
16
  }
17
17
  return parameters;
18
18
  }
19
- function analyzeZodField(name, schema) {
19
+ function analyzeZodField(name, schema, functionInfo) {
20
20
  let baseSchema = schema;
21
21
  let required = true;
22
22
  let defaultValue = undefined;
@@ -53,6 +53,12 @@ function analyzeZodField(name, schema) {
53
53
  // Handle Record<string, any> as JSON string input
54
54
  paramType = "string";
55
55
  }
56
+ // Check if this parameter has a resolver
57
+ let paramHasResolver = false;
58
+ // Check function-specific resolvers first
59
+ if (functionInfo?.resolvers?.[name]) {
60
+ paramHasResolver = true;
61
+ }
56
62
  // Extract resolver metadata
57
63
  return {
58
64
  name,
@@ -61,7 +67,7 @@ function analyzeZodField(name, schema) {
61
67
  description: schema.description,
62
68
  default: defaultValue,
63
69
  choices,
64
- hasResolver: hasResolver(name),
70
+ hasResolver: paramHasResolver,
65
71
  isPositional: isPositional(schema),
66
72
  };
67
73
  }
@@ -1,34 +1,13 @@
1
1
  import { z } from "zod";
2
- import { hasResolver, isPositional, formatErrorMessage, ZapierError, } from "@zapier/zapier-sdk";
2
+ import { isPositional, formatErrorMessage, ZapierError, } from "@zapier/zapier-sdk";
3
3
  import { SchemaParameterResolver } from "./parameter-resolver";
4
- import { formatItemsFromSchema } from "./schema-formatter";
4
+ import { formatItemsFromSchema, formatJsonOutput } from "./schema-formatter";
5
5
  import chalk from "chalk";
6
- import util from "util";
7
6
  import inquirer from "inquirer";
8
7
  // ============================================================================
9
- // JSON Formatting
10
- // ============================================================================
11
- function formatJsonOutput(data) {
12
- // Don't print anything for undefined results (commands that just perform actions)
13
- if (data === undefined) {
14
- return;
15
- }
16
- // Show success message for action results
17
- if (data &&
18
- typeof data === "object" &&
19
- !Array.isArray(data) &&
20
- (data.success !== undefined ||
21
- data.id ||
22
- data.status)) {
23
- console.log(chalk.green("āœ… Action completed successfully!\n"));
24
- }
25
- // Use util.inspect for colored output
26
- console.log(util.inspect(data, { colors: true, depth: null, breakLength: 80 }));
27
- }
28
- // ============================================================================
29
8
  // Schema Analysis
30
9
  // ============================================================================
31
- function analyzeZodSchema(schema) {
10
+ function analyzeZodSchema(schema, functionInfo) {
32
11
  const parameters = [];
33
12
  // Handle ZodEffects (schemas with .refine(), .transform(), etc.)
34
13
  if (schema._def &&
@@ -37,12 +16,12 @@ function analyzeZodSchema(schema) {
37
16
  // Get the underlying schema
38
17
  const innerSchema = schema
39
18
  ._def.schema;
40
- return analyzeZodSchema(innerSchema);
19
+ return analyzeZodSchema(innerSchema, functionInfo);
41
20
  }
42
21
  if (schema instanceof z.ZodObject) {
43
22
  const shape = schema.shape;
44
23
  for (const [key, fieldSchema] of Object.entries(shape)) {
45
- const param = analyzeZodField(key, fieldSchema);
24
+ const param = analyzeZodField(key, fieldSchema, functionInfo);
46
25
  if (param) {
47
26
  parameters.push(param);
48
27
  }
@@ -50,7 +29,7 @@ function analyzeZodSchema(schema) {
50
29
  }
51
30
  return parameters;
52
31
  }
53
- function analyzeZodField(name, schema) {
32
+ function analyzeZodField(name, schema, functionInfo) {
54
33
  let baseSchema = schema;
55
34
  let required = true;
56
35
  let defaultValue = undefined;
@@ -98,6 +77,12 @@ function analyzeZodField(name, schema) {
98
77
  // Handle Record<string, any> as JSON string input
99
78
  paramType = "string";
100
79
  }
80
+ // Check if this parameter has a resolver
81
+ let paramHasResolver = false;
82
+ // Check function-specific resolvers first
83
+ if (functionInfo?.resolvers?.[name]) {
84
+ paramHasResolver = true;
85
+ }
101
86
  // Extract resolver metadata
102
87
  return {
103
88
  name,
@@ -106,7 +91,7 @@ function analyzeZodField(name, schema) {
106
91
  description: schema.description,
107
92
  default: defaultValue,
108
93
  choices,
109
- hasResolver: hasResolver(name),
94
+ hasResolver: paramHasResolver,
110
95
  isPositional: isPositional(schema),
111
96
  };
112
97
  }
@@ -145,7 +130,7 @@ export function generateCliCommands(program, sdk) {
145
130
  }
146
131
  // Convert methodName to kebab-case CLI command
147
132
  const cliCommandName = methodNameToCliCommand(fnInfo.name);
148
- const config = createCommandConfig(cliCommandName, fnInfo.name, fnInfo.inputSchema, sdk);
133
+ const config = createCommandConfig(cliCommandName, fnInfo, sdk);
149
134
  addCommand(program, cliCommandName, config);
150
135
  });
151
136
  // Override the help display to show commands grouped by category
@@ -200,8 +185,9 @@ export function generateCliCommands(program, sdk) {
200
185
  },
201
186
  });
202
187
  }
203
- function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
204
- const parameters = analyzeZodSchema(schema);
188
+ function createCommandConfig(cliCommandName, functionInfo, sdk) {
189
+ const schema = functionInfo.inputSchema;
190
+ const parameters = analyzeZodSchema(schema, functionInfo);
205
191
  const description = schema.description || `${cliCommandName} command`;
206
192
  const handler = async (...args) => {
207
193
  try {
@@ -209,7 +195,7 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
209
195
  const commandObj = args[args.length - 1];
210
196
  const options = commandObj.opts();
211
197
  // Check if this is a list command for pagination
212
- const isListCommand = cliCommandName.startsWith("list-");
198
+ const isListCommand = functionInfo.type === "list";
213
199
  const hasPaginationParams = parameters.some((p) => p.name === "maxItems" || p.name === "pageSize");
214
200
  const hasUserSpecifiedMaxItems = "maxItems" in options && options.maxItems !== undefined;
215
201
  const shouldUseJson = options.json;
@@ -217,7 +203,7 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
217
203
  const rawParams = convertCliArgsToSdkParams(parameters, args.slice(0, -1), options);
218
204
  // Resolve missing parameters interactively using schema metadata
219
205
  const resolver = new SchemaParameterResolver();
220
- const resolvedParams = await resolver.resolveParameters(schema, rawParams, sdk);
206
+ const resolvedParams = await resolver.resolveParameters(schema, rawParams, sdk, functionInfo.name);
221
207
  // Handle paginated list commands with async iteration
222
208
  if (isListCommand &&
223
209
  hasPaginationParams &&
@@ -225,8 +211,8 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
225
211
  !hasUserSpecifiedMaxItems) {
226
212
  // Get the async iterable directly from the SDK method call (don't await it! that breaks the next page behavior)
227
213
  const sdkObj = sdk;
228
- const sdkIterator = sdkObj[sdkMethodName](resolvedParams);
229
- await handlePaginatedListWithAsyncIteration(sdkMethodName, sdkIterator, schema);
214
+ const sdkIterator = sdkObj[functionInfo.name](resolvedParams);
215
+ await handlePaginatedListWithAsyncIteration(functionInfo.name, sdkIterator, functionInfo);
230
216
  }
231
217
  else {
232
218
  // Special handling for commands that write to files
@@ -234,14 +220,14 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
234
220
  if (hasOutputFile) {
235
221
  // Call the SDK method for file output commands
236
222
  const sdkObj = sdk;
237
- await sdkObj[sdkMethodName](resolvedParams);
223
+ await sdkObj[functionInfo.name](resolvedParams);
238
224
  console.log(chalk.green(`āœ… ${cliCommandName} completed successfully!`));
239
225
  console.log(chalk.gray(`Output written to: ${hasOutputFile}`));
240
226
  return;
241
227
  }
242
228
  // Call the SDK method and handle non-paginated results
243
229
  const sdkObj = sdk;
244
- const result = await sdkObj[sdkMethodName](resolvedParams);
230
+ const result = await sdkObj[functionInfo.name](resolvedParams);
245
231
  const items = result?.data
246
232
  ? result.data
247
233
  : result;
@@ -249,7 +235,7 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
249
235
  console.log(JSON.stringify(items, null, 2));
250
236
  }
251
237
  else if (isListCommand) {
252
- formatNonPaginatedResults(items, resolvedParams.maxItems, hasUserSpecifiedMaxItems, shouldUseJson, schema, sdkMethodName);
238
+ formatNonPaginatedResults(items, resolvedParams.maxItems, hasUserSpecifiedMaxItems, shouldUseJson, functionInfo);
253
239
  }
254
240
  else {
255
241
  formatJsonOutput(items);
@@ -294,6 +280,8 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
294
280
  }
295
281
  function addCommand(program, commandName, config) {
296
282
  const command = program.command(commandName).description(config.description);
283
+ // Track whether we've already used a positional array parameter
284
+ let hasPositionalArray = false;
297
285
  // Add parameters to command
298
286
  config.parameters.forEach((param) => {
299
287
  // Convert camelCase to kebab-case for CLI display
@@ -302,6 +290,19 @@ function addCommand(program, commandName, config) {
302
290
  // Required parameters with resolvers become optional positional arguments (resolver handles prompting)
303
291
  command.argument(`[${kebabName}]`, param.description || `${kebabName} parameter`);
304
292
  }
293
+ else if (param.required &&
294
+ param.type === "array" &&
295
+ !hasPositionalArray) {
296
+ // First required array parameter becomes a variadic positional argument
297
+ hasPositionalArray = true;
298
+ command.argument(`<${kebabName}...>`, param.description || `${kebabName} parameter`);
299
+ }
300
+ else if (param.required && param.type === "array") {
301
+ // Subsequent required array parameters become required flags
302
+ const flags = [`--${kebabName}`];
303
+ const flagSignature = flags.join(", ") + ` <values...>`;
304
+ command.requiredOption(flagSignature, param.description || `${kebabName} parameter (required)`);
305
+ }
305
306
  else if (param.required) {
306
307
  // Required parameters without resolvers become required positional arguments
307
308
  command.argument(`<${kebabName}>`, param.description || `${kebabName} parameter`);
@@ -358,6 +359,10 @@ function convertCliArgsToSdkParams(parameters, positionalArgs, options) {
358
359
  return sdkParams;
359
360
  }
360
361
  function convertValue(value, type) {
362
+ // Don't convert undefined values - let the resolver system handle them
363
+ if (value === undefined) {
364
+ return undefined;
365
+ }
361
366
  switch (type) {
362
367
  case "number":
363
368
  return Number(value);
@@ -383,11 +388,11 @@ function convertValue(value, type) {
383
388
  // ============================================================================
384
389
  // Pagination Handlers
385
390
  // ============================================================================
386
- async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult, schema) {
387
- const itemName = getItemNameFromMethod(sdkMethodName);
391
+ async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult, functionInfo) {
392
+ const itemName = getItemNameFromMethod(functionInfo);
388
393
  let totalShown = 0;
389
394
  let pageCount = 0;
390
- console.log(chalk.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName)}\n`));
395
+ console.log(chalk.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName, functionInfo)}\n`));
391
396
  try {
392
397
  // Use async iteration to go through pages
393
398
  for await (const page of sdkResult) {
@@ -407,11 +412,11 @@ async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult, s
407
412
  // Clear screen for subsequent pages (not the first)
408
413
  if (pageCount > 1) {
409
414
  console.clear();
410
- console.log(chalk.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName)}\n`));
415
+ console.log(chalk.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName, functionInfo)}\n`));
411
416
  }
412
- // Format and display items using schema
413
- if (schema) {
414
- formatItemsFromSchema(schema, items, totalShown);
417
+ // Format and display items using function info
418
+ if (functionInfo) {
419
+ formatItemsFromSchema(functionInfo, items, totalShown);
415
420
  }
416
421
  else {
417
422
  formatItemsGeneric(items, totalShown);
@@ -447,8 +452,8 @@ async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult, s
447
452
  console.log(chalk.yellow(`No ${itemName} found.`));
448
453
  return;
449
454
  }
450
- if (schema) {
451
- formatItemsFromSchema(schema, items, 0);
455
+ if (functionInfo) {
456
+ formatItemsFromSchema(functionInfo, items, 0);
452
457
  }
453
458
  else {
454
459
  formatItemsGeneric(items, 0);
@@ -460,7 +465,7 @@ async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult, s
460
465
  }
461
466
  }
462
467
  }
463
- function formatNonPaginatedResults(result, requestedMaxItems, userSpecifiedMaxItems, useRawJson, schema, methodName) {
468
+ function formatNonPaginatedResults(result, requestedMaxItems, userSpecifiedMaxItems, useRawJson, functionInfo) {
464
469
  if (!Array.isArray(result)) {
465
470
  if (useRawJson) {
466
471
  console.log(JSON.stringify(result, null, 2));
@@ -474,15 +479,15 @@ function formatNonPaginatedResults(result, requestedMaxItems, userSpecifiedMaxIt
474
479
  console.log(JSON.stringify(result, null, 2));
475
480
  return;
476
481
  }
477
- const itemName = methodName ? getItemNameFromMethod(methodName) : "items";
482
+ const itemName = functionInfo ? getItemNameFromMethod(functionInfo) : "items";
478
483
  if (result.length === 0) {
479
484
  console.log(chalk.yellow(`No ${itemName} found.`));
480
485
  return;
481
486
  }
482
487
  console.log(chalk.green(`\nāœ… Found ${result.length} ${itemName}:\n`));
483
- // Use schema for formatting
484
- if (schema) {
485
- formatItemsFromSchema(schema, result);
488
+ // Use function info for formatting
489
+ if (functionInfo) {
490
+ formatItemsFromSchema(functionInfo, result);
486
491
  }
487
492
  else {
488
493
  // Fallback to generic formatting
@@ -509,20 +514,15 @@ function formatItemsGeneric(items, startingNumber = 0) {
509
514
  });
510
515
  }
511
516
  // Generic helper functions that infer from schema description or method name
512
- function getItemNameFromMethod(methodName) {
513
- // Extract from method name: listApps -> apps, listActions -> actions
514
- const listMatch = methodName.match(/^list(.+)$/);
515
- if (listMatch) {
516
- return listMatch[1].toLowerCase();
517
+ function getItemNameFromMethod(functionInfo) {
518
+ if (functionInfo.itemType) {
519
+ return `${functionInfo.itemType} items`;
517
520
  }
518
- // Fallback to generic
519
521
  return "items";
520
522
  }
521
- function getListTitleFromMethod(methodName) {
522
- const itemName = getItemNameFromMethod(methodName);
523
- if (itemName === "items")
524
- return "Available Items";
525
- // Capitalize first letter: apps -> Apps
526
- const capitalized = itemName.charAt(0).toUpperCase() + itemName.slice(1);
527
- return `Available ${capitalized}`;
523
+ function getListTitleFromMethod(methodName, functionInfo) {
524
+ if (functionInfo.itemType) {
525
+ return `Available ${functionInfo.itemType} items`;
526
+ }
527
+ return `${methodName} items`;
528
528
  }
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import type { ZapierSdk } from "@zapier/zapier-sdk";
3
3
  export declare class SchemaParameterResolver {
4
- resolveParameters(schema: z.ZodSchema, providedParams: unknown, sdk: ZapierSdk): Promise<unknown>;
4
+ resolveParameters(schema: z.ZodSchema, providedParams: unknown, sdk: ZapierSdk, functionName?: string): Promise<unknown>;
5
5
  private extractParametersFromSchema;
6
6
  private analyzeFieldSchema;
7
7
  private createResolvableParameter;
@@ -11,4 +11,7 @@ export declare class SchemaParameterResolver {
11
11
  private setNestedValue;
12
12
  private promptForField;
13
13
  private isUserCancellation;
14
+ private hasResolver;
15
+ private getResolver;
16
+ private getLocalResolvers;
14
17
  }
@@ -1,17 +1,59 @@
1
1
  import inquirer from "inquirer";
2
2
  import chalk from "chalk";
3
3
  import { z } from "zod";
4
- import { getResolver, hasResolver, getResolutionOrderForParams, } from "@zapier/zapier-sdk";
4
+ // ============================================================================
5
+ // Local Resolution Helper Functions
6
+ // ============================================================================
7
+ /**
8
+ * Resolve dependency chain for a parameter using local resolvers
9
+ * Returns parameters in the order they need to be resolved
10
+ */
11
+ function getLocalResolutionOrder(paramName, resolvers, resolved = new Set()) {
12
+ const resolver = resolvers[paramName];
13
+ if (!resolver || resolver.type === "static") {
14
+ return [paramName];
15
+ }
16
+ const order = [];
17
+ if ("depends" in resolver && resolver.depends) {
18
+ for (const dependency of resolver.depends) {
19
+ if (!resolved.has(dependency)) {
20
+ order.push(...getLocalResolutionOrder(dependency, resolvers, resolved));
21
+ resolved.add(dependency);
22
+ }
23
+ }
24
+ }
25
+ if (!resolved.has(paramName)) {
26
+ order.push(paramName);
27
+ resolved.add(paramName);
28
+ }
29
+ return order;
30
+ }
31
+ /**
32
+ * Get resolution order for multiple parameters using local resolvers
33
+ */
34
+ function getLocalResolutionOrderForParams(paramNames, resolvers) {
35
+ const resolved = new Set();
36
+ const order = [];
37
+ for (const paramName of paramNames) {
38
+ const paramOrder = getLocalResolutionOrder(paramName, resolvers, resolved);
39
+ for (const param of paramOrder) {
40
+ if (!order.includes(param)) {
41
+ order.push(param);
42
+ }
43
+ }
44
+ }
45
+ return order;
46
+ }
5
47
  // ============================================================================
6
48
  // Schema Parameter Resolver
7
49
  // ============================================================================
8
50
  export class SchemaParameterResolver {
9
- async resolveParameters(schema, providedParams, sdk) {
51
+ async resolveParameters(schema, providedParams, sdk, functionName) {
10
52
  // 1. Try to parse with current parameters
11
53
  const parseResult = schema.safeParse(providedParams);
12
54
  // Get all schema parameters to check which ones have resolvers
13
55
  const allParams = this.extractParametersFromSchema(schema);
14
- const resolvableParams = allParams.filter((param) => hasResolver(param.name));
56
+ const resolvableParams = allParams.filter((param) => this.hasResolver(param.name, sdk, functionName));
15
57
  // Get all missing parameters that have resolvers
16
58
  const missingResolvable = resolvableParams.filter((param) => {
17
59
  const hasValue = this.getNestedValue(providedParams, param.path) !== undefined;
@@ -61,10 +103,13 @@ export class SchemaParameterResolver {
61
103
  sdk,
62
104
  currentParams: providedParams,
63
105
  resolvedParams,
106
+ functionName,
64
107
  };
108
+ // Get local resolvers for this function
109
+ const localResolvers = this.getLocalResolvers(sdk, functionName);
65
110
  if (functionallyRequired.length > 0) {
66
111
  const requiredParamNames = functionallyRequired.map((p) => p.name);
67
- const requiredResolutionOrder = getResolutionOrderForParams(requiredParamNames);
112
+ const requiredResolutionOrder = getLocalResolutionOrderForParams(requiredParamNames, localResolvers);
68
113
  // Find all parameters that need to be resolved (including dependencies)
69
114
  // from the available resolvable parameters
70
115
  const orderedRequiredParams = requiredResolutionOrder
@@ -84,7 +129,7 @@ export class SchemaParameterResolver {
84
129
  .filter((param) => param !== undefined);
85
130
  for (const param of orderedRequiredParams) {
86
131
  try {
87
- const value = await this.resolveParameter(param, context);
132
+ const value = await this.resolveParameter(param, context, functionName);
88
133
  this.setNestedValue(resolvedParams, param.path, value);
89
134
  // Update context with newly resolved value
90
135
  context.resolvedParams = resolvedParams;
@@ -105,13 +150,13 @@ export class SchemaParameterResolver {
105
150
  // 3. Resolve parameters that should always be prompted for (but can be skipped)
106
151
  if (alwaysPrompt.length > 0) {
107
152
  const alwaysPromptNames = alwaysPrompt.map((p) => p.name);
108
- const alwaysPromptResolutionOrder = getResolutionOrderForParams(alwaysPromptNames);
153
+ const alwaysPromptResolutionOrder = getLocalResolutionOrderForParams(alwaysPromptNames, localResolvers);
109
154
  const orderedAlwaysPromptParams = alwaysPromptResolutionOrder
110
155
  .map((paramName) => alwaysPrompt.find((p) => p.name === paramName))
111
156
  .filter((param) => param !== undefined);
112
157
  for (const param of orderedAlwaysPromptParams) {
113
158
  try {
114
- const value = await this.resolveParameter(param, context);
159
+ const value = await this.resolveParameter(param, context, functionName);
115
160
  this.setNestedValue(resolvedParams, param.path, value);
116
161
  // Update context with newly resolved value
117
162
  context.resolvedParams = resolvedParams;
@@ -139,13 +184,13 @@ export class SchemaParameterResolver {
139
184
  if (shouldResolveOptional.resolveOptional) {
140
185
  // Resolve optional parameters using their resolvers
141
186
  const optionalParamNames = trulyOptional.map((p) => p.name);
142
- const optionalResolutionOrder = getResolutionOrderForParams(optionalParamNames);
187
+ const optionalResolutionOrder = getLocalResolutionOrderForParams(optionalParamNames, localResolvers);
143
188
  const orderedOptionalParams = optionalResolutionOrder
144
189
  .map((paramName) => trulyOptional.find((p) => p.name === paramName))
145
190
  .filter((param) => param !== undefined);
146
191
  for (const param of orderedOptionalParams) {
147
192
  try {
148
- const value = await this.resolveParameter(param, context);
193
+ const value = await this.resolveParameter(param, context, functionName);
149
194
  this.setNestedValue(resolvedParams, param.path, value);
150
195
  // Update context with newly resolved value
151
196
  context.resolvedParams = resolvedParams;
@@ -208,8 +253,8 @@ export class SchemaParameterResolver {
208
253
  isRequired,
209
254
  };
210
255
  }
211
- async resolveParameter(param, context) {
212
- const resolver = getResolver(param.name);
256
+ async resolveParameter(param, context, functionName) {
257
+ const resolver = this.getResolver(param.name, context.sdk, functionName);
213
258
  if (!resolver) {
214
259
  throw new Error(`No resolver found for parameter: ${param.name}`);
215
260
  }
@@ -285,8 +330,8 @@ export class SchemaParameterResolver {
285
330
  break;
286
331
  }
287
332
  // Separate new required and optional fields
288
- const newRequiredFields = newFields.filter((field) => field.required);
289
- const newOptionalFields = newFields.filter((field) => !field.required);
333
+ const newRequiredFields = newFields.filter((field) => field.is_required);
334
+ const newOptionalFields = newFields.filter((field) => !field.is_required);
290
335
  // Prompt for new required fields
291
336
  if (newRequiredFields.length > 0) {
292
337
  console.log(chalk.blue(`\nšŸ“ Please provide values for the following ${iteration === 1 ? "" : "additional "}input fields:`));
@@ -358,7 +403,7 @@ export class SchemaParameterResolver {
358
403
  const fieldPrompt = {
359
404
  type: fieldObj.type === "boolean" ? "confirm" : "input",
360
405
  name: fieldObj.key,
361
- message: `${fieldObj.label || fieldObj.key}${fieldObj.required ? " (required)" : " (optional)"}:`,
406
+ message: `${fieldObj.label || fieldObj.key}${fieldObj.is_required ? " (required)" : " (optional)"}:`,
362
407
  };
363
408
  if (fieldObj.helpText) {
364
409
  fieldPrompt.prefix = chalk.gray(`ℹ ${fieldObj.helpText}\n`);
@@ -381,7 +426,7 @@ export class SchemaParameterResolver {
381
426
  if (answer[fieldObj.key] !== undefined && answer[fieldObj.key] !== "") {
382
427
  inputs[fieldObj.key] = answer[fieldObj.key];
383
428
  }
384
- else if (fieldObj.required) {
429
+ else if (fieldObj.is_required) {
385
430
  throw new Error(`Required field ${fieldObj.key} cannot be empty`);
386
431
  }
387
432
  }
@@ -399,4 +444,36 @@ export class SchemaParameterResolver {
399
444
  errorObj?.message?.includes("User force closed") ||
400
445
  errorObj?.isTTYError === true);
401
446
  }
447
+ hasResolver(paramName, sdk, functionName) {
448
+ // Check plugin-specific resolvers first
449
+ if (functionName && typeof sdk.getRegistry === "function") {
450
+ const registry = sdk.getRegistry();
451
+ const functionInfo = registry.functions.find((f) => f.name === functionName);
452
+ if (functionInfo && functionInfo.resolvers?.[paramName]) {
453
+ return true;
454
+ }
455
+ }
456
+ // No global registry fallback
457
+ return false;
458
+ }
459
+ getResolver(paramName, sdk, functionName) {
460
+ // Check plugin-specific resolvers first
461
+ if (functionName && typeof sdk.getRegistry === "function") {
462
+ const registry = sdk.getRegistry();
463
+ const functionInfo = registry.functions.find((f) => f.name === functionName);
464
+ if (functionInfo && functionInfo.resolvers?.[paramName]) {
465
+ return functionInfo.resolvers[paramName];
466
+ }
467
+ }
468
+ // No global registry fallback
469
+ return null;
470
+ }
471
+ getLocalResolvers(sdk, functionName) {
472
+ if (!functionName || typeof sdk.getRegistry !== "function") {
473
+ return {};
474
+ }
475
+ const registry = sdk.getRegistry();
476
+ const functionInfo = registry.functions.find((f) => f.name === functionName);
477
+ return functionInfo?.resolvers || {};
478
+ }
402
479
  }
@@ -1,2 +1,6 @@
1
1
  import type { z } from "zod";
2
- export declare function formatItemsFromSchema(inputSchema: z.ZodType, items: unknown[], startingNumber?: number): void;
2
+ export declare function formatJsonOutput(data: unknown): void;
3
+ export declare function formatItemsFromSchema(functionInfo: {
4
+ inputSchema: z.ZodType;
5
+ outputSchema?: z.ZodType;
6
+ }, items: unknown[], startingNumber?: number): void;