@zapier/zapier-sdk-cli 0.9.0 → 0.11.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zapier/zapier-sdk-cli",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "Command line interface for Zapier SDK",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
@@ -42,9 +42,9 @@
42
42
  "ora": "^8.2.0",
43
43
  "pkce-challenge": "^5.0.0",
44
44
  "zod": "^3.25.67",
45
- "@zapier/zapier-sdk": "0.9.0",
46
45
  "@zapier/zapier-sdk-cli-login": "0.3.2",
47
- "@zapier/zapier-sdk-mcp": "0.3.5"
46
+ "@zapier/zapier-sdk-mcp": "0.3.8",
47
+ "@zapier/zapier-sdk": "0.11.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/express": "^5.0.3",
@@ -99,17 +99,13 @@ export const addPlugin: Plugin<
99
99
 
100
100
  // Process each app
101
101
  for (const app of apps) {
102
- console.log(`šŸ“¦ Adding ${app.key}...`);
102
+ const appSlugAndKey = app.slug ? `${app.slug} (${app.key})` : app.key;
103
+ console.log(`šŸ“¦ Adding ${appSlugAndKey}...`);
103
104
 
104
105
  try {
105
- // Extract implementation name and version from current_implementation_id
106
- const currentImplementationId = app.current_implementation_id;
107
- const [implementationName, version] =
108
- currentImplementationId.split("@");
109
-
110
- if (!implementationName || !version) {
106
+ if (!app.version) {
111
107
  console.warn(
112
- `āš ļø Invalid implementation ID format for '${app.key}': ${currentImplementationId}. Expected format: <implementationName>@<version>. Skipping...`,
108
+ `āš ļø Invalid implementation ID format for '${appSlugAndKey}': ${app.implementation_id}. Expected format: <implementationName>@<version>. Skipping...`,
113
109
  );
114
110
  continue;
115
111
  }
@@ -118,14 +114,14 @@ export const addPlugin: Plugin<
118
114
  const [manifestKey] = await context.updateManifestEntry(
119
115
  app.key,
120
116
  {
121
- implementationName,
122
- version,
117
+ implementationName: app.key,
118
+ version: app.version,
123
119
  },
124
120
  configPath,
125
121
  );
126
122
 
127
123
  console.log(
128
- `šŸ“ Locked ${app.key} to ${implementationName}@${version} using key '${manifestKey}'`,
124
+ `šŸ“ Locked ${appSlugAndKey} to ${app.key}@${app.version} using key '${manifestKey}'`,
129
125
  );
130
126
 
131
127
  // Find matching authentication for this app if authentications were provided
@@ -139,10 +135,12 @@ export const addPlugin: Plugin<
139
135
  if (matchingAuth) {
140
136
  authenticationId = matchingAuth.id;
141
137
  console.log(
142
- `šŸ” Using authentication ${authenticationId} (${matchingAuth.title}) for ${app.key}`,
138
+ `šŸ” Using authentication ${authenticationId} (${matchingAuth.title}) for ${appSlugAndKey}`,
143
139
  );
144
140
  } else {
145
- console.warn(`āš ļø No matching authentication found for ${app.key}`);
141
+ console.warn(
142
+ `āš ļø No matching authentication found for ${appSlugAndKey}`,
143
+ );
146
144
  }
147
145
  }
148
146
 
@@ -162,11 +160,13 @@ export const addPlugin: Plugin<
162
160
  await writeFile(typesPath, typeDefinitions, "utf8");
163
161
  console.log(`šŸ”§ Generated types for ${manifestKey} at ${typesPath}`);
164
162
  } catch (error) {
165
- console.warn(`āš ļø Failed to generate types for ${app.key}: ${error}`);
163
+ console.warn(
164
+ `āš ļø Failed to generate types for ${appSlugAndKey}: ${error}`,
165
+ );
166
166
  // Continue even if type generation fails
167
167
  }
168
168
  } catch (error) {
169
- console.warn(`āš ļø Failed to process ${app.key}: ${error}`);
169
+ console.warn(`āš ļø Failed to process ${appSlugAndKey}: ${error}`);
170
170
  }
171
171
  }
