@zapier/zapier-sdk-cli 0.8.3 → 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 +20 -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 +3 -3
  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
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
3
  import { z } from 'zod';
4
- import { createFunction, OutputPropertySchema, AuthenticationIdPropertySchema, AppKeyPropertySchema, createZapierSdkWithoutRegistry, registryPlugin, ZapierError, formatErrorMessage, isPositional, hasResolver, getResolutionOrderForParams, getResolver } from '@zapier/zapier-sdk';
4
+ import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH, createZapierSdkWithoutRegistry, registryPlugin, ZapierError, formatErrorMessage, isPositional, hasResolver, getResolutionOrderForParams, getResolver } from '@zapier/zapier-sdk';
5
5
  import inquirer from 'inquirer';
6
6
  import chalk3 from 'chalk';
7
7
  import util from 'util';
@@ -12,9 +12,12 @@ import pkceChallenge from 'pkce-challenge';
12
12
  import ora from 'ora';
13
13
  import { getLoggedInUser, logout, updateLogin, getConfigPath } from '@zapier/zapier-sdk-cli-login';
14
14
  import { startMcpServerAsProcess } from '@zapier/zapier-sdk-mcp';
15
+ import { buildSync } from 'esbuild';
15
16
  import * as fs from 'fs';
16
17
  import * as path from 'path';
17
- import { buildSync } from 'esbuild';
18
+ import { resolve, join } from 'path';
19
+ import * as ts from 'typescript';
20
+ import { mkdir, writeFile, access } from 'fs/promises';
18
21
 
