@zapier/zapier-sdk-cli 0.4.1 → 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
package/dist/cli.js CHANGED
@@ -1,12 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { Command as Command5 } from "commander";
5
- import { createZapierSdk } from "@zapier/zapier-sdk";
4
+ import { Command as Command7 } from "commander";
5
+ import { createZapierSdk as createZapierSdk2 } from "@zapier/zapier-sdk";
6
6
 
7
7
  // src/utils/cli-generator.ts
8
8
  import { z as z2 } from "zod";
9
- import { hasResolver as hasResolver2, isPositional } from "@zapier/zapier-sdk";
9
+ import {
10
+ hasResolver as hasResolver2,
11
+ isPositional,
12
+ formatErrorMessage,
13
+ ZapierError
14
+ } from "@zapier/zapier-sdk";
10
15
 
11
16
  // src/utils/parameter-resolver.ts
12
17
  import inquirer from "inquirer";
@@ -30,18 +35,25 @@ var SchemaParameterResolver = class {
30
35
  });
31
36
  const functionallyRequired = missingResolvable.filter((param) => {
32
37
  if (param.isRequired) return true;
33
- if (param.name === "inputs" || param.name === "authenticationId") {
38
+ if (param.name === "inputs") {
39
+ return true;
40
+ }
41
+ return false;
42
+ });
43
+ const alwaysPrompt = missingResolvable.filter((param) => {
44
+ if (functionallyRequired.includes(param)) return false;
45
+ if (param.name === "authenticationId") {
34
46
  return true;
35
47
  }
36
48
  return false;
37
49
  });
38
50
  const trulyOptional = missingResolvable.filter(
39
- (param) => !functionallyRequired.includes(param)
51
+ (param) => !functionallyRequired.includes(param) && !alwaysPrompt.includes(param)
40
52
  );
41
- if (parseResult.success && functionallyRequired.length === 0) {
53
+ if (parseResult.success && functionallyRequired.length === 0 && alwaysPrompt.length === 0) {
42
54
  return parseResult.data;
43
55
  }
44
- if (functionallyRequired.length === 0) {
56
+ if (functionallyRequired.length === 0 && alwaysPrompt.length === 0) {
45
57
  if (!parseResult.success) {
46
58
  throw parseResult.error;
47
59
  }
@@ -56,9 +68,16 @@ var SchemaParameterResolver = class {
56
68
  if (functionallyRequired.length > 0) {
57
69
  const requiredParamNames = functionallyRequired.map((p) => p.name);
58
70
  const requiredResolutionOrder = getResolutionOrderForParams(requiredParamNames);
59
- const orderedRequiredParams = requiredResolutionOrder.map(
60
- (paramName) => functionallyRequired.find((p) => p.name === paramName)
61
- ).filter((param) => param !== void 0);
71
+ const orderedRequiredParams = requiredResolutionOrder.map((paramName) => {
72
+ let param = functionallyRequired.find((p) => p.name === paramName);
73
+ if (!param) {
74
+ param = alwaysPrompt.find((p) => p.name === paramName);
75
+ }
76
+ if (!param) {
77
+ param = trulyOptional.find((p) => p.name === paramName);
78
+ }
79
+ return param;
80
+ }).filter((param) => param !== void 0);
62
81
  for (const param of orderedRequiredParams) {
63
82
  try {
64
83
  const value = await this.resolveParameter(param, context);
@@ -69,7 +88,37 @@ var SchemaParameterResolver = class {
69
88
  console.log(chalk.yellow("\n\nOperation cancelled by user"));
70
89
  process.exit(0);
71
90
  }
72
- console.error(chalk.red(`Failed to resolve ${param.name}:`), error);
91
+ throw error;
92
+ }
93
+ }
94
+ const resolvedParamNames = new Set(
95
+ orderedRequiredParams.map((p) => p.name)
96
+ );
97
+ alwaysPrompt.splice(
98
+ 0,
99
+ alwaysPrompt.length,
100
+ ...alwaysPrompt.filter((p) => !resolvedParamNames.has(p.name))
101
+ );
102
+ trulyOptional.splice(
103
+ 0,
104
+ trulyOptional.length,
105
+ ...trulyOptional.filter((p) => !resolvedParamNames.has(p.name))
106
+ );
107
+ }
108
+ if (alwaysPrompt.length > 0) {
109
+ const alwaysPromptNames = alwaysPrompt.map((p) => p.name);
110
+ const alwaysPromptResolutionOrder = getResolutionOrderForParams(alwaysPromptNames);
111
+ const orderedAlwaysPromptParams = alwaysPromptResolutionOrder.map((paramName) => alwaysPrompt.find((p) => p.name === paramName)).filter((param) => param !== void 0);
112
+ for (const param of orderedAlwaysPromptParams) {
113
+ try {
114
+ const value = await this.resolveParameter(param, context);
115
+ this.setNestedValue(resolvedParams, param.path, value);
116
+ context.resolvedParams = resolvedParams;
117
+ } catch (error) {
118
+ if (this.isUserCancellation(error)) {
119
+ console.log(chalk.yellow("\n\nOperation cancelled by user"));
120
+ process.exit(0);
121
+ }
73
122
  throw error;
74
123
  }
75
124
  }
@@ -98,7 +147,6 @@ var SchemaParameterResolver = class {
98
147
  console.log(chalk.yellow("\n\nOperation cancelled by user"));
99
148
  process.exit(0);
100
149
  }
101
- console.error(chalk.red(`Failed to resolve ${param.name}:`), error);
102
150
  throw error;
103
151
  }
104
152
  }
@@ -139,12 +187,12 @@ var SchemaParameterResolver = class {
139
187
  }
140
188
  return this.createResolvableParameter([fieldName], baseSchema, isRequired);
141
189
  }
142
- createResolvableParameter(path, schema, isRequired) {
143
- if (path.length === 0) return null;
144
- const name = path[path.length - 1];
190
+ createResolvableParameter(path3, schema, isRequired) {
191
+ if (path3.length === 0) return null;
192
+ const name = path3[path3.length - 1];
145
193
  return {
146
194
  name,
147
- path,
195
+ path: path3,
148
196
  schema,
149
197
  description: schema.description,
150
198
  isRequired
@@ -168,97 +216,138 @@ var SchemaParameterResolver = class {
168
216
  return answers[param.name];
169
217
  } else if (resolver.type === "dynamic") {
170
218
  try {
171
- console.log(chalk.gray(`Fetching options for ${param.name}...`));
172
- const items = await resolver.fetch(context.sdk, context.resolvedParams);
173
- if (!items || items.length === 0) {
174
- throw new Error(`No options available for ${param.name}`);
219
+ if (param.isRequired && param.name !== "authenticationId") {
220
+ console.log(chalk.gray(`Fetching options for ${param.name}...`));
175
221
  }
176
- const promptConfig = resolver.prompt(items, context.resolvedParams);
222
+ const items = await resolver.fetch(context.sdk, context.resolvedParams);
223
+ const safeItems = items || [];
224
+ const promptConfig = resolver.prompt(safeItems, context.resolvedParams);
177
225
  const answers = await inquirer.prompt([promptConfig]);
178
226
  return answers[param.name];
179
227
  } catch (error) {
180
- console.error(
181
- chalk.red(`Failed to fetch options for ${param.name}:`),
182
- error instanceof Error ? error.message : error
183
- );
184
228
  throw error;
185
229
  }
186
230
  } else if (resolver.type === "fields") {
187
- try {
188
- console.log(chalk.gray(`Fetching input fields for ${param.name}...`));
189
- const fields = await resolver.fetch(
190
- context.sdk,
191
- context.resolvedParams
192
- );
193
- if (!fields || fields.length === 0) {
231
+ return await this.resolveFieldsRecursively(
232
+ resolver,
233
+ context,
234
+ param
235
+ );
236
+ }
237
+ throw new Error(`Unknown resolver type for ${param.name}`);
238
+ }
239
+ async resolveFieldsRecursively(resolver, context, param) {
240
+ const inputs = {};
241
+ let processedFieldKeys = /* @__PURE__ */ new Set();
242
+ let iteration = 0;
243
+ const maxIterations = 5;
244
+ while (iteration < maxIterations) {
245
+ iteration++;
246
+ const updatedContext = {
247
+ ...context,
248
+ resolvedParams: {
249
+ ...context.resolvedParams,
250
+ inputs
251
+ }
252
+ };
253
+ console.log(
254
+ chalk.gray(
255
+ `Fetching input fields for ${param.name}${iteration > 1 ? ` (iteration ${iteration})` : ""}...`
256
+ )
257
+ );
258
+ const fields = await resolver.fetch(
259
+ updatedContext.sdk,
260
+ updatedContext.resolvedParams
261
+ );
262
+ if (!fields || fields.length === 0) {
263
+ if (iteration === 1) {
194
264
  console.log(
195
265
  chalk.yellow(`No input fields required for this action.`)
196
266
  );
197
- return {};
198
267
  }
199
- const inputs = {};
200
- const requiredFields = fields.filter((field) => field.required);
201
- const optionalFields = fields.filter((field) => !field.required);
202
- if (requiredFields.length > 0) {
203
- console.log(
204
- chalk.blue(
205
- `
206
- \u{1F4DD} Please provide values for the following input fields:`
207
- )
208
- );
209
- for (const field of requiredFields) {
210
- await this.promptForField(field, inputs);
211
- }
268
+ break;
269
+ }
270
+ const newFields = fields.filter(
271
+ (field) => !processedFieldKeys.has(field.key)
272
+ );
273
+ if (newFields.length === 0) {
274
+ break;
275
+ }
276
+ const newRequiredFields = newFields.filter(
277
+ (field) => field.required
278
+ );
279
+ const newOptionalFields = newFields.filter(
280
+ (field) => !field.required
281
+ );
282
+ if (newRequiredFields.length > 0) {
283
+ console.log(
284
+ chalk.blue(
285
+ `
286
+ \u{1F4DD} Please provide values for the following ${iteration === 1 ? "" : "additional "}input fields:`
287
+ )
288
+ );
289
+ for (const field of newRequiredFields) {
290
+ await this.promptForField(field, inputs);
291
+ processedFieldKeys.add(field.key);
212
292
  }
213
- if (optionalFields.length > 0) {
214
- console.log(
215
- chalk.gray(
216
- `
217
- There are ${optionalFields.length} optional field(s) available.`
218
- )
219
- );
220
- let shouldConfigureOptional;
221
- try {
222
- shouldConfigureOptional = await inquirer.prompt([
223
- {
224
- type: "confirm",
225
- name: "configure",
226
- message: "Would you like to configure optional fields?",
227
- default: false
228
- }
229
- ]);
230
- } catch (error) {
231
- if (this.isUserCancellation(error)) {
232
- console.log(chalk.yellow("\n\nOperation cancelled by user"));
233
- process.exit(0);
293
+ }
294
+ let shouldConfigureOptional = { configure: false };
295
+ if (newOptionalFields.length > 0) {
296
+ console.log(
297
+ chalk.gray(
298
+ `
299
+ There are ${newOptionalFields.length} ${iteration === 1 ? "" : "additional "}optional field(s) available.`
300
+ )
301
+ );
302
+ try {
303
+ shouldConfigureOptional = await inquirer.prompt([
304
+ {
305
+ type: "confirm",
306
+ name: "configure",
307
+ message: `Would you like to configure ${iteration === 1 ? "" : "these additional "}optional fields?`,
308
+ default: false
234
309
  }
235
- throw error;
310
+ ]);
311
+ } catch (error) {
312
+ if (this.isUserCancellation(error)) {
313
+ console.log(chalk.yellow("\n\nOperation cancelled by user"));
314
+ process.exit(0);
236
315
  }
237
- if (shouldConfigureOptional.configure) {
238
- console.log(chalk.cyan(`
316
+ throw error;
317
+ }
318
+ if (shouldConfigureOptional.configure) {
319
+ console.log(chalk.cyan(`
239
320
  Optional fields:`));
240
- for (const field of optionalFields) {
241
- await this.promptForField(field, inputs);
242
- }
321
+ for (const field of newOptionalFields) {
322
+ await this.promptForField(field, inputs);
323
+ processedFieldKeys.add(field.key);
243
324
  }
325
+ } else {
326
+ newOptionalFields.forEach(
327
+ (field) => processedFieldKeys.add(field.key)
328
+ );
244
329
  }
245
- return inputs;
246
- } catch (error) {
247
- console.error(
248
- chalk.red(`Failed to fetch fields for ${param.name}:`),
249
- error instanceof Error ? error.message : error
250
- );
251
- throw error;
330
+ }
331
+ if (newRequiredFields.length === 0 && (!newOptionalFields.length || !shouldConfigureOptional.configure)) {
332
+ break;
252
333
  }
253
334
  }
254
- throw new Error(`Unknown resolver type for ${param.name}`);
335
+ if (iteration >= maxIterations) {
336
+ console.log(
337
+ chalk.yellow(
338
+ `
339
+ \u26A0\uFE0F Maximum field resolution iterations reached. Some dynamic fields may not have been discovered.`
340
+ )
341
+ );
342
+ }
343
+ return inputs;
255
344
  }
256
- getNestedValue(obj, path) {
257
- return path.reduce((current, key) => current?.[key], obj);
345
+ getNestedValue(obj, path3) {
346
+ return path3.reduce((current, key) => current?.[key], obj);
258
347
  }
259
- setNestedValue(obj, path, value) {
260
- const lastKey = path[path.length - 1];
261
- const parent = path.slice(0, -1).reduce((current, key) => {
348
+ setNestedValue(obj, path3, value) {
349
+ const lastKey = path3[path3.length - 1];
350
+ const parent = path3.slice(0, -1).reduce((current, key) => {
262
351
  if (!(key in current)) {
263
352
  current[key] = {};
264
353
  }
@@ -302,86 +391,8 @@ Optional fields:`));
302
391
  }
303
392
  };
304
393
 
305
- // src/utils/pager.ts
306
- import inquirer2 from "inquirer";
307
- import chalk2 from "chalk";
308
- var Pager = class {
309
- constructor(options = {}) {
310
- this.allItems = [];
311
- this.currentOffset = 0;
312
- this.pageSize = options.pageSize || 20;
313
- this.showPrompt = options.showPrompt !== false;
314
- this.itemName = options.itemName || "items";
315
- }
316
- /**
317
- * Fetch and display paginated results with interactive loading
318
- */
319
- async paginate(fetchFunction, baseParams, displayFunction) {
320
- let hasMore = true;
321
- let totalAvailable;
322
- while (hasMore) {
323
- const params = {
324
- ...baseParams,
325
- limit: this.pageSize,
326
- offset: this.currentOffset
327
- };
328
- try {
329
- const items = await fetchFunction(params);
330
- if (items.length === 0) {
331
- displayFunction(this.allItems, this.allItems.length, totalAvailable);
332
- hasMore = false;
333
- break;
334
- }
335
- const pagination = items.__pagination;
336
- if (pagination && pagination.count) {
337
- totalAvailable = pagination.count;
338
- hasMore = pagination.hasNext;
339
- } else {
340
- hasMore = items.length >= this.pageSize;
341
- }
342
- this.allItems.push(...items);
343
- this.currentOffset += items.length;
344
- displayFunction(this.allItems, this.allItems.length, totalAvailable);
345
- if (!this.showPrompt) {
346
- continue;
347
- }
348
- const totalInfo = totalAvailable ? ` of ${totalAvailable.toLocaleString()}` : "";
349
- const message = `Load more ${this.itemName}? (${this.allItems.length}${totalInfo} shown so far)`;
350
- const { loadMore } = await inquirer2.prompt([
351
- {
352
- type: "confirm",
353
- name: "loadMore",
354
- message,
355
- default: true
356
- }
357
- ]);
358
- if (!loadMore) {
359
- hasMore = false;
360
- }
361
- } catch (error) {
362
- throw error;
363
- }
364
- }
365
- return {
366
- items: this.allItems,
367
- hasMore: this.currentOffset > 0 && hasMore,
368
- totalShown: this.allItems.length
369
- };
370
- }
371
- /**
372
- * Reset the pager state
373
- */
374
- reset() {
375
- this.allItems = [];
376
- this.currentOffset = 0;
377
- }
378
- };
379
- function createPager(options = {}) {
380
- return new Pager(options);
381
- }
382
-
383
394
  // src/utils/schema-formatter.ts
384
- import chalk3 from "chalk";
395
+ import chalk2 from "chalk";
385
396
  function getFormatMetadata(schema) {
386
397
  return schema?._def?.formatMeta;
387
398
  }
@@ -405,9 +416,9 @@ function formatItemsFromSchema(inputSchema, items) {
405
416
  }
406
417
  function formatSingleItem(item, index, formatMeta) {
407
418
  const formatted = formatMeta.format(item);
408
- let titleLine = `${chalk3.gray(`${index + 1}.`)} ${chalk3.cyan(formatted.title)}`;
419
+ let titleLine = `${chalk2.gray(`${index + 1}.`)} ${chalk2.cyan(formatted.title)}`;
409
420
  if (formatted.subtitle) {
410
- titleLine += ` ${chalk3.gray(formatted.subtitle)}`;
421
+ titleLine += ` ${chalk2.gray(formatted.subtitle)}`;
411
422
  }
412
423
  console.log(titleLine);
413
424
  for (const detail of formatted.details) {
@@ -419,35 +430,36 @@ function formatSingleItem(item, index, formatMeta) {
419
430
  function applyStyle(value, style) {
420
431
  switch (style) {
421
432
  case "dim":
422
- return chalk3.dim(value);
433
+ return chalk2.dim(value);
423
434
  case "accent":
424
- return chalk3.magenta(value);
435
+ return chalk2.magenta(value);
425
436
  case "warning":
426
- return chalk3.red(value);
437
+ return chalk2.red(value);
427
438
  case "success":
428
- return chalk3.green(value);
439
+ return chalk2.green(value);
429
440
  case "normal":
430
441
  default:
431
- return chalk3.blue(value);
442
+ return chalk2.blue(value);
432
443
  }
433
444
  }
434
445
  function formatItemsGeneric(items) {
435
446
  items.forEach((item, index) => {
436
- const name = item.name || item.key || item.id || "Item";
437
- console.log(`${chalk3.gray(`${index + 1}.`)} ${chalk3.cyan(name)}`);
447
+ const name = item.title || item.name || item.key || item.id || "Item";
448
+ console.log(`${chalk2.gray(`${index + 1}.`)} ${chalk2.cyan(name)}`);
438
449
  if (item.description) {
439
- console.log(` ${chalk3.dim(item.description)}`);
450
+ console.log(` ${chalk2.dim(item.description)}`);
440
451
  }
441
452
  console.log();
442
453
  });
443
454
  }
444
455
 
445
456
  // src/utils/cli-generator.ts
446
- import chalk4 from "chalk";
457
+ import chalk3 from "chalk";
447
458
  import util from "util";
459
+ import inquirer2 from "inquirer";
448
460
  function formatJsonOutput(data) {
449
461
  if (data && typeof data === "object" && !Array.isArray(data) && (data.success !== void 0 || data.id || data.status)) {
450
- console.log(chalk4.green("\u2705 Action completed successfully!\n"));
462
+ console.log(chalk3.green("\u2705 Action completed successfully!\n"));
451
463
  }
452
464
  console.log(
453
465
  util.inspect(data, { colors: true, depth: null, breakLength: 80 })
@@ -541,10 +553,9 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk2) {
541
553
  const options = commandObj.opts();
542
554
  const isListCommand = cliCommandName.startsWith("list-");
543
555
  const hasPaginationParams = parameters.some(
544
- (p) => p.name === "limit" || p.name === "offset"
556
+ (p) => p.name === "maxItems" || p.name === "pageSize"
545
557
  );
546
- const hasUserSpecifiedLimit = "limit" in options && options.limit !== void 0;
547
- const shouldUsePaging = isListCommand && hasPaginationParams && !hasUserSpecifiedLimit;
558
+ const hasUserSpecifiedMaxItems = "maxItems" in options && options.maxItems !== void 0;
548
559
  const shouldUseJson = options.json;
549
560
  const rawParams = convertCliArgsToSdkParams(
550
561
  parameters,
@@ -557,55 +568,61 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk2) {
557
568
  rawParams,
558
569
  sdk2
559
570
  );
560
- if (shouldUsePaging && !shouldUseJson) {
561
- await handlePaginatedList(sdkMethodName, resolvedParams, sdk2, schema);
571
+ const hasOutputFile = resolvedParams.output;
572
+ if (hasOutputFile) {
573
+ await sdk2[sdkMethodName](resolvedParams);
574
+ console.log(
575
+ chalk3.green(`\u2705 ${cliCommandName} completed successfully!`)
576
+ );
577
+ console.log(chalk3.gray(`Output written to: ${resolvedParams.output}`));
578
+ return;
579
+ }
580
+ if (isListCommand && hasPaginationParams && !shouldUseJson && !hasUserSpecifiedMaxItems) {
581
+ const sdkIterator = sdk2[sdkMethodName](resolvedParams);
582
+ await handlePaginatedListWithAsyncIteration(
583
+ sdkMethodName,
584
+ sdkIterator,
585
+ schema
586
+ );
562
587
  } else {
563
588
  const result = await sdk2[sdkMethodName](resolvedParams);
564
- const hasOutputFile = resolvedParams.output;
565
- if (!hasOutputFile && (shouldUseJson || !isListCommand)) {
566
- if (shouldUseJson) {
567
- console.log(JSON.stringify(result, null, 2));
568
- } else {
569
- formatJsonOutput(result);
570
- }
571
- } else if (!hasOutputFile) {
589
+ const items = result?.data ? result.data : result;
590
+ if (shouldUseJson) {
591
+ console.log(JSON.stringify(items, null, 2));
592
+ } else if (isListCommand) {
572
593
  formatNonPaginatedResults(
573
- result,
574
- resolvedParams.limit,
575
- hasUserSpecifiedLimit,
594
+ items,
595
+ resolvedParams.maxItems,
596
+ hasUserSpecifiedMaxItems,
576
597
  shouldUseJson,
577
598
  schema,
578
599
  sdkMethodName
579
600
  );
580
- } else if (hasOutputFile) {
581
- console.log(
582
- chalk4.green(`\u2705 ${cliCommandName} completed successfully!`)
583
- );
584
- console.log(
585
- chalk4.gray(`Output written to: ${resolvedParams.output}`)
586
- );
601
+ } else {
602
+ formatJsonOutput(items);
587
603
  }
588
604
  }
589
605
  } catch (error) {
590
606
  if (error instanceof Error && error.message.includes('"code"')) {
591
607
  try {
592
608
  const validationErrors = JSON.parse(error.message);
593
- console.error(chalk4.red("\u274C Validation Error:"));
609
+ console.error(chalk3.red("\u274C Validation Error:"));
594
610
  validationErrors.forEach((err) => {
595
611
  const field = err.path?.join(".") || "unknown";
596
- console.error(chalk4.yellow(` \u2022 ${field}: ${err.message}`));
612
+ console.error(chalk3.yellow(` \u2022 ${field}: ${err.message}`));
597
613
  });
598
614
  console.error(
599
- "\n" + chalk4.dim(`Use --help to see available options`)
615
+ "\n" + chalk3.dim(`Use --help to see available options`)
600
616
  );
601
617
  } catch {
602
- console.error(chalk4.red("Error:"), error.message);
618
+ console.error(chalk3.red("Error:"), error.message);
603
619
  }
620
+ } else if (error instanceof ZapierError) {
621
+ const formattedMessage = formatErrorMessage(error);
622
+ console.error(chalk3.red("\u274C Error:"), formattedMessage);
604
623
  } else {
605
- console.error(
606
- chalk4.red("Error:"),
607
- error instanceof Error ? error.message : "Unknown error"
608
- );
624
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
625
+ console.error(chalk3.red("\u274C Error:"), errorMessage);
609
626
  }
610
627
  process.exit(1);
611
628
  }
@@ -639,6 +656,9 @@ function addCommand(program2, commandName, config) {
639
656
  const flags = [`--${kebabName}`];
640
657
  if (param.type === "boolean") {
641
658
  command.option(flags.join(", "), param.description);
659
+ } else if (param.type === "array") {
660
+ const flagSignature = flags.join(", ") + ` <values...>`;
661
+ command.option(flagSignature, param.description, param.default);
642
662
  } else {
643
663
  const flagSignature = flags.join(", ") + ` <${param.type}>`;
644
664
  command.option(flagSignature, param.description, param.default);
@@ -689,45 +709,84 @@ function convertValue(value, type) {
689
709
  return value;
690
710
  }
691
711
  }
692
- async function handlePaginatedList(sdkMethodName, baseParams, sdk2, schema) {
693
- const limit = baseParams.limit || 20;
712
+ async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult, schema) {
694
713
  const itemName = getItemNameFromMethod(sdkMethodName);
695
- console.log(chalk4.blue(`\u{1F4CB} Fetching ${itemName}...`));
696
- const pager = createPager({
697
- pageSize: Math.min(limit, 20),
698
- itemName
699
- });
700
- const displayFunction = (items, totalShown, totalAvailable) => {
701
- if (items.length > 0) {
702
- console.clear();
703
- }
704
- console.log(chalk4.blue(`\u{1F4CB} ${getListTitleFromMethod(sdkMethodName)}
714
+ let totalShown = 0;
715
+ let pageCount = 0;
716
+ console.log(chalk3.blue(`\u{1F4CB} ${getListTitleFromMethod(sdkMethodName)}
705
717
  `));
706
- if (items.length === 0) {
707
- console.log(chalk4.yellow(`No ${itemName} found.`));
708
- return;
718
+ try {
719
+ for await (const page of sdkResult) {
720
+ const items = page.data || page;
721
+ pageCount++;
722
+ if (!Array.isArray(items)) {
723
+ console.log(chalk3.yellow(`No ${itemName} found.`));
724
+ return;
725
+ }
726
+ if (items.length === 0 && pageCount === 1) {
727
+ console.log(chalk3.yellow(`No ${itemName} found.`));
728
+ return;
729
+ }
730
+ if (items.length === 0) {
731
+ break;
732
+ }
733
+ if (pageCount > 1) {
734
+ console.clear();
735
+ console.log(
736
+ chalk3.blue(`\u{1F4CB} ${getListTitleFromMethod(sdkMethodName)}
737
+ `)
738
+ );
739
+ }
740
+ if (schema) {
741
+ formatItemsFromSchema(schema, items);
742
+ } else {
743
+ formatItemsGeneric2(items);
744
+ }
745
+ totalShown += items.length;
746
+ console.log(
747
+ chalk3.green(
748
+ `
749
+ \u2705 Showing ${totalShown} ${itemName} (page ${pageCount})`
750
+ )
751
+ );
752
+ if (page.nextCursor) {
753
+ const { continueReading } = await inquirer2.prompt([
754
+ {
755
+ type: "confirm",
756
+ name: "continueReading",
757
+ message: `Load next page?`,
758
+ default: true
759
+ }
760
+ ]);
761
+ if (!continueReading) {
762
+ break;
763
+ }
764
+ } else {
765
+ break;
766
+ }
709
767
  }
710
- if (schema) {
711
- formatItemsFromSchema(schema, items);
768
+ console.log(chalk3.gray(`
769
+ \u{1F4C4} Finished browsing ${itemName}`));
770
+ } catch (error) {
771
+ const items = sdkResult?.data || sdkResult;
772
+ if (Array.isArray(items)) {
773
+ if (items.length === 0) {
774
+ console.log(chalk3.yellow(`No ${itemName} found.`));
775
+ return;
776
+ }
777
+ if (schema) {
778
+ formatItemsFromSchema(schema, items);
779
+ } else {
780
+ formatItemsGeneric2(items);
781
+ }
782
+ console.log(chalk3.green(`
783
+ \u2705 Showing ${items.length} ${itemName}`));
712
784
  } else {
713
- formatItemsGeneric2(items);
785
+ throw error;
714
786
  }
715
- const totalInfo = totalAvailable ? ` of ${totalAvailable.toLocaleString()} total` : "";
716
- console.log(
717
- chalk4.green(`
718
- \u2705 Showing ${totalShown}${totalInfo} ${itemName}`)
719
- );
720
- };
721
- await pager.paginate(
722
- (params) => sdk2[sdkMethodName]({
723
- ...baseParams,
724
- ...params
725
- }),
726
- {},
727
- displayFunction
728
- );
787
+ }
729
788
  }
730
- function formatNonPaginatedResults(result, requestedLimit, userSpecifiedLimit, useRawJson, schema, methodName) {
789
+ function formatNonPaginatedResults(result, requestedMaxItems, userSpecifiedMaxItems, useRawJson, schema, methodName) {
731
790
  if (!Array.isArray(result)) {
732
791
  if (useRawJson) {
733
792
  console.log(JSON.stringify(result, null, 2));
@@ -742,10 +801,10 @@ function formatNonPaginatedResults(result, requestedLimit, userSpecifiedLimit, u
742
801
  }
743
802
  const itemName = methodName ? getItemNameFromMethod(methodName) : "items";
744
803
  if (result.length === 0) {
745
- console.log(chalk4.yellow(`No ${itemName} found.`));
804
+ console.log(chalk3.yellow(`No ${itemName} found.`));
746
805
  return;
747
806
  }
748
- console.log(chalk4.green(`
807
+ console.log(chalk3.green(`
749
808
  \u2705 Found ${result.length} ${itemName}:
750
809
  `));
751
810
  if (schema) {
@@ -753,24 +812,24 @@ function formatNonPaginatedResults(result, requestedLimit, userSpecifiedLimit, u
753
812
  } else {
754
813
  formatItemsGeneric2(result);
755
814
  }
756
- if (userSpecifiedLimit && requestedLimit) {
815
+ if (userSpecifiedMaxItems && requestedMaxItems) {
757
816
  console.log(
758
- chalk4.gray(
817
+ chalk3.gray(
759
818
  `
760
- \u{1F4C4} Showing up to ${requestedLimit} ${itemName} (--limit ${requestedLimit})`
819
+ \u{1F4C4} Showing up to ${requestedMaxItems} ${itemName} (--max-items ${requestedMaxItems})`
761
820
  )
762
821
  );
763
822
  } else {
764
- console.log(chalk4.gray(`
823
+ console.log(chalk3.gray(`
765
824
  \u{1F4C4} All available ${itemName} shown`));
766
825
  }
767
826
  }
768
827
  function formatItemsGeneric2(items) {
769
828
  items.forEach((item, index) => {
770
- const name = item.name || item.key || item.id || "Item";
771
- console.log(`${chalk4.gray(`${index + 1}.`)} ${chalk4.cyan(name)}`);
829
+ const name = item.title || item.name || item.key || item.id || "Item";
830
+ console.log(`${chalk3.gray(`${index + 1}.`)} ${chalk3.cyan(name)}`);
772
831
  if (item.description) {
773
- console.log(` ${chalk4.dim(item.description)}`);
832
+ console.log(` ${chalk3.dim(item.description)}`);
774
833
  }
775
834
  console.log();
776
835
  });
@@ -820,19 +879,19 @@ var spinPromise = async (promise, text) => {
820
879
  };
821
880
 
822
881
  // src/utils/log.ts
823
- import chalk5 from "chalk";
882
+ import chalk4 from "chalk";
824
883
  var log = {
825
884
  info: (message, ...args) => {
826
- console.log(chalk5.blue("\u2139"), message, ...args);
885
+ console.log(chalk4.blue("\u2139"), message, ...args);
827
886
  },
828
887
  error: (message, ...args) => {
829
- console.error(chalk5.red("\u2716"), message, ...args);
888
+ console.error(chalk4.red("\u2716"), message, ...args);
830
889
  },
831
890
  success: (message, ...args) => {
832
- console.log(chalk5.green("\u2713"), message, ...args);
891
+ console.log(chalk4.green("\u2713"), message, ...args);
833
892
  },
834
893
  warn: (message, ...args) => {
835
- console.log(chalk5.yellow("\u26A0"), message, ...args);
894
+ console.log(chalk4.yellow("\u26A0"), message, ...args);
836
895
  }
837
896
  };
838
897
  var log_default = log;
@@ -868,17 +927,17 @@ var client_default = api;
868
927
 
869
928
  // src/utils/getCallablePromise.ts
870
929
  var getCallablePromise = () => {
871
- let resolve = () => {
930
+ let resolve2 = () => {
872
931
  };
873
932
  let reject = () => {
874
933
  };
875
934
  const promise = new Promise((_resolve, _reject) => {
876
- resolve = _resolve;
935
+ resolve2 = _resolve;
877
936
  reject = _reject;
878
937
  });
879
938
  return {
880
939
  promise,
881
- resolve,
940
+ resolve: resolve2,
882
941
  reject
883
942
  };
884
943
  };
@@ -887,12 +946,12 @@ var getCallablePromise_default = getCallablePromise;
887
946
  // src/utils/auth/login.ts
888
947
  import { updateLogin, logout } from "@zapier/zapier-sdk-cli-login";
889
948
  var findAvailablePort = () => {
890
- return new Promise((resolve, reject) => {
949
+ return new Promise((resolve2, reject) => {
891
950
  let portIndex = 0;
892
951
  const tryPort = (port) => {
893
952
  const server = express().listen(port, () => {
894
953
  server.close();
895
- resolve(port);
954
+ resolve2(port);
896
955
  });
897
956
  server.on("error", (err) => {
898
957
  if (err.code === "EADDRINUSE") {
@@ -982,15 +1041,15 @@ var login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
982
1041
  } finally {
983
1042
  process.off("SIGINT", cleanup);
984
1043
  process.off("SIGTERM", cleanup);
985
- await new Promise((resolve) => {
1044
+ await new Promise((resolve2) => {
986
1045
  const timeout = setTimeout(() => {
987
1046
  log_default.info("Server close timed out, forcing connection shutdown...");
988
1047
  connections.forEach((conn) => conn.destroy());
989
- resolve();
1048
+ resolve2();
990
1049
  }, 1e3);
991
1050
  server.close(() => {
992
1051
  clearTimeout(timeout);
993
- resolve();
1052
+ resolve2();
994
1053
  });
995
1054
  });
996
1055
  }
@@ -1062,47 +1121,665 @@ function createLogoutCommand() {
1062
1121
  });
1063
1122
  }
1064
1123
 
1065
- // src/commands/whoami.ts
1124
+ // src/commands/configPath.ts
1066
1125
  import { Command as Command3 } from "commander";
1067
- import { getLoggedInUser as getLoggedInUser2 } from "@zapier/zapier-sdk-cli-login";
1068
- function createWhoamiCommand() {
1069
- return new Command3("whoami").description("Show current login status and user information").action(async () => {
1126
+ import { getConfigPath } from "@zapier/zapier-sdk-cli-login";
1127
+ function createConfigPathCommand() {
1128
+ return new Command3("get-config-path").description("Show the path to the configuration file").action(async () => {
1129
+ console.log(`Configuration file: ${getConfigPath()}`);
1130
+ });
1131
+ }
1132
+
1133
+ // src/commands/generate-types/cli.ts
1134
+ import { Command as Command4 } from "commander";
1135
+ import { createZapierSdk } from "@zapier/zapier-sdk";
1136
+
1137
+ // src/commands/generate-types/schemas.ts
1138
+ import { z as z3 } from "zod";
1139
+ import {
1140
+ AppKeyPropertySchema,
1141
+ AuthenticationIdPropertySchema,
1142
+ OutputPropertySchema,
1143
+ DebugPropertySchema
1144
+ } from "@zapier/zapier-sdk";
1145
+ var GenerateTypesSchema = z3.object({
1146
+ appKey: AppKeyPropertySchema.describe("App key to generate SDK code for"),
1147
+ authenticationId: AuthenticationIdPropertySchema.optional(),
1148
+ output: OutputPropertySchema.optional().describe(
1149
+ "Output file path (defaults to generated/<appKey>.ts)"
1150
+ ),
1151
+ debug: DebugPropertySchema.describe(
1152
+ "Enable debug logging during generation"
1153
+ )
1154
+ }).describe("Generate TypeScript SDK code for a specific app");
1155
+
1156
+ // src/commands/generate-types/index.ts
1157
+ import * as fs from "fs";
1158
+ import * as path from "path";
1159
+ function generateFetchMethodSignature() {
1160
+ return ` /** Make authenticated HTTP requests through Zapier's Relay service */
1161
+ fetch: (options: Omit<z.infer<typeof RelayFetchSchema>, 'authenticationId'>) => Promise<Response>`;
1162
+ }
1163
+ async function generateTypes(options) {
1164
+ const {
1165
+ appKey,
1166
+ authenticationId,
1167
+ output = `./types/${appKey}.d.ts`,
1168
+ sdk: sdk2
1169
+ } = options;
1170
+ const { app, version } = parseAppIdentifier(appKey);
1171
+ const actionsResult = await sdk2.listActions({
1172
+ appKey: app
1173
+ });
1174
+ const actions = actionsResult.data;
1175
+ if (actions.length === 0) {
1176
+ const typeDefinitions2 = generateEmptyTypesFile(app, version);
1177
+ if (output) {
1178
+ fs.mkdirSync(path.dirname(output), { recursive: true });
1179
+ fs.writeFileSync(output, typeDefinitions2, "utf8");
1180
+ }
1181
+ return typeDefinitions2;
1182
+ }
1183
+ const actionsWithFields = [];
1184
+ if (authenticationId) {
1185
+ for (const action of actions) {
1186
+ try {
1187
+ const fieldsResult = await sdk2.listInputFields({
1188
+ appKey: action.app_key,
1189
+ actionKey: action.key,
1190
+ actionType: action.action_type,
1191
+ authenticationId
1192
+ });
1193
+ const fields = fieldsResult.data;
1194
+ actionsWithFields.push({ ...action, inputFields: fields });
1195
+ } catch {
1196
+ actionsWithFields.push({ ...action, inputFields: [] });
1197
+ }
1198
+ }
1199
+ } else {
1200
+ actions.forEach((action) => {
1201
+ actionsWithFields.push({ ...action, inputFields: [] });
1202
+ });
1203
+ }
1204
+ const typeDefinitions = generateTypeDefinitions(
1205
+ app,
1206
+ actionsWithFields,
1207
+ version
1208
+ );
1209
+ if (output) {
1210
+ fs.mkdirSync(path.dirname(output), { recursive: true });
1211
+ fs.writeFileSync(output, typeDefinitions, "utf8");
1212
+ }
1213
+ return typeDefinitions;
1214
+ }
1215
+ function parseAppIdentifier(identifier) {
1216
+ const parts = identifier.split("@");
1217
+ return {
1218
+ app: parts[0],
1219
+ version: parts[1]
1220
+ };
1221
+ }
1222
+ function generateTypeDefinitions(appKey, actions, version) {
1223
+ if (actions.length === 0) {
1224
+ return generateEmptyTypesFile(appKey, version);
1225
+ }
1226
+ const actionsByType = actions.reduce(
1227
+ (acc, action) => {
1228
+ if (!acc[action.action_type]) {
1229
+ acc[action.action_type] = [];
1230
+ }
1231
+ acc[action.action_type].push(action);
1232
+ return acc;
1233
+ },
1234
+ {}
1235
+ );
1236
+ const appName = capitalize(appKey);
1237
+ const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
1238
+ let output = `/* eslint-disable @typescript-eslint/naming-convention */
1239
+ /**
1240
+ * Auto-generated TypeScript types for Zapier ${appKey} actions
1241
+ ${versionComment}
1242
+ * Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
1243
+ *
1244
+ * Usage:
1245
+ * import type { ${appName}Sdk } from './path/to/this/file'
1246
+ * const sdk = createZapierSdk() as unknown as ${appName}Sdk
1247
+ *
1248
+ * // Direct usage (per-call auth):
1249
+ * await sdk.apps.${appKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
1250
+ *
1251
+ * // Factory usage (pinned auth):
1252
+ * const my${appName} = sdk.apps.${appKey}({ authenticationId: 123 })
1253
+ * await my${appName}.search.user_by_email({ inputs: { email } })
1254
+ */
1255
+
1256
+ import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/zapier-sdk'
1257
+ import { z } from 'zod'
1258
+ import { RelayFetchSchema } from '@zapier/zapier-sdk'
1259
+
1260
+ `;
1261
+ actions.forEach((action) => {
1262
+ if (action.inputFields.length > 0) {
1263
+ const inputTypeName = `${appName}${capitalize(action.action_type)}${capitalize(
1264
+ sanitizeActionName(action.key)
1265
+ )}Inputs`;
1266
+ output += `interface ${inputTypeName} {
1267
+ `;
1268
+ action.inputFields.forEach((field) => {
1269
+ const isOptional = !field.required;
1270
+ const fieldType = mapFieldTypeToTypeScript(field);
1271
+ const description = field.helpText ? ` /** ${escapeComment(field.helpText)} */
1272
+ ` : "";
1273
+ output += `${description} ${sanitizeFieldName(field.key)}${isOptional ? "?" : ""}: ${fieldType}
1274
+ `;
1275
+ });
1276
+ output += `}
1277
+
1278
+ `;
1279
+ }
1280
+ });
1281
+ Object.entries(actionsByType).forEach(([actionType, typeActions]) => {
1282
+ const typeName = `${appName}${capitalize(actionType)}Actions`;
1283
+ output += `interface ${typeName} {
1284
+ `;
1285
+ typeActions.forEach((action) => {
1286
+ const actionName = sanitizeActionName(action.key);
1287
+ const description = action.description ? ` /** ${escapeComment(action.description)} */
1288
+ ` : "";
1289
+ if (action.inputFields.length > 0) {
1290
+ const inputTypeName = `${appName}${capitalize(action.action_type)}${capitalize(
1291
+ sanitizeActionName(action.key)
1292
+ )}Inputs`;
1293
+ output += `${description} ${actionName}: (options: { inputs: ${inputTypeName} } & Omit<ActionExecutionOptions, 'inputs'>) => Promise<ActionExecutionResult>
1294
+ `;
1295
+ } else {
1296
+ output += `${description} ${actionName}: (options?: { inputs?: Record<string, any> } & ActionExecutionOptions) => Promise<ActionExecutionResult>
1297
+ `;
1298
+ }
1299
+ });
1300
+ output += `}
1301
+
1302
+ `;
1303
+ });
1304
+ output += `interface ${appName}AppProxy {
1305
+ `;
1306
+ Object.keys(actionsByType).forEach((actionType) => {
1307
+ const typeName = `${appName}${capitalize(actionType)}Actions`;
1308
+ output += ` ${actionType}: ${typeName}
1309
+ `;
1310
+ });
1311
+ output += generateFetchMethodSignature() + "\n";
1312
+ output += `}
1313
+
1314
+ `;
1315
+ output += `interface ${appName}AppFactory {
1316
+ `;
1317
+ output += ` (options: { authenticationId: number }): ${appName}AppProxy
1318
+ `;
1319
+ output += `}
1320
+
1321
+ `;
1322
+ output += `type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
1323
+
1324
+ `;
1325
+ output += `export interface ${appName}Sdk {
1326
+ `;
1327
+ output += ` apps: {
1328
+ `;
1329
+ output += ` ${appKey}: ${appName}AppWithFactory
1330
+ `;
1331
+ output += ` }
1332
+ `;
1333
+ output += `}
1334
+ `;
1335
+ return output;
1336
+ }
1337
+ function generateEmptyTypesFile(appKey, version) {
1338
+ const appName = capitalize(appKey);
1339
+ const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
1340
+ return `/* eslint-disable @typescript-eslint/naming-convention */
1341
+ /**
1342
+ * Auto-generated TypeScript types for Zapier ${appKey} actions
1343
+ ${versionComment}
1344
+ * Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
1345
+ *
1346
+ * No actions found for this app.
1347
+ */
1348
+
1349
+ import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/zapier-sdk'
1350
+ import { z } from 'zod'
1351
+ import { RelayFetchSchema } from '@zapier/zapier-sdk'
1352
+
1353
+ interface ${appName}AppProxy {
1354
+ // No actions available
1355
+ ${generateFetchMethodSignature()}
1356
+ }
1357
+
1358
+ interface ${appName}AppFactory {
1359
+ (options: { authenticationId: number }): ${appName}AppProxy
1360
+ }
1361
+
1362
+ type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
1363
+
1364
+ export interface ${appName}Sdk {
1365
+ apps: {
1366
+ ${appKey}: ${appName}AppWithFactory
1367
+ }
1368
+ }
1369
+ `;
1370
+ }
1371
+ function capitalize(str) {
1372
+ return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, "");
1373
+ }
1374
+ function sanitizeActionName(actionKey) {
1375
+ let sanitized = actionKey.replace(/[^a-zA-Z0-9_$]/g, "_");
1376
+ if (/^[0-9]/.test(sanitized)) {
1377
+ sanitized = "_" + sanitized;
1378
+ }
1379
+ return sanitized;
1380
+ }
1381
+ function sanitizeFieldName(fieldKey) {
1382
+ let sanitized = fieldKey.replace(/[^a-zA-Z0-9_$]/g, "_");
1383
+ if (/^[0-9]/.test(sanitized)) {
1384
+ sanitized = "_" + sanitized;
1385
+ }
1386
+ return sanitized;
1387
+ }
1388
+ function escapeComment(comment) {
1389
+ return comment.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
1390
+ }
1391
+ function mapFieldTypeToTypeScript(field) {
1392
+ if (field.choices && field.choices.length > 0) {
1393
+ const choiceValues = field.choices.filter(
1394
+ (choice) => choice.value !== void 0 && choice.value !== null && choice.value !== ""
1395
+ ).map(
1396
+ (choice) => typeof choice.value === "string" ? `"${choice.value}"` : choice.value
1397
+ );
1398
+ if (choiceValues.length > 0) {
1399
+ return choiceValues.join(" | ");
1400
+ }
1401
+ }
1402
+ switch (field.type?.toLowerCase()) {
1403
+ case "string":
1404
+ case "text":
1405
+ case "email":
1406
+ case "url":
1407
+ case "password":
1408
+ return "string";
1409
+ case "integer":
1410
+ case "number":
1411
+ return "number";
1412
+ case "boolean":
1413
+ return "boolean";
1414
+ case "datetime":
1415
+ case "date":
1416
+ return "string";
1417
+ // ISO date strings
1418
+ case "file":
1419
+ return "string";
1420
+ // File URL or content
1421
+ case "array":
1422
+ return "any[]";
1423
+ case "object":
1424
+ return "Record<string, any>";
1425
+ default:
1426
+ return "string | number | boolean";
1427
+ }
1428
+ }
1429
+
1430
+ // src/commands/generate-types/cli.ts
1431
+ import chalk5 from "chalk";
1432
+
1433
+ // src/utils/cli-generator-utils.ts
1434
+ import { z as z4 } from "zod";
1435
+ import { hasResolver as hasResolver3, isPositional as isPositional2 } from "@zapier/zapier-sdk";
1436
+ function analyzeZodSchema2(schema) {
1437
+ const parameters = [];
1438
+ if (schema instanceof z4.ZodObject) {
1439
+ const shape = schema.shape;
1440
+ for (const [key, fieldSchema] of Object.entries(shape)) {
1441
+ const param = analyzeZodField2(key, fieldSchema);
1442
+ if (param) {
1443
+ parameters.push(param);
1444
+ }
1445
+ }
1446
+ }
1447
+ return parameters;
1448
+ }
1449
+ function analyzeZodField2(name, schema) {
1450
+ let baseSchema = schema;
1451
+ let required = true;
1452
+ let defaultValue = void 0;
1453
+ if (baseSchema instanceof z4.ZodOptional) {
1454
+ required = false;
1455
+ baseSchema = baseSchema._def.innerType;
1456
+ }
1457
+ if (baseSchema instanceof z4.ZodDefault) {
1458
+ required = false;
1459
+ defaultValue = baseSchema._def.defaultValue();
1460
+ baseSchema = baseSchema._def.innerType;
1461
+ }
1462
+ let paramType = "string";
1463
+ let choices;
1464
+ if (baseSchema instanceof z4.ZodString) {
1465
+ paramType = "string";
1466
+ } else if (baseSchema instanceof z4.ZodNumber) {
1467
+ paramType = "number";
1468
+ } else if (baseSchema instanceof z4.ZodBoolean) {
1469
+ paramType = "boolean";
1470
+ } else if (baseSchema instanceof z4.ZodArray) {
1471
+ paramType = "array";
1472
+ } else if (baseSchema instanceof z4.ZodEnum) {
1473
+ paramType = "string";
1474
+ choices = baseSchema._def.values;
1475
+ } else if (baseSchema instanceof z4.ZodRecord) {
1476
+ paramType = "string";
1477
+ }
1478
+ return {
1479
+ name,
1480
+ type: paramType,
1481
+ required,
1482
+ description: schema.description,
1483
+ default: defaultValue,
1484
+ choices,
1485
+ hasResolver: hasResolver3(name),
1486
+ isPositional: isPositional2(schema)
1487
+ };
1488
+ }
1489
+ function convertCliArgsToSdkParams2(parameters, positionalArgs, options) {
1490
+ const sdkParams = {};
1491
+ let argIndex = 0;
1492
+ parameters.forEach((param) => {
1493
+ if ((param.required || param.isPositional) && argIndex < positionalArgs.length) {
1494
+ sdkParams[param.name] = convertValue2(
1495
+ positionalArgs[argIndex],
1496
+ param.type
1497
+ );
1498
+ argIndex++;
1499
+ }
1500
+ });
1501
+ Object.entries(options).forEach(([key, value]) => {
1502
+ const camelKey = key.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
1503
+ const param = parameters.find((p) => p.name === camelKey);
1504
+ if (param && value !== void 0) {
1505
+ sdkParams[camelKey] = convertValue2(value, param.type);
1506
+ }
1507
+ });
1508
+ return sdkParams;
1509
+ }
1510
+ function convertValue2(value, type) {
1511
+ switch (type) {
1512
+ case "number":
1513
+ return Number(value);
1514
+ case "boolean":
1515
+ return Boolean(value);
1516
+ case "array":
1517
+ return Array.isArray(value) ? value : [value];
1518
+ case "string":
1519
+ default:
1520
+ if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) {
1521
+ try {
1522
+ return JSON.parse(value);
1523
+ } catch {
1524
+ return value;
1525
+ }
1526
+ }
1527
+ return value;
1528
+ }
1529
+ }
1530
+
1531
+ // src/commands/generate-types/cli.ts
1532
+ function createGenerateTypesCommand() {
1533
+ const parameters = analyzeZodSchema2(GenerateTypesSchema);
1534
+ const description = GenerateTypesSchema.description || "Generate TypeScript SDK types for a specific app";
1535
+ const command = new Command4("generate-types").description(description);
1536
+ parameters.forEach((param) => {
1537
+ const kebabName = param.name.replace(/([A-Z])/g, "-$1").toLowerCase();
1538
+ if (param.hasResolver && param.required) {
1539
+ command.argument(
1540
+ `[${kebabName}]`,
1541
+ param.description || `${kebabName} parameter`
1542
+ );
1543
+ } else if (param.required) {
1544
+ command.argument(
1545
+ `<${kebabName}>`,
1546
+ param.description || `${kebabName} parameter`
1547
+ );
1548
+ } else if (param.isPositional) {
1549
+ command.argument(
1550
+ `[${kebabName}]`,
1551
+ param.description || `${kebabName} parameter`
1552
+ );
1553
+ } else {
1554
+ const flags = [`--${kebabName}`];
1555
+ if (param.type === "boolean") {
1556
+ command.option(flags.join(", "), param.description);
1557
+ } else {
1558
+ const flagSignature = flags.join(", ") + ` <${param.type}>`;
1559
+ command.option(flagSignature, param.description, param.default);
1560
+ }
1561
+ }
1562
+ });
1563
+ command.option("--json", "Output raw JSON instead of formatted results");
1564
+ command.action(async (...args) => {
1070
1565
  try {
1071
- const user = await spinPromise(
1072
- getLoggedInUser2(),
1073
- "Checking login status..."
1566
+ const commandObj = args[args.length - 1];
1567
+ const options = commandObj.opts();
1568
+ const rawParams = convertCliArgsToSdkParams2(
1569
+ parameters,
1570
+ args.slice(0, -1),
1571
+ options
1074
1572
  );
1075
- console.log(
1076
- `\u2705 Logged in as ${user.email} (Account ID: ${user.accountId})`
1573
+ const sdk2 = createZapierSdk();
1574
+ const resolver = new SchemaParameterResolver();
1575
+ const resolvedParams = await resolver.resolveParameters(
1576
+ GenerateTypesSchema,
1577
+ rawParams,
1578
+ sdk2
1077
1579
  );
1078
- } catch {
1079
1580
  console.log(
1080
- "\u274C Not logged in. Use 'zapier-sdk login' to authenticate."
1581
+ chalk5.blue(
1582
+ `\u{1F527} Generating TypeScript types for ${resolvedParams.appKey}...`
1583
+ )
1584
+ );
1585
+ const result = await generateTypes({ ...resolvedParams, sdk: sdk2 });
1586
+ if (options.json) {
1587
+ console.log(JSON.stringify({ result }, null, 2));
1588
+ } else {
1589
+ const output = resolvedParams.output || `./types/${resolvedParams.appKey}.d.ts`;
1590
+ console.log(chalk5.green("\u2705 TypeScript types generated successfully!"));
1591
+ console.log(chalk5.gray(`Output written to: ${output}`));
1592
+ }
1593
+ } catch (error) {
1594
+ console.error(
1595
+ chalk5.red("Error:"),
1596
+ error instanceof Error ? error.message : "Unknown error"
1081
1597
  );
1082
1598
  process.exit(1);
1083
1599
  }
1084
1600
  });
1601
+ return command;
1085
1602
  }
1086
1603
 
1087
- // src/commands/configPath.ts
1088
- import { Command as Command4 } from "commander";
1089
- import { getConfigPath } from "@zapier/zapier-sdk-cli-login";
1090
- function createConfigPathCommand() {
1091
- return new Command4("get-config-path").description("Show the path to the configuration file").action(async () => {
1092
- console.log(`Configuration file: ${getConfigPath()}`);
1604
+ // src/commands/bundle-code/cli.ts
1605
+ import { Command as Command5 } from "commander";
1606
+
1607
+ // src/commands/bundle-code/schemas.ts
1608
+ import { z as z5 } from "zod";
1609
+ import { OutputPropertySchema as OutputPropertySchema2 } from "@zapier/zapier-sdk";
1610
+ var BundleCodeSchema = z5.object({
1611
+ input: z5.string().min(1).describe("Input TypeScript file path to bundle"),
1612
+ output: OutputPropertySchema2.optional().describe(
1613
+ "Output file path (defaults to input with .js extension)"
1614
+ ),
1615
+ string: z5.boolean().default(false).describe("Return bundled code as string instead of writing to file"),
1616
+ minify: z5.boolean().default(false).describe("Minify the bundled output"),
1617
+ target: z5.string().default("es2017").describe("ECMAScript target version"),
1618
+ cjs: z5.boolean().default(false).describe("Output CommonJS format instead of ESM")
1619
+ }).describe("Bundle TypeScript code into executable JavaScript");
1620
+
1621
+ // src/commands/bundle-code/index.ts
1622
+ import { buildSync } from "esbuild";
1623
+ import * as fs2 from "fs";
1624
+ import * as path2 from "path";
1625
+ var ZapierBundleError = class extends Error {
1626
+ constructor(message, details, originalError) {
1627
+ super(message);
1628
+ this.code = "ZAPIER_BUNDLE_ERROR";
1629
+ this.name = "ZapierBundleError";
1630
+ this.details = details;
1631
+ this.originalError = originalError;
1632
+ }
1633
+ };
1634
+ async function bundleCode(options) {
1635
+ const {
1636
+ input,
1637
+ output,
1638
+ target = "es2020",
1639
+ cjs = false,
1640
+ minify = false,
1641
+ string: returnString = false
1642
+ } = options;
1643
+ const resolvedInput = path2.resolve(process.cwd(), input);
1644
+ try {
1645
+ const result = buildSync({
1646
+ entryPoints: [resolvedInput],
1647
+ bundle: true,
1648
+ platform: "node",
1649
+ target,
1650
+ format: cjs ? "cjs" : "esm",
1651
+ minify,
1652
+ write: false,
1653
+ external: [],
1654
+ // Bundle everything
1655
+ banner: {
1656
+ js: "#!/usr/bin/env node"
1657
+ }
1658
+ });
1659
+ if (result.errors.length > 0) {
1660
+ const errorMessages = result.errors.map((e) => e.text);
1661
+ throw new ZapierBundleError(
1662
+ `Bundle failed: ${errorMessages.join(", ")}`,
1663
+ errorMessages
1664
+ );
1665
+ }
1666
+ const bundledCode = result.outputFiles?.[0]?.text;
1667
+ if (!bundledCode) {
1668
+ throw new ZapierBundleError("No output generated");
1669
+ }
1670
+ let finalOutput = bundledCode;
1671
+ if (returnString) {
1672
+ finalOutput = JSON.stringify(bundledCode);
1673
+ }
1674
+ if (output) {
1675
+ fs2.mkdirSync(path2.dirname(output), { recursive: true });
1676
+ fs2.writeFileSync(output, finalOutput, "utf8");
1677
+ }
1678
+ return finalOutput;
1679
+ } catch (error) {
1680
+ if (error instanceof ZapierBundleError) {
1681
+ throw error;
1682
+ }
1683
+ throw new ZapierBundleError(
1684
+ `Bundle failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1685
+ void 0,
1686
+ error instanceof Error ? error : void 0
1687
+ );
1688
+ }
1689
+ }
1690
+
1691
+ // src/commands/bundle-code/cli.ts
1692
+ import chalk6 from "chalk";
1693
+ function createBundleCodeCommand() {
1694
+ const parameters = analyzeZodSchema2(BundleCodeSchema);
1695
+ const description = BundleCodeSchema.description || "Bundle TypeScript code into executable JavaScript";
1696
+ const command = new Command5("bundle-code").description(description);
1697
+ parameters.forEach((param) => {
1698
+ const kebabName = param.name.replace(/([A-Z])/g, "-$1").toLowerCase();
1699
+ if (param.hasResolver && param.required) {
1700
+ command.argument(
1701
+ `[${kebabName}]`,
1702
+ param.description || `${kebabName} parameter`
1703
+ );
1704
+ } else if (param.required) {
1705
+ command.argument(
1706
+ `<${kebabName}>`,
1707
+ param.description || `${kebabName} parameter`
1708
+ );
1709
+ } else if (param.isPositional) {
1710
+ command.argument(
1711
+ `[${kebabName}]`,
1712
+ param.description || `${kebabName} parameter`
1713
+ );
1714
+ } else {
1715
+ const flags = [`--${kebabName}`];
1716
+ if (param.type === "boolean") {
1717
+ command.option(flags.join(", "), param.description);
1718
+ } else {
1719
+ const flagSignature = flags.join(", ") + ` <${param.type}>`;
1720
+ command.option(flagSignature, param.description, param.default);
1721
+ }
1722
+ }
1093
1723
  });
1724
+ command.option("--json", "Output raw JSON instead of formatted results");
1725
+ command.action(async (...args) => {
1726
+ try {
1727
+ const commandObj = args[args.length - 1];
1728
+ const options = commandObj.opts();
1729
+ const rawParams = convertCliArgsToSdkParams2(
1730
+ parameters,
1731
+ args.slice(0, -1),
1732
+ options
1733
+ );
1734
+ if (!rawParams.input) {
1735
+ throw new Error("Input file path is required");
1736
+ }
1737
+ console.log(chalk6.blue(`\u{1F4E6} Bundling ${rawParams.input}...`));
1738
+ const result = await bundleCode(rawParams);
1739
+ if (options.json) {
1740
+ console.log(JSON.stringify({ result }, null, 2));
1741
+ } else if (rawParams.output && !rawParams.string) {
1742
+ console.log(chalk6.green("\u2705 Bundle created successfully!"));
1743
+ console.log(chalk6.gray(`Output written to: ${rawParams.output}`));
1744
+ } else if (rawParams.string) {
1745
+ console.log(chalk6.green("\u2705 Bundle generated as string!"));
1746
+ console.log("\n" + result);
1747
+ } else {
1748
+ console.log(chalk6.green("\u2705 Bundle completed!"));
1749
+ console.log("\n" + result);
1750
+ }
1751
+ } catch (error) {
1752
+ console.error(
1753
+ chalk6.red("Error:"),
1754
+ error instanceof Error ? error.message : "Unknown error"
1755
+ );
1756
+ process.exit(1);
1757
+ }
1758
+ });
1759
+ return command;
1760
+ }
1761
+
1762
+ // src/commands/mcp.ts
1763
+ import { Command as Command6 } from "commander";
1764
+ import { startMcpServerAsProcess } from "@zapier/zapier-sdk-mcp";
1765
+ function createMcpCommand() {
1766
+ const command = new Command6("mcp");
1767
+ command.description("Start MCP server for Zapier SDK").option("--debug", "Enable debug logging").option("--port <port>", "Port to listen on (for future HTTP transport)").action(startMcpServerAsProcess);
1768
+ return command;
1094
1769
  }
1095
1770
 
1096
1771
  // src/cli.ts
1097
- var program = new Command5();
1772
+ var program = new Command7();
1098
1773
  program.name("zapier-sdk").description("CLI for Zapier SDK - Commands auto-generated from SDK schemas").version("1.0.0").option("--debug", "Enable debug logging");
1099
1774
  var isDebugMode = process.env.DEBUG === "true" || process.argv.includes("--debug");
1100
- var sdk = createZapierSdk({
1775
+ var sdk = createZapierSdk2({
1101
1776
  debug: isDebugMode
1102
1777
  });
1103
1778
  program.addCommand(createLoginCommand());
1104
1779
  program.addCommand(createLogoutCommand());
1105
- program.addCommand(createWhoamiCommand());
1106
- program.addCommand(createConfigPathCommand());
1107
1780
  generateCliCommands(program, sdk);
1781
+ program.addCommand(createGenerateTypesCommand());
1782
+ program.addCommand(createBundleCodeCommand());
1783
+ program.addCommand(createConfigPathCommand());
1784
+ program.addCommand(createMcpCommand());
1108
1785
  program.parse();