@zapier/zapier-sdk-cli 0.8.4 → 0.9.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.
Files changed (45) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +35 -51
  3. package/dist/cli.cjs +750 -346
  4. package/dist/cli.mjs +751 -347
  5. package/dist/index.cjs +726 -336
  6. package/dist/index.mjs +727 -337
  7. package/dist/package.json +1 -1
  8. package/dist/src/plugins/add/ast-generator.d.ts +37 -0
  9. package/dist/src/plugins/add/ast-generator.js +403 -0
  10. package/dist/src/plugins/add/index.d.ts +13 -0
  11. package/dist/src/plugins/add/index.js +122 -0
  12. package/dist/src/plugins/add/schemas.d.ts +18 -0
  13. package/dist/src/plugins/add/schemas.js +19 -0
  14. package/dist/src/plugins/getLoginConfigPath/index.d.ts +15 -0
  15. package/dist/src/plugins/getLoginConfigPath/index.js +19 -0
  16. package/dist/src/plugins/getLoginConfigPath/schemas.d.ts +3 -0
  17. package/dist/src/plugins/getLoginConfigPath/schemas.js +5 -0
  18. package/dist/src/plugins/index.d.ts +2 -2
  19. package/dist/src/plugins/index.js +2 -2
  20. package/dist/src/sdk.js +3 -3
  21. package/dist/src/utils/cli-generator.js +15 -0
  22. package/dist/tsconfig.tsbuildinfo +1 -1
  23. package/package.json +4 -4
  24. package/src/plugins/add/ast-generator.ts +777 -0
  25. package/src/plugins/add/index.test.ts +58 -0
  26. package/src/plugins/add/index.ts +187 -0
  27. package/src/plugins/add/schemas.ts +26 -0
  28. package/src/plugins/getLoginConfigPath/index.ts +45 -0
  29. package/src/plugins/getLoginConfigPath/schemas.ts +10 -0
  30. package/src/plugins/index.ts +2 -2
  31. package/src/sdk.ts +4 -4
  32. package/src/utils/cli-generator.ts +22 -0
  33. package/tsup.config.ts +1 -1
  34. package/dist/src/plugins/generateTypes/index.d.ts +0 -21
  35. package/dist/src/plugins/generateTypes/index.js +0 -312
  36. package/dist/src/plugins/generateTypes/schemas.d.ts +0 -18
  37. package/dist/src/plugins/generateTypes/schemas.js +0 -14
  38. package/dist/src/plugins/getConfigPath/index.d.ts +0 -15
  39. package/dist/src/plugins/getConfigPath/index.js +0 -19
  40. package/dist/src/plugins/getConfigPath/schemas.d.ts +0 -3
  41. package/dist/src/plugins/getConfigPath/schemas.js +0 -5
  42. package/src/plugins/generateTypes/index.ts +0 -444
  43. package/src/plugins/generateTypes/schemas.ts +0 -23
  44. package/src/plugins/getConfigPath/index.ts +0 -42
  45. package/src/plugins/getConfigPath/schemas.ts +0 -8
