@zapier/zapier-sdk-cli 0.18.3 → 0.21.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 (89) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +31 -28
  3. package/dist/cli.cjs +2 -2
  4. package/dist/cli.mjs +2 -2
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.mjs +1 -1
  7. package/package.json +4 -4
  8. package/dist/package.json +0 -78
  9. package/dist/src/cli.d.ts +0 -2
  10. package/dist/src/cli.js +0 -105
  11. package/dist/src/generators/ast-generator.d.ts +0 -41
  12. package/dist/src/generators/ast-generator.js +0 -409
  13. package/dist/src/index.d.ts +0 -4
  14. package/dist/src/index.js +0 -4
  15. package/dist/src/plugins/add/index.d.ts +0 -15
  16. package/dist/src/plugins/add/index.js +0 -103
  17. package/dist/src/plugins/add/schemas.d.ts +0 -8
  18. package/dist/src/plugins/add/schemas.js +0 -22
  19. package/dist/src/plugins/buildManifest/index.d.ts +0 -13
  20. package/dist/src/plugins/buildManifest/index.js +0 -81
  21. package/dist/src/plugins/buildManifest/schemas.d.ts +0 -44
  22. package/dist/src/plugins/buildManifest/schemas.js +0 -17
  23. package/dist/src/plugins/bundleCode/index.d.ts +0 -15
  24. package/dist/src/plugins/bundleCode/index.js +0 -80
  25. package/dist/src/plugins/bundleCode/schemas.d.ts +0 -10
  26. package/dist/src/plugins/bundleCode/schemas.js +0 -19
  27. package/dist/src/plugins/generateAppTypes/index.d.ts +0 -13
  28. package/dist/src/plugins/generateAppTypes/index.js +0 -157
  29. package/dist/src/plugins/generateAppTypes/schemas.d.ts +0 -58
  30. package/dist/src/plugins/generateAppTypes/schemas.js +0 -21
  31. package/dist/src/plugins/getLoginConfigPath/index.d.ts +0 -15
  32. package/dist/src/plugins/getLoginConfigPath/index.js +0 -19
  33. package/dist/src/plugins/getLoginConfigPath/schemas.d.ts +0 -3
  34. package/dist/src/plugins/getLoginConfigPath/schemas.js +0 -5
  35. package/dist/src/plugins/index.d.ts +0 -8
  36. package/dist/src/plugins/index.js +0 -8
  37. package/dist/src/plugins/login/index.d.ts +0 -23
  38. package/dist/src/plugins/login/index.js +0 -95
  39. package/dist/src/plugins/login/schemas.d.ts +0 -5
  40. package/dist/src/plugins/login/schemas.js +0 -10
  41. package/dist/src/plugins/logout/index.d.ts +0 -15
  42. package/dist/src/plugins/logout/index.js +0 -18
  43. package/dist/src/plugins/logout/schemas.d.ts +0 -3
  44. package/dist/src/plugins/logout/schemas.js +0 -5
  45. package/dist/src/plugins/mcp/index.d.ts +0 -15
  46. package/dist/src/plugins/mcp/index.js +0 -24
  47. package/dist/src/plugins/mcp/schemas.d.ts +0 -5
  48. package/dist/src/plugins/mcp/schemas.js +0 -10
  49. package/dist/src/sdk.d.ts +0 -9
  50. package/dist/src/sdk.js +0 -24
  51. package/dist/src/telemetry/builders.d.ts +0 -42
  52. package/dist/src/telemetry/builders.js +0 -55
  53. package/dist/src/telemetry/events.d.ts +0 -37
  54. package/dist/src/telemetry/events.js +0 -4
  55. package/dist/src/types/sdk.d.ts +0 -5
  56. package/dist/src/types/sdk.js +0 -1
  57. package/dist/src/utils/api/client.d.ts +0 -15
  58. package/dist/src/utils/api/client.js +0 -27
  59. package/dist/src/utils/auth/login.d.ts +0 -7
  60. package/dist/src/utils/auth/login.js +0 -154
  61. package/dist/src/utils/cli-generator-utils.d.ts +0 -14
  62. package/dist/src/utils/cli-generator-utils.js +0 -122
  63. package/dist/src/utils/cli-generator.d.ts +0 -3
  64. package/dist/src/utils/cli-generator.js +0 -555
  65. package/dist/src/utils/constants.d.ts +0 -3
  66. package/dist/src/utils/constants.js +0 -5
  67. package/dist/src/utils/directory-detection.d.ts +0 -5
  68. package/dist/src/utils/directory-detection.js +0 -21
  69. package/dist/src/utils/errors.d.ts +0 -16
  70. package/dist/src/utils/errors.js +0 -19
  71. package/dist/src/utils/getCallablePromise.d.ts +0 -6
  72. package/dist/src/utils/getCallablePromise.js +0 -14
  73. package/dist/src/utils/log.d.ts +0 -8
  74. package/dist/src/utils/log.js +0 -21
  75. package/dist/src/utils/manifest-helpers.d.ts +0 -10
  76. package/dist/src/utils/manifest-helpers.js +0 -19
  77. package/dist/src/utils/package-manager-detector.d.ts +0 -16
  78. package/dist/src/utils/package-manager-detector.js +0 -77
  79. package/dist/src/utils/parameter-resolver.d.ts +0 -42
  80. package/dist/src/utils/parameter-resolver.js +0 -699
  81. package/dist/src/utils/schema-formatter.d.ts +0 -6
  82. package/dist/src/utils/schema-formatter.js +0 -115
  83. package/dist/src/utils/serializeAsync.d.ts +0 -2
  84. package/dist/src/utils/serializeAsync.js +0 -16
  85. package/dist/src/utils/spinner.d.ts +0 -1
  86. package/dist/src/utils/spinner.js +0 -21
  87. package/dist/src/utils/version-checker.d.ts +0 -17
  88. package/dist/src/utils/version-checker.js +0 -156
  89. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,409 +0,0 @@
