@zapier/zapier-sdk-cli 0.5.0 → 0.6.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.
@@ -108,12 +108,13 @@ function methodNameToCliCommand(methodName) {
108
108
  // ============================================================================
109
109
  export function generateCliCommands(program, sdk) {
110
110
  // Check if SDK has registry
111
- if (!sdk.__registry) {
111
+ if (typeof sdk.getRegistry !== "function") {
112
112
  console.error("SDK registry not available");
113
113
  return;
114
114
  }
115
- // Generate one flat command for each function in the registry
116
- sdk.__registry.forEach((fnInfo) => {
115
+ const registry = sdk.getRegistry();
116
+ // Create all commands first
117
+ registry.functions.forEach((fnInfo) => {
117
118
  if (!fnInfo.inputSchema) {
118
119
  console.warn(`Schema not found for ${fnInfo.name}`);
119
120
  return;
@@ -123,6 +124,57 @@ export function generateCliCommands(program, sdk) {
123
124
  const config = createCommandConfig(cliCommandName, fnInfo.name, fnInfo.inputSchema, sdk);
124
125
  addCommand(program, cliCommandName, config);
125
126
  });
127
+ // Override the help display to show commands grouped by category
128
+ program.configureHelp({
129
+ formatHelp: (cmd, helper) => {
130
+ const helpWidth = helper.helpWidth || 80;
131
+ let output = helper.commandUsage(cmd) + "\n";
132
+ if (cmd.description()) {
133
+ output += helper.wrap(cmd.description(), helpWidth, 0) + "\n";
134
+ }
135
+ // Add options section
136
+ const options = helper.visibleOptions(cmd);
137
+ if (options.length > 0) {
138
+ output += "\nOptions:\n";
139
+ const longestOptionLength = Math.max(...options.map((opt) => helper.optionTerm(opt).length));
140
+ options.forEach((option) => {
141
+ const term = helper.optionTerm(option);
142
+ const padding = " ".repeat(Math.max(2, longestOptionLength - term.length + 4));
143
+ output += ` ${term}${padding}${helper.optionDescription(option)}\n`;
144
+ });
145
+ }
146
+ // Add categorized commands section
147
+ const commands = helper.visibleCommands(cmd);
148
+ if (commands.length > 0) {
149
+ output += "\nCommands:\n";
150
+ // Collect all SDK commands that belong to categories
151
+ const categorizedCommands = new Set();
152
+ // Group SDK commands by categories
153
+ registry.categories.forEach((category) => {
154
+ const categoryCommands = commands.filter((command) => category.functions.some((functionName) => {
155
+ const cliCommandName = methodNameToCliCommand(functionName);
156
+ return command.name() === cliCommandName;
157
+ }));
158
+ if (categoryCommands.length > 0) {
159
+ output += `\n ${category.titlePlural}:\n`;
160
+ categoryCommands.forEach((command) => {
161
+ output += ` ${helper.subcommandTerm(command)}\n`;
162
+ categorizedCommands.add(command.name());
163
+ });
164
+ }
165
+ });
166
+ // Add any remaining commands that aren't part of SDK categories
167
+ const otherCommands = commands.filter((command) => !categorizedCommands.has(command.name()));
168
+ if (otherCommands.length > 0) {
169
+ output += `\n Other:\n`;
170
+ otherCommands.forEach((command) => {
171
+ output += ` ${helper.subcommandTerm(command)}\n`;
172
+ });
173
+ }
174
+ }
175
+ return output;
176
+ },
177
+ });
126
178
  }
127
179
  function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
128
180
  const parameters = analyzeZodSchema(schema);
@@ -214,28 +214,31 @@ export class SchemaParameterResolver {
214
214
  throw new Error(`No resolver found for parameter: ${param.name}`);
215
215
  }
216
216
  console.log(chalk.blue(`\nšŸ” Resolving ${param.name}...`));
217
- if (resolver.type === "static") {
217
+ const typedResolver = resolver;
218
+ if (typedResolver.type === "static") {
218
219
  // Static resolver - just prompt for input
219
220
  const promptConfig = {
220
- type: resolver.inputType === "password" ? "password" : "input",
221
+ type: typedResolver.inputType === "password" ? "password" : "input",
221
222
  name: param.name,
222
223
  message: `Enter ${param.name}:`,
223
- ...(resolver.placeholder && { default: resolver.placeholder }),
224
+ ...(typedResolver.placeholder && {
225
+ default: typedResolver.placeholder,
226
+ }),
224
227
  };
225
228
  const answers = await inquirer.prompt([promptConfig]);
226
229
  return answers[param.name];
227
230
  }
228
- else if (resolver.type === "dynamic") {
231
+ else if (typedResolver.type === "dynamic") {
229
232
  // Dynamic resolver - fetch options and prompt for selection
230
233
  try {
231
234
  // Only show "Fetching..." for required parameters that typically have many options
232
235
  if (param.isRequired && param.name !== "authenticationId") {
233
236
  console.log(chalk.gray(`Fetching options for ${param.name}...`));
234
237
  }
235
- const items = await resolver.fetch(context.sdk, context.resolvedParams);
238
+ const items = await typedResolver.fetch(context.sdk, context.resolvedParams);
236
239
  // Let the resolver's prompt handle empty lists (e.g., authenticationId can show "skip authentication")
237
240
  const safeItems = items || [];
238
- const promptConfig = resolver.prompt(safeItems, context.resolvedParams);
241
+ const promptConfig = typedResolver.prompt(safeItems, context.resolvedParams);
239
242
  const answers = await inquirer.prompt([promptConfig]);
240
243
  return answers[param.name];
241
244
  }
@@ -244,13 +247,14 @@ export class SchemaParameterResolver {
244
247
  throw error;
245
248
  }
246
249
  }
247
- else if (resolver.type === "fields") {
250
+ else if (typedResolver.type === "fields") {
248
251
  // Fields resolver - fetch field definitions and prompt for each input with recursive field resolution
249
252
  return await this.resolveFieldsRecursively(resolver, context, param);
250
253
  }
251
254
  throw new Error(`Unknown resolver type for ${param.name}`);
252
255
  }
253
256
  async resolveFieldsRecursively(resolver, context, param) {
257
+ const typedResolver = resolver;
254
258
  const inputs = {};
255
259
  let processedFieldKeys = new Set();
256
260
  let iteration = 0;
@@ -266,7 +270,7 @@ export class SchemaParameterResolver {
266
270
  },
267
271
  };
268
272
  console.log(chalk.gray(`Fetching input fields for ${param.name}${iteration > 1 ? ` (iteration ${iteration})` : ""}...`));
269
- const fields = await resolver.fetch(updatedContext.sdk, updatedContext.resolvedParams);
273
+ const fields = await typedResolver.fetch(updatedContext.sdk, updatedContext.resolvedParams);
270
274
  if (!fields || fields.length === 0) {
271
275
  if (iteration === 1) {
272
276
  console.log(chalk.yellow(`No input fields required for this action.`));
@@ -1,2 +1,2 @@
1
1
  import { z } from "zod";
2
- export declare function formatItemsFromSchema(inputSchema: z.ZodType, items: any[]): void;
2
+ export declare function formatItemsFromSchema(inputSchema: z.ZodType, items: unknown[]): void;
@@ -1,6 +1,7 @@
1
1
  import chalk from "chalk";
2
2
  function getFormatMetadata(schema) {
3
- return schema?._def?.formatMeta;
3
+ return schema?._def
4
+ ?.formatMeta;
4
5
  }
5
6
  function getOutputSchema(schema) {
6
7
  return schema?._def?.outputSchema;
@@ -61,10 +62,11 @@ function applyStyle(value, style) {
61
62
  function formatItemsGeneric(items) {
62
63
  // Fallback formatting for items without schema metadata
63
64
  items.forEach((item, index) => {
64
- const name = item.title || item.name || item.key || item.id || "Item";
65
+ const itemObj = item;
66
+ const name = itemObj.title || itemObj.name || itemObj.key || itemObj.id || "Item";
65
67
  console.log(`${chalk.gray(`${index + 1}.`)} ${chalk.cyan(name)}`);
66
- if (item.description) {
67
- console.log(` ${chalk.dim(item.description)}`);
68
+ if (itemObj.description) {
69
+ console.log(` ${chalk.dim(itemObj.description)}`);
68
70
  }
69
71
  console.log();
70
72
  });