@zapier/zapier-sdk-cli 0.4.0 → 0.4.2

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 (70) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cli.js +961 -284
  3. package/dist/src/cli.d.ts +2 -0
  4. package/dist/src/cli.js +28 -0
  5. package/dist/src/commands/bundle-code/cli.d.ts +2 -0
  6. package/dist/src/commands/bundle-code/cli.js +77 -0
  7. package/dist/src/commands/bundle-code/index.d.ts +5 -0
  8. package/dist/src/commands/bundle-code/index.js +62 -0
  9. package/dist/src/commands/bundle-code/schemas.d.ts +24 -0
  10. package/dist/src/commands/bundle-code/schemas.js +19 -0
  11. package/dist/src/commands/configPath.d.ts +2 -0
  12. package/dist/src/commands/configPath.js +9 -0
  13. package/dist/src/commands/generate-types/cli.d.ts +2 -0
  14. package/dist/src/commands/generate-types/cli.js +73 -0
  15. package/dist/src/commands/generate-types/index.d.ts +8 -0
  16. package/dist/src/commands/generate-types/index.js +273 -0
  17. package/dist/src/commands/generate-types/schemas.d.ts +18 -0
  18. package/dist/src/commands/generate-types/schemas.js +11 -0
  19. package/dist/src/commands/index.d.ts +6 -0
  20. package/dist/src/commands/index.js +6 -0
  21. package/dist/src/commands/login.d.ts +2 -0
  22. package/dist/src/commands/login.js +25 -0
  23. package/dist/src/commands/logout.d.ts +2 -0
  24. package/dist/src/commands/logout.js +16 -0
  25. package/dist/src/commands/mcp.d.ts +2 -0
  26. package/dist/src/commands/mcp.js +11 -0
  27. package/dist/src/index.d.ts +0 -0
  28. package/dist/src/index.js +3 -0
  29. package/dist/src/utils/api/client.d.ts +15 -0
  30. package/dist/src/utils/api/client.js +27 -0
  31. package/dist/src/utils/auth/login.d.ts +2 -0
  32. package/dist/src/utils/auth/login.js +134 -0
  33. package/dist/src/utils/cli-generator-utils.d.ts +13 -0
  34. package/dist/src/utils/cli-generator-utils.js +116 -0
  35. package/dist/src/utils/cli-generator.d.ts +3 -0
  36. package/dist/src/utils/cli-generator.js +443 -0
  37. package/dist/src/utils/constants.d.ts +5 -0
  38. package/dist/src/utils/constants.js +6 -0
  39. package/dist/src/utils/getCallablePromise.d.ts +6 -0
  40. package/dist/src/utils/getCallablePromise.js +14 -0
  41. package/dist/src/utils/log.d.ts +7 -0
  42. package/dist/src/utils/log.js +16 -0
  43. package/dist/src/utils/parameter-resolver.d.ts +14 -0
  44. package/dist/src/utils/parameter-resolver.js +387 -0
  45. package/dist/src/utils/schema-formatter.d.ts +2 -0
  46. package/dist/src/utils/schema-formatter.js +71 -0
  47. package/dist/src/utils/serializeAsync.d.ts +2 -0
  48. package/dist/src/utils/serializeAsync.js +16 -0
  49. package/dist/src/utils/spinner.d.ts +1 -0
  50. package/dist/src/utils/spinner.js +13 -0
  51. package/dist/tsconfig.tsbuildinfo +1 -0
  52. package/package.json +5 -3
  53. package/src/cli.test.ts +15 -0
  54. package/src/cli.ts +9 -3
  55. package/src/commands/bundle-code/cli.ts +103 -0
  56. package/src/commands/bundle-code/index.ts +91 -0
  57. package/src/commands/bundle-code/schemas.ts +24 -0
  58. package/src/commands/generate-types/cli.ts +110 -0
  59. package/src/commands/generate-types/index.ts +365 -0
  60. package/src/commands/generate-types/schemas.ts +23 -0
  61. package/src/commands/index.ts +3 -1
  62. package/src/commands/mcp.ts +14 -0
  63. package/src/utils/cli-generator-utils.ts +157 -0
  64. package/src/utils/cli-generator.ts +148 -91
  65. package/src/utils/parameter-resolver.ts +217 -85
  66. package/src/utils/schema-formatter.ts +1 -1
  67. package/tsconfig.json +3 -5
  68. package/src/commands/whoami.ts +0 -25
  69. package/src/utils/pager.ts +0 -202
  70. package/test/cli.test.ts +0 -46