19
22
  var SchemaParameterResolver = class {
20
23
  async resolveParameters(schema, providedParams, sdk2) {
@@ -181,12 +184,12 @@ var SchemaParameterResolver = class {
181
184
  }
182
185
  return this.createResolvableParameter([fieldName], baseSchema, isRequired);
183
186
  }
184
- createResolvableParameter(path3, schema, isRequired) {
185
- if (path3.length === 0) return null;
186
- const name = path3[path3.length - 1];
187
+ createResolvableParameter(path2, schema, isRequired) {
188
+ if (path2.length === 0) return null;
189
+ const name = path2[path2.length - 1];
187
190
  return {
188
191
  name,
189
- path: path3,
192
+ path: path2,
190
193
  schema,
191
194
  description: schema.description,
192
195
  isRequired
@@ -346,15 +349,15 @@ Optional fields:`));
346
349
  }
347
350
  return inputs;
348
351
  }
349
- getNestedValue(obj, path3) {
350
- return path3.reduce(
352
+ getNestedValue(obj, path2) {
353
+ return path2.reduce(
351
354
  (current, key) => current?.[key],
352
355
  obj
353
356
  );
354
357
  }
355
- setNestedValue(obj, path3, value) {
356
- const lastKey = path3[path3.length - 1];
357
- const parent = path3.slice(0, -1).reduce((current, key) => {
358
+ setNestedValue(obj, path2, value) {
359
+ const lastKey = path2[path2.length - 1];
360
+ const parent = path2.slice(0, -1).reduce((current, key) => {
358
361
  const currentObj = current;
359
362
  if (!(key in currentObj)) {
360
363
  currentObj[key] = {};
@@ -730,6 +733,7 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk2) {
730
733
  }
731
734
  function addCommand(program2, commandName, config) {
732
735
  const command = program2.command(commandName).description(config.description);
736
+ let hasPositionalArray = false;
733
737
  config.parameters.forEach((param) => {
734
738
  const kebabName = param.name.replace(/([A-Z])/g, "-$1").toLowerCase();
735
739
  if (param.hasResolver && param.required) {
@@ -737,6 +741,19 @@ function addCommand(program2, commandName, config) {
737
741
  `[${kebabName}]`,
738
742
  param.description || `${kebabName} parameter`
739
743
  );
744
+ } else if (param.required && param.type === "array" && !hasPositionalArray) {
745
+ hasPositionalArray = true;
746
+ command.argument(
747
+ `<${kebabName}...>`,
748
+ param.description || `${kebabName} parameter`
749
+ );
750
+ } else if (param.required && param.type === "array") {
751
+ const flags = [`--${kebabName}`];
752
+ const flagSignature = flags.join(", ") + ` <values...>`;
753
+ command.requiredOption(
754
+ flagSignature,
755
+ param.description || `${kebabName} parameter (required)`
756
+ );
740
757
  } else if (param.required) {
741
758
  command.argument(
742
759
  `<${kebabName}>`,
@@ -1018,28 +1035,28 @@ var client_default = api;
1018
1035
 
1019
1036
  // src/utils/getCallablePromise.ts
1020
1037
  var getCallablePromise = () => {
1021
- let resolve2 = () => {
1038
+ let resolve3 = () => {
1022
1039
  };
1023
1040
  let reject = () => {
1024
1041
  };
1025
1042
  const promise = new Promise((_resolve, _reject) => {
1026
- resolve2 = _resolve;
1043
+ resolve3 = _resolve;
1027
1044
  reject = _reject;
1028
1045
  });
1029
1046
  return {
1030
1047
  promise,
1031
- resolve: resolve2,
1048
+ resolve: resolve3,
1032
1049
  reject
1033
1050
  };
1034
1051
  };
1035
1052
  var getCallablePromise_default = getCallablePromise;
1036
1053
  var findAvailablePort = () => {
1037
- return new Promise((resolve2, reject) => {
1054
+ return new Promise((resolve3, reject) => {
1038
1055
  let portIndex = 0;
1039
1056
  const tryPort = (port) => {
1040
1057
  const server = express().listen(port, () => {
1041
1058
  server.close();
1042
- resolve2(port);
1059
+ resolve3(port);
1043
1060
  });
1044
1061
  server.on("error", (err) => {
1045
1062
  if (err.code === "EADDRINUSE") {
@@ -1129,15 +1146,15 @@ var login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
1129
1146
  } finally {
1130
1147
  process.off("SIGINT", cleanup);
1131
1148
  process.off("SIGTERM", cleanup);
1132
- await new Promise((resolve2) => {
1149
+ await new Promise((resolve3) => {
1133
1150
  const timeout = setTimeout(() => {
1134
1151
  log_default.info("Server close timed out, forcing connection shutdown...");
1135
1152
  connections.forEach((conn) => conn.destroy());
1136
- resolve2();
1153
+ resolve3();
1137
1154
  }, 1e3);
1138
1155
  server.close(() => {
1139
1156
  clearTimeout(timeout);
1140
- resolve2();
1157
+ resolve3();
1141
1158
  });
1142
1159
  });
1143
1160
  }
@@ -1232,323 +1249,6 @@ var mcpPlugin = ({ context }) => {
1232
1249
  }
1233
1250
  };
1234
1251
  };
1235
- var GenerateTypesSchema = z.object({
1236
- appKey: AppKeyPropertySchema.describe("App key to generate SDK code for"),
1237
- authenticationId: AuthenticationIdPropertySchema.optional(),
1238
- output: OutputPropertySchema.optional().describe(
1239
- "Output file path (defaults to generated/<appKey>.ts)"
1240
- ),
1241
- lockFilePath: z.string().optional().describe("Path to the .zapierrc lock file (defaults to .zapierrc)")
1242
- }).describe("Generate TypeScript SDK code for a specific app");
1243
- var generateTypesPlugin = ({ sdk: sdk2 }) => {
1244
- const generateTypesWithSdk = createFunction(
1245
- async function generateTypesWithSdk2(options) {
1246
- return await generateTypes({ ...options, sdk: sdk2 });
1247
- },
1248
- GenerateTypesSchema
1249
- );
1250
- return {
1251
- generateTypes: generateTypesWithSdk,
1252
- context: {
1253
- meta: {
1254
- generateTypes: {
1255
- categories: ["utility"],
1256
- inputSchema: GenerateTypesSchema
1257
- }
1258
- }
1259
- }
1260
- };
1261
- };
1262
- function generateFetchMethodSignature() {
1263
- return ` /** Make authenticated HTTP requests through Zapier's Relay service */
1264
- fetch: (options: Omit<z.infer<typeof RelayFetchSchema>, 'authenticationId'>) => Promise<Response>`;
1265
- }
1266
- async function generateTypes(options) {
1267
- const {
1268
- appKey,
1269
- authenticationId,
1270
- output = `./types/${appKey}.d.ts`,
1271
- sdk: sdk2
1272
- } = options;
1273
- const { app, version } = parseAppIdentifier(appKey);
1274
- const actionsResult = await sdk2.listActions({
1275
- appKey: app
1276
- });
1277
- const actions = actionsResult.data;
1278
- if (actions.length === 0) {
1279
- const typeDefinitions2 = generateEmptyTypesFile(app, version);
1280
- if (output) {
1281
- fs.mkdirSync(path.dirname(output), { recursive: true });
1282
- fs.writeFileSync(output, typeDefinitions2, "utf8");
1283
- }
1284
- return typeDefinitions2;
1285
- }
1286
- const actionsWithFields = [];
1287
- if (authenticationId) {
1288
- for (const action of actions) {
1289
- try {
1290
- const manifestEntry = sdk2.getContext().getManifestEntry(appKey);
1291
- const fieldsResult = await sdk2.listInputFields({
1292
- // 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
1293
- appKey: manifestEntry ? appKey : action.app_key,
1294
- actionKey: action.key,
1295
- actionType: action.action_type,
1296
- authenticationId
1297
- });
1298
- const fields = fieldsResult.data.map((field) => {
1299
- const fieldObj = field;
1300
- return {
1301
- ...fieldObj,
1302
- required: fieldObj.is_required || fieldObj.required || false
1303
- };
1304
- });
1305
- actionsWithFields.push({
1306
- ...action,
1307
- inputFields: fields,
1308
- name: action.title || action.key
1309
- });
1310
- } catch {
1311
- actionsWithFields.push({
1312
- ...action,
1313
- inputFields: [],
1314
- name: action.title || action.key
1315
- });
1316
- }
1317
- }
1318
- } else {
1319
- actions.forEach((action) => {
1320
- actionsWithFields.push({
1321
- ...action,
1322
- inputFields: [],
1323
- name: action.title || action.key
1324
- });
1325
- });
1326
- }
1327
- const typeDefinitions = generateTypeDefinitions(
1328
- app,
1329
- actionsWithFields,
1330
- version
1331
- );
1332
- if (output) {
1333
- fs.mkdirSync(path.dirname(output), { recursive: true });
1334
- fs.writeFileSync(output, typeDefinitions, "utf8");
1335
- }
1336
- return typeDefinitions;
1337
- }
1338
- function parseAppIdentifier(identifier) {
1339
- const parts = identifier.split("@");
1340
- return {
1341
- app: parts[0],
1342
- version: parts[1]
1343
- };
1344
- }
1345
- function generateTypeDefinitions(appKey, actions, version) {
1346
- if (actions.length === 0) {
1347
- return generateEmptyTypesFile(appKey, version);
1348
- }
1349
- const actionsByType = actions.reduce(
1350
- (acc, action) => {
1351
- if (!acc[action.action_type]) {
1352
- acc[action.action_type] = [];
1353
- }
1354
- acc[action.action_type].push(action);
1355
- return acc;
1356
- },
1357
- {}
1358
- );
1359
- const appName = capitalize(appKey);
1360
- const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
1361
- let output = `/* eslint-disable @typescript-eslint/naming-convention */
1362
- /**
1363
- * Auto-generated TypeScript types for Zapier ${appKey} actions
1364
- ${versionComment}
1365
- * Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
1366
- *
1367
- * Usage:
1368
- * import type { ${appName}Sdk } from './path/to/this/file'
1369
- * const sdk = createZapierSdk() as unknown as ${appName}Sdk
1370
- *
1371
- * // Direct usage (per-call auth):
1372
- * await sdk.apps.${appKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
1373
- *
1374
- * // Factory usage (pinned auth):
1375
- * const my${appName} = sdk.apps.${appKey}({ authenticationId: 123 })
1376
- * await my${appName}.search.user_by_email({ inputs: { email } })
1377
- */
1378
-
1379
- import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/zapier-sdk'
1380
- import { z } from 'zod'
1381
- import { RelayFetchSchema } from '@zapier/zapier-sdk'
1382
-
1383
- `;
1384
- actions.forEach((action) => {
1385
- if (action.inputFields.length > 0) {
1386
- const inputTypeName = `${appName}${capitalize(action.action_type)}${capitalize(
1387
- sanitizeActionName(action.key)
1388
- )}Inputs`;
1389
- output += `interface ${inputTypeName} {
1390
- `;
1391
- action.inputFields.forEach((field) => {
1392
- const isOptional = !field.required;
1393
- const fieldType = mapFieldTypeToTypeScript(field);
1394
- const description = field.helpText ? ` /** ${escapeComment(field.helpText)} */
1395
- ` : "";
1396
- output += `${description} ${sanitizeFieldName(field.key)}${isOptional ? "?" : ""}: ${fieldType}
1397
- `;
1398
- });
1399
- output += `}
1400
-
1401
- `;
1402
- }
1403
- });
1404
- Object.entries(actionsByType).forEach(([actionType, typeActions]) => {
1405
- const typeName = `${appName}${capitalize(actionType)}Actions`;
1406
- output += `interface ${typeName} {
1407
- `;
1408
- typeActions.forEach((action) => {
1409
- const actionName = sanitizeActionName(action.key);
1410
- const description = action.description ? ` /** ${escapeComment(action.description)} */
1411
- ` : "";
1412
- if (action.inputFields.length > 0) {
1413
- const inputTypeName = `${appName}${capitalize(action.action_type)}${capitalize(
1414
- sanitizeActionName(action.key)
1415
- )}Inputs`;
1416
- output += `${description} ${actionName}: (options: { inputs: ${inputTypeName} } & Omit<ActionExecutionOptions, 'inputs'>) => Promise<ActionExecutionResult>
1417
- `;
1418
- } else {
1419
- output += `${description} ${actionName}: (options?: { inputs?: Record<string, any> } & ActionExecutionOptions) => Promise<ActionExecutionResult>
1420
- `;
1421
- }
1422
- });
1423
- output += `}
1424
-
1425
- `;
1426
- });
1427
- output += `interface ${appName}AppProxy {
1428
- `;
1429
- Object.keys(actionsByType).forEach((actionType) => {
1430
- const typeName = `${appName}${capitalize(actionType)}Actions`;
1431
- output += ` ${actionType}: ${typeName}
1432
- `;
1433
- });
1434
- output += generateFetchMethodSignature() + "\n";
1435
- output += `}
1436
-
1437
- `;
1438
- output += `interface ${appName}AppFactory {
1439
- `;
1440
- output += ` (options: { authenticationId: number }): ${appName}AppProxy
1441
- `;
1442
- output += `}
1443
-
1444
- `;
1445
- output += `type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
1446
-
1447
- `;
1448
- output += `export interface ${appName}Sdk {
1449
- `;
1450
- output += ` apps: {
1451
- `;
1452
- output += ` ${appKey}: ${appName}AppWithFactory
1453
- `;
1454
- output += ` }
1455
- `;
1456
- output += `}
1457
- `;
1458
- return output;
1459
- }
1460
- function generateEmptyTypesFile(appKey, version) {
1461
- const appName = capitalize(appKey);
1462
- const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
1463
- return `/* eslint-disable @typescript-eslint/naming-convention */
1464
- /**
1465
- * Auto-generated TypeScript types for Zapier ${appKey} actions
1466
- ${versionComment}
1467
- * Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
1468
- *
1469
- * No actions found for this app.
1470
- */
1471
-
1472
- import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/zapier-sdk'
1473
- import { z } from 'zod'
1474
- import { RelayFetchSchema } from '@zapier/zapier-sdk'
1475
-
1476
- interface ${appName}AppProxy {
1477
- // No actions available
1478
- ${generateFetchMethodSignature()}
1479
- }
1480
-
1481
- interface ${appName}AppFactory {
1482
- (options: { authenticationId: number }): ${appName}AppProxy
1483
- }
1484
-
1485
- type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
1486
-
1487
- export interface ${appName}Sdk {
1488
- apps: {
1489
- ${appKey}: ${appName}AppWithFactory
1490
- }
1491
- }
1492
- `;
1493
- }
1494
- function capitalize(str) {
1495
- return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, "");
1496
- }
1497
- function sanitizeActionName(actionKey) {
1498
- let sanitized = actionKey.replace(/[^a-zA-Z0-9_$]/g, "_");
1499
- if (/^[0-9]/.test(sanitized)) {
1500
- sanitized = "_" + sanitized;
1501
- }
1502
- return sanitized;
1503
- }
1504
- function sanitizeFieldName(fieldKey) {
1505
- let sanitized = fieldKey.replace(/[^a-zA-Z0-9_$]/g, "_");
1506
- if (/^[0-9]/.test(sanitized)) {
1507
- sanitized = "_" + sanitized;
1508
- }
1509
- return sanitized;
1510
- }
1511
- function escapeComment(comment) {
1512
- return comment.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
1513
- }
1514
- function mapFieldTypeToTypeScript(field) {
1515
- if (field.choices && field.choices.length > 0) {
1516
- const choiceValues = field.choices.filter(
1517
- (choice) => choice.value !== void 0 && choice.value !== null && choice.value !== ""
1518
- ).map(
1519
- (choice) => typeof choice.value === "string" ? `"${choice.value}"` : choice.value
1520
- );
1521
- if (choiceValues.length > 0) {
1522
- return choiceValues.join(" | ");
1523
- }
1524
- }
1525
- switch (field.type?.toLowerCase()) {
1526
- case "string":
1527
- case "text":
1528
- case "email":
1529
- case "url":
1530
- case "password":
1531
- return "string";
1532
- case "integer":
1533
- case "number":
1534
- return "number";
1535
- case "boolean":
1536
- return "boolean";
1537
- case "datetime":
1538
- case "date":
1539
- return "string";
1540
- // ISO date strings
1541
- case "file":
1542
- return "string";
1543
- // File URL or content
1544
- case "array":
1545
- return "any[]";
1546
- case "object":
1547
- return "Record<string, any>";
1548
- default:
1549
- return "string | number | boolean";
1550
- }
1551
- }
1552
1252
  var BundleCodeSchema = z.object({
1553
1253
  input: z.string().min(1).describe("Input TypeScript file path to bundle"),
1554
1254
  output: OutputPropertySchema.optional().describe(
@@ -1640,21 +1340,725 @@ async function bundleCode(options) {
1640
1340
  );
1641
1341
  }
1642
1342
  }
1643
- var GetConfigPathSchema = z.object({}).describe("Show the path to the configuration file");
1644
- var getConfigPathPlugin = () => {
1645
- const getConfigPathWithSdk = createFunction(
1646
- async function getConfigPathWithSdk2(_options) {
1343
+ var GetLoginConfigPathSchema = z.object({}).describe("Show the path to the login configuration file");
1344
+ var getLoginConfigPathPlugin = () => {
1345
+ const getLoginConfigPathWithSdk = createFunction(
1346
+ async function getLoginConfigPathWithSdk2(_options) {
1647
1347
  return getConfigPath();
1648
1348
  },
1649
- GetConfigPathSchema
1349
+ GetLoginConfigPathSchema
1650
1350
  );
1651
1351
  return {
1652
- getConfigPath: getConfigPathWithSdk,
1352
+ getLoginConfigPath: getLoginConfigPathWithSdk,
1353
+ context: {
1354
+ meta: {
1355
+ getLoginConfigPath: {
1356
+ categories: ["utility"],
1357
+ inputSchema: GetLoginConfigPathSchema
1358
+ }
1359
+ }
1360
+ }
1361
+ };
1362
+ };
1363
+ var AddSchema = z.object({
1364
+ appKeys: z.array(z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required"),
1365
+ authenticationIds: z.array(z.string()).optional().describe("Authentication IDs to use for type generation"),
1366
+ configPath: z.string().optional().describe(
1367
+ `Path to Zapier config file (defaults to '${DEFAULT_CONFIG_PATH}')`
1368
+ ),
1369
+ typesOutput: z.string().optional().describe(
1370
+ "Directory for TypeScript type files (defaults to (src|lib|.)/zapier/apps/)"
1371
+ )
1372
+ });
1373
+ var AstTypeGenerator = class {
1374
+ constructor() {
1375
+ this.factory = ts.factory;
1376
+ this.printer = ts.createPrinter({
1377
+ newLine: ts.NewLineKind.LineFeed,
1378
+ removeComments: false,
1379
+ omitTrailingSemicolon: false
1380
+ });
1381
+ }
1382
+ /**
1383
+ * Generate TypeScript types using AST for a specific app
1384
+ */
1385
+ async generateTypes(options) {
1386
+ const { appKey, authenticationId, sdk: sdk2 } = options;
1387
+ const { app, version } = this.parseAppIdentifier(appKey);
1388
+ const actionsResult = await sdk2.listActions({
1389
+ appKey: app
1390
+ });
1391
+ const actions = actionsResult.data;
1392
+ if (actions.length === 0) {
1393
+ return this.generateEmptyTypesFile(app, version);
1394
+ }
1395
+ const actionsWithFields = [];
1396
+ if (authenticationId) {
1397
+ for (const action of actions) {
1398
+ try {
1399
+ const fieldsResult = await sdk2.listInputFields({
1400
+ appKey,
1401
+ actionKey: action.key,
1402
+ actionType: action.action_type,
1403
+ authenticationId
1404
+ });
1405
+ const fields = fieldsResult.data.map(
1406
+ (field) => {
1407
+ const fieldObj = field;
1408
+ return {
1409
+ ...fieldObj,
1410
+ required: fieldObj.is_required || fieldObj.required || false
1411
+ };
1412
+ }
1413
+ );
1414
+ actionsWithFields.push({
1415
+ ...action,
1416
+ inputFields: fields,
1417
+ name: action.title || action.key
1418
+ });
1419
+ } catch {
1420
+ actionsWithFields.push({
1421
+ ...action,
1422
+ inputFields: [],
1423
+ name: action.title || action.key
1424
+ });
1425
+ }
1426
+ }
1427
+ } else {
1428
+ actions.forEach(
1429
+ (action) => {
1430
+ actionsWithFields.push({
1431
+ ...action,
1432
+ inputFields: [],
1433
+ name: action.title || action.key,
1434
+ app_key: action.app_key || appKey,
1435
+ action_type: action.action_type || "write",
1436
+ title: action.title || action.key,
1437
+ type: "action",
1438
+ description: action.description || ""
1439
+ });
1440
+ }
1441
+ );
1442
+ }
1443
+ const sourceFile = this.createSourceFile(app, actionsWithFields, version);
1444
+ return this.printer.printFile(sourceFile);
1445
+ }
1446
+ parseAppIdentifier(identifier) {
1447
+ const parts = identifier.split("@");
1448
+ return {
1449
+ app: parts[0],
1450
+ version: parts[1]
1451
+ };
1452
+ }
1453
+ createSourceFile(appKey, actions, version) {
1454
+ const appName = this.capitalize(appKey);
1455
+ const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
1456
+ const headerComment = `Auto-generated TypeScript types for Zapier ${appKey} actions
1457
+ ${versionComment.slice(3)}
1458
+ Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
1459
+
1460
+ This file automatically augments the base SDK types when present.
1461
+ No manual imports or type casting required.
1462
+
1463
+ Usage:
1464
+ import { createZapierSdk } from "@zapier/zapier-sdk";
1465
+
1466
+ const zapier = createZapierSdk();
1467
+ // Types are automatically available:
1468
+ await zapier.apps.${appKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
1469
+
1470
+ // Factory usage (pinned auth):
1471
+ const my${appName} = zapier.apps.${appKey}({ authenticationId: 123 })
1472
+ await my${appName}.search.user_by_email({ inputs: { email } })`;
1473
+ const statements = [
1474
+ // Import the SDK to activate module augmentation
1475
+ this.createImportStatement(["@zapier/zapier-sdk"]),
1476
+ // Import types we'll use
1477
+ this.createTypeImportStatement(
1478
+ [
1479
+ "ActionExecutionOptions",
1480
+ "ActionExecutionResult",
1481
+ "ZapierFetchInitOptions"
1482
+ ],
1483
+ "@zapier/zapier-sdk"
1484
+ )
1485
+ ];
1486
+ const actionsByType = this.groupActionsByType(actions);
1487
+ actions.forEach((action) => {
1488
+ if (action.inputFields.length > 0) {
1489
+ const inputInterface = this.createInputInterface(appName, action);
1490
+ statements.push(inputInterface);
1491
+ }
1492
+ });
1493
+ Object.entries(actionsByType).forEach(([actionType, typeActions]) => {
1494
+ const actionInterface = this.createActionInterface(
1495
+ appName,
1496
+ actionType,
1497
+ typeActions
1498
+ );
1499
+ statements.push(actionInterface);
1500
+ });
1501
+ const appProxyInterface = this.createAppProxyInterface(
1502
+ appName,
1503
+ actionsByType
1504
+ );
1505
+ statements.push(appProxyInterface);
1506
+ const appFactoryInterface = this.createAppFactoryInterface(appName);
1507
+ statements.push(appFactoryInterface);
1508
+ const appWithFactoryType = this.createAppWithFactoryType(appName);
1509
+ statements.push(appWithFactoryType);
1510
+ const moduleAugmentation = this.createModuleAugmentation(appKey, appName);
1511
+ statements.push(moduleAugmentation);
1512
+ statements.push(
1513
+ this.factory.createExportDeclaration(
1514
+ void 0,
1515
+ false,
1516
+ this.factory.createNamedExports([])
1517
+ )
1518
+ );
1519
+ const sourceFile = ts.createSourceFile(
1520
+ "generated.d.ts",
1521
+ "",
1522
+ ts.ScriptTarget.Latest,
1523
+ false,
1524
+ ts.ScriptKind.TS
1525
+ );
1526
+ if (statements.length > 0) {
1527
+ ts.addSyntheticLeadingComment(
1528
+ statements[0],
1529
+ ts.SyntaxKind.MultiLineCommentTrivia,
1530
+ " eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any ",
1531
+ true
1532
+ );
1533
+ ts.addSyntheticLeadingComment(
1534
+ statements[0],
1535
+ ts.SyntaxKind.MultiLineCommentTrivia,
1536
+ headerComment,
1537
+ true
1538
+ );
1539
+ }
1540
+ return this.factory.updateSourceFile(sourceFile, statements);
1541
+ }
1542
+ createImportStatement(imports, from) {
1543
+ if (imports.length === 1 && !from && imports[0].startsWith("@")) {
1544
+ return this.factory.createImportDeclaration(
1545
+ void 0,
1546
+ void 0,
1547
+ this.factory.createStringLiteral(imports[0]),
1548
+ void 0
1549
+ );
1550
+ }
1551
+ const fromModule = from || imports[0];
1552
+ const importNames = from ? imports : [];
1553
+ return this.factory.createImportDeclaration(
1554
+ void 0,
1555
+ importNames.length > 0 ? this.factory.createImportClause(
1556
+ false,
1557
+ void 0,
1558
+ this.factory.createNamedImports(
1559
+ importNames.map(
1560
+ (name) => this.factory.createImportSpecifier(
1561
+ false,
1562
+ void 0,
1563
+ this.factory.createIdentifier(name)
1564
+ )
1565
+ )
1566
+ )
1567
+ ) : void 0,
1568
+ this.factory.createStringLiteral(fromModule),
1569
+ void 0
1570
+ );
1571
+ }
1572
+ createTypeImportStatement(imports, from) {
1573
+ return this.factory.createImportDeclaration(
1574
+ void 0,
1575
+ this.factory.createImportClause(
1576
+ true,
1577
+ // typeOnly: true
1578
+ void 0,
1579
+ this.factory.createNamedImports(
1580
+ imports.map(
1581
+ (name) => this.factory.createImportSpecifier(
1582
+ false,
1583
+ void 0,
1584
+ this.factory.createIdentifier(name)
1585
+ )
1586
+ )
1587
+ )
1588
+ ),
1589
+ this.factory.createStringLiteral(from),
1590
+ void 0
1591
+ );
1592
+ }
1593
+ groupActionsByType(actions) {
1594
+ return actions.reduce(
1595
+ (acc, action) => {
1596
+ if (!acc[action.action_type]) {
1597
+ acc[action.action_type] = [];
1598
+ }
1599
+ acc[action.action_type].push(action);
1600
+ return acc;
1601
+ },
1602
+ {}
1603
+ );
1604
+ }
1605
+ createInputInterface(appName, action) {
1606
+ const inputTypeName = `${appName}${this.capitalize(action.action_type)}${this.capitalize(
1607
+ this.sanitizeActionName(action.key)
1608
+ )}Inputs`;
1609
+ const properties = action.inputFields.map((field) => {
1610
+ const fieldType = this.mapFieldTypeToTypeNode(field);
1611
+ const isOptional = !field.required;
1612
+ let property = this.factory.createPropertySignature(
1613
+ void 0,
1614
+ this.sanitizeFieldName(field.key),
1615
+ isOptional ? this.factory.createToken(ts.SyntaxKind.QuestionToken) : void 0,
1616
+ fieldType
1617
+ );
1618
+ if (field.helpText) {
1619
+ property = ts.addSyntheticLeadingComment(
1620
+ property,
1621
+ ts.SyntaxKind.MultiLineCommentTrivia,
1622
+ `* ${this.escapeComment(field.helpText)} `,
1623
+ true
1624
+ );
1625
+ }
1626
+ return property;
1627
+ });
1628
+ return this.factory.createInterfaceDeclaration(
1629
+ void 0,
1630
+ inputTypeName,
1631
+ void 0,
1632
+ void 0,
1633
+ properties
1634
+ );
1635
+ }
1636
+ createActionInterface(appName, actionType, typeActions) {
1637
+ const typeName = `${appName}${this.capitalize(actionType)}Actions`;
1638
+ const methods = typeActions.map((action) => {
1639
+ const actionName = this.sanitizeActionName(action.key);
1640
+ let methodSignature;
1641
+ if (action.inputFields.length > 0) {
1642
+ const inputTypeName = `${appName}${this.capitalize(action.action_type)}${this.capitalize(
1643
+ this.sanitizeActionName(action.key)
1644
+ )}Inputs`;
1645
+ const inputsType = this.factory.createTypeLiteralNode([
1646
+ this.factory.createPropertySignature(
1647
+ void 0,
1648
+ "inputs",
1649
+ void 0,
1650
+ this.factory.createTypeReferenceNode(inputTypeName)
1651
+ )
1652
+ ]);
1653
+ const omitType = this.factory.createTypeReferenceNode("Omit", [
1654
+ this.factory.createTypeReferenceNode("ActionExecutionOptions"),
1655
+ this.factory.createLiteralTypeNode(
1656
+ this.factory.createStringLiteral("inputs")
1657
+ )
1658
+ ]);
1659
+ const optionsType = this.factory.createIntersectionTypeNode([
1660
+ inputsType,
1661
+ omitType
1662
+ ]);
1663
+ methodSignature = this.factory.createMethodSignature(
1664
+ void 0,
1665
+ actionName,
1666
+ void 0,
1667
+ void 0,
1668
+ [
1669
+ this.factory.createParameterDeclaration(
1670
+ void 0,
1671
+ void 0,
1672
+ "options",
1673
+ void 0,
1674
+ optionsType
1675
+ )
1676
+ ],
1677
+ this.factory.createTypeReferenceNode("Promise", [
1678
+ this.factory.createTypeReferenceNode("ActionExecutionResult")
1679
+ ])
1680
+ );
1681
+ } else {
1682
+ const genericInputsType = this.factory.createTypeLiteralNode([
1683
+ this.factory.createPropertySignature(
1684
+ void 0,
1685
+ "inputs",
1686
+ this.factory.createToken(ts.SyntaxKind.QuestionToken),
1687
+ this.factory.createTypeReferenceNode("Record", [
1688
+ this.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
1689
+ this.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)
1690
+ ])
1691
+ )
1692
+ ]);
1693
+ const intersectionType = this.factory.createIntersectionTypeNode([
1694
+ genericInputsType,
1695
+ this.factory.createTypeReferenceNode("ActionExecutionOptions")
1696
+ ]);
1697
+ methodSignature = this.factory.createMethodSignature(
1698
+ void 0,
1699
+ actionName,
1700
+ void 0,
1701
+ void 0,
1702
+ [
1703
+ this.factory.createParameterDeclaration(
1704
+ void 0,
1705
+ void 0,
1706
+ "options",
1707
+ this.factory.createToken(ts.SyntaxKind.QuestionToken),
1708
+ intersectionType
1709
+ )
1710
+ ],
1711
+ this.factory.createTypeReferenceNode("Promise", [
1712
+ this.factory.createTypeReferenceNode("ActionExecutionResult")
1713
+ ])
1714
+ );
1715
+ }
1716
+ if (action.description) {
1717
+ methodSignature = ts.addSyntheticLeadingComment(
1718
+ methodSignature,
1719
+ ts.SyntaxKind.MultiLineCommentTrivia,
1720
+ `* ${this.escapeComment(action.description)} `,
1721
+ true
1722
+ );
1723
+ }
1724
+ return methodSignature;
1725
+ });
1726
+ return this.factory.createInterfaceDeclaration(
1727
+ void 0,
1728
+ typeName,
1729
+ void 0,
1730
+ void 0,
1731
+ methods
1732
+ );
1733
+ }
1734
+ createAppProxyInterface(appName, actionsByType) {
1735
+ const properties = [
1736
+ ...Object.keys(actionsByType).map(
1737
+ (actionType) => this.factory.createPropertySignature(
1738
+ void 0,
1739
+ actionType,
1740
+ void 0,
1741
+ this.factory.createTypeReferenceNode(
1742
+ `${appName}${this.capitalize(actionType)}Actions`
1743
+ )
1744
+ )
1745
+ ),
1746
+ // Always include fetch method for authenticated HTTP requests
1747
+ this.createFetchMethodProperty()
1748
+ ];
1749
+ return this.factory.createInterfaceDeclaration(
1750
+ void 0,
1751
+ `${appName}AppProxy`,
1752
+ void 0,
1753
+ void 0,
1754
+ properties
1755
+ );
1756
+ }
1757
+ createFetchMethodProperty() {
1758
+ let property = this.factory.createPropertySignature(
1759
+ void 0,
1760
+ "fetch",
1761
+ void 0,
1762
+ this.factory.createFunctionTypeNode(
1763
+ void 0,
1764
+ [
1765
+ this.factory.createParameterDeclaration(
1766
+ void 0,
1767
+ void 0,
1768
+ "url",
1769
+ void 0,
1770
+ this.factory.createUnionTypeNode([
1771
+ this.factory.createTypeReferenceNode("string"),
1772
+ this.factory.createTypeReferenceNode("URL")
1773
+ ])
1774
+ ),
1775
+ this.factory.createParameterDeclaration(
1776
+ void 0,
1777
+ void 0,
1778
+ "init",
1779
+ this.factory.createToken(ts.SyntaxKind.QuestionToken),
1780
+ this.factory.createTypeReferenceNode("ZapierFetchInitOptions")
1781
+ )
1782
+ ],
1783
+ this.factory.createTypeReferenceNode("Promise", [
1784
+ this.factory.createTypeReferenceNode("Response")
1785
+ ])
1786
+ )
1787
+ );
1788
+ property = ts.addSyntheticLeadingComment(
1789
+ property,
1790
+ ts.SyntaxKind.MultiLineCommentTrivia,
1791
+ "* Make authenticated HTTP requests through Zapier's Relay service ",
1792
+ true
1793
+ );
1794
+ return property;
1795
+ }
1796
+ createAppFactoryInterface(appName) {
1797
+ const callSignature = this.factory.createCallSignature(
1798
+ void 0,
1799
+ [
1800
+ this.factory.createParameterDeclaration(
1801
+ void 0,
1802
+ void 0,
1803
+ "options",
1804
+ void 0,
1805
+ this.factory.createTypeLiteralNode([
1806
+ this.factory.createPropertySignature(
1807
+ void 0,
1808
+ "authenticationId",
1809
+ void 0,
1810
+ this.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
1811
+ )
1812
+ ])
1813
+ )
1814
+ ],
1815
+ this.factory.createTypeReferenceNode(`${appName}AppProxy`)
1816
+ );
1817
+ return this.factory.createInterfaceDeclaration(
1818
+ void 0,
1819
+ `${appName}AppFactory`,
1820
+ void 0,
1821
+ void 0,
1822
+ [callSignature]
1823
+ );
1824
+ }
1825
+ createAppWithFactoryType(appName) {
1826
+ return this.factory.createTypeAliasDeclaration(
1827
+ void 0,
1828
+ `${appName}AppWithFactory`,
1829
+ void 0,
1830
+ this.factory.createIntersectionTypeNode([
1831
+ this.factory.createTypeReferenceNode(`${appName}AppFactory`),
1832
+ this.factory.createTypeReferenceNode(`${appName}AppProxy`)
1833
+ ])
1834
+ );
1835
+ }
1836
+ createModuleAugmentation(appKey, appName) {
1837
+ return this.factory.createModuleDeclaration(
1838
+ [this.factory.createToken(ts.SyntaxKind.DeclareKeyword)],
1839
+ this.factory.createStringLiteral("@zapier/zapier-sdk"),
1840
+ this.factory.createModuleBlock([
1841
+ this.factory.createInterfaceDeclaration(
1842
+ void 0,
1843
+ "ZapierSdkApps",
1844
+ void 0,
1845
+ void 0,
1846
+ [
1847
+ this.factory.createPropertySignature(
1848
+ void 0,
1849
+ appKey,
1850
+ void 0,
1851
+ this.factory.createTypeReferenceNode(`${appName}AppWithFactory`)
1852
+ )
1853
+ ]
1854
+ )
1855
+ ])
1856
+ );
1857
+ }
1858
+ mapFieldTypeToTypeNode(field) {
1859
+ if (field.choices && field.choices.length > 0) {
1860
+ const choiceValues = field.choices.filter(
1861
+ (choice) => choice.value !== void 0 && choice.value !== null && choice.value !== ""
1862
+ ).map(
1863
+ (choice) => typeof choice.value === "string" ? this.factory.createLiteralTypeNode(
1864
+ this.factory.createStringLiteral(choice.value)
1865
+ ) : this.factory.createLiteralTypeNode(
1866
+ this.factory.createNumericLiteral(String(choice.value))
1867
+ )
1868
+ );
1869
+ if (choiceValues.length > 0) {
1870
+ return this.factory.createUnionTypeNode(choiceValues);
1871
+ }
1872
+ }
1873
+ switch (field.type?.toLowerCase()) {
1874
+ case "string":
1875
+ case "text":
1876
+ case "email":
1877
+ case "url":
1878
+ case "password":
1879
+ case "datetime":
1880
+ case "date":
1881
+ case "file":
1882
+ return this.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
1883
+ case "integer":
1884
+ case "number":
1885
+ return this.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
1886
+ case "boolean":
1887
+ return this.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
1888
+ case "array":
1889
+ return this.factory.createArrayTypeNode(
1890
+ this.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)
1891
+ );
1892
+ case "object":
1893
+ return this.factory.createTypeReferenceNode("Record", [
1894
+ this.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
1895
+ this.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)
1896
+ ]);
1897
+ default:
1898
+ return this.factory.createUnionTypeNode([
1899
+ this.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
1900
+ this.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
1901
+ this.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword)
1902
+ ]);
1903
+ }
1904
+ }
1905
+ generateEmptyTypesFile(appKey, version) {
1906
+ const appName = this.capitalize(appKey);
1907
+ const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
1908
+ return `/* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any */
1909
+ /**
1910
+ * Auto-generated TypeScript types for Zapier ${appKey} actions
1911
+ ${versionComment}
1912
+ * Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
1913
+ *
1914
+ * No actions found for this app.
1915
+ */
1916
+
1917
+ import type { ActionExecutionOptions, ActionExecutionResult, ZapierFetchInitOptions } from '@zapier/zapier-sdk'
1918
+
1919
+ interface ${appName}AppProxy {
1920
+ /** Make authenticated HTTP requests through Zapier's Relay service */
1921
+ fetch: (url: string | URL, init?: ZapierFetchInitOptions) => Promise<Response>
1922
+ }
1923
+
1924
+ interface ${appName}AppFactory {
1925
+ (options: { authenticationId: number }): ${appName}AppProxy
1926
+ }
1927
+
1928
+ type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
1929
+
1930
+ declare module "@zapier/zapier-sdk" {
1931
+ interface ZapierSdkApps {
1932
+ ${appKey}: ${appName}AppWithFactory
1933
+ }
1934
+ }
1935
+ `;
1936
+ }
1937
+ capitalize(str) {
1938
+ return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, "");
1939
+ }
1940
+ sanitizeActionName(actionKey) {
1941
+ let sanitized = actionKey.replace(/[^a-zA-Z0-9_$]/g, "_");
1942
+ if (/^[0-9]/.test(sanitized)) {
1943
+ sanitized = "_" + sanitized;
1944
+ }
1945
+ return sanitized;
1946
+ }
1947
+ sanitizeFieldName(fieldKey) {
1948
+ let sanitized = fieldKey.replace(/[^a-zA-Z0-9_$]/g, "_");
1949
+ if (/^[0-9]/.test(sanitized)) {
1950
+ sanitized = "_" + sanitized;
1951
+ }
1952
+ return sanitized;
1953
+ }
1954
+ escapeComment(comment) {
1955
+ return comment.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
1956
+ }
1957
+ };
1958
+ async function detectTypesOutputDirectory() {
1959
+ const candidates = ["src", "lib"];
1960
+ for (const candidate of candidates) {
1961
+ try {
1962
+ await access(candidate);
1963
+ return join(candidate, "zapier", "apps");
1964
+ } catch {
1965
+ }
1966
+ }
1967
+ return "./zapier/apps/";
1968
+ }
1969
+ var addPlugin = ({ sdk: sdk2, context }) => {
1970
+ const add = createFunction(async function add2(options) {
1971
+ const {
1972
+ appKeys,
1973
+ authenticationIds,
1974
+ configPath,
1975
+ typesOutput = await detectTypesOutputDirectory()
1976
+ } = options;
1977
+ const resolvedTypesOutput = resolve(typesOutput);
1978
+ await mkdir(resolvedTypesOutput, { recursive: true });
1979
+ console.log(`\u{1F4E6} Looking up ${appKeys.length} app(s)...`);
1980
+ const appsIterator = sdk2.listApps({ appKeys }).items();
1981
+ const apps = [];
1982
+ for await (const app of appsIterator) {
1983
+ apps.push(app);
1984
+ }
1985
+ if (apps.length === 0) {
1986
+ console.warn("\u26A0\uFE0F No apps found");
1987
+ return;
1988
+ }
1989
+ let authentications = [];
1990
+ if (authenticationIds && authenticationIds.length > 0) {
1991
+ console.log(
1992
+ `\u{1F510} Looking up ${authenticationIds.length} authentication(s)...`
1993
+ );
1994
+ const authsIterator = sdk2.listAuthentications({ authenticationIds }).items();
1995
+ for await (const auth of authsIterator) {
1996
+ authentications.push(auth);
1997
+ }
1998
+ console.log(`\u{1F510} Found ${authentications.length} authentication(s)`);
1999
+ }
2000
+ for (const app of apps) {
2001
+ console.log(`\u{1F4E6} Adding ${app.key}...`);
2002
+ try {
2003
+ const currentImplementationId = app.current_implementation_id;
2004
+ const [implementationName, version] = currentImplementationId.split("@");
2005
+ if (!implementationName || !version) {
2006
+ console.warn(
2007
+ `\u26A0\uFE0F Invalid implementation ID format for '${app.key}': ${currentImplementationId}. Expected format: <implementationName>@<version>. Skipping...`
2008
+ );
2009
+ continue;
2010
+ }
2011
+ const [manifestKey] = await context.updateManifestEntry(
2012
+ app.key,
2013
+ {
2014
+ implementationName,
2015
+ version
2016
+ },
2017
+ configPath
2018
+ );
2019
+ console.log(
2020
+ `\u{1F4DD} Locked ${app.key} to ${implementationName}@${version} using key '${manifestKey}'`
2021
+ );
2022
+ let authenticationId;
2023
+ if (authentications.length > 0) {
2024
+ const matchingAuth = authentications.find((auth) => {
2025
+ return auth.app_key === app.key;
2026
+ });
2027
+ if (matchingAuth) {
2028
+ authenticationId = matchingAuth.id;
2029
+ console.log(
2030
+ `\u{1F510} Using authentication ${authenticationId} (${matchingAuth.title}) for ${app.key}`
2031
+ );
2032
+ } else {
2033
+ console.warn(`\u26A0\uFE0F No matching authentication found for ${app.key}`);
2034
+ }
2035
+ }
2036
+ const typesPath = join(resolvedTypesOutput, `${manifestKey}.d.ts`);
2037
+ try {
2038
+ const generator = new AstTypeGenerator();
2039
+ const typeDefinitions = await generator.generateTypes({
2040
+ appKey: manifestKey,
2041
+ authenticationId,
2042
+ sdk: sdk2
2043
+ });
2044
+ await writeFile(typesPath, typeDefinitions, "utf8");
2045
+ console.log(`\u{1F527} Generated types for ${manifestKey} at ${typesPath}`);
2046
+ } catch (error) {
2047
+ console.warn(`\u26A0\uFE0F Failed to generate types for ${app.key}: ${error}`);
2048
+ }
2049
+ } catch (error) {
2050
+ console.warn(`\u26A0\uFE0F Failed to process ${app.key}: ${error}`);
2051
+ }
2052
+ }
2053
+ console.log(`\u2705 Added ${apps.length} app(s) to manifest`);
2054
+ }, AddSchema);
2055
+ return {
2056
+ add,
1653
2057
  context: {
1654
2058
  meta: {
1655
- getConfigPath: {
2059
+ add: {
1656
2060
  categories: ["utility"],
1657
- inputSchema: GetConfigPathSchema
2061
+ inputSchema: AddSchema
1658
2062
  }
1659
2063
  }
1660
2064
  }
@@ -1666,9 +2070,9 @@ function createZapierCliSdk(options = {}) {
1666
2070
  let sdk2 = createZapierSdkWithoutRegistry({
1667
2071
  debug: options.debug
1668
2072
  });
1669
- sdk2 = sdk2.addPlugin(generateTypesPlugin);
1670
2073
  sdk2 = sdk2.addPlugin(bundleCodePlugin);
1671
- sdk2 = sdk2.addPlugin(getConfigPathPlugin);
2074
+ sdk2 = sdk2.addPlugin(getLoginConfigPathPlugin);
2075
+ sdk2 = sdk2.addPlugin(addPlugin);
1672
2076
  sdk2 = sdk2.addPlugin(mcpPlugin);
1673
2077
  sdk2 = sdk2.addPlugin(loginPlugin);
1674
2078
  sdk2 = sdk2.addPlugin(logoutPlugin);
@@ -1678,7 +2082,7 @@ function createZapierCliSdk(options = {}) {
1678
2082
 
1679
2083
  // package.json
1680
2084
  var package_default = {
1681
- version: "0.8.3"};
2085
+ version: "0.9.0"};
1682
2086
 
1683
2087
  // src/cli.ts
1684
2088
  var program = new Command();