172
172
 
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { hasResolver, isPositional } from "@zapier/zapier-sdk";
2
+ import { isPositional, type FunctionRegistryEntry } from "@zapier/zapier-sdk";
3
3
 
4
4
  // ============================================================================
5
5
  // Types
@@ -20,14 +20,17 @@ export interface CliParameter {
20
20
  // Schema Analysis
21
21
  // ============================================================================
22
22
 
23
- export function analyzeZodSchema(schema: z.ZodSchema): CliParameter[] {
23
+ export function analyzeZodSchema(
24
+ schema: z.ZodSchema,
25
+ functionInfo?: FunctionRegistryEntry,
26
+ ): CliParameter[] {
24
27
  const parameters: CliParameter[] = [];
25
28
 
26
29
  if (schema instanceof z.ZodObject) {
27
30
  const shape = schema.shape;
28
31
 
29
- for (const [key, fieldSchema] of Object.entries(shape)) {
30
- const param = analyzeZodField(key, fieldSchema as z.ZodSchema);
32
+ for (const [key, fieldSchema] of Object.entries<z.ZodSchema>(shape)) {
33
+ const param = analyzeZodField(key, fieldSchema, functionInfo);
31
34
  if (param) {
32
35
  parameters.push(param);
33
36
  }
@@ -40,6 +43,7 @@ export function analyzeZodSchema(schema: z.ZodSchema): CliParameter[] {
40
43
  function analyzeZodField(
41
44
  name: string,
42
45
  schema: z.ZodSchema,
46
+ functionInfo?: FunctionRegistryEntry,
43
47
  ): CliParameter | null {
44
48
  let baseSchema = schema;
45
49
  let required = true;
@@ -77,6 +81,14 @@ function analyzeZodField(
77
81
  paramType = "string";
78
82
  }
79
83
 
84
+ // Check if this parameter has a resolver
85
+ let paramHasResolver = false;
86
+
87
+ // Check function-specific resolvers first
88
+ if (functionInfo?.resolvers?.[name]) {
89
+ paramHasResolver = true;
90
+ }
91
+
80
92
  // Extract resolver metadata
81
93
  return {
82
94
  name,
@@ -85,7 +97,7 @@ function analyzeZodField(
85
97
  description: schema.description,
86
98
  default: defaultValue,
87
99
  choices,
88
- hasResolver: hasResolver(name),
100
+ hasResolver: paramHasResolver,
89
101
  isPositional: isPositional(schema),
90
102
  };
91
103
  }
@@ -2,45 +2,16 @@ import type { Command } from "commander";
2
2
  import { z } from "zod";
3
3
  import type { ZapierSdk } from "@zapier/zapier-sdk";
4
4
  import {
5
- hasResolver,
6
5
  isPositional,
7
6
  formatErrorMessage,
8
7
  ZapierError,
8
+ type FunctionRegistryEntry,
9
9
  } from "@zapier/zapier-sdk";
10
10
  import { SchemaParameterResolver } from "./parameter-resolver";
11
- import { formatItemsFromSchema } from "./schema-formatter";
11
+ import { formatItemsFromSchema, formatJsonOutput } from "./schema-formatter";
12
12
  import chalk from "chalk";
13
- import util from "util";
14
13
  import inquirer from "inquirer";
15
14
 
16
- // ============================================================================
17
- // JSON Formatting
18
- // ============================================================================
19
-
20
- function formatJsonOutput(data: unknown): void {
21
- // Don't print anything for undefined results (commands that just perform actions)
22
- if (data === undefined) {
23
- return;
24
- }
25
-
26
- // Show success message for action results
27
- if (
28
- data &&
29
- typeof data === "object" &&
30
- !Array.isArray(data) &&
31
- ((data as Record<string, unknown>).success !== undefined ||
32
- (data as Record<string, unknown>).id ||
33
- (data as Record<string, unknown>).status)
34
- ) {
35
- console.log(chalk.green("āœ… Action completed successfully!\n"));
36
- }
37
-
38
- // Use util.inspect for colored output
39
- console.log(
40
- util.inspect(data, { colors: true, depth: null, breakLength: 80 }),
41
- );
42
- }
43
-
44
15
  // ============================================================================
45
16
  // Types
46
17
  // ============================================================================
@@ -66,7 +37,10 @@ interface CliParameter {
66
37
  // Schema Analysis
67
38
  // ============================================================================
68
39
 
69
- function analyzeZodSchema(schema: z.ZodSchema): CliParameter[] {
40
+ function analyzeZodSchema(
41
+ schema: z.ZodSchema,
42
+ functionInfo?: FunctionRegistryEntry,
43
+ ): CliParameter[] {
70
44
  const parameters: CliParameter[] = [];
71
45
 
72
46
  // Handle ZodEffects (schemas with .refine(), .transform(), etc.)
@@ -78,14 +52,18 @@ function analyzeZodSchema(schema: z.ZodSchema): CliParameter[] {
78
52
  // Get the underlying schema
79
53
  const innerSchema = (schema as unknown as { _def: { schema: z.ZodSchema } })
80
54
  ._def.schema;
81
- return analyzeZodSchema(innerSchema);
55
+ return analyzeZodSchema(innerSchema, functionInfo);
82
56
  }
83
57
 
84
58
  if (schema instanceof z.ZodObject) {
85
59
  const shape = schema.shape;
86
60
 
87
61
  for (const [key, fieldSchema] of Object.entries(shape)) {
88
- const param = analyzeZodField(key, fieldSchema as z.ZodSchema);
62
+ const param = analyzeZodField(
63
+ key,
64
+ fieldSchema as z.ZodSchema,
65
+ functionInfo,
66
+ );
89
67
  if (param) {
90
68
  parameters.push(param);
91
69
  }
@@ -98,6 +76,7 @@ function analyzeZodSchema(schema: z.ZodSchema): CliParameter[] {
98
76
  function analyzeZodField(
99
77
  name: string,
100
78
  schema: z.ZodSchema,
79
+ functionInfo?: FunctionRegistryEntry,
101
80
  ): CliParameter | null {
102
81
  let baseSchema = schema;
103
82
  let required = true;
@@ -150,6 +129,14 @@ function analyzeZodField(
150
129
  paramType = "string";
151
130
  }
152
131
 
132
+ // Check if this parameter has a resolver
133
+ let paramHasResolver = false;
134
+
135
+ // Check function-specific resolvers first
136
+ if (functionInfo?.resolvers?.[name]) {
137
+ paramHasResolver = true;
138
+ }
139
+
153
140
  // Extract resolver metadata
154
141
  return {
155
142
  name,
@@ -158,7 +145,7 @@ function analyzeZodField(
158
145
  description: schema.description,
159
146
  default: defaultValue,
160
147
  choices,
161
- hasResolver: hasResolver(name),
148
+ hasResolver: paramHasResolver,
162
149
  isPositional: isPositional(schema),
163
150
  };
164
151
  }
@@ -206,12 +193,7 @@ export function generateCliCommands(program: Command, sdk: ZapierSdk): void {
206
193
  // Convert methodName to kebab-case CLI command
207
194
  const cliCommandName = methodNameToCliCommand(fnInfo.name);
208
195
 
209
- const config = createCommandConfig(
210
- cliCommandName,
211
- fnInfo.name,
212
- fnInfo.inputSchema as z.ZodSchema,
213
- sdk,
214
- );
196
+ const config = createCommandConfig(cliCommandName, fnInfo, sdk);
215
197
 
216
198
  addCommand(program, cliCommandName, config);
217
199
  });
@@ -288,11 +270,11 @@ export function generateCliCommands(program: Command, sdk: ZapierSdk): void {
288
270
 
289
271
  function createCommandConfig(
290
272
  cliCommandName: string,
291
- sdkMethodName: string,
292
- schema: z.ZodSchema,
273
+ functionInfo: FunctionRegistryEntry,
293
274
  sdk: ZapierSdk,
294
275
  ): CliCommandConfig {
295
- const parameters = analyzeZodSchema(schema);
276
+ const schema = functionInfo.inputSchema as z.ZodSchema;
277
+ const parameters = analyzeZodSchema(schema, functionInfo);
296
278
  const description = schema.description || `${cliCommandName} command`;
297
279
 
298
280
  const handler = async (...args: unknown[]) => {
@@ -304,7 +286,7 @@ function createCommandConfig(
304
286
  const options = commandObj.opts();
305
287
 
306
288
  // Check if this is a list command for pagination
307
- const isListCommand = cliCommandName.startsWith("list-");
289
+ const isListCommand = functionInfo.type === "list";
308
290
  const hasPaginationParams = parameters.some(
309
291
  (p) => p.name === "maxItems" || p.name === "pageSize",
310
292
  );
@@ -325,6 +307,7 @@ function createCommandConfig(
325
307
  schema,
326
308
  rawParams,
327
309
  sdk,
310
+ functionInfo.name,
328
311
  );
329
312
 
330
313
  // Handle paginated list commands with async iteration
@@ -339,11 +322,11 @@ function createCommandConfig(
339
322
  string,
340
323
  (params: unknown) => Promise<unknown> & AsyncIterable<unknown>
341
324
  >;
342
- const sdkIterator = sdkObj[sdkMethodName](resolvedParams);
325
+ const sdkIterator = sdkObj[functionInfo.name](resolvedParams);
343
326
  await handlePaginatedListWithAsyncIteration(
344
- sdkMethodName,
327
+ functionInfo.name,
345
328
  sdkIterator,
346
- schema,
329
+ functionInfo,
347
330
  );
348
331
  } else {
349
332
  // Special handling for commands that write to files
@@ -354,7 +337,7 @@ function createCommandConfig(
354
337
  string,
355
338
  (params: unknown) => Promise<unknown>
356
339
  >;
357
- await sdkObj[sdkMethodName](resolvedParams);
340
+ await sdkObj[functionInfo.name](resolvedParams);
358
341
  console.log(
359
342
  chalk.green(`āœ… ${cliCommandName} completed successfully!`),
360
343
  );
@@ -367,7 +350,7 @@ function createCommandConfig(
367
350
  string,
368
351
  (params: unknown) => Promise<unknown>
369
352
  >;
370
- const result: unknown = await sdkObj[sdkMethodName](resolvedParams);
353
+ const result: unknown = await sdkObj[functionInfo.name](resolvedParams);
371
354
  const items = (result as { data?: unknown })?.data
372
355
  ? (result as { data: unknown }).data
373
356
  : result;
@@ -380,8 +363,7 @@ function createCommandConfig(
380
363
  (resolvedParams as { maxItems?: number }).maxItems,
381
364
  hasUserSpecifiedMaxItems,
382
365
  shouldUseJson as boolean,
383
- schema,
384
- sdkMethodName,
366
+ functionInfo,
385
367
  );
386
368
  } else {
387
369
  formatJsonOutput(items);
@@ -554,6 +536,11 @@ function convertCliArgsToSdkParams(
554
536
  }
555
537
 
556
538
  function convertValue(value: unknown, type: CliParameter["type"]): unknown {
539
+ // Don't convert undefined values - let the resolver system handle them
540
+ if (value === undefined) {
541
+ return undefined;
542
+ }
543
+
557
544
  switch (type) {
558
545
  case "number":
559
546
  return Number(value);
@@ -585,13 +572,15 @@ function convertValue(value: unknown, type: CliParameter["type"]): unknown {
585
572
  async function handlePaginatedListWithAsyncIteration(
586
573
  sdkMethodName: string,
587
574
  sdkResult: unknown,
588
- schema: z.ZodSchema,
575
+ functionInfo: FunctionRegistryEntry,
589
576
  ): Promise<void> {
590
- const itemName = getItemNameFromMethod(sdkMethodName);
577
+ const itemName = getItemNameFromMethod(functionInfo);
591
578
  let totalShown = 0;
592
579
  let pageCount = 0;
593
580
 
594
- console.log(chalk.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName)}\n`));
581
+ console.log(
582
+ chalk.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName, functionInfo)}\n`),
583
+ );
595
584
 
596
585
  try {
597
586
  // Use async iteration to go through pages
@@ -620,13 +609,15 @@ async function handlePaginatedListWithAsyncIteration(
620
609
  if (pageCount > 1) {
621
610
  console.clear();
622
611
  console.log(
623
- chalk.blue(`šŸ“‹ ${getListTitleFromMethod(sdkMethodName)}\n`),
612
+ chalk.blue(
613
+ `šŸ“‹ ${getListTitleFromMethod(sdkMethodName, functionInfo)}\n`,
614
+ ),
624
615
  );
625
616
  }
626
617
 
627
- // Format and display items using schema
628
- if (schema) {
629
- formatItemsFromSchema(schema as z.ZodType, items, totalShown);
618
+ // Format and display items using function info
619
+ if (functionInfo) {
620
+ formatItemsFromSchema(functionInfo, items, totalShown);
630
621
  } else {
631
622
  formatItemsGeneric(items, totalShown);
632
623
  }
@@ -668,8 +659,8 @@ async function handlePaginatedListWithAsyncIteration(
668
659
  return;
669
660
  }
670
661
 
671
- if (schema) {
672
- formatItemsFromSchema(schema as z.ZodType, items, 0);
662
+ if (functionInfo) {
663
+ formatItemsFromSchema(functionInfo, items, 0);
673
664
  } else {
674
665
  formatItemsGeneric(items, 0);
675
666
  }
@@ -686,8 +677,7 @@ function formatNonPaginatedResults(
686
677
  requestedMaxItems?: number,
687
678
  userSpecifiedMaxItems?: boolean,
688
679
  useRawJson?: boolean,
689
- schema?: z.ZodSchema,
690
- methodName?: string,
680
+ functionInfo?: FunctionRegistryEntry,
691
681
  ): void {
692
682
  if (!Array.isArray(result)) {
693
683
  if (useRawJson) {
@@ -703,7 +693,7 @@ function formatNonPaginatedResults(
703
693
  return;
704
694
  }
705
695
 
706
- const itemName = methodName ? getItemNameFromMethod(methodName) : "items";
696
+ const itemName = functionInfo ? getItemNameFromMethod(functionInfo) : "items";
707
697
 
708
698
  if (result.length === 0) {
709
699
  console.log(chalk.yellow(`No ${itemName} found.`));
@@ -712,9 +702,9 @@ function formatNonPaginatedResults(
712
702
 
713
703
  console.log(chalk.green(`\nāœ… Found ${result.length} ${itemName}:\n`));
714
704
 
715
- // Use schema for formatting
716
- if (schema) {
717
- formatItemsFromSchema(schema as z.ZodType, result);
705
+ // Use function info for formatting
706
+ if (functionInfo) {
707
+ formatItemsFromSchema(functionInfo, result);
718
708
  } else {
719
709
  // Fallback to generic formatting
720
710
  formatItemsGeneric(result);
@@ -751,22 +741,21 @@ function formatItemsGeneric(
751
741
  }
752
742
 
753
743
  // Generic helper functions that infer from schema description or method name
754
- function getItemNameFromMethod(methodName: string): string {
755
- // Extract from method name: listApps -> apps, listActions -> actions
756
- const listMatch = methodName.match(/^list(.+)$/);
757
- if (listMatch) {
758
- return listMatch[1].toLowerCase();
744
+ function getItemNameFromMethod(functionInfo: FunctionRegistryEntry): string {
745
+ if (functionInfo.itemType) {
746
+ return `${functionInfo.itemType} items`;
759
747
  }
760
748
 
761
- // Fallback to generic
762
749
  return "items";
763
750
  }
764
751
 
765
- function getListTitleFromMethod(methodName: string): string {
766
- const itemName = getItemNameFromMethod(methodName);
767
- if (itemName === "items") return "Available Items";
752
+ function getListTitleFromMethod(
753
+ methodName: string,
754
+ functionInfo: FunctionRegistryEntry,
755
+ ): string {
756
+ if (functionInfo.itemType) {
757
+ return `Available ${functionInfo.itemType} items`;
758
+ }
768
759
 
769
- // Capitalize first letter: apps -> Apps
770
- const capitalized = itemName.charAt(0).toUpperCase() + itemName.slice(1);
771
- return `Available ${capitalized}`;
760
+ return `${methodName} items`;
772
761
  }