@@ -1,11 +1,17 @@
1
1
  import { Command } from "commander";
2
2
  import { z } from "zod";
3
- import { ZapierSdk, hasResolver, isPositional } from "@zapier/zapier-sdk";
3
+ import {
4
+ ZapierSdk,
5
+ hasResolver,
6
+ isPositional,
7
+ formatErrorMessage,
8
+ ZapierError,
9
+ } from "@zapier/zapier-sdk";
4
10
  import { SchemaParameterResolver } from "./parameter-resolver";
5
- import { createPager } from "./pager";
6
11
  import { formatItemsFromSchema } from "./schema-formatter";
7
12
  import chalk from "chalk";
8
13
  import util from "util";
14
+ import inquirer from "inquirer";
9
15
 
10
16
  // ============================================================================
11
17
  // JSON Formatting
@@ -193,12 +199,10 @@ function createCommandConfig(
193
199
  // Check if this is a list command for pagination
194
200
  const isListCommand = cliCommandName.startsWith("list-");
195
201
  const hasPaginationParams = parameters.some(
196
- (p) => p.name === "limit" || p.name === "offset",
202
+ (p) => p.name === "maxItems" || p.name === "pageSize",
197
203
  );
198
- const hasUserSpecifiedLimit =
199
- "limit" in options && options.limit !== undefined;
200
- const shouldUsePaging =
201
- isListCommand && hasPaginationParams && !hasUserSpecifiedLimit;
204
+ const hasUserSpecifiedMaxItems =
205
+ "maxItems" in options && options.maxItems !== undefined;
202
206
  const shouldUseJson = options.json;
203
207
 
204
208
  // Convert CLI args to SDK method parameters
@@ -216,42 +220,50 @@ function createCommandConfig(
216
220
  sdk,
217
221
  );
218
222
 
219
- if (shouldUsePaging && !shouldUseJson) {
220
- // Use interactive paging for list commands
221
- await handlePaginatedList(sdkMethodName, resolvedParams, sdk, schema);
223
+ // Special handling for commands that write to files
224
+ const hasOutputFile = resolvedParams.output;
225
+ if (hasOutputFile) {
226
+ // Call the SDK method for file output commands
227
+ await (sdk as any)[sdkMethodName](resolvedParams);
228
+ console.log(
229
+ chalk.green(`āœ… ${cliCommandName} completed successfully!`),
230
+ );
231
+ console.log(chalk.gray(`Output written to: ${resolvedParams.output}`));
232
+ return;
233
+ }
234
+
235
+ // Handle paginated list commands with async iteration
236
+ if (
237
+ isListCommand &&
238
+ hasPaginationParams &&
239
+ !shouldUseJson &&
240
+ !hasUserSpecifiedMaxItems
241
+ ) {
242
+ // Get the async iterator directly from the SDK method call
243
+ const sdkIterator = (sdk as any)[sdkMethodName](resolvedParams);
244
+ await handlePaginatedListWithAsyncIteration(
245
+ sdkMethodName,
246
+ sdkIterator,
247
+ schema,
248
+ );
222
249
  } else {
223
- // Call the SDK method directly
224
- const result: any = await (sdk as any)[sdkMethodName](resolvedParams);
225
-
226
- // Special handling for commands that write to files
227
- const hasOutputFile = resolvedParams.output;
228
-
229
- // Output result (JSON or formatted)
230
- if (!hasOutputFile && (shouldUseJson || !isListCommand)) {
231
- // Use raw JSON if --json flag is specified, otherwise use pretty formatting
232
- if (shouldUseJson) {
233
- console.log(JSON.stringify(result, null, 2));
234
- } else {
235
- formatJsonOutput(result);
236
- }
237
- } else if (!hasOutputFile) {
238
- // Format list results nicely (non-paginated)
250
+ // Call the SDK method and handle non-paginated results
251
+ const result = await (sdk as any)[sdkMethodName](resolvedParams);
252
+ const items = result?.data ? result.data : result;
253
+
254
+ if (shouldUseJson) {
255
+ console.log(JSON.stringify(items, null, 2));
256
+ } else if (isListCommand) {
239
257
  formatNonPaginatedResults(
240
- result,
241
- resolvedParams.limit,
242
- hasUserSpecifiedLimit,
258
+ items,
259
+ resolvedParams.maxItems,
260
+ hasUserSpecifiedMaxItems,
243
261
  shouldUseJson,
244
262
  schema,
245
263
  sdkMethodName,
246
264
  );
247
- } else if (hasOutputFile) {
248
- // Show success message for file output instead of printing generated content
249
- console.log(
250
- chalk.green(`āœ… ${cliCommandName} completed successfully!`),
251
- );
252
- console.log(
253
- chalk.gray(`Output written to: ${resolvedParams.output}`),
254
- );
265
+ } else {
266
+ formatJsonOutput(items);
255
267
  }
256
268
  }
257
269
  } catch (error) {
@@ -270,11 +282,15 @@ function createCommandConfig(
270
282
  } catch {
271
283
  console.error(chalk.red("Error:"), error.message);
272
284
  }
285
+ } else if (error instanceof ZapierError) {
286
+ // Handle SDK errors with clean, user-friendly messages using our formatter
287
+ const formattedMessage = formatErrorMessage(error);
288
+ console.error(chalk.red("āŒ Error:"), formattedMessage);
273
289
  } else {
274
- console.error(
275
- chalk.red("Error:"),
276
- error instanceof Error ? error.message : "Unknown error",
277
- );
290
+ // Handle other errors
291
+ const errorMessage =
292
+ error instanceof Error ? error.message : "Unknown error";
293
+ console.error(chalk.red("āŒ Error:"), errorMessage);
278
294
  }
279
295
  process.exit(1);
280
296
  }
@@ -323,6 +339,10 @@ function addCommand(
323
339
 
324
340
  if (param.type === "boolean") {
325
341
  command.option(flags.join(", "), param.description);
342
+ } else if (param.type === "array") {
343
+ // For arrays, use variadic syntax to collect multiple values
344
+ const flagSignature = flags.join(", ") + ` <values...>`;
345
+ command.option(flagSignature, param.description, param.default);
326
346
  } else {
327
347
  const flagSignature = flags.join(", ") + ` <${param.type}>`;
328
348
  command.option(flagSignature, param.description, param.default);
@@ -406,69 +426,106 @@ function convertValue(value: any, type: CliParameter["type"]): any {
406
426
  // Pagination Handlers
407
427
  // ============================================================================
408
428
 
409
- async function handlePaginatedList(
429
+ async function handlePaginatedListWithAsyncIteration(
410
430
  sdkMethodName: string,
411
- baseParams: any,
412
- sdk: ZapierSdk,
431
+ sdkResult: any,
413
432
  schema: z.ZodSchema,
414
433
  ): Promise<void> {
415
- const limit = baseParams.limit || 20;
416
434
  const itemName = getItemNameFromMethod(sdkMethodName);
435
+ let totalShown = 0;
436
+ let pageCount = 0;
417
437
 
418
- console.log(chalk.blue(`šŸ“‹ Fetching ${itemName}...`));
438
+ console.log(chalk.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName)}\n`));
419
439
 
420
- const pager = createPager({
421
- pageSize: Math.min(limit, 20),
422
- itemName,
423
- });
440
+ try {
441
+ // Use async iteration to go through pages
442
+ for await (const page of sdkResult) {
443
+ const items = page.data || page;
444
+ pageCount++;
424
445
 
425
- const displayFunction = (
426
- items: any[],
427
- totalShown: number,
428
- totalAvailable?: number,
429
- ) => {
430
- // Only clear screen if we have items to show
431
- if (items.length > 0) {
432
- console.clear();
433
- }
434
- console.log(chalk.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName)}\n`));
446
+ if (!Array.isArray(items)) {
447
+ console.log(chalk.yellow(`No ${itemName} found.`));
448
+ return;
449
+ }
435
450
 
436
- if (items.length === 0) {
437
- console.log(chalk.yellow(`No ${itemName} found.`));
438
- return;
439
- }
451
+ if (items.length === 0 && pageCount === 1) {
452
+ console.log(chalk.yellow(`No ${itemName} found.`));
453
+ return;
454
+ }
440
455
 
441
- // Use schema for formatting
442
- if (schema) {
443
- formatItemsFromSchema(schema as z.ZodType, items);
444
- } else {
445
- // Fallback to generic formatting
446
- formatItemsGeneric(items);
456
+ if (items.length === 0) {
457
+ break; // No more items
458
+ }
459
+
460
+ // Clear screen for subsequent pages (not the first)
461
+ if (pageCount > 1) {
462
+ console.clear();
463
+ console.log(
464
+ chalk.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName)}\n`),
465
+ );
466
+ }
467
+
468
+ // Format and display items using schema
469
+ if (schema) {
470
+ formatItemsFromSchema(schema as z.ZodType, items);
471
+ } else {
472
+ formatItemsGeneric(items);
473
+ }
474
+
475
+ totalShown += items.length;
476
+ console.log(
477
+ chalk.green(
478
+ `\nāœ… Showing ${totalShown} ${itemName} (page ${pageCount})`,
479
+ ),
480
+ );
481
+
482
+ // Only prompt if there's a nextCursor (more pages available)
483
+ if (page.nextCursor) {
484
+ const { continueReading } = await inquirer.prompt([
485
+ {
486
+ type: "confirm",
487
+ name: "continueReading",
488
+ message: `Load next page?`,
489
+ default: true,
490
+ },
491
+ ]);
492
+
493
+ if (!continueReading) {
494
+ break;
495
+ }
496
+ } else {
497
+ // No more pages available, exit gracefully
498
+ break;
499
+ }
447
500
  }
448
501
 
449
- const totalInfo = totalAvailable
450
- ? ` of ${totalAvailable.toLocaleString()} total`
451
- : "";
452
- console.log(
453
- chalk.green(`\nāœ… Showing ${totalShown}${totalInfo} ${itemName}`),
454
- );
455
- };
502
+ console.log(chalk.gray(`\nšŸ“„ Finished browsing ${itemName}`));
503
+ } catch (error) {
504
+ // If the result is not async iterable, fall back to showing the first page
505
+ const items = sdkResult?.data || sdkResult;
506
+ if (Array.isArray(items)) {
507
+ if (items.length === 0) {
508
+ console.log(chalk.yellow(`No ${itemName} found.`));
509
+ return;
510
+ }
456
511
 
457
- await pager.paginate(
458
- (params) =>
459
- (sdk as any)[sdkMethodName]({
460
- ...baseParams,
461
- ...params,
462
- }),
463
- {},
464
- displayFunction,
465
- );
512
+ if (schema) {
513
+ formatItemsFromSchema(schema as z.ZodType, items);
514
+ } else {
515
+ formatItemsGeneric(items);
516
+ }
517
+
518
+ console.log(chalk.green(`\nāœ… Showing ${items.length} ${itemName}`));
519
+ } else {
520
+ throw error;
521
+ }
522
+ }
466
523
  }
467
524
 
468
525
  function formatNonPaginatedResults(
469
526
  result: any[],
470
- requestedLimit?: number,
471
- userSpecifiedLimit?: boolean,
527
+ requestedMaxItems?: number,
528
+ userSpecifiedMaxItems?: boolean,
472
529
  useRawJson?: boolean,
473
530
  schema?: z.ZodSchema,
474
531
  methodName?: string,
@@ -505,10 +562,10 @@ function formatNonPaginatedResults(
505
562
  }
506
563
 
507
564
  // Show appropriate status message
508
- if (userSpecifiedLimit && requestedLimit) {
565
+ if (userSpecifiedMaxItems && requestedMaxItems) {
509
566
  console.log(
510
567
  chalk.gray(
511
- `\nšŸ“„ Showing up to ${requestedLimit} ${itemName} (--limit ${requestedLimit})`,
568
+ `\nšŸ“„ Showing up to ${requestedMaxItems} ${itemName} (--max-items ${requestedMaxItems})`,
512
569
  ),
513
570
  );
514
571
  } else {
@@ -519,7 +576,7 @@ function formatNonPaginatedResults(
519
576
  function formatItemsGeneric(items: any[]): void {
520
577
  // Fallback formatting for items without schema metadata
521
578
  items.forEach((item, index) => {
522
- const name = item.name || item.key || item.id || "Item";
579
+ const name = item.title || item.name || item.key || item.id || "Item";
523
580
  console.log(`${chalk.gray(`${index + 1}.`)} ${chalk.cyan(name)}`);
524
581
  if (item.description) {
525
582
  console.log(` ${chalk.dim(item.description)}`);