@@ -1,312 +0,0 @@
1
- import { GenerateTypesSchema } from "./schemas";
2
- import { createFunction } from "@zapier/zapier-sdk";
3
- import * as fs from "fs";
4
- import * as path from "path";
5
- export const generateTypesPlugin = ({ sdk }) => {
6
- const generateTypesWithSdk = createFunction(async function generateTypesWithSdk(options) {
7
- return await generateTypes({ ...options, sdk });
8
- }, GenerateTypesSchema);
9
- return {
10
- generateTypes: generateTypesWithSdk,
11
- context: {
12
- meta: {
13
- generateTypes: {
14
- categories: ["utility"],
15
- inputSchema: GenerateTypesSchema,
16
- },
17
- },
18
- },
19
- };
20
- };
21
- /**
22
- * Generate the fetch method signature for app proxies
23
- */
24
- function generateFetchMethodSignature() {
25
- return ` /** Make authenticated HTTP requests through Zapier's Relay service */
26
- fetch: (options: Omit<z.infer<typeof RelayFetchSchema>, 'authenticationId'>) => Promise<Response>`;
27
- }
28
- /**
29
- * Generate TypeScript types for a specific app (CLI version)
30
- */
31
- export async function generateTypes(options) {
32
- const { appKey, authenticationId, output = `./types/${appKey}.d.ts`, sdk, } = options;
33
- // Parse app identifier (support app@version format)
34
- const { app, version } = parseAppIdentifier(appKey);
35
- // Fetch all actions for the app
36
- const actionsResult = await sdk.listActions({
37
- appKey: app,
38
- });
39
- const actions = actionsResult.data;
40
- if (actions.length === 0) {
41
- const typeDefinitions = generateEmptyTypesFile(app, version);
42
- if (output) {
43
- fs.mkdirSync(path.dirname(output), { recursive: true });
44
- fs.writeFileSync(output, typeDefinitions, "utf8");
45
- }
46
- return typeDefinitions;
47
- }
48
- // Fetch input fields for each action
49
- const actionsWithFields = [];
50
- if (authenticationId) {
51
- for (const action of actions) {
52
- try {
53
- // Check to see if the appKey is in the manifest
54
- const manifestEntry = sdk.getContext().getManifestEntry(appKey);
55
- const fieldsResult = await sdk.listInputFields({
56
- // If the appKey is in the manifest, use the appKey so that the types are consistent with the manifest's version, otherwise use the action.app_key
57
- appKey: manifestEntry ? appKey : action.app_key,
58
- actionKey: action.key,
59
- actionType: action.action_type,
60
- authenticationId: authenticationId,
61
- });
62
- const fields = fieldsResult.data.map((field) => {
63
- const fieldObj = field;
64
- return {
65
- ...fieldObj,
66
- required: fieldObj.is_required || fieldObj.required || false,
67
- };
68
- });
69
- actionsWithFields.push({
70
- ...action,
71
- inputFields: fields,
72
- name: action.title || action.key,
73
- });
74
- }
75
- catch {
76
- // If we can't get fields for an action, include it without fields
77
- actionsWithFields.push({
78
- ...action,
79
- inputFields: [],
80
- name: action.title || action.key,
81
- });
82
- }
83
- }
84
- }
85
- else {
86
- // Convert actions to have empty input fields (will generate generic types)
87
- actions.forEach((action) => {
88
- actionsWithFields.push({
89
- ...action,
90
- inputFields: [],
91
- name: action.title || action.key,
92
- });
93
- });
94
- }
95
- // Generate TypeScript types
96
- const typeDefinitions = generateTypeDefinitions(app, actionsWithFields, version);
97
- // Write to file if output path specified
98
- if (output) {
99
- fs.mkdirSync(path.dirname(output), { recursive: true });
100
- fs.writeFileSync(output, typeDefinitions, "utf8");
101
- }
102
- return typeDefinitions;
103
- }
104
- function parseAppIdentifier(identifier) {
105
- const parts = identifier.split("@");
106
- return {
107
- app: parts[0],
108
- version: parts[1],
109
- };
110
- }
111
- function generateTypeDefinitions(appKey, actions, version) {
112
- // Handle empty actions
113
- if (actions.length === 0) {
114
- return generateEmptyTypesFile(appKey, version);
115
- }
116
- // Group actions by type
117
- const actionsByType = actions.reduce((acc, action) => {
118
- if (!acc[action.action_type]) {
119
- acc[action.action_type] = [];
120
- }
121
- acc[action.action_type].push(action);
122
- return acc;
123
- }, {});
124
- const appName = capitalize(appKey);
125
- const versionComment = version
126
- ? ` * Generated for ${appKey}@${version}`
127
- : ` * Generated for ${appKey}`;
128
- let output = `/* eslint-disable @typescript-eslint/naming-convention */
129
- /**
130
- * Auto-generated TypeScript types for Zapier ${appKey} actions
131
- ${versionComment}
132
- * Generated on: ${new Date().toISOString()}
133
- *
134
- * Usage:
135
- * import type { ${appName}Sdk } from './path/to/this/file'
136
- * const sdk = createZapierSdk() as unknown as ${appName}Sdk
137
- *
138
- * // Direct usage (per-call auth):
139
- * await sdk.apps.${appKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
140
- *
141
- * // Factory usage (pinned auth):
142
- * const my${appName} = sdk.apps.${appKey}({ authenticationId: 123 })
143
- * await my${appName}.search.user_by_email({ inputs: { email } })
144
- */
145
-
146
- import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/zapier-sdk'
147
- import { z } from 'zod'
148
- import { RelayFetchSchema } from '@zapier/zapier-sdk'
149
-
150
- `;
151
- // Generate input types for each action
152
- actions.forEach((action) => {
153
- if (action.inputFields.length > 0) {
154
- const inputTypeName = `${appName}${capitalize(action.action_type)}${capitalize(sanitizeActionName(action.key))}Inputs`;
155
- output += `interface ${inputTypeName} {\n`;
156
- action.inputFields.forEach((field) => {
157
- const isOptional = !field.required;
158
- const fieldType = mapFieldTypeToTypeScript(field);
159
- const description = field.helpText
160
- ? ` /** ${escapeComment(field.helpText)} */\n`
161
- : "";
162
- output += `${description} ${sanitizeFieldName(field.key)}${isOptional ? "?" : ""}: ${fieldType}\n`;
163
- });
164
- output += `}\n\n`;
165
- }
166
- });
167
- // Generate action type interfaces for each action type
168
- Object.entries(actionsByType).forEach(([actionType, typeActions]) => {
169
- const typeName = `${appName}${capitalize(actionType)}Actions`;
170
- output += `interface ${typeName} {\n`;
171
- typeActions.forEach((action) => {
172
- const actionName = sanitizeActionName(action.key);
173
- const description = action.description
174
- ? ` /** ${escapeComment(action.description)} */\n`
175
- : "";
176
- // Generate type-safe action method signature
177
- if (action.inputFields.length > 0) {
178
- const inputTypeName = `${appName}${capitalize(action.action_type)}${capitalize(sanitizeActionName(action.key))}Inputs`;
179
- output += `${description} ${actionName}: (options: { inputs: ${inputTypeName} } & Omit<ActionExecutionOptions, 'inputs'>) => Promise<ActionExecutionResult>\n`;
180
- }
181
- else {
182
- // No specific input fields available - use generic Record<string, any> for inputs
183
- output += `${description} ${actionName}: (options?: { inputs?: Record<string, any> } & ActionExecutionOptions) => Promise<ActionExecutionResult>\n`;
184
- }
185
- });
186
- output += `}\n\n`;
187
- });
188
- // Generate the main app SDK interface with factory pattern support
189
- // Generate the app proxy interface (actions grouped by type)
190
- output += `interface ${appName}AppProxy {\n`;
191
- Object.keys(actionsByType).forEach((actionType) => {
192
- const typeName = `${appName}${capitalize(actionType)}Actions`;
193
- output += ` ${actionType}: ${typeName}\n`;
194
- });
195
- // Always include fetch method for authenticated HTTP requests
196
- output += generateFetchMethodSignature() + "\n";
197
- output += `}\n\n`;
198
- // Generate the factory function interface
199
- output += `interface ${appName}AppFactory {\n`;
200
- output += ` (options: { authenticationId: number }): ${appName}AppProxy\n`;
201
- output += `}\n\n`;
202
- // Combine factory and direct access
203
- output += `type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy\n\n`;
204
- // Generate the main SDK interface
205
- output += `export interface ${appName}Sdk {\n`;
206
- output += ` apps: {\n`;
207
- output += ` ${appKey}: ${appName}AppWithFactory\n`;
208
- output += ` }\n`;
209
- output += `}\n`;
210
- return output;
211
- }
212
- function generateEmptyTypesFile(appKey, version) {
213
- const appName = capitalize(appKey);
214
- const versionComment = version
215
- ? ` * Generated for ${appKey}@${version}`
216
- : ` * Generated for ${appKey}`;
217
- return `/* eslint-disable @typescript-eslint/naming-convention */
218
- /**
219
- * Auto-generated TypeScript types for Zapier ${appKey} actions
220
- ${versionComment}
221
- * Generated on: ${new Date().toISOString()}
222
- *
223
- * No actions found for this app.
224
- */
225
-
226
- import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/zapier-sdk'
227
- import { z } from 'zod'
228
- import { RelayFetchSchema } from '@zapier/zapier-sdk'
229
-
230
- interface ${appName}AppProxy {
231
- // No actions available
232
- ${generateFetchMethodSignature()}
233
- }
234
-
235
- interface ${appName}AppFactory {
236
- (options: { authenticationId: number }): ${appName}AppProxy
237
- }
238
-
239
- type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
240
-
241
- export interface ${appName}Sdk {
242
- apps: {
243
- ${appKey}: ${appName}AppWithFactory
244
- }
245
- }
246
- `;
247
- }
248
- function capitalize(str) {
249
- return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, "");
250
- }
251
- function sanitizeActionName(actionKey) {
252
- // Ensure the action name is a valid TypeScript identifier
253
- let sanitized = actionKey.replace(/[^a-zA-Z0-9_$]/g, "_");
254
- // If it starts with a number, prepend an underscore
255
- if (/^[0-9]/.test(sanitized)) {
256
- sanitized = "_" + sanitized;
257
- }
258
- return sanitized;
259
- }
260
- function sanitizeFieldName(fieldKey) {
261
- // Ensure the field name is a valid TypeScript identifier
262
- let sanitized = fieldKey.replace(/[^a-zA-Z0-9_$]/g, "_");
263
- // If it starts with a number, prepend an underscore
264
- if (/^[0-9]/.test(sanitized)) {
265
- sanitized = "_" + sanitized;
266
- }
267
- return sanitized;
268
- }
269
- function escapeComment(comment) {
270
- // Escape comment text to prevent breaking the JSDoc comment
271
- return comment.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
272
- }
273
- function mapFieldTypeToTypeScript(field) {
274
- // Handle choices (enum-like fields)
275
- if (field.choices && field.choices.length > 0) {
276
- const choiceValues = field.choices
277
- .filter((choice) => choice.value !== undefined &&
278
- choice.value !== null &&
279
- choice.value !== "")
280
- .map((choice) => typeof choice.value === "string" ? `"${choice.value}"` : choice.value);
281
- if (choiceValues.length > 0) {
282
- return choiceValues.join(" | ");
283
- }
284
- // If all choices were filtered out, fall through to default type handling
285
- }
286
- // Map Zapier field types to TypeScript types
287
- switch (field.type?.toLowerCase()) {
288
- case "string":
289
- case "text":
290
- case "email":
291
- case "url":
292
- case "password":
293
- return "string";
294
- case "integer":
295
- case "number":
296
- return "number";
297
- case "boolean":
298
- return "boolean";
299
- case "datetime":
300
- case "date":
301
- return "string"; // ISO date strings
302
- case "file":
303
- return "string"; // File URL or content
304
- case "array":
305
- return "any[]";
306
- case "object":
307
- return "Record<string, any>";
308
- default:
309
- // Default to string for unknown types, with union for common cases
310
- return "string | number | boolean";
311
- }
312
- }
@@ -1,18 +0,0 @@
1
- import { z } from "zod";
2
- export declare const GenerateTypesSchema: z.ZodObject<{
3
- appKey: z.ZodString;
4
- authenticationId: z.ZodOptional<z.ZodNumber>;
5
- output: z.ZodOptional<z.ZodString>;
6
- lockFilePath: z.ZodOptional<z.ZodString>;
7
- }, "strip", z.ZodTypeAny, {
8
- appKey: string;
9
- authenticationId?: number | undefined;
10
- output?: string | undefined;
11
- lockFilePath?: string | undefined;
12
- }, {
13
- appKey: string;
14
- authenticationId?: number | undefined;
15
- output?: string | undefined;
16
- lockFilePath?: string | undefined;
17
- }>;
18
- export type GenerateTypesOptions = z.infer<typeof GenerateTypesSchema>;
@@ -1,14 +0,0 @@
1
- import { z } from "zod";
2
- import { AppKeyPropertySchema, AuthenticationIdPropertySchema, OutputPropertySchema, } from "@zapier/zapier-sdk";
3
- // Generate types schema - mirrors the original from SDK but for CLI use
4
- export const GenerateTypesSchema = z
5
- .object({
6
- appKey: AppKeyPropertySchema.describe("App key to generate SDK code for"),
7
- authenticationId: AuthenticationIdPropertySchema.optional(),
8
- output: OutputPropertySchema.optional().describe("Output file path (defaults to generated/<appKey>.ts)"),
9
- lockFilePath: z
10
- .string()
11
- .optional()
12
- .describe("Path to the .zapierrc lock file (defaults to .zapierrc)"),
13
- })
14
- .describe("Generate TypeScript SDK code for a specific app");
@@ -1,15 +0,0 @@
1
- import type { Plugin } from "@zapier/zapier-sdk";
2
- import { GetConfigPathSchema, type GetConfigPathOptions } from "./schemas";
3
- export interface GetConfigPathPluginProvides {
4
- getConfigPath: (options?: GetConfigPathOptions) => Promise<string>;
5
- context: {
6
- meta: {
7
- getConfigPath: {
8
- inputSchema: typeof GetConfigPathSchema;
9
- };
10
- };
11
- };
12
- }
13
- export declare const getConfigPathPlugin: Plugin<{}, // requires no existing SDK methods
14
- {}, // requires no context
15
- GetConfigPathPluginProvides>;
@@ -1,19 +0,0 @@
1
- import { GetConfigPathSchema } from "./schemas";
2
- import { createFunction } from "@zapier/zapier-sdk";
3
- import { getConfigPath } from "@zapier/zapier-sdk-cli-login";
4
- export const getConfigPathPlugin = () => {
5
- const getConfigPathWithSdk = createFunction(async function getConfigPathWithSdk(_options) {
6
- return getConfigPath();
7
- }, GetConfigPathSchema);
8
- return {
9
- getConfigPath: getConfigPathWithSdk,
10
- context: {
11
- meta: {
12
- getConfigPath: {
13
- categories: ["utility"],
14
- inputSchema: GetConfigPathSchema,
15
- },
16
- },
17
- },
18
- };
19
- };
@@ -1,3 +0,0 @@
1
- import { z } from "zod";
2
- export declare const GetConfigPathSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
3
- export type GetConfigPathOptions = z.infer<typeof GetConfigPathSchema>;
@@ -1,5 +0,0 @@
1
- import { z } from "zod";
2
- // Get config path schema - simple command with no parameters
3
- export const GetConfigPathSchema = z
4
- .object({})
5
- .describe("Show the path to the configuration file");