@zapier/zapier-sdk-cli 0.0.3 → 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.
package/dist/cli.js CHANGED
@@ -14,12 +14,10 @@ program
14
14
  const isDebugMode = process.env.DEBUG === "true" || process.argv.includes("--debug");
15
15
  // Create SDK instance for CLI operations
16
16
  // Auth will be resolved from environment variables or command options
17
- const sdk = (0, zapier_sdk_1.createActionsSdk)({
17
+ const sdk = (0, zapier_sdk_1.createZapierSdk)({
18
18
  // Token will be picked up from ZAPIER_TOKEN env var or provided via options
19
19
  debug: isDebugMode,
20
20
  });
21
21
  // Generate CLI commands from SDK schemas
22
22
  (0, cli_generator_1.generateCliCommands)(program, sdk);
23
- // Add enhanced help information
24
- (0, cli_generator_1.enhanceCommandHelp)(program);
25
23
  program.parse();
@@ -1,4 +1,3 @@
1
1
  import { Command } from "commander";
2
- import { ActionsSdk } from "@zapier/zapier-sdk";
3
- export declare function generateCliCommands(program: Command, sdk: ActionsSdk): void;
4
- export declare function enhanceCommandHelp(program: Command): void;
2
+ import { ZapierSdk } from "@zapier/zapier-sdk";
3
+ export declare function generateCliCommands(program: Command, sdk: ZapierSdk): void;
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.generateCliCommands = generateCliCommands;
7
- exports.enhanceCommandHelp = enhanceCommandHelp;
8
7
  const zod_1 = require("zod");
9
8
  const zapier_sdk_1 = require("@zapier/zapier-sdk");
10
9
  const parameter_resolver_1 = require("./parameter-resolver");
@@ -80,7 +79,6 @@ function analyzeZodField(name, schema) {
80
79
  paramType = "string";
81
80
  }
82
81
  // Extract resolver metadata
83
- const resolverMeta = schema._def.resolverMeta;
84
82
  return {
85
83
  name,
86
84
  type: paramType,
@@ -88,81 +86,75 @@ function analyzeZodField(name, schema) {
88
86
  description: schema.description,
89
87
  default: defaultValue,
90
88
  choices,
91
- resolverMeta,
89
+ hasResolver: (0, zapier_sdk_1.hasResolver)(name),
92
90
  };
93
91
  }
94
92
  // ============================================================================
95
- // CLI Command Generation
93
+ // CLI Structure Derivation - Purely Generic
94
+ // ============================================================================
95
+ /**
96
+ * Convert camelCase to kebab-case
97
+ * e.g., listApps -> list-apps, generateTypes -> generate-types
98
+ */
99
+ function toKebabCase(str) {
100
+ return str.replace(/([A-Z])/g, "-$1").toLowerCase();
101
+ }
102
+ /**
103
+ * Convert SDK method name directly to CLI command
104
+ * e.g., listApps -> list-apps, getApp -> get-app, generateTypes -> generate-types
105
+ */
106
+ function methodNameToCliCommand(methodName) {
107
+ return toKebabCase(methodName);
108
+ }
109
+ // ============================================================================
110
+ // CLI Command Generation - Completely Generic
96
111
  // ============================================================================
97
112
  function generateCliCommands(program, sdk) {
98
- // Check if SdkSchemas is available
99
- if (!zapier_sdk_1.SdkSchemas) {
100
- console.error("SdkSchemas not available");
113
+ // Check if SDK has registry
114
+ if (!sdk.__registry) {
115
+ console.error("SDK registry not available");
101
116
  return;
102
117
  }
103
- // Generate namespace commands (apps, actions, auths, fields)
104
- Object.entries(zapier_sdk_1.SdkSchemas).forEach(([namespace, methods]) => {
105
- if (namespace === "generate" || namespace === "bundle") {
106
- // Handle root tools separately
118
+ // Generate one flat command for each function in the registry
119
+ sdk.__registry.forEach((fnInfo) => {
120
+ if (!fnInfo.inputSchema) {
121
+ console.warn(`Schema not found for ${fnInfo.name}`);
107
122
  return;
108
123
  }
109
- const namespaceCommand = program
110
- .command(namespace)
111
- .description(`${namespace} management commands`);
112
- if (typeof methods === "object" && methods !== null) {
113
- Object.entries(methods).forEach(([method, schema]) => {
114
- const config = createCommandConfig(namespace, method, schema, sdk);
115
- addSubCommand(namespaceCommand, method, config);
116
- });
117
- }
124
+ // Convert methodName to kebab-case CLI command
125
+ const cliCommandName = methodNameToCliCommand(fnInfo.name);
126
+ const config = createCommandConfig(cliCommandName, fnInfo.name, fnInfo.inputSchema, sdk);
127
+ addCommand(program, cliCommandName, config);
118
128
  });
119
- // Generate root tool commands
120
- if (zapier_sdk_1.SdkSchemas.generate) {
121
- const generateConfig = createCommandConfig("", "generate", zapier_sdk_1.SdkSchemas.generate, sdk);
122
- addSubCommand(program, "generate", generateConfig);
123
- }
124
- if (zapier_sdk_1.SdkSchemas.bundle) {
125
- const bundleConfig = createCommandConfig("", "bundle", zapier_sdk_1.SdkSchemas.bundle, sdk);
126
- addSubCommand(program, "bundle", bundleConfig);
127
- }
128
129
  }
129
- function createCommandConfig(namespace, method, schema, sdk) {
130
+ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
130
131
  const parameters = analyzeZodSchema(schema);
131
- const description = schema.description || `${namespace} ${method} command`;
132
+ const description = schema.description || `${cliCommandName} command`;
132
133
  const handler = async (...args) => {
133
134
  try {
134
135
  // The last argument is always the command object with parsed options
135
- const command = args[args.length - 1];
136
- const options = command.opts();
137
- // Check if this is a list command with pagination support
138
- const isListCommand = method === "list";
136
+ const commandObj = args[args.length - 1];
137
+ const options = commandObj.opts();
138
+ // Check if this is a list command for pagination
139
+ const isListCommand = cliCommandName.startsWith("list-");
139
140
  const hasPaginationParams = parameters.some((p) => p.name === "limit" || p.name === "offset");
140
141
  const hasUserSpecifiedLimit = "limit" in options && options.limit !== undefined;
141
142
  const shouldUsePaging = isListCommand && hasPaginationParams && !hasUserSpecifiedLimit;
142
143
  const shouldUseJson = options.json;
143
144
  // Convert CLI args to SDK method parameters
144
145
  const rawParams = convertCliArgsToSdkParams(parameters, args.slice(0, -1), options);
145
- // NEW: Resolve missing parameters interactively using schema metadata
146
+ // Resolve missing parameters interactively using schema metadata
146
147
  const resolver = new parameter_resolver_1.SchemaParameterResolver();
147
148
  const resolvedParams = await resolver.resolveParameters(schema, rawParams, sdk);
148
149
  if (shouldUsePaging && !shouldUseJson) {
149
150
  // Use interactive paging for list commands
150
- await handlePaginatedList(namespace, method, resolvedParams, sdk);
151
+ await handlePaginatedList(sdkMethodName, resolvedParams, sdk, schema);
151
152
  }
152
153
  else {
153
- // Call the appropriate SDK method with complete, validated parameters
154
- let result;
155
- if (namespace === "") {
156
- // Root tool (generate, bundle)
157
- result = await sdk[method](resolvedParams);
158
- }
159
- else {
160
- // Regular namespace method
161
- result = await sdk[namespace][method](resolvedParams);
162
- }
163
- // Special handling for generate and bundle commands - don't output to console if writing to file
164
- const isRootCommandWithOutput = namespace === "" && (method === "generate" || method === "bundle");
165
- const hasOutputFile = isRootCommandWithOutput && resolvedParams.output;
154
+ // Call the SDK method directly
155
+ const result = await sdk[sdkMethodName](resolvedParams);
156
+ // Special handling for commands that write to files
157
+ const hasOutputFile = resolvedParams.output;
166
158
  // Output result (JSON or formatted)
167
159
  if (!hasOutputFile && (shouldUseJson || !isListCommand)) {
168
160
  // Use raw JSON if --json flag is specified, otherwise use pretty formatting
@@ -175,17 +167,34 @@ function createCommandConfig(namespace, method, schema, sdk) {
175
167
  }
176
168
  else if (!hasOutputFile) {
177
169
  // Format list results nicely (non-paginated)
178
- formatNonPaginatedResults(namespace, result, resolvedParams.limit, hasUserSpecifiedLimit, shouldUseJson);
170
+ formatNonPaginatedResults(result, resolvedParams.limit, hasUserSpecifiedLimit, shouldUseJson, schema, sdkMethodName);
179
171
  }
180
172
  else if (hasOutputFile) {
181
173
  // Show success message for file output instead of printing generated content
182
- console.log(chalk_1.default.green(`āœ… ${method} completed successfully!`));
174
+ console.log(chalk_1.default.green(`āœ… ${cliCommandName} completed successfully!`));
183
175
  console.log(chalk_1.default.gray(`Output written to: ${resolvedParams.output}`));
184
176
  }
185
177
  }
186
178
  }
187
179
  catch (error) {
188
- console.error("Error:", error instanceof Error ? error.message : "Unknown error");
180
+ // Handle Zod validation errors more gracefully
181
+ if (error instanceof Error && error.message.includes('"code"')) {
182
+ try {
183
+ const validationErrors = JSON.parse(error.message);
184
+ console.error(chalk_1.default.red("āŒ Validation Error:"));
185
+ validationErrors.forEach((err) => {
186
+ const field = err.path?.join(".") || "unknown";
187
+ console.error(chalk_1.default.yellow(` • ${field}: ${err.message}`));
188
+ });
189
+ console.error("\n" + chalk_1.default.dim(`Use --help to see available options`));
190
+ }
191
+ catch {
192
+ console.error(chalk_1.default.red("Error:"), error.message);
193
+ }
194
+ }
195
+ else {
196
+ console.error(chalk_1.default.red("Error:"), error instanceof Error ? error.message : "Unknown error");
197
+ }
189
198
  process.exit(1);
190
199
  }
191
200
  };
@@ -195,23 +204,23 @@ function createCommandConfig(namespace, method, schema, sdk) {
195
204
  handler,
196
205
  };
197
206
  }
198
- function addSubCommand(parentCommand, name, config) {
199
- const command = parentCommand.command(name).description(config.description);
207
+ function addCommand(program, commandName, config) {
208
+ const command = program.command(commandName).description(config.description);
200
209
  // Add parameters to command
201
210
  config.parameters.forEach((param) => {
202
- if (param.resolverMeta?.resolver && param.required) {
211
+ // Convert camelCase to kebab-case for CLI display
212
+ const kebabName = param.name.replace(/([A-Z])/g, "-$1").toLowerCase();
213
+ if (param.hasResolver && param.required) {
203
214
  // Required parameters with resolvers become optional positional arguments (resolver handles prompting)
204
- command.argument(`[${param.name}]`, param.description || `${param.name} parameter`);
215
+ command.argument(`[${kebabName}]`, param.description || `${kebabName} parameter`);
205
216
  }
206
217
  else if (param.required) {
207
218
  // Required parameters without resolvers become required positional arguments
208
- command.argument(`<${param.name}>`, param.description || `${param.name} parameter`);
219
+ command.argument(`<${kebabName}>`, param.description || `${kebabName} parameter`);
209
220
  }
210
221
  else {
211
222
  // Optional parameters become flags (whether they have resolvers or not)
212
- const flags = [
213
- `--${param.name.replace(/([A-Z])/g, "-$1").toLowerCase()}`,
214
- ];
223
+ const flags = [`--${kebabName}`];
215
224
  if (param.type === "boolean") {
216
225
  command.option(flags.join(", "), param.description);
217
226
  }
@@ -234,6 +243,7 @@ function convertCliArgsToSdkParams(parameters, positionalArgs, options) {
234
243
  let argIndex = 0;
235
244
  parameters.forEach((param) => {
236
245
  if (param.required && argIndex < positionalArgs.length) {
246
+ // Use the original camelCase parameter name for the SDK
237
247
  sdkParams[param.name] = convertValue(positionalArgs[argIndex], param.type);
238
248
  argIndex++;
239
249
  }
@@ -275,9 +285,9 @@ function convertValue(value, type) {
275
285
  // ============================================================================
276
286
  // Pagination Handlers
277
287
  // ============================================================================
278
- async function handlePaginatedList(namespace, method, baseParams, sdk) {
288
+ async function handlePaginatedList(sdkMethodName, baseParams, sdk, schema) {
279
289
  const limit = baseParams.limit || 20;
280
- const itemName = getItemName(namespace);
290
+ const itemName = getItemNameFromMethod(sdkMethodName);
281
291
  console.log(chalk_1.default.blue(`šŸ“‹ Fetching ${itemName}...`));
282
292
  const pager = (0, pager_1.createPager)({
283
293
  pageSize: Math.min(limit, 20),
@@ -288,18 +298,14 @@ async function handlePaginatedList(namespace, method, baseParams, sdk) {
288
298
  if (items.length > 0) {
289
299
  console.clear();
290
300
  }
291
- console.log(chalk_1.default.blue(`šŸ“‹ ${getListTitle(namespace)}\n`));
301
+ console.log(chalk_1.default.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName)}\n`));
292
302
  if (items.length === 0) {
293
303
  console.log(chalk_1.default.yellow(`No ${itemName} found.`));
294
304
  return;
295
305
  }
296
- // Get the schema for this namespace/method to extract formatting info
297
- const schema = zapier_sdk_1.SdkSchemas[namespace];
298
- const listSchema = schema && typeof schema === "object" && "list" in schema
299
- ? schema.list
300
- : null;
301
- if (listSchema) {
302
- (0, schema_formatter_1.formatItemsFromSchema)(listSchema, items);
306
+ // Use schema for formatting
307
+ if (schema) {
308
+ (0, schema_formatter_1.formatItemsFromSchema)(schema, items);
303
309
  }
304
310
  else {
305
311
  // Fallback to generic formatting
@@ -310,12 +316,12 @@ async function handlePaginatedList(namespace, method, baseParams, sdk) {
310
316
  : "";
311
317
  console.log(chalk_1.default.green(`\nāœ… Showing ${totalShown}${totalInfo} ${itemName}`));
312
318
  };
313
- await pager.paginate((params) => sdk[namespace][method]({
319
+ await pager.paginate((params) => sdk[sdkMethodName]({
314
320
  ...baseParams,
315
321
  ...params,
316
322
  }), {}, displayFunction);
317
323
  }
318
- function formatNonPaginatedResults(namespace, result, requestedLimit, userSpecifiedLimit, useRawJson) {
324
+ function formatNonPaginatedResults(result, requestedLimit, userSpecifiedLimit, useRawJson, schema, methodName) {
319
325
  if (!Array.isArray(result)) {
320
326
  if (useRawJson) {
321
327
  console.log(JSON.stringify(result, null, 2));
@@ -329,19 +335,15 @@ function formatNonPaginatedResults(namespace, result, requestedLimit, userSpecif
329
335
  console.log(JSON.stringify(result, null, 2));
330
336
  return;
331
337
  }
332
- const itemName = getItemName(namespace);
338
+ const itemName = methodName ? getItemNameFromMethod(methodName) : "items";
333
339
  if (result.length === 0) {
334
340
  console.log(chalk_1.default.yellow(`No ${itemName} found.`));
335
341
  return;
336
342
  }
337
343
  console.log(chalk_1.default.green(`\nāœ… Found ${result.length} ${itemName}:\n`));
338
- // Get the schema for this namespace/method to extract formatting info
339
- const schema = zapier_sdk_1.SdkSchemas[namespace];
340
- const listSchema = schema && typeof schema === "object" && "list" in schema
341
- ? schema.list
342
- : null;
343
- if (listSchema) {
344
- (0, schema_formatter_1.formatItemsFromSchema)(listSchema, result);
344
+ // Use schema for formatting
345
+ if (schema) {
346
+ (0, schema_formatter_1.formatItemsFromSchema)(schema, result);
345
347
  }
346
348
  else {
347
349
  // Fallback to generic formatting
@@ -366,49 +368,21 @@ function formatItemsGeneric(items) {
366
368
  console.log();
367
369
  });
368
370
  }
369
- function getItemName(namespace) {
370
- switch (namespace) {
371
- case "apps":
372
- return "apps";
373
- case "actions":
374
- return "actions";
375
- case "auths":
376
- return "authentications";
377
- case "fields":
378
- return "fields";
379
- default:
380
- return "items";
371
+ // Generic helper functions that infer from schema description or method name
372
+ function getItemNameFromMethod(methodName) {
373
+ // Extract from method name: listApps -> apps, listActions -> actions
374
+ const listMatch = methodName.match(/^list(.+)$/);
375
+ if (listMatch) {
376
+ return listMatch[1].toLowerCase();
381
377
  }
378
+ // Fallback to generic
379
+ return "items";
382
380
  }
383
- function getListTitle(namespace) {
384
- switch (namespace) {
385
- case "apps":
386
- return "Available Apps";
387
- case "actions":
388
- return "Available Actions";
389
- case "auths":
390
- return "Available Authentications";
391
- case "fields":
392
- return "Available Fields";
393
- default:
394
- return "Available Items";
395
- }
396
- }
397
- // ============================================================================
398
- // Help Text Enhancement
399
- // ============================================================================
400
- function enhanceCommandHelp(program) {
401
- // Add custom help that shows schema-driven nature
402
- program.on("--help", () => {
403
- console.log("");
404
- console.log("Commands are automatically generated from SDK schemas.");
405
- console.log("Each command maps directly to an SDK method with the same parameters.");
406
- console.log("");
407
- console.log("Examples:");
408
- console.log(" zapier-sdk apps list --category=productivity --limit=10");
409
- console.log(' zapier-sdk actions run slack search user_by_email --inputs=\'{"email":"user@example.com"}\'');
410
- console.log(" zapier-sdk generate my-app --output=./generated/");
411
- console.log(" zsdk apps list --limit=5 # Using the shorter alias");
412
- console.log("");
413
- });
381
+ function getListTitleFromMethod(methodName) {
382
+ const itemName = getItemNameFromMethod(methodName);
383
+ if (itemName === "items")
384
+ return "Available Items";
385
+ // Capitalize first letter: apps -> Apps
386
+ const capitalized = itemName.charAt(0).toUpperCase() + itemName.slice(1);
387
+ return `Available ${capitalized}`;
414
388
  }
@@ -1,18 +1,13 @@
1
1
  import { z } from "zod";
2
- import { ActionsSdk } from "@zapier/zapier-sdk";
2
+ import { ZapierSdk } from "@zapier/zapier-sdk";
3
3
  export declare class SchemaParameterResolver {
4
- resolveParameters(schema: z.ZodSchema, providedParams: any, sdk: ActionsSdk): Promise<any>;
5
- private findAllResolvableParameters;
6
- private findResolvableParameters;
7
- private analyzeSchema;
8
- private analyzeSchemaField;
9
- private sortByDependencies;
4
+ resolveParameters(schema: z.ZodSchema, providedParams: any, sdk: ZapierSdk): Promise<any>;
5
+ private extractParametersFromSchema;
6
+ private analyzeFieldSchema;
7
+ private createResolvableParameter;
10
8
  private resolveParameter;
11
- private promptStaticInput;
12
- private resolveDynamicParameter;
13
- private resolveFieldsParameter;
14
- private promptForField;
15
9
  private getNestedValue;
16
10
  private setNestedValue;
11
+ private promptForField;
17
12
  private isUserCancellation;
18
13
  }