1
- import * as ts from "typescript";
2
- import { toSnakeCase, batch } from "@zapier/zapier-sdk";
3
- /**
4
- * AST-based TypeScript type generator using the TypeScript Compiler API
5
- */
6
- export class AstTypeGenerator {
7
- constructor() {
8
- this.factory = ts.factory;
9
- this.printer = ts.createPrinter({
10
- newLine: ts.NewLineKind.LineFeed,
11
- removeComments: false,
12
- omitTrailingSemicolon: false,
13
- });
14
- }
15
- /**
16
- * Generate TypeScript types using AST for a specific app
17
- */
18
- async generateTypes(options) {
19
- const { app, authenticationId, sdk } = options;
20
- // Fetch all actions for the app using implementation_id for correct versioning
21
- const actionsResult = await sdk.listActions({
22
- appKey: app.implementation_id,
23
- });
24
- const actions = actionsResult.data;
25
- // Fetch input fields for each action
26
- const actionsWithFields = [];
27
- // Fetch all input fields with concurrency limiting for better reliability
28
- // Using batch() instead of Promise.allSettled() prevents overwhelming the API
29
- // and triggering rate limits when apps have many actions
30
- const inputFieldsTasks = actions.map((action) => () => sdk.listInputFields({
31
- appKey: app.implementation_id,
32
- actionKey: action.key,
33
- actionType: action.action_type,
34
- authenticationId: authenticationId,
35
- }));
36
- const results = await batch(inputFieldsTasks, {
37
- concurrency: 50, // Limit to 50 concurrent requests
38
- retry: true, // Automatically retry transient failures
39
- timeoutMs: 180000, // 3 minute overall timeout
40
- taskTimeoutMs: 30000, // 30 seconds per-task timeout (API calls shouldn't take longer)
41
- });
42
- const failedActions = [];
43
- results.forEach((result, i) => {
44
- const action = actions[i];
45
- if (result.status === "fulfilled") {
46
- actionsWithFields.push({
47
- ...action,
48
- inputFields: result.value.data,
49
- name: action.title || action.key,
50
- });
51
- }
52
- else {
53
- failedActions.push(`${action.key} (${action.action_type}): ${result.reason?.message || "Unknown error"}`);
54
- actionsWithFields.push({
55
- ...action,
56
- inputFields: [],
57
- name: action.title || action.key,
58
- app_key: action.app_key || app.implementation_id,
59
- action_type: action.action_type || "write",
60
- title: action.title || action.key,
61
- type: "action",
62
- description: action.description || "",
63
- });
64
- }
65
- });
66
- if (failedActions.length > 0) {
67
- console.warn(`Failed to fetch input fields for ${failedActions.length} action(s):`);
68
- failedActions.forEach((failedAction) => {
69
- console.warn(` - ${failedAction}`);
70
- });
71
- }
72
- // Generate TypeScript AST nodes
73
- const sourceFile = this.createSourceFile(app, actionsWithFields);
74
- // Print the AST to string
75
- return this.printer.printFile(sourceFile);
76
- }
77
- createSourceFile(app, actions) {
78
- const appName = this.getPreferredAppName(app);
79
- const versionComment = ` * Generated for ${app.implementation_id}`;
80
- const preferredKey = this.getPreferredProgrammaticKey(app);
81
- const myVariableName = `my${appName}`;
82
- // Create header comment
83
- const headerComment = `Auto-generated TypeScript types for Zapier ${app.key} actions
84
- ${versionComment.slice(3)}
85
- Generated on: ${new Date().toISOString()}
86
-
87
- This file automatically augments the base SDK types when present.
88
- No manual imports or type casting required.
89
-
90
- Usage:
91
- import { createZapierSdk } from "@zapier/zapier-sdk";
92
-
93
- const zapier = createZapierSdk();
94
- // Types are automatically available:
95
- await zapier.apps.${preferredKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
96
-
97
- // Factory usage (pinned auth):
98
- const ${myVariableName} = zapier.apps.${preferredKey}({ authenticationId: 123 })
99
- await ${myVariableName}.search.user_by_email({ inputs: { email } })`;
100
- const statements = [
101
- // Import the SDK to activate module augmentation
102
- this.createImportStatement(["@zapier/zapier-sdk"]),
103
- // Import types we'll use
104
- this.createTypeImportStatement([
105
- "ActionExecutionOptions",
106
- "ActionExecutionResult",
107
- "ZapierFetchInitOptions",
108
- ], "@zapier/zapier-sdk"),
109
- ];
110
- // Group actions by type
111
- const actionsByType = this.groupActionsByType(actions);
112
- // Generate input interfaces for each action
113
- actions.forEach((action) => {
114
- if (action.inputFields.length > 0) {
115
- const inputInterface = this.createInputInterface(appName, action);
116
- statements.push(inputInterface);
117
- }
118
- });
119
- // Generate action type interfaces
120
- Object.entries(actionsByType).forEach(([actionType, typeActions]) => {
121
- const actionInterface = this.createActionInterface(appName, actionType, typeActions);
122
- statements.push(actionInterface);
123
- });
124
- // Generate app proxy interface
125
- const appProxyInterface = this.createAppProxyInterface(appName, actionsByType);
126
- statements.push(appProxyInterface);
127
- // Generate app factory interface
128
- const appFactoryInterface = this.createAppFactoryInterface(appName);
129
- statements.push(appFactoryInterface);
130
- // Generate combined app type
131
- const appWithFactoryType = this.createAppWithFactoryType(appName);
132
- statements.push(appWithFactoryType);
133
- // Generate module augmentation for automatic type integration
134
- const allKeys = this.getAllKeys(app);
135
- const moduleAugmentation = this.createModuleAugmentation(allKeys, appName);
136
- statements.push(moduleAugmentation);
137
- // Add empty export to make this a module
138
- statements.push(this.factory.createExportDeclaration(undefined, false, this.factory.createNamedExports([])));
139
- // Create source file
140
- const sourceFile = ts.createSourceFile("generated.d.ts", "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
141
- // Add the header comment and ESLint disable as leading trivia to the first statement
142
- if (statements.length > 0) {
143
- // Add ESLint disable comment
144
- ts.addSyntheticLeadingComment(statements[0], ts.SyntaxKind.MultiLineCommentTrivia, " eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any ", true);
145
- // Add header comment
146
- ts.addSyntheticLeadingComment(statements[0], ts.SyntaxKind.MultiLineCommentTrivia, headerComment, true);
147
- }
148
- return this.factory.updateSourceFile(sourceFile, statements);
149
- }
150
- createImportStatement(imports, from) {
151
- // Handle side-effect only import (no imports, just the module path)
152
- if (imports.length === 1 && !from && imports[0].startsWith("@")) {
153
- return this.factory.createImportDeclaration(undefined, undefined, this.factory.createStringLiteral(imports[0]), undefined);
154
- }
155
- const fromModule = from || imports[0];
156
- const importNames = from ? imports : [];
157
- return this.factory.createImportDeclaration(undefined, importNames.length > 0
158
- ? this.factory.createImportClause(false, undefined, this.factory.createNamedImports(importNames.map((name) => this.factory.createImportSpecifier(false, undefined, this.factory.createIdentifier(name)))))
159
- : undefined, this.factory.createStringLiteral(fromModule), undefined);
160
- }
161
- createTypeImportStatement(imports, from) {
162
- return this.factory.createImportDeclaration(undefined, this.factory.createImportClause(true, // typeOnly: true
163
- undefined, this.factory.createNamedImports(imports.map((name) => this.factory.createImportSpecifier(false, undefined, this.factory.createIdentifier(name))))), this.factory.createStringLiteral(from), undefined);
164
- }
165
- groupActionsByType(actions) {
166
- return actions.reduce((acc, action) => {
167
- if (!acc[action.action_type]) {
168
- acc[action.action_type] = [];
169
- }
170
- acc[action.action_type].push(action);
171
- return acc;
172
- }, {});
173
- }
174
- createInputInterface(appName, action) {
175
- const inputTypeName = `${appName}${this.capitalize(action.action_type)}${this.capitalize(this.sanitizeActionName(action.key))}Inputs`;
176
- const properties = action.inputFields.map((field) => {
177
- const fieldType = this.mapFieldTypeToTypeNode(field);
178
- const isOptional = !field.is_required;
179
- let property = this.factory.createPropertySignature(undefined, this.sanitizeFieldName(field.key), isOptional
180
- ? this.factory.createToken(ts.SyntaxKind.QuestionToken)
181
- : undefined, fieldType);
182
- // Add JSDoc comment if description exists
183
- if (field.description) {
184
- property = ts.addSyntheticLeadingComment(property, ts.SyntaxKind.MultiLineCommentTrivia, `* ${this.escapeComment(field.description)} `, true);
185
- }
186
- return property;
187
- });
188
- return this.factory.createInterfaceDeclaration(undefined, inputTypeName, undefined, undefined, properties);
189
- }
190
- createActionInterface(appName, actionType, typeActions) {
191
- const typeName = `${appName}${this.capitalize(actionType)}Actions`;
192
- const methods = typeActions.map((action) => {
193
- const actionName = this.sanitizeActionName(action.key);
194
- let methodSignature;
195
- if (action.inputFields.length > 0) {
196
- // Generate type-safe action method signature
197
- const inputTypeName = `${appName}${this.capitalize(action.action_type)}${this.capitalize(this.sanitizeActionName(action.key))}Inputs`;
198
- const inputsType = this.factory.createTypeLiteralNode([
199
- this.factory.createPropertySignature(undefined, "inputs", undefined, this.factory.createTypeReferenceNode(inputTypeName)),
200
- ]);
201
- const omitType = this.factory.createTypeReferenceNode("Omit", [
202
- this.factory.createTypeReferenceNode("ActionExecutionOptions"),
203
- this.factory.createLiteralTypeNode(this.factory.createStringLiteral("inputs")),
204
- ]);
205
- const optionsType = this.factory.createIntersectionTypeNode([
206
- inputsType,
207
- omitType,
208
- ]);
209
- methodSignature = this.factory.createMethodSignature(undefined, actionName, undefined, undefined, [
210
- this.factory.createParameterDeclaration(undefined, undefined, "options", undefined, optionsType),
211
- ], this.factory.createTypeReferenceNode("Promise", [
212
- this.factory.createTypeReferenceNode("ActionExecutionResult"),
213
- ]));
214
- }
215
- else {
216
- // No specific input fields available - use generic Record<string, any> for inputs
217
- const genericInputsType = this.factory.createTypeLiteralNode([
218
- this.factory.createPropertySignature(undefined, "inputs", this.factory.createToken(ts.SyntaxKind.QuestionToken), this.factory.createTypeReferenceNode("Record", [
219
- this.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
220
- this.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword),
221
- ])),
222
- ]);
223
- const intersectionType = this.factory.createIntersectionTypeNode([
224
- genericInputsType,
225
- this.factory.createTypeReferenceNode("ActionExecutionOptions"),
226
- ]);
227
- methodSignature = this.factory.createMethodSignature(undefined, actionName, undefined, undefined, [
228
- this.factory.createParameterDeclaration(undefined, undefined, "options", this.factory.createToken(ts.SyntaxKind.QuestionToken), intersectionType),
229
- ], this.factory.createTypeReferenceNode("Promise", [
230
- this.factory.createTypeReferenceNode("ActionExecutionResult"),
231
- ]));
232
- }
233
- // Add JSDoc comment if description exists
234
- if (action.description) {
235
- methodSignature = ts.addSyntheticLeadingComment(methodSignature, ts.SyntaxKind.MultiLineCommentTrivia, `* ${this.escapeComment(action.description)} `, true);
236
- }
237
- return methodSignature;
238
- });
239
- return this.factory.createInterfaceDeclaration(undefined, typeName, undefined, undefined, methods);
240
- }
241
- createAppProxyInterface(appName, actionsByType) {
242
- const properties = [
243
- ...Object.keys(actionsByType).map((actionType) => this.factory.createPropertySignature(undefined, actionType, undefined, this.factory.createTypeReferenceNode(`${appName}${this.capitalize(actionType)}Actions`))),
244
- // Always include fetch method for authenticated HTTP requests
245
- this.createFetchMethodProperty(),
246
- ];
247
- return this.factory.createInterfaceDeclaration(undefined, `${appName}AppProxy`, undefined, undefined, properties);
248
- }
249
- createFetchMethodProperty() {
250
- let property = this.factory.createPropertySignature(undefined, "fetch", undefined, this.factory.createFunctionTypeNode(undefined, [
251
- this.factory.createParameterDeclaration(undefined, undefined, "url", undefined, this.factory.createUnionTypeNode([
252
- this.factory.createTypeReferenceNode("string"),
253
- this.factory.createTypeReferenceNode("URL"),
254
- ])),
255
- this.factory.createParameterDeclaration(undefined, undefined, "init", this.factory.createToken(ts.SyntaxKind.QuestionToken), this.factory.createTypeReferenceNode("ZapierFetchInitOptions")),
256
- ], this.factory.createTypeReferenceNode("Promise", [
257
- this.factory.createTypeReferenceNode("Response"),
258
- ])));
259
- // Add JSDoc comment
260
- property = ts.addSyntheticLeadingComment(property, ts.SyntaxKind.MultiLineCommentTrivia, "* Make authenticated HTTP requests through Zapier's Relay service ", true);
261
- return property;
262
- }
263
- createAppFactoryInterface(appName) {
264
- const callSignature = this.factory.createCallSignature(undefined, [
265
- this.factory.createParameterDeclaration(undefined, undefined, "options", undefined, this.factory.createTypeLiteralNode([
266
- this.factory.createPropertySignature(undefined, "authenticationId", undefined, this.factory.createUnionTypeNode([
267
- this.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
268
- this.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
269
- ])),
270
- ])),
271
- ], this.factory.createTypeReferenceNode(`${appName}AppProxy`));
272
- return this.factory.createInterfaceDeclaration(undefined, `${appName}AppFactory`, undefined, undefined, [callSignature]);
273
- }
274
- createAppWithFactoryType(appName) {
275
- return this.factory.createTypeAliasDeclaration(undefined, `${appName}AppWithFactory`, undefined, this.factory.createIntersectionTypeNode([
276
- this.factory.createTypeReferenceNode(`${appName}AppFactory`),
277
- this.factory.createTypeReferenceNode(`${appName}AppProxy`),
278
- ]));
279
- }
280
- createModuleAugmentation(appKeys, appName) {
281
- // Create: declare module "@zapier/zapier-sdk" { interface ZapierSdkApps { [appKey]: AppWithFactory } }
282
- // This creates a new interface that we can merge with ZapierSdk
283
- // Create properties for all keys (main key + other_keys)
284
- const properties = appKeys.map((appKey) => this.factory.createPropertySignature(undefined, this.createPropertyName(appKey), undefined, this.factory.createTypeReferenceNode(`${appName}AppWithFactory`)));
285
- return this.factory.createModuleDeclaration([this.factory.createToken(ts.SyntaxKind.DeclareKeyword)], this.factory.createStringLiteral("@zapier/zapier-sdk"), this.factory.createModuleBlock([
286
- this.factory.createInterfaceDeclaration(undefined, "ZapierSdkApps", undefined, undefined, properties),
287
- ]));
288
- }
289
- mapFieldTypeToTypeNode(field) {
290
- // TODO: Handle choices when needed - choices are handled separately through listInputFieldChoices
291
- // Map Zapier field types to TypeScript types
292
- // Handle the new enum types from InputFieldItem.value_type
293
- switch (field.value_type?.toLowerCase()) {
294
- case "string":
295
- case "text":
296
- case "email":
297
- case "url":
298
- case "password":
299
- case "datetime":
300
- case "date":
301
- case "file":
302
- return this.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
303
- case "integer":
304
- case "number":
305
- return this.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
306
- case "boolean":
307
- return this.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
308
- case "array":
309
- return this.factory.createArrayTypeNode(this.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword));
310
- case "object":
311
- return this.factory.createTypeReferenceNode("Record", [
312
- this.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
313
- this.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword),
314
- ]);
315
- default:
316
- // Default to string | number | boolean for unknown types
317
- return this.factory.createUnionTypeNode([
318
- this.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
319
- this.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
320
- this.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword),
321
- ]);
322
- }
323
- }
324
- capitalize(str) {
325
- return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, "");
326
- }
327
- sanitizeActionName(actionKey) {
328
- // Ensure the action name is a valid TypeScript identifier
329
- let sanitized = actionKey.replace(/[^a-zA-Z0-9_$]/g, "_");
330
- // If it starts with a number, prepend an underscore
331
- if (/^[0-9]/.test(sanitized)) {
332
- sanitized = "_" + sanitized;
333
- }
334
- return sanitized;
335
- }
336
- sanitizeFieldName(fieldKey) {
337
- // Ensure the field name is a valid TypeScript identifier
338
- let sanitized = fieldKey.replace(/[^a-zA-Z0-9_$]/g, "_");
339
- // If it starts with a number, prepend an underscore
340
- if (/^[0-9]/.test(sanitized)) {
341
- sanitized = "_" + sanitized;
342
- }
343
- return sanitized;
344
- }
345
- escapeComment(comment) {
346
- // Escape comment text to prevent breaking the JSDoc comment
347
- return comment.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
348
- }
349
- createPropertyName(name) {
350
- // Check if the name is a valid JavaScript identifier
351
- if (this.isValidIdentifier(name)) {
352
- return this.factory.createIdentifier(name);
353
- }
354
- else {
355
- // Use string literal for invalid identifiers (e.g., contains dashes)
356
- return this.factory.createStringLiteral(name);
357
- }
358
- }
359
- isValidIdentifier(name) {
360
- // JavaScript identifier rules: must start with letter, $, or _,
361
- // followed by letters, digits, $, or _
362
- return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
363
- }
364
- getPreferredProgrammaticKey(app) {
365
- // If we have a slug, convert it to snake_case as the preferred programmatic key
366
- if (app.slug) {
367
- const snakeCaseSlug = toSnakeCase(app.slug);
368
- if (this.isValidIdentifier(snakeCaseSlug)) {
369
- return snakeCaseSlug;
370
- }
371
- }
372
- // Otherwise, use the main key if it's a valid identifier
373
- if (this.isValidIdentifier(app.key)) {
374
- return app.key;
375
- }
376
- // Fallback: sanitize the key to make it a valid identifier
377
- return this.sanitizeToIdentifier(app.key);
378
- }
379
- getPreferredAppName(app) {
380
- const preferredKey = this.getPreferredProgrammaticKey(app);
381
- // If it's snake_case, convert to PascalCase
382
- if (preferredKey.includes("_")) {
383
- return preferredKey
384
- .split("_")
385
- .map((word) => this.capitalize(word.toLowerCase()))
386
- .join("");
387
- }
388
- // Otherwise, capitalize first letter for PascalCase
389
- return this.capitalize(preferredKey);
390
- }
391
- sanitizeToIdentifier(name) {
392
- // Convert any string to a valid JavaScript identifier
393
- let sanitized = name.replace(/[^a-zA-Z0-9_$]/g, "_");
394
- // If it starts with a number, prepend an underscore
395
- if (/^[0-9]/.test(sanitized)) {
396
- sanitized = "_" + sanitized;
397
- }
398
- return sanitized;
399
- }
400
- getAllKeys(app) {
401
- // Return all possible keys for this app
402
- const allKeys = new Set([app.key]);
403
- if (app.slug) {
404
- allKeys.add(app.slug);
405
- allKeys.add(toSnakeCase(app.slug));
406
- }
407
- return Array.from(allKeys);
408
- }
409
- }
@@ -1,4 +0,0 @@
1
- export { createZapierCliSdk, type ZapierCliSdkOptions } from "./sdk";
2
- export type { CliEventContext, CliCommandExecutedEventData, } from "./telemetry/builders";
3
- export { buildCliCommandExecutedEvent } from "./telemetry/builders";
4
- export type { CliCommandExecutedEvent } from "./telemetry/events";
package/dist/src/index.js DELETED
@@ -1,4 +0,0 @@
1
- // Main exports for the CLI package
2
- export { createZapierCliSdk } from "./sdk";
3
- export { buildCliCommandExecutedEvent } from "./telemetry/builders";
4
- // All CLI functionality is now schema-driven via generateCLICommands
@@ -1,15 +0,0 @@
1
- import type { Plugin, GetSdkType, ListActionsPluginProvides, ListAppsPluginProvides, ListInputFieldsPluginProvides, ListAuthenticationsPluginProvides } from "@zapier/zapier-sdk";
2
- import { AddSchema, type AddOptions } from "./schemas";
3
- import { type GenerateAppTypesPluginProvides } from "../generateAppTypes";
4
- import { type BuildManifestPluginProvides } from "../buildManifest";
5
- export interface AddPluginProvides {
6
- add: (options: AddOptions) => Promise<void>;
7
- context: {
8
- meta: {
9
- add: {
10
- inputSchema: typeof AddSchema;
11
- };
12
- };
13
- };
14
- }
15
- export declare const addPlugin: Plugin<GetSdkType<ListAppsPluginProvides & ListActionsPluginProvides & ListInputFieldsPluginProvides & ListAuthenticationsPluginProvides & BuildManifestPluginProvides & GenerateAppTypesPluginProvides>, {}, AddPluginProvides>;
@@ -1,103 +0,0 @@
1
- import { createFunction } from "@zapier/zapier-sdk";
2
- import { AddSchema } from "./schemas";
3
- import { detectTypesOutputDirectory } from "../../utils/directory-detection";
4
- import { resolve } from "path";
5
- export const addPlugin = ({ sdk }) => {
6
- const add = createFunction(async function add(options) {
7
- const { appKeys, authenticationIds, configPath, typesOutput = await detectTypesOutputDirectory(), } = options;
8
- const resolvedTypesOutput = resolve(typesOutput);
9
- console.log(`📦 Adding ${appKeys.length} app(s)...`);
10
- // Track app names for better console output
11
- const appSlugAndKeyMap = new Map();
12
- // Define progress handler for manifest building
13
- const handleManifestProgress = (event) => {
14
- switch (event.type) {
15
- case "apps_lookup_start":
16
- console.log(`📦 Looking up ${event.count} app(s)...`);
17
- break;
18
- case "app_found":
19
- // Store the app display name for later use
20
- const displayName = event.app.slug
21
- ? `${event.app.slug} (${event.app.key})`
22
- : event.app.key;
23
- appSlugAndKeyMap.set(event.app.key, displayName);
24
- break;
25
- case "apps_lookup_complete":
26
- if (event.count === 0) {
27
- console.warn("⚠️ No apps found");
28
- }
29
- break;
30
- case "app_processing_start":
31
- const appName = event.slug
32
- ? `${event.slug} (${event.appKey})`
33
- : event.appKey;
34
- console.log(`📦 Adding ${appName}...`);
35
- break;
36
- case "manifest_updated":
37
- const appDisplay = appSlugAndKeyMap.get(event.appKey) || event.appKey;
38
- console.log(`📝 Locked ${appDisplay} to ${event.appKey}@${event.version} using key '${event.manifestKey}'`);
39
- break;
40
- case "app_processing_error":
41
- const errorApp = appSlugAndKeyMap.get(event.appKey) || event.appKey;
42
- console.warn(`⚠️ ${event.error} for ${errorApp}`);
43
- break;
44
- }
45
- };
46
- // Define progress handler for type generation
47
- const handleTypesProgress = (event) => {
48
- switch (event.type) {
49
- case "authentications_lookup_start":
50
- console.log(`🔐 Looking up ${event.count} authentication(s)...`);
51
- break;
52
- case "authentications_lookup_complete":
53
- console.log(`🔐 Found ${event.count} authentication(s)`);
54
- break;
55
- case "authentication_matched":
56
- const appWithAuth = appSlugAndKeyMap.get(event.appKey) || event.appKey;
57
- console.log(`🔐 Using authentication ${event.authenticationId} (${event.authenticationTitle}) for ${appWithAuth}`);
58
- break;
59
- case "authentication_not_matched":
60
- const appWithoutAuth = appSlugAndKeyMap.get(event.appKey) || event.appKey;
61
- console.warn(`⚠️ No matching authentication found for ${appWithoutAuth}`);
62
- break;
63
- case "file_written":
64
- console.log(`🔧 Generated types for ${event.manifestKey} at ${event.filePath}`);
65
- break;
66
- case "app_processing_error":
67
- const errorApp = appSlugAndKeyMap.get(event.appKey) || event.appKey;
68
- console.warn(`⚠️ ${event.error} for ${errorApp}`);
69
- break;
70
- }
71
- };
72
- const manifestResult = await sdk.buildManifest({
73
- appKeys,
74
- skipWrite: false,
75
- configPath,
76
- onProgress: handleManifestProgress,
77
- });
78
- const typesResult = await sdk.generateAppTypes({
79
- appKeys,
80
- authenticationIds,
81
- skipWrite: false,
82
- typesOutputDirectory: resolvedTypesOutput,
83
- onProgress: handleTypesProgress,
84
- });
85
- const results = manifestResult.manifest?.apps || {};
86
- // Final summary
87
- const successfulApps = Object.keys(results).filter((manifestKey) => typesResult.writtenFiles?.[manifestKey]);
88
- if (successfulApps.length > 0) {
89
- console.log(`✅ Added ${successfulApps.length} app(s) to manifest`);
90
- }
91
- }, AddSchema);
92
- return {
93
- add,
94
- context: {
95
- meta: {
96
- add: {
97
- categories: ["utility"],
98
- inputSchema: AddSchema,
99
- },
100
- },
101
- },
102
- };
103
- };
@@ -1,8 +0,0 @@
1
- import { z } from "zod";
2
- export declare const AddSchema: z.ZodObject<{
3
- appKeys: z.ZodArray<z.ZodString>;
4
- authenticationIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
5
- configPath: z.ZodOptional<z.ZodString>;
6
- typesOutput: z.ZodOptional<z.ZodString>;
7
- }, z.core.$strip>;
8
- export type AddOptions = z.infer<typeof AddSchema>;
@@ -1,22 +0,0 @@
1
- import { z } from "zod";
2
- import { DEFAULT_CONFIG_PATH } from "@zapier/zapier-sdk";
3
- export const AddSchema = z
4
- .object({
5
- appKeys: z
6
- .array(z.string().min(1, "App key cannot be empty"))
7
- .min(1, "At least one app key is required")
8
- .describe("One or more app keys to add (e.g., 'slack', 'github', 'trello')"),
9
- authenticationIds: z
10
- .array(z.string())
11
- .optional()
12
- .describe("Authentication IDs to use for type generation (e.g., ['123', '456'])"),
13
- configPath: z
14
- .string()
15
- .optional()
16
- .describe(`Path to Zapier config file (defaults to '${DEFAULT_CONFIG_PATH}', e.g., './custom/.zapierrc')`),
17
- typesOutput: z
18
- .string()
19
- .optional()
20
- .describe("Directory for TypeScript type files (defaults to (src/lib/.)/zapier/apps/, e.g., './src/types/zapier/')"),
21
- })
22
- .describe("Add apps with manifest locking and TypeScript type generation - updates .zapierrc with app versions and generates TypeScript definition files");
@@ -1,13 +0,0 @@
1
- import type { Plugin, GetSdkType, GetContextType, ListAppsPluginProvides, ManifestPluginProvides } from "@zapier/zapier-sdk";
2
- import { BuildManifestSchema, type BuildManifestOptions, type BuildManifestResult } from "./schemas";
3
- export interface BuildManifestPluginProvides {
4
- buildManifest: (options: BuildManifestOptions) => Promise<BuildManifestResult>;
5
- context: {
6
- meta: {
7
- buildManifest: {
8
- inputSchema: typeof BuildManifestSchema;
9
- };
10
- };
11
- };
12
- }
13
- export declare const buildManifestPlugin: Plugin<GetSdkType<ListAppsPluginProvides>, GetContextType<ManifestPluginProvides>, BuildManifestPluginProvides>;
@@ -1,81 +0,0 @@
1
- import { createFunction, ZapierValidationError, ZapierUnknownError, } from "@zapier/zapier-sdk";
2
- import { BuildManifestSchema, } from "./schemas";
3
- import { createManifestEntry } from "../../utils/manifest-helpers";
4
- export const buildManifestPlugin = ({ sdk, context }) => {
5
- const buildManifest = createFunction(async function buildManifest(options) {
6
- const { appKeys, skipWrite = false, configPath, onProgress } = options;
7
- // Get apps using listApps (which respects existing manifest for version locking)
8
- onProgress?.({ type: "apps_lookup_start", count: appKeys.length });
9
- const appsIterator = sdk.listApps({ appKeys }).items();
10
- const apps = [];
11
- for await (const app of appsIterator) {
12
- apps.push(app);
13
- onProgress?.({ type: "app_found", app });
14
- }
15
- onProgress?.({ type: "apps_lookup_complete", count: apps.length });
16
- if (apps.length === 0) {
17
- return {};
18
- }
19
- let updatedManifest;
20
- // Process each app
21
- for (const app of apps) {
22
- onProgress?.({
23
- type: "app_processing_start",
24
- appKey: app.key,
25
- slug: app.slug,
26
- });
27
- try {
28
- const manifestEntry = createManifestEntry(app);
29
- onProgress?.({
30
- type: "manifest_entry_built",
31
- appKey: app.key,
32
- manifestKey: manifestEntry.implementationName,
33
- version: manifestEntry.version || "",
34
- });
35
- const { key: updatedManifestKey, manifest } = await context.updateManifestEntry({
36
- appKey: app.key,
37
- entry: manifestEntry,
38
- configPath,
39
- skipWrite,
40
- manifest: updatedManifest,
41
- });
42
- updatedManifest = manifest;
43
- onProgress?.({
44
- type: "manifest_updated",
45
- appKey: app.key,
46
- manifestKey: updatedManifestKey,
47
- version: manifestEntry.version || "",
48
- });
49
- onProgress?.({ type: "app_processing_complete", appKey: app.key });
50
- }
51
- catch (error) {
52
- const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
53
- onProgress?.({
54
- type: "app_processing_error",
55
- appKey: app.key,
56
- error: errorMessage,
57
- });
58
- if (error instanceof ZapierValidationError) {
59
- throw error; // Preserve the specific error type
60
- }
61
- else {
62
- throw new ZapierUnknownError(errorMessage, {
63
- cause: error, // Works for both Error and non-Error
64
- });
65
- }
66
- }
67
- }
68
- return { manifest: updatedManifest };
69
- }, BuildManifestSchema);
70
- return {
71
- buildManifest,
72
- context: {
73
- meta: {
74
- buildManifest: {
75
- categories: ["utility"],
76
- inputSchema: BuildManifestSchema,
77
- },
78
- },
79
- },
80
- };
81
- };