@zapier/zapier-sdk-cli 0.13.1 → 0.13.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.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH, createZapierSdkWithoutRegistry, registryPlugin } from '@zapier/zapier-sdk';
1
+ import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH, createZapierSdkWithoutRegistry, registryPlugin, toSnakeCase } from '@zapier/zapier-sdk';
2
2
  import open from 'open';
3
3
  import crypto from 'crypto';
4
4
  import express from 'express';
@@ -435,21 +435,17 @@ var AstTypeGenerator = class {
435
435
  * Generate TypeScript types using AST for a specific app
436
436
  */
437
437
  async generateTypes(options) {
438
- const { appKey, authenticationId, sdk } = options;
439
- const { app, version } = this.parseAppIdentifier(appKey);
438
+ const { app, authenticationId, sdk } = options;
440
439
  const actionsResult = await sdk.listActions({
441
- appKey: app
440
+ appKey: app.implementation_id
442
441
  });
443
442
  const actions = actionsResult.data;
444
- if (actions.length === 0) {
445
- return this.generateEmptyTypesFile(app, version);
446
- }
447
443
  const actionsWithFields = [];
448
444
  if (authenticationId) {
449
445
  for (const action of actions) {
450
446
  try {
451
447
  const fieldsResult = await sdk.listInputFields({
452
- appKey,
448
+ appKey: app.implementation_id,
453
449
  actionKey: action.key,
454
450
  actionType: action.action_type,
455
451
  authenticationId
@@ -475,7 +471,7 @@ var AstTypeGenerator = class {
475
471
  ...action,
476
472
  inputFields: [],
477
473
  name: action.title || action.key,
478
- app_key: action.app_key || appKey,
474
+ app_key: action.app_key || app.implementation_id,
479
475
  action_type: action.action_type || "write",
480
476
  title: action.title || action.key,
481
477
  type: "action",
@@ -484,20 +480,15 @@ var AstTypeGenerator = class {
484
480
  }
485
481
  );
486
482
  }
487
- const sourceFile = this.createSourceFile(app, actionsWithFields, version);
483
+ const sourceFile = this.createSourceFile(app, actionsWithFields);
488
484
  return this.printer.printFile(sourceFile);
489
485
  }
490
- parseAppIdentifier(identifier) {
491
- const parts = identifier.split("@");
492
- return {
493
- app: parts[0],
494
- version: parts[1]
495
- };
496
- }
497
- createSourceFile(appKey, actions, version) {
498
- const appName = this.capitalize(appKey);
499
- const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
500
- const headerComment = `Auto-generated TypeScript types for Zapier ${appKey} actions
486
+ createSourceFile(app, actions) {
487
+ const appName = this.getPreferredAppName(app);
488
+ const versionComment = ` * Generated for ${app.implementation_id}`;
489
+ const preferredKey = this.getPreferredProgrammaticKey(app);
490
+ const myVariableName = `my${appName}`;
491
+ const headerComment = `Auto-generated TypeScript types for Zapier ${app.key} actions
501
492
  ${versionComment.slice(3)}
502
493
  Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
503
494
 
@@ -509,11 +500,11 @@ Usage:
509
500
 
510
501
  const zapier = createZapierSdk();
511
502
  // Types are automatically available:
512
- await zapier.apps.${appKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
503
+ await zapier.apps.${preferredKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
513
504
 
514
505
  // Factory usage (pinned auth):
515
- const my${appName} = zapier.apps.${appKey}({ authenticationId: 123 })
516
- await my${appName}.search.user_by_email({ inputs: { email } })`;
506
+ const ${myVariableName} = zapier.apps.${preferredKey}({ authenticationId: 123 })
507
+ await ${myVariableName}.search.user_by_email({ inputs: { email } })`;
517
508
  const statements = [
518
509
  // Import the SDK to activate module augmentation
519
510
  this.createImportStatement(["@zapier/zapier-sdk"]),
@@ -551,7 +542,8 @@ Usage:
551
542
  statements.push(appFactoryInterface);
552
543
  const appWithFactoryType = this.createAppWithFactoryType(appName);
553
544
  statements.push(appWithFactoryType);
554
- const moduleAugmentation = this.createModuleAugmentation(appKey, appName);
545
+ const allKeys = this.getAllKeys(app);
546
+ const moduleAugmentation = this.createModuleAugmentation(allKeys, appName);
555
547
  statements.push(moduleAugmentation);
556
548
  statements.push(
557
549
  this.factory.createExportDeclaration(
@@ -877,7 +869,15 @@ Usage:
877
869
  ])
878
870
  );
879
871
  }
880
- createModuleAugmentation(appKey, appName) {
872
+ createModuleAugmentation(appKeys, appName) {
873
+ const properties = appKeys.map(
874
+ (appKey) => this.factory.createPropertySignature(
875
+ void 0,
876
+ this.createPropertyName(appKey),
877
+ void 0,
878
+ this.factory.createTypeReferenceNode(`${appName}AppWithFactory`)
879
+ )
880
+ );
881
881
  return this.factory.createModuleDeclaration(
882
882
  [this.factory.createToken(ts.SyntaxKind.DeclareKeyword)],
883
883
  this.factory.createStringLiteral("@zapier/zapier-sdk"),
@@ -887,14 +887,7 @@ Usage:
887
887
  "ZapierSdkApps",
888
888
  void 0,
889
889
  void 0,
890
- [
891
- this.factory.createPropertySignature(
892
- void 0,
893
- appKey,
894
- void 0,
895
- this.factory.createTypeReferenceNode(`${appName}AppWithFactory`)
896
- )
897
- ]
890
+ properties
898
891
  )
899
892
  ])
900
893
  );
@@ -932,38 +925,6 @@ Usage:
932
925
  ]);
933
926
  }
934
927
  }
935
- generateEmptyTypesFile(appKey, version) {
936
- const appName = this.capitalize(appKey);
937
- const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
938
- return `/* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any */
939
- /**
940
- * Auto-generated TypeScript types for Zapier ${appKey} actions
941
- ${versionComment}
942
- * Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
943
- *
944
- * No actions found for this app.
945
- */
946
-
947
- import type { ActionExecutionOptions, ActionExecutionResult, ZapierFetchInitOptions } from '@zapier/zapier-sdk'
948
-
949
- interface ${appName}AppProxy {
950
- /** Make authenticated HTTP requests through Zapier's Relay service */
951
- fetch: (url: string | URL, init?: ZapierFetchInitOptions) => Promise<Response>
952
- }
953
-
954
- interface ${appName}AppFactory {
955
- (options: { authenticationId: number }): ${appName}AppProxy
956
- }
957
-
958
- type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
959
-
960
- declare module "@zapier/zapier-sdk" {
961
- interface ZapierSdkApps {
962
- ${appKey}: ${appName}AppWithFactory
963
- }
964
- }
965
- `;
966
- }
967
928
  capitalize(str) {
968
929
  return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, "");
969
930
  }
@@ -984,6 +945,50 @@ declare module "@zapier/zapier-sdk" {
984
945
  escapeComment(comment) {
985
946
  return comment.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
986
947
  }
948
+ createPropertyName(name) {
949
+ if (this.isValidIdentifier(name)) {
950
+ return this.factory.createIdentifier(name);
951
+ } else {
952
+ return this.factory.createStringLiteral(name);
953
+ }
954
+ }
955
+ isValidIdentifier(name) {
956
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
957
+ }
958
+ getPreferredProgrammaticKey(app) {
959
+ if (app.slug) {
960
+ const snakeCaseSlug = toSnakeCase(app.slug);
961
+ if (this.isValidIdentifier(snakeCaseSlug)) {
962
+ return snakeCaseSlug;
963
+ }
964
+ }
965
+ if (this.isValidIdentifier(app.key)) {
966
+ return app.key;
967
+ }
968
+ return this.sanitizeToIdentifier(app.key);
969
+ }
970
+ getPreferredAppName(app) {
971
+ const preferredKey = this.getPreferredProgrammaticKey(app);
972
+ if (preferredKey.includes("_")) {
973
+ return preferredKey.split("_").map((word) => this.capitalize(word.toLowerCase())).join("");
974
+ }
975
+ return this.capitalize(preferredKey);
976
+ }
977
+ sanitizeToIdentifier(name) {
978
+ let sanitized = name.replace(/[^a-zA-Z0-9_$]/g, "_");
979
+ if (/^[0-9]/.test(sanitized)) {
980
+ sanitized = "_" + sanitized;
981
+ }
982
+ return sanitized;
983
+ }
984
+ getAllKeys(app) {
985
+ const allKeys = /* @__PURE__ */ new Set([app.key]);
986
+ if (app.slug) {
987
+ allKeys.add(app.slug);
988
+ allKeys.add(toSnakeCase(app.slug));
989
+ }
990
+ return Array.from(allKeys);
991
+ }
987
992
  };
988
993
  async function detectTypesOutputDirectory() {
989
994
  const candidates = ["src", "lib"];
@@ -1068,7 +1073,7 @@ var addPlugin = ({ sdk, context }) => {
1068
1073
  try {
1069
1074
  const generator = new AstTypeGenerator();
1070
1075
  const typeDefinitions = await generator.generateTypes({
1071
- appKey: manifestKey,
1076
+ app,
1072
1077
  authenticationId,
1073
1078
  sdk
1074
1079
  });
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zapier/zapier-sdk-cli",
3
- "version": "0.13.1",
3
+ "version": "0.13.2",
4
4
  "description": "Command line interface for Zapier SDK",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
@@ -1,6 +1,6 @@
1
- import type { GetSdkType, ListActionsPluginProvides, ListInputFieldsPluginProvides, ManifestPluginProvides } from "@zapier/zapier-sdk";
1
+ import type { GetSdkType, ListActionsPluginProvides, ListInputFieldsPluginProvides, ManifestPluginProvides, AppItem } from "@zapier/zapier-sdk";
2
2
  interface GenerateTypesOptions {
3
- appKey: string;
3
+ app: AppItem;
4
4
  authenticationId?: number;
5
5
  }
6
6
  /**
@@ -15,7 +15,6 @@ export declare class AstTypeGenerator {
15
15
  generateTypes(options: GenerateTypesOptions & {
16
16
  sdk: GetSdkType<ListActionsPluginProvides & ListInputFieldsPluginProvides & ManifestPluginProvides>;
17
17
  }): Promise<string>;
18
- private parseAppIdentifier;
19
18
  private createSourceFile;
20
19
  private createImportStatement;
21
20
  private createTypeImportStatement;
@@ -28,10 +27,15 @@ export declare class AstTypeGenerator {
28
27
  private createAppWithFactoryType;
29
28
  private createModuleAugmentation;
30
29
  private mapFieldTypeToTypeNode;
31
- private generateEmptyTypesFile;
32
30
  private capitalize;
33
31
  private sanitizeActionName;
34
32
  private sanitizeFieldName;
35
33
  private escapeComment;
34
+ private createPropertyName;
35
+ private isValidIdentifier;
36
+ private getPreferredProgrammaticKey;
37
+ private getPreferredAppName;
38
+ private sanitizeToIdentifier;
39
+ private getAllKeys;
36
40
  }
37
41
  export {};
@@ -1,4 +1,5 @@
1
1
  import * as ts from "typescript";
2
+ import { toSnakeCase } from "@zapier/zapier-sdk";
2
3
  /**
3
4
  * AST-based TypeScript type generator using the TypeScript Compiler API
4
5
  */
@@ -15,24 +16,19 @@ export class AstTypeGenerator {
15
16
  * Generate TypeScript types using AST for a specific app
16
17
  */
17
18
  async generateTypes(options) {
18
- const { appKey, authenticationId, sdk } = options;
19
- // Parse app identifier (support app@version format)
20
- const { app, version } = this.parseAppIdentifier(appKey);
21
- // Fetch all actions for the app
19
+ const { app, authenticationId, sdk } = options;
20
+ // Fetch all actions for the app using implementation_id for correct versioning
22
21
  const actionsResult = await sdk.listActions({
23
- appKey: app,
22
+ appKey: app.implementation_id,
24
23
  });
25
24
  const actions = actionsResult.data;
26
- if (actions.length === 0) {
27
- return this.generateEmptyTypesFile(app, version);
28
- }
29
25
  // Fetch input fields for each action
30
26
  const actionsWithFields = [];
31
27
  if (authenticationId) {
32
28
  for (const action of actions) {
33
29
  try {
34
30
  const fieldsResult = await sdk.listInputFields({
35
- appKey: appKey,
31
+ appKey: app.implementation_id,
36
32
  actionKey: action.key,
37
33
  actionType: action.action_type,
38
34
  authenticationId: authenticationId,
@@ -61,7 +57,7 @@ export class AstTypeGenerator {
61
57
  ...action,
62
58
  inputFields: [],
63
59
  name: action.title || action.key,
64
- app_key: action.app_key || appKey,
60
+ app_key: action.app_key || app.implementation_id,
65
61
  action_type: action.action_type || "write",
66
62
  title: action.title || action.key,
67
63
  type: "action",
@@ -70,24 +66,17 @@ export class AstTypeGenerator {
70
66
  });
71
67
  }
72
68
  // Generate TypeScript AST nodes
73
- const sourceFile = this.createSourceFile(app, actionsWithFields, version);
69
+ const sourceFile = this.createSourceFile(app, actionsWithFields);
74
70
  // Print the AST to string
75
71
  return this.printer.printFile(sourceFile);
76
72
  }
77
- parseAppIdentifier(identifier) {
78
- const parts = identifier.split("@");
79
- return {
80
- app: parts[0],
81
- version: parts[1],
82
- };
83
- }
84
- createSourceFile(appKey, actions, version) {
85
- const appName = this.capitalize(appKey);
86
- const versionComment = version
87
- ? ` * Generated for ${appKey}@${version}`
88
- : ` * Generated for ${appKey}`;
73
+ createSourceFile(app, actions) {
74
+ const appName = this.getPreferredAppName(app);
75
+ const versionComment = ` * Generated for ${app.implementation_id}`;
76
+ const preferredKey = this.getPreferredProgrammaticKey(app);
77
+ const myVariableName = `my${appName}`;
89
78
  // Create header comment
90
- const headerComment = `Auto-generated TypeScript types for Zapier ${appKey} actions
79
+ const headerComment = `Auto-generated TypeScript types for Zapier ${app.key} actions
91
80
  ${versionComment.slice(3)}
92
81
  Generated on: ${new Date().toISOString()}
93
82
 
@@ -99,11 +88,11 @@ Usage:
99
88
 
100
89
  const zapier = createZapierSdk();
101
90
  // Types are automatically available:
102
- await zapier.apps.${appKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
91
+ await zapier.apps.${preferredKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
103
92
 
104
93
  // Factory usage (pinned auth):
105
- const my${appName} = zapier.apps.${appKey}({ authenticationId: 123 })
106
- await my${appName}.search.user_by_email({ inputs: { email } })`;
94
+ const ${myVariableName} = zapier.apps.${preferredKey}({ authenticationId: 123 })
95
+ await ${myVariableName}.search.user_by_email({ inputs: { email } })`;
107
96
  const statements = [
108
97
  // Import the SDK to activate module augmentation
109
98
  this.createImportStatement(["@zapier/zapier-sdk"]),
@@ -138,7 +127,8 @@ Usage:
138
127
  const appWithFactoryType = this.createAppWithFactoryType(appName);
139
128
  statements.push(appWithFactoryType);
140
129
  // Generate module augmentation for automatic type integration
141
- const moduleAugmentation = this.createModuleAugmentation(appKey, appName);
130
+ const allKeys = this.getAllKeys(app);
131
+ const moduleAugmentation = this.createModuleAugmentation(allKeys, appName);
142
132
  statements.push(moduleAugmentation);
143
133
  // Add empty export to make this a module
144
134
  statements.push(this.factory.createExportDeclaration(undefined, false, this.factory.createNamedExports([])));
@@ -280,13 +270,13 @@ Usage:
280
270
  this.factory.createTypeReferenceNode(`${appName}AppProxy`),
281
271
  ]));
282
272
  }
283
- createModuleAugmentation(appKey, appName) {
273
+ createModuleAugmentation(appKeys, appName) {
284
274
  // Create: declare module "@zapier/zapier-sdk" { interface ZapierSdkApps { [appKey]: AppWithFactory } }
285
275
  // This creates a new interface that we can merge with ZapierSdk
276
+ // Create properties for all keys (main key + other_keys)
277
+ const properties = appKeys.map((appKey) => this.factory.createPropertySignature(undefined, this.createPropertyName(appKey), undefined, this.factory.createTypeReferenceNode(`${appName}AppWithFactory`)));
286
278
  return this.factory.createModuleDeclaration([this.factory.createToken(ts.SyntaxKind.DeclareKeyword)], this.factory.createStringLiteral("@zapier/zapier-sdk"), this.factory.createModuleBlock([
287
- this.factory.createInterfaceDeclaration(undefined, "ZapierSdkApps", undefined, undefined, [
288
- this.factory.createPropertySignature(undefined, appKey, undefined, this.factory.createTypeReferenceNode(`${appName}AppWithFactory`)),
289
- ]),
279
+ this.factory.createInterfaceDeclaration(undefined, "ZapierSdkApps", undefined, undefined, properties),
290
280
  ]));
291
281
  }
292
282
  mapFieldTypeToTypeNode(field) {
@@ -324,40 +314,6 @@ Usage:
324
314
  ]);
325
315
  }
326
316
  }
327
- generateEmptyTypesFile(appKey, version) {
328
- const appName = this.capitalize(appKey);
329
- const versionComment = version
330
- ? ` * Generated for ${appKey}@${version}`
331
- : ` * Generated for ${appKey}`;
332
- return `/* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any */
333
- /**
334
- * Auto-generated TypeScript types for Zapier ${appKey} actions
335
- ${versionComment}
336
- * Generated on: ${new Date().toISOString()}
337
- *
338
- * No actions found for this app.
339
- */
340
-
341
- import type { ActionExecutionOptions, ActionExecutionResult, ZapierFetchInitOptions } from '@zapier/zapier-sdk'
342
-
343
- interface ${appName}AppProxy {
344
- /** Make authenticated HTTP requests through Zapier's Relay service */
345
- fetch: (url: string | URL, init?: ZapierFetchInitOptions) => Promise<Response>
346
- }
347
-
348
- interface ${appName}AppFactory {
349
- (options: { authenticationId: number }): ${appName}AppProxy
350
- }
351
-
352
- type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
353
-
354
- declare module "@zapier/zapier-sdk" {
355
- interface ZapierSdkApps {
356
- ${appKey}: ${appName}AppWithFactory
357
- }
358
- }
359
- `;
360
- }
361
317
  capitalize(str) {
362
318
  return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, "");
363
319
  }
@@ -383,4 +339,64 @@ declare module "@zapier/zapier-sdk" {
383
339
  // Escape comment text to prevent breaking the JSDoc comment
384
340
  return comment.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
385
341
  }
342
+ createPropertyName(name) {
343
+ // Check if the name is a valid JavaScript identifier
344
+ if (this.isValidIdentifier(name)) {
345
+ return this.factory.createIdentifier(name);
346
+ }
347
+ else {
348
+ // Use string literal for invalid identifiers (e.g., contains dashes)
349
+ return this.factory.createStringLiteral(name);
350
+ }
351
+ }
352
+ isValidIdentifier(name) {
353
+ // JavaScript identifier rules: must start with letter, $, or _,
354
+ // followed by letters, digits, $, or _
355
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
356
+ }
357
+ getPreferredProgrammaticKey(app) {
358
+ // If we have a slug, convert it to snake_case as the preferred programmatic key
359
+ if (app.slug) {
360
+ const snakeCaseSlug = toSnakeCase(app.slug);
361
+ if (this.isValidIdentifier(snakeCaseSlug)) {
362
+ return snakeCaseSlug;
363
+ }
364
+ }
365
+ // Otherwise, use the main key if it's a valid identifier
366
+ if (this.isValidIdentifier(app.key)) {
367
+ return app.key;
368
+ }
369
+ // Fallback: sanitize the key to make it a valid identifier
370
+ return this.sanitizeToIdentifier(app.key);
371
+ }
372
+ getPreferredAppName(app) {
373
+ const preferredKey = this.getPreferredProgrammaticKey(app);
374
+ // If it's snake_case, convert to PascalCase
375
+ if (preferredKey.includes("_")) {
376
+ return preferredKey
377
+ .split("_")
378
+ .map((word) => this.capitalize(word.toLowerCase()))
379
+ .join("");
380
+ }
381
+ // Otherwise, capitalize first letter for PascalCase
382
+ return this.capitalize(preferredKey);
383
+ }
384
+ sanitizeToIdentifier(name) {
385
+ // Convert any string to a valid JavaScript identifier
386
+ let sanitized = name.replace(/[^a-zA-Z0-9_$]/g, "_");
387
+ // If it starts with a number, prepend an underscore
388
+ if (/^[0-9]/.test(sanitized)) {
389
+ sanitized = "_" + sanitized;
390
+ }
391
+ return sanitized;
392
+ }
393
+ getAllKeys(app) {
394
+ // Return all possible keys for this app
395
+ const allKeys = new Set([app.key]);
396
+ if (app.slug) {
397
+ allKeys.add(app.slug);
398
+ allKeys.add(toSnakeCase(app.slug));
399
+ }
400
+ return Array.from(allKeys);
401
+ }
386
402
  }
@@ -87,7 +87,7 @@ export const addPlugin = ({ sdk, context }) => {
87
87
  // Use AST-based generator directly
88
88
  const generator = new AstTypeGenerator();
89
89
  const typeDefinitions = await generator.generateTypes({
90
- appKey: manifestKey,
90
+ app,
91
91
  authenticationId,
92
92
  sdk,
93
93
  });