@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.
- package/CHANGELOG.md +20 -0
- package/README.md +35 -51
- package/dist/cli.cjs +750 -346
- package/dist/cli.mjs +751 -347
- package/dist/index.cjs +726 -336
- package/dist/index.mjs +727 -337
- package/dist/package.json +1 -1
- package/dist/src/plugins/add/ast-generator.d.ts +37 -0
- package/dist/src/plugins/add/ast-generator.js +403 -0
- package/dist/src/plugins/add/index.d.ts +13 -0
- package/dist/src/plugins/add/index.js +122 -0
- package/dist/src/plugins/add/schemas.d.ts +18 -0
- package/dist/src/plugins/add/schemas.js +19 -0
- package/dist/src/plugins/getLoginConfigPath/index.d.ts +15 -0
- package/dist/src/plugins/getLoginConfigPath/index.js +19 -0
- package/dist/src/plugins/getLoginConfigPath/schemas.d.ts +3 -0
- package/dist/src/plugins/getLoginConfigPath/schemas.js +5 -0
- package/dist/src/plugins/index.d.ts +2 -2
- package/dist/src/plugins/index.js +2 -2
- package/dist/src/sdk.js +3 -3
- package/dist/src/utils/cli-generator.js +15 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/plugins/add/ast-generator.ts +777 -0
- package/src/plugins/add/index.test.ts +58 -0
- package/src/plugins/add/index.ts +187 -0
- package/src/plugins/add/schemas.ts +26 -0
- package/src/plugins/getLoginConfigPath/index.ts +45 -0
- package/src/plugins/getLoginConfigPath/schemas.ts +10 -0
- package/src/plugins/index.ts +2 -2
- package/src/sdk.ts +4 -4
- package/src/utils/cli-generator.ts +22 -0
- package/tsup.config.ts +1 -1
- package/dist/src/plugins/generateTypes/index.d.ts +0 -21
- package/dist/src/plugins/generateTypes/index.js +0 -312
- package/dist/src/plugins/generateTypes/schemas.d.ts +0 -18
- package/dist/src/plugins/generateTypes/schemas.js +0 -14
- package/dist/src/plugins/getConfigPath/index.d.ts +0 -15
- package/dist/src/plugins/getConfigPath/index.js +0 -19
- package/dist/src/plugins/getConfigPath/schemas.d.ts +0 -3
- package/dist/src/plugins/getConfigPath/schemas.js +0 -5
- package/src/plugins/generateTypes/index.ts +0 -444
- package/src/plugins/generateTypes/schemas.ts +0 -23
- package/src/plugins/getConfigPath/index.ts +0 -42
- package/src/plugins/getConfigPath/schemas.ts +0 -8
package/dist/cli.cjs
CHANGED
|
@@ -14,9 +14,11 @@ var pkceChallenge = require('pkce-challenge');
|
|
|
14
14
|
var ora = require('ora');
|
|
15
15
|
var zapierSdkCliLogin = require('@zapier/zapier-sdk-cli-login');
|
|
16
16
|
var zapierSdkMcp = require('@zapier/zapier-sdk-mcp');
|
|
17
|
+
var esbuild = require('esbuild');
|
|
17
18
|
var fs = require('fs');
|
|
18
19
|
var path = require('path');
|
|
19
|
-
var
|
|
20
|
+
var ts = require('typescript');
|
|
21
|
+
var promises = require('fs/promises');
|
|
20
22
|
|
|
21
23
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
24
|
|
|
@@ -48,6 +50,7 @@ var pkceChallenge__default = /*#__PURE__*/_interopDefault(pkceChallenge);
|
|
|
48
50
|
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
49
51
|
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
50
52
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
53
|
+
var ts__namespace = /*#__PURE__*/_interopNamespace(ts);
|
|
51
54
|
|
|
52
55
|
var SchemaParameterResolver = class {
|
|
53
56
|
async resolveParameters(schema, providedParams, sdk2) {
|
|
@@ -214,12 +217,12 @@ var SchemaParameterResolver = class {
|
|
|
214
217
|
}
|
|
215
218
|
return this.createResolvableParameter([fieldName], baseSchema, isRequired);
|
|
216
219
|
}
|
|
217
|
-
createResolvableParameter(
|
|
218
|
-
if (
|
|
219
|
-
const name =
|
|
220
|
+
createResolvableParameter(path2, schema, isRequired) {
|
|
221
|
+
if (path2.length === 0) return null;
|
|
222
|
+
const name = path2[path2.length - 1];
|
|
220
223
|
return {
|
|
221
224
|
name,
|
|
222
|
-
path:
|
|
225
|
+
path: path2,
|
|
223
226
|
schema,
|
|
224
227
|
description: schema.description,
|
|
225
228
|
isRequired
|
|
@@ -379,15 +382,15 @@ Optional fields:`));
|
|
|
379
382
|
}
|
|
380
383
|
return inputs;
|
|
381
384
|
}
|
|
382
|
-
getNestedValue(obj,
|
|
383
|
-
return
|
|
385
|
+
getNestedValue(obj, path2) {
|
|
386
|
+
return path2.reduce(
|
|
384
387
|
(current, key) => current?.[key],
|
|
385
388
|
obj
|
|
386
389
|
);
|
|
387
390
|
}
|
|
388
|
-
setNestedValue(obj,
|
|
389
|
-
const lastKey =
|
|
390
|
-
const parent =
|
|
391
|
+
setNestedValue(obj, path2, value) {
|
|
392
|
+
const lastKey = path2[path2.length - 1];
|
|
393
|
+
const parent = path2.slice(0, -1).reduce((current, key) => {
|
|
391
394
|
const currentObj = current;
|
|
392
395
|
if (!(key in currentObj)) {
|
|
393
396
|
currentObj[key] = {};
|
|
@@ -763,6 +766,7 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk2) {
|
|
|
763
766
|
}
|
|
764
767
|
function addCommand(program2, commandName, config) {
|
|
765
768
|
const command = program2.command(commandName).description(config.description);
|
|
769
|
+
let hasPositionalArray = false;
|
|
766
770
|
config.parameters.forEach((param) => {
|
|
767
771
|
const kebabName = param.name.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
768
772
|
if (param.hasResolver && param.required) {
|
|
@@ -770,6 +774,19 @@ function addCommand(program2, commandName, config) {
|
|
|
770
774
|
`[${kebabName}]`,
|
|
771
775
|
param.description || `${kebabName} parameter`
|
|
772
776
|
);
|
|
777
|
+
} else if (param.required && param.type === "array" && !hasPositionalArray) {
|
|
778
|
+
hasPositionalArray = true;
|
|
779
|
+
command.argument(
|
|
780
|
+
`<${kebabName}...>`,
|
|
781
|
+
param.description || `${kebabName} parameter`
|
|
782
|
+
);
|
|
783
|
+
} else if (param.required && param.type === "array") {
|
|
784
|
+
const flags = [`--${kebabName}`];
|
|
785
|
+
const flagSignature = flags.join(", ") + ` <values...>`;
|
|
786
|
+
command.requiredOption(
|
|
787
|
+
flagSignature,
|
|
788
|
+
param.description || `${kebabName} parameter (required)`
|
|
789
|
+
);
|
|
773
790
|
} else if (param.required) {
|
|
774
791
|
command.argument(
|
|
775
792
|
`<${kebabName}>`,
|
|
@@ -1051,28 +1068,28 @@ var client_default = api;
|
|
|
1051
1068
|
|
|
1052
1069
|
// src/utils/getCallablePromise.ts
|
|
1053
1070
|
var getCallablePromise = () => {
|
|
1054
|
-
let
|
|
1071
|
+
let resolve3 = () => {
|
|
1055
1072
|
};
|
|
1056
1073
|
let reject = () => {
|
|
1057
1074
|
};
|
|
1058
1075
|
const promise = new Promise((_resolve, _reject) => {
|
|
1059
|
-
|
|
1076
|
+
resolve3 = _resolve;
|
|
1060
1077
|
reject = _reject;
|
|
1061
1078
|
});
|
|
1062
1079
|
return {
|
|
1063
1080
|
promise,
|
|
1064
|
-
resolve:
|
|
1081
|
+
resolve: resolve3,
|
|
1065
1082
|
reject
|
|
1066
1083
|
};
|
|
1067
1084
|
};
|
|
1068
1085
|
var getCallablePromise_default = getCallablePromise;
|
|
1069
1086
|
var findAvailablePort = () => {
|
|
1070
|
-
return new Promise((
|
|
1087
|
+
return new Promise((resolve3, reject) => {
|
|
1071
1088
|
let portIndex = 0;
|
|
1072
1089
|
const tryPort = (port) => {
|
|
1073
1090
|
const server = express__default.default().listen(port, () => {
|
|
1074
1091
|
server.close();
|
|
1075
|
-
|
|
1092
|
+
resolve3(port);
|
|
1076
1093
|
});
|
|
1077
1094
|
server.on("error", (err) => {
|
|
1078
1095
|
if (err.code === "EADDRINUSE") {
|
|
@@ -1162,15 +1179,15 @@ var login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
|
|
|
1162
1179
|
} finally {
|
|
1163
1180
|
process.off("SIGINT", cleanup);
|
|
1164
1181
|
process.off("SIGTERM", cleanup);
|
|
1165
|
-
await new Promise((
|
|
1182
|
+
await new Promise((resolve3) => {
|
|
1166
1183
|
const timeout = setTimeout(() => {
|
|
1167
1184
|
log_default.info("Server close timed out, forcing connection shutdown...");
|
|
1168
1185
|
connections.forEach((conn) => conn.destroy());
|
|
1169
|
-
|
|
1186
|
+
resolve3();
|
|
1170
1187
|
}, 1e3);
|
|
1171
1188
|
server.close(() => {
|
|
1172
1189
|
clearTimeout(timeout);
|
|
1173
|
-
|
|
1190
|
+
resolve3();
|
|
1174
1191
|
});
|
|
1175
1192
|
});
|
|
1176
1193
|
}
|
|
@@ -1265,323 +1282,6 @@ var mcpPlugin = ({ context }) => {
|
|
|
1265
1282
|
}
|
|
1266
1283
|
};
|
|
1267
1284
|
};
|
|
1268
|
-
var GenerateTypesSchema = zod.z.object({
|
|
1269
|
-
appKey: zapierSdk.AppKeyPropertySchema.describe("App key to generate SDK code for"),
|
|
1270
|
-
authenticationId: zapierSdk.AuthenticationIdPropertySchema.optional(),
|
|
1271
|
-
output: zapierSdk.OutputPropertySchema.optional().describe(
|
|
1272
|
-
"Output file path (defaults to generated/<appKey>.ts)"
|
|
1273
|
-
),
|
|
1274
|
-
lockFilePath: zod.z.string().optional().describe("Path to the .zapierrc lock file (defaults to .zapierrc)")
|
|
1275
|
-
}).describe("Generate TypeScript SDK code for a specific app");
|
|
1276
|
-
var generateTypesPlugin = ({ sdk: sdk2 }) => {
|
|
1277
|
-
const generateTypesWithSdk = zapierSdk.createFunction(
|
|
1278
|
-
async function generateTypesWithSdk2(options) {
|
|
1279
|
-
return await generateTypes({ ...options, sdk: sdk2 });
|
|
1280
|
-
},
|
|
1281
|
-
GenerateTypesSchema
|
|
1282
|
-
);
|
|
1283
|
-
return {
|
|
1284
|
-
generateTypes: generateTypesWithSdk,
|
|
1285
|
-
context: {
|
|
1286
|
-
meta: {
|
|
1287
|
-
generateTypes: {
|
|
1288
|
-
categories: ["utility"],
|
|
1289
|
-
inputSchema: GenerateTypesSchema
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
};
|
|
1294
|
-
};
|
|
1295
|
-
function generateFetchMethodSignature() {
|
|
1296
|
-
return ` /** Make authenticated HTTP requests through Zapier's Relay service */
|
|
1297
|
-
fetch: (options: Omit<z.infer<typeof RelayFetchSchema>, 'authenticationId'>) => Promise<Response>`;
|
|
1298
|
-
}
|
|
1299
|
-
async function generateTypes(options) {
|
|
1300
|
-
const {
|
|
1301
|
-
appKey,
|
|
1302
|
-
authenticationId,
|
|
1303
|
-
output = `./types/${appKey}.d.ts`,
|
|
1304
|
-
sdk: sdk2
|
|
1305
|
-
} = options;
|
|
1306
|
-
const { app, version } = parseAppIdentifier(appKey);
|
|
1307
|
-
const actionsResult = await sdk2.listActions({
|
|
1308
|
-
appKey: app
|
|
1309
|
-
});
|
|
1310
|
-
const actions = actionsResult.data;
|
|
1311
|
-
if (actions.length === 0) {
|
|
1312
|
-
const typeDefinitions2 = generateEmptyTypesFile(app, version);
|
|
1313
|
-
if (output) {
|
|
1314
|
-
fs__namespace.mkdirSync(path__namespace.dirname(output), { recursive: true });
|
|
1315
|
-
fs__namespace.writeFileSync(output, typeDefinitions2, "utf8");
|
|
1316
|
-
}
|
|
1317
|
-
return typeDefinitions2;
|
|
1318
|
-
}
|
|
1319
|
-
const actionsWithFields = [];
|
|
1320
|
-
if (authenticationId) {
|
|
1321
|
-
for (const action of actions) {
|
|
1322
|
-
try {
|
|
1323
|
-
const manifestEntry = sdk2.getContext().getManifestEntry(appKey);
|
|
1324
|
-
const fieldsResult = await sdk2.listInputFields({
|
|
1325
|
-
// 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
|
|
1326
|
-
appKey: manifestEntry ? appKey : action.app_key,
|
|
1327
|
-
actionKey: action.key,
|
|
1328
|
-
actionType: action.action_type,
|
|
1329
|
-
authenticationId
|
|
1330
|
-
});
|
|
1331
|
-
const fields = fieldsResult.data.map((field) => {
|
|
1332
|
-
const fieldObj = field;
|
|
1333
|
-
return {
|
|
1334
|
-
...fieldObj,
|
|
1335
|
-
required: fieldObj.is_required || fieldObj.required || false
|
|
1336
|
-
};
|
|
1337
|
-
});
|
|
1338
|
-
actionsWithFields.push({
|
|
1339
|
-
...action,
|
|
1340
|
-
inputFields: fields,
|
|
1341
|
-
name: action.title || action.key
|
|
1342
|
-
});
|
|
1343
|
-
} catch {
|
|
1344
|
-
actionsWithFields.push({
|
|
1345
|
-
...action,
|
|
1346
|
-
inputFields: [],
|
|
1347
|
-
name: action.title || action.key
|
|
1348
|
-
});
|
|
1349
|
-
}
|
|
1350
|
-
}
|
|
1351
|
-
} else {
|
|
1352
|
-
actions.forEach((action) => {
|
|
1353
|
-
actionsWithFields.push({
|
|
1354
|
-
...action,
|
|
1355
|
-
inputFields: [],
|
|
1356
|
-
name: action.title || action.key
|
|
1357
|
-
});
|
|
1358
|
-
});
|
|
1359
|
-
}
|
|
1360
|
-
const typeDefinitions = generateTypeDefinitions(
|
|
1361
|
-
app,
|
|
1362
|
-
actionsWithFields,
|
|
1363
|
-
version
|
|
1364
|
-
);
|
|
1365
|
-
if (output) {
|
|
1366
|
-
fs__namespace.mkdirSync(path__namespace.dirname(output), { recursive: true });
|
|
1367
|
-
fs__namespace.writeFileSync(output, typeDefinitions, "utf8");
|
|
1368
|
-
}
|
|
1369
|
-
return typeDefinitions;
|
|
1370
|
-
}
|
|
1371
|
-
function parseAppIdentifier(identifier) {
|
|
1372
|
-
const parts = identifier.split("@");
|
|
1373
|
-
return {
|
|
1374
|
-
app: parts[0],
|
|
1375
|
-
version: parts[1]
|
|
1376
|
-
};
|
|
1377
|
-
}
|
|
1378
|
-
function generateTypeDefinitions(appKey, actions, version) {
|
|
1379
|
-
if (actions.length === 0) {
|
|
1380
|
-
return generateEmptyTypesFile(appKey, version);
|
|
1381
|
-
}
|
|
1382
|
-
const actionsByType = actions.reduce(
|
|
1383
|
-
(acc, action) => {
|
|
1384
|
-
if (!acc[action.action_type]) {
|
|
1385
|
-
acc[action.action_type] = [];
|
|
1386
|
-
}
|
|
1387
|
-
acc[action.action_type].push(action);
|
|
1388
|
-
return acc;
|
|
1389
|
-
},
|
|
1390
|
-
{}
|
|
1391
|
-
);
|
|
1392
|
-
const appName = capitalize(appKey);
|
|
1393
|
-
const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
|
|
1394
|
-
let output = `/* eslint-disable @typescript-eslint/naming-convention */
|
|
1395
|
-
/**
|
|
1396
|
-
* Auto-generated TypeScript types for Zapier ${appKey} actions
|
|
1397
|
-
${versionComment}
|
|
1398
|
-
* Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
1399
|
-
*
|
|
1400
|
-
* Usage:
|
|
1401
|
-
* import type { ${appName}Sdk } from './path/to/this/file'
|
|
1402
|
-
* const sdk = createZapierSdk() as unknown as ${appName}Sdk
|
|
1403
|
-
*
|
|
1404
|
-
* // Direct usage (per-call auth):
|
|
1405
|
-
* await sdk.apps.${appKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
|
|
1406
|
-
*
|
|
1407
|
-
* // Factory usage (pinned auth):
|
|
1408
|
-
* const my${appName} = sdk.apps.${appKey}({ authenticationId: 123 })
|
|
1409
|
-
* await my${appName}.search.user_by_email({ inputs: { email } })
|
|
1410
|
-
*/
|
|
1411
|
-
|
|
1412
|
-
import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/zapier-sdk'
|
|
1413
|
-
import { z } from 'zod'
|
|
1414
|
-
import { RelayFetchSchema } from '@zapier/zapier-sdk'
|
|
1415
|
-
|
|
1416
|
-
`;
|
|
1417
|
-
actions.forEach((action) => {
|
|
1418
|
-
if (action.inputFields.length > 0) {
|
|
1419
|
-
const inputTypeName = `${appName}${capitalize(action.action_type)}${capitalize(
|
|
1420
|
-
sanitizeActionName(action.key)
|
|
1421
|
-
)}Inputs`;
|
|
1422
|
-
output += `interface ${inputTypeName} {
|
|
1423
|
-
`;
|
|
1424
|
-
action.inputFields.forEach((field) => {
|
|
1425
|
-
const isOptional = !field.required;
|
|
1426
|
-
const fieldType = mapFieldTypeToTypeScript(field);
|
|
1427
|
-
const description = field.helpText ? ` /** ${escapeComment(field.helpText)} */
|
|
1428
|
-
` : "";
|
|
1429
|
-
output += `${description} ${sanitizeFieldName(field.key)}${isOptional ? "?" : ""}: ${fieldType}
|
|
1430
|
-
`;
|
|
1431
|
-
});
|
|
1432
|
-
output += `}
|
|
1433
|
-
|
|
1434
|
-
`;
|
|
1435
|
-
}
|
|
1436
|
-
});
|
|
1437
|
-
Object.entries(actionsByType).forEach(([actionType, typeActions]) => {
|
|
1438
|
-
const typeName = `${appName}${capitalize(actionType)}Actions`;
|
|
1439
|
-
output += `interface ${typeName} {
|
|
1440
|
-
`;
|
|
1441
|
-
typeActions.forEach((action) => {
|
|
1442
|
-
const actionName = sanitizeActionName(action.key);
|
|
1443
|
-
const description = action.description ? ` /** ${escapeComment(action.description)} */
|
|
1444
|
-
` : "";
|
|
1445
|
-
if (action.inputFields.length > 0) {
|
|
1446
|
-
const inputTypeName = `${appName}${capitalize(action.action_type)}${capitalize(
|
|
1447
|
-
sanitizeActionName(action.key)
|
|
1448
|
-
)}Inputs`;
|
|
1449
|
-
output += `${description} ${actionName}: (options: { inputs: ${inputTypeName} } & Omit<ActionExecutionOptions, 'inputs'>) => Promise<ActionExecutionResult>
|
|
1450
|
-
`;
|
|
1451
|
-
} else {
|
|
1452
|
-
output += `${description} ${actionName}: (options?: { inputs?: Record<string, any> } & ActionExecutionOptions) => Promise<ActionExecutionResult>
|
|
1453
|
-
`;
|
|
1454
|
-
}
|
|
1455
|
-
});
|
|
1456
|
-
output += `}
|
|
1457
|
-
|
|
1458
|
-
`;
|
|
1459
|
-
});
|
|
1460
|
-
output += `interface ${appName}AppProxy {
|
|
1461
|
-
`;
|
|
1462
|
-
Object.keys(actionsByType).forEach((actionType) => {
|
|
1463
|
-
const typeName = `${appName}${capitalize(actionType)}Actions`;
|
|
1464
|
-
output += ` ${actionType}: ${typeName}
|
|
1465
|
-
`;
|
|
1466
|
-
});
|
|
1467
|
-
output += generateFetchMethodSignature() + "\n";
|
|
1468
|
-
output += `}
|
|
1469
|
-
|
|
1470
|
-
`;
|
|
1471
|
-
output += `interface ${appName}AppFactory {
|
|
1472
|
-
`;
|
|
1473
|
-
output += ` (options: { authenticationId: number }): ${appName}AppProxy
|
|
1474
|
-
`;
|
|
1475
|
-
output += `}
|
|
1476
|
-
|
|
1477
|
-
`;
|
|
1478
|
-
output += `type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
|
|
1479
|
-
|
|
1480
|
-
`;
|
|
1481
|
-
output += `export interface ${appName}Sdk {
|
|
1482
|
-
`;
|
|
1483
|
-
output += ` apps: {
|
|
1484
|
-
`;
|
|
1485
|
-
output += ` ${appKey}: ${appName}AppWithFactory
|
|
1486
|
-
`;
|
|
1487
|
-
output += ` }
|
|
1488
|
-
`;
|
|
1489
|
-
output += `}
|
|
1490
|
-
`;
|
|
1491
|
-
return output;
|
|
1492
|
-
}
|
|
1493
|
-
function generateEmptyTypesFile(appKey, version) {
|
|
1494
|
-
const appName = capitalize(appKey);
|
|
1495
|
-
const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
|
|
1496
|
-
return `/* eslint-disable @typescript-eslint/naming-convention */
|
|
1497
|
-
/**
|
|
1498
|
-
* Auto-generated TypeScript types for Zapier ${appKey} actions
|
|
1499
|
-
${versionComment}
|
|
1500
|
-
* Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
1501
|
-
*
|
|
1502
|
-
* No actions found for this app.
|
|
1503
|
-
*/
|
|
1504
|
-
|
|
1505
|
-
import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/zapier-sdk'
|
|
1506
|
-
import { z } from 'zod'
|
|
1507
|
-
import { RelayFetchSchema } from '@zapier/zapier-sdk'
|
|
1508
|
-
|
|
1509
|
-
interface ${appName}AppProxy {
|
|
1510
|
-
// No actions available
|
|
1511
|
-
${generateFetchMethodSignature()}
|
|
1512
|
-
}
|
|
1513
|
-
|
|
1514
|
-
interface ${appName}AppFactory {
|
|
1515
|
-
(options: { authenticationId: number }): ${appName}AppProxy
|
|
1516
|
-
}
|
|
1517
|
-
|
|
1518
|
-
type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
|
|
1519
|
-
|
|
1520
|
-
export interface ${appName}Sdk {
|
|
1521
|
-
apps: {
|
|
1522
|
-
${appKey}: ${appName}AppWithFactory
|
|
1523
|
-
}
|
|
1524
|
-
}
|
|
1525
|
-
`;
|
|
1526
|
-
}
|
|
1527
|
-
function capitalize(str) {
|
|
1528
|
-
return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, "");
|
|
1529
|
-
}
|
|
1530
|
-
function sanitizeActionName(actionKey) {
|
|
1531
|
-
let sanitized = actionKey.replace(/[^a-zA-Z0-9_$]/g, "_");
|
|
1532
|
-
if (/^[0-9]/.test(sanitized)) {
|
|
1533
|
-
sanitized = "_" + sanitized;
|
|
1534
|
-
}
|
|
1535
|
-
return sanitized;
|
|
1536
|
-
}
|
|
1537
|
-
function sanitizeFieldName(fieldKey) {
|
|
1538
|
-
let sanitized = fieldKey.replace(/[^a-zA-Z0-9_$]/g, "_");
|
|
1539
|
-
if (/^[0-9]/.test(sanitized)) {
|
|
1540
|
-
sanitized = "_" + sanitized;
|
|
1541
|
-
}
|
|
1542
|
-
return sanitized;
|
|
1543
|
-
}
|
|
1544
|
-
function escapeComment(comment) {
|
|
1545
|
-
return comment.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
|
|
1546
|
-
}
|
|
1547
|
-
function mapFieldTypeToTypeScript(field) {
|
|
1548
|
-
if (field.choices && field.choices.length > 0) {
|
|
1549
|
-
const choiceValues = field.choices.filter(
|
|
1550
|
-
(choice) => choice.value !== void 0 && choice.value !== null && choice.value !== ""
|
|
1551
|
-
).map(
|
|
1552
|
-
(choice) => typeof choice.value === "string" ? `"${choice.value}"` : choice.value
|
|
1553
|
-
);
|
|
1554
|
-
if (choiceValues.length > 0) {
|
|
1555
|
-
return choiceValues.join(" | ");
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
switch (field.type?.toLowerCase()) {
|
|
1559
|
-
case "string":
|
|
1560
|
-
case "text":
|
|
1561
|
-
case "email":
|
|
1562
|
-
case "url":
|
|
1563
|
-
case "password":
|
|
1564
|
-
return "string";
|
|
1565
|
-
case "integer":
|
|
1566
|
-
case "number":
|
|
1567
|
-
return "number";
|
|
1568
|
-
case "boolean":
|
|
1569
|
-
return "boolean";
|
|
1570
|
-
case "datetime":
|
|
1571
|
-
case "date":
|
|
1572
|
-
return "string";
|
|
1573
|
-
// ISO date strings
|
|
1574
|
-
case "file":
|
|
1575
|
-
return "string";
|
|
1576
|
-
// File URL or content
|
|
1577
|
-
case "array":
|
|
1578
|
-
return "any[]";
|
|
1579
|
-
case "object":
|
|
1580
|
-
return "Record<string, any>";
|
|
1581
|
-
default:
|
|
1582
|
-
return "string | number | boolean";
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
1285
|
var BundleCodeSchema = zod.z.object({
|
|
1586
1286
|
input: zod.z.string().min(1).describe("Input TypeScript file path to bundle"),
|
|
1587
1287
|
output: zapierSdk.OutputPropertySchema.optional().describe(
|
|
@@ -1673,21 +1373,725 @@ async function bundleCode(options) {
|
|
|
1673
1373
|
);
|
|
1674
1374
|
}
|
|
1675
1375
|
}
|
|
1676
|
-
var
|
|
1677
|
-
var
|
|
1678
|
-
const
|
|
1679
|
-
async function
|
|
1376
|
+
var GetLoginConfigPathSchema = zod.z.object({}).describe("Show the path to the login configuration file");
|
|
1377
|
+
var getLoginConfigPathPlugin = () => {
|
|
1378
|
+
const getLoginConfigPathWithSdk = zapierSdk.createFunction(
|
|
1379
|
+
async function getLoginConfigPathWithSdk2(_options) {
|
|
1680
1380
|
return zapierSdkCliLogin.getConfigPath();
|
|
1681
1381
|
},
|
|
1682
|
-
|
|
1382
|
+
GetLoginConfigPathSchema
|
|
1683
1383
|
);
|
|
1684
1384
|
return {
|
|
1685
|
-
|
|
1385
|
+
getLoginConfigPath: getLoginConfigPathWithSdk,
|
|
1386
|
+
context: {
|
|
1387
|
+
meta: {
|
|
1388
|
+
getLoginConfigPath: {
|
|
1389
|
+
categories: ["utility"],
|
|
1390
|
+
inputSchema: GetLoginConfigPathSchema
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
};
|
|
1396
|
+
var AddSchema = zod.z.object({
|
|
1397
|
+
appKeys: zod.z.array(zod.z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required"),
|
|
1398
|
+
authenticationIds: zod.z.array(zod.z.string()).optional().describe("Authentication IDs to use for type generation"),
|
|
1399
|
+
configPath: zod.z.string().optional().describe(
|
|
1400
|
+
`Path to Zapier config file (defaults to '${zapierSdk.DEFAULT_CONFIG_PATH}')`
|
|
1401
|
+
),
|
|
1402
|
+
typesOutput: zod.z.string().optional().describe(
|
|
1403
|
+
"Directory for TypeScript type files (defaults to (src|lib|.)/zapier/apps/)"
|
|
1404
|
+
)
|
|
1405
|
+
});
|
|
1406
|
+
var AstTypeGenerator = class {
|
|
1407
|
+
constructor() {
|
|
1408
|
+
this.factory = ts__namespace.factory;
|
|
1409
|
+
this.printer = ts__namespace.createPrinter({
|
|
1410
|
+
newLine: ts__namespace.NewLineKind.LineFeed,
|
|
1411
|
+
removeComments: false,
|
|
1412
|
+
omitTrailingSemicolon: false
|
|
1413
|
+
});
|
|
1414
|
+
}
|
|
1415
|
+
/**
|
|
1416
|
+
* Generate TypeScript types using AST for a specific app
|
|
1417
|
+
*/
|
|
1418
|
+
async generateTypes(options) {
|
|
1419
|
+
const { appKey, authenticationId, sdk: sdk2 } = options;
|
|
1420
|
+
const { app, version } = this.parseAppIdentifier(appKey);
|
|
1421
|
+
const actionsResult = await sdk2.listActions({
|
|
1422
|
+
appKey: app
|
|
1423
|
+
});
|
|
1424
|
+
const actions = actionsResult.data;
|
|
1425
|
+
if (actions.length === 0) {
|
|
1426
|
+
return this.generateEmptyTypesFile(app, version);
|
|
1427
|
+
}
|
|
1428
|
+
const actionsWithFields = [];
|
|
1429
|
+
if (authenticationId) {
|
|
1430
|
+
for (const action of actions) {
|
|
1431
|
+
try {
|
|
1432
|
+
const fieldsResult = await sdk2.listInputFields({
|
|
1433
|
+
appKey,
|
|
1434
|
+
actionKey: action.key,
|
|
1435
|
+
actionType: action.action_type,
|
|
1436
|
+
authenticationId
|
|
1437
|
+
});
|
|
1438
|
+
const fields = fieldsResult.data.map(
|
|
1439
|
+
(field) => {
|
|
1440
|
+
const fieldObj = field;
|
|
1441
|
+
return {
|
|
1442
|
+
...fieldObj,
|
|
1443
|
+
required: fieldObj.is_required || fieldObj.required || false
|
|
1444
|
+
};
|
|
1445
|
+
}
|
|
1446
|
+
);
|
|
1447
|
+
actionsWithFields.push({
|
|
1448
|
+
...action,
|
|
1449
|
+
inputFields: fields,
|
|
1450
|
+
name: action.title || action.key
|
|
1451
|
+
});
|
|
1452
|
+
} catch {
|
|
1453
|
+
actionsWithFields.push({
|
|
1454
|
+
...action,
|
|
1455
|
+
inputFields: [],
|
|
1456
|
+
name: action.title || action.key
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
} else {
|
|
1461
|
+
actions.forEach(
|
|
1462
|
+
(action) => {
|
|
1463
|
+
actionsWithFields.push({
|
|
1464
|
+
...action,
|
|
1465
|
+
inputFields: [],
|
|
1466
|
+
name: action.title || action.key,
|
|
1467
|
+
app_key: action.app_key || appKey,
|
|
1468
|
+
action_type: action.action_type || "write",
|
|
1469
|
+
title: action.title || action.key,
|
|
1470
|
+
type: "action",
|
|
1471
|
+
description: action.description || ""
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
);
|
|
1475
|
+
}
|
|
1476
|
+
const sourceFile = this.createSourceFile(app, actionsWithFields, version);
|
|
1477
|
+
return this.printer.printFile(sourceFile);
|
|
1478
|
+
}
|
|
1479
|
+
parseAppIdentifier(identifier) {
|
|
1480
|
+
const parts = identifier.split("@");
|
|
1481
|
+
return {
|
|
1482
|
+
app: parts[0],
|
|
1483
|
+
version: parts[1]
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1486
|
+
createSourceFile(appKey, actions, version) {
|
|
1487
|
+
const appName = this.capitalize(appKey);
|
|
1488
|
+
const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
|
|
1489
|
+
const headerComment = `Auto-generated TypeScript types for Zapier ${appKey} actions
|
|
1490
|
+
${versionComment.slice(3)}
|
|
1491
|
+
Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
1492
|
+
|
|
1493
|
+
This file automatically augments the base SDK types when present.
|
|
1494
|
+
No manual imports or type casting required.
|
|
1495
|
+
|
|
1496
|
+
Usage:
|
|
1497
|
+
import { createZapierSdk } from "@zapier/zapier-sdk";
|
|
1498
|
+
|
|
1499
|
+
const zapier = createZapierSdk();
|
|
1500
|
+
// Types are automatically available:
|
|
1501
|
+
await zapier.apps.${appKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
|
|
1502
|
+
|
|
1503
|
+
// Factory usage (pinned auth):
|
|
1504
|
+
const my${appName} = zapier.apps.${appKey}({ authenticationId: 123 })
|
|
1505
|
+
await my${appName}.search.user_by_email({ inputs: { email } })`;
|
|
1506
|
+
const statements = [
|
|
1507
|
+
// Import the SDK to activate module augmentation
|
|
1508
|
+
this.createImportStatement(["@zapier/zapier-sdk"]),
|
|
1509
|
+
// Import types we'll use
|
|
1510
|
+
this.createTypeImportStatement(
|
|
1511
|
+
[
|
|
1512
|
+
"ActionExecutionOptions",
|
|
1513
|
+
"ActionExecutionResult",
|
|
1514
|
+
"ZapierFetchInitOptions"
|
|
1515
|
+
],
|
|
1516
|
+
"@zapier/zapier-sdk"
|
|
1517
|
+
)
|
|
1518
|
+
];
|
|
1519
|
+
const actionsByType = this.groupActionsByType(actions);
|
|
1520
|
+
actions.forEach((action) => {
|
|
1521
|
+
if (action.inputFields.length > 0) {
|
|
1522
|
+
const inputInterface = this.createInputInterface(appName, action);
|
|
1523
|
+
statements.push(inputInterface);
|
|
1524
|
+
}
|
|
1525
|
+
});
|
|
1526
|
+
Object.entries(actionsByType).forEach(([actionType, typeActions]) => {
|
|
1527
|
+
const actionInterface = this.createActionInterface(
|
|
1528
|
+
appName,
|
|
1529
|
+
actionType,
|
|
1530
|
+
typeActions
|
|
1531
|
+
);
|
|
1532
|
+
statements.push(actionInterface);
|
|
1533
|
+
});
|
|
1534
|
+
const appProxyInterface = this.createAppProxyInterface(
|
|
1535
|
+
appName,
|
|
1536
|
+
actionsByType
|
|
1537
|
+
);
|
|
1538
|
+
statements.push(appProxyInterface);
|
|
1539
|
+
const appFactoryInterface = this.createAppFactoryInterface(appName);
|
|
1540
|
+
statements.push(appFactoryInterface);
|
|
1541
|
+
const appWithFactoryType = this.createAppWithFactoryType(appName);
|
|
1542
|
+
statements.push(appWithFactoryType);
|
|
1543
|
+
const moduleAugmentation = this.createModuleAugmentation(appKey, appName);
|
|
1544
|
+
statements.push(moduleAugmentation);
|
|
1545
|
+
statements.push(
|
|
1546
|
+
this.factory.createExportDeclaration(
|
|
1547
|
+
void 0,
|
|
1548
|
+
false,
|
|
1549
|
+
this.factory.createNamedExports([])
|
|
1550
|
+
)
|
|
1551
|
+
);
|
|
1552
|
+
const sourceFile = ts__namespace.createSourceFile(
|
|
1553
|
+
"generated.d.ts",
|
|
1554
|
+
"",
|
|
1555
|
+
ts__namespace.ScriptTarget.Latest,
|
|
1556
|
+
false,
|
|
1557
|
+
ts__namespace.ScriptKind.TS
|
|
1558
|
+
);
|
|
1559
|
+
if (statements.length > 0) {
|
|
1560
|
+
ts__namespace.addSyntheticLeadingComment(
|
|
1561
|
+
statements[0],
|
|
1562
|
+
ts__namespace.SyntaxKind.MultiLineCommentTrivia,
|
|
1563
|
+
" eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any ",
|
|
1564
|
+
true
|
|
1565
|
+
);
|
|
1566
|
+
ts__namespace.addSyntheticLeadingComment(
|
|
1567
|
+
statements[0],
|
|
1568
|
+
ts__namespace.SyntaxKind.MultiLineCommentTrivia,
|
|
1569
|
+
headerComment,
|
|
1570
|
+
true
|
|
1571
|
+
);
|
|
1572
|
+
}
|
|
1573
|
+
return this.factory.updateSourceFile(sourceFile, statements);
|
|
1574
|
+
}
|
|
1575
|
+
createImportStatement(imports, from) {
|
|
1576
|
+
if (imports.length === 1 && !from && imports[0].startsWith("@")) {
|
|
1577
|
+
return this.factory.createImportDeclaration(
|
|
1578
|
+
void 0,
|
|
1579
|
+
void 0,
|
|
1580
|
+
this.factory.createStringLiteral(imports[0]),
|
|
1581
|
+
void 0
|
|
1582
|
+
);
|
|
1583
|
+
}
|
|
1584
|
+
const fromModule = from || imports[0];
|
|
1585
|
+
const importNames = from ? imports : [];
|
|
1586
|
+
return this.factory.createImportDeclaration(
|
|
1587
|
+
void 0,
|
|
1588
|
+
importNames.length > 0 ? this.factory.createImportClause(
|
|
1589
|
+
false,
|
|
1590
|
+
void 0,
|
|
1591
|
+
this.factory.createNamedImports(
|
|
1592
|
+
importNames.map(
|
|
1593
|
+
(name) => this.factory.createImportSpecifier(
|
|
1594
|
+
false,
|
|
1595
|
+
void 0,
|
|
1596
|
+
this.factory.createIdentifier(name)
|
|
1597
|
+
)
|
|
1598
|
+
)
|
|
1599
|
+
)
|
|
1600
|
+
) : void 0,
|
|
1601
|
+
this.factory.createStringLiteral(fromModule),
|
|
1602
|
+
void 0
|
|
1603
|
+
);
|
|
1604
|
+
}
|
|
1605
|
+
createTypeImportStatement(imports, from) {
|
|
1606
|
+
return this.factory.createImportDeclaration(
|
|
1607
|
+
void 0,
|
|
1608
|
+
this.factory.createImportClause(
|
|
1609
|
+
true,
|
|
1610
|
+
// typeOnly: true
|
|
1611
|
+
void 0,
|
|
1612
|
+
this.factory.createNamedImports(
|
|
1613
|
+
imports.map(
|
|
1614
|
+
(name) => this.factory.createImportSpecifier(
|
|
1615
|
+
false,
|
|
1616
|
+
void 0,
|
|
1617
|
+
this.factory.createIdentifier(name)
|
|
1618
|
+
)
|
|
1619
|
+
)
|
|
1620
|
+
)
|
|
1621
|
+
),
|
|
1622
|
+
this.factory.createStringLiteral(from),
|
|
1623
|
+
void 0
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1626
|
+
groupActionsByType(actions) {
|
|
1627
|
+
return actions.reduce(
|
|
1628
|
+
(acc, action) => {
|
|
1629
|
+
if (!acc[action.action_type]) {
|
|
1630
|
+
acc[action.action_type] = [];
|
|
1631
|
+
}
|
|
1632
|
+
acc[action.action_type].push(action);
|
|
1633
|
+
return acc;
|
|
1634
|
+
},
|
|
1635
|
+
{}
|
|
1636
|
+
);
|
|
1637
|
+
}
|
|
1638
|
+
createInputInterface(appName, action) {
|
|
1639
|
+
const inputTypeName = `${appName}${this.capitalize(action.action_type)}${this.capitalize(
|
|
1640
|
+
this.sanitizeActionName(action.key)
|
|
1641
|
+
)}Inputs`;
|
|
1642
|
+
const properties = action.inputFields.map((field) => {
|
|
1643
|
+
const fieldType = this.mapFieldTypeToTypeNode(field);
|
|
1644
|
+
const isOptional = !field.required;
|
|
1645
|
+
let property = this.factory.createPropertySignature(
|
|
1646
|
+
void 0,
|
|
1647
|
+
this.sanitizeFieldName(field.key),
|
|
1648
|
+
isOptional ? this.factory.createToken(ts__namespace.SyntaxKind.QuestionToken) : void 0,
|
|
1649
|
+
fieldType
|
|
1650
|
+
);
|
|
1651
|
+
if (field.helpText) {
|
|
1652
|
+
property = ts__namespace.addSyntheticLeadingComment(
|
|
1653
|
+
property,
|
|
1654
|
+
ts__namespace.SyntaxKind.MultiLineCommentTrivia,
|
|
1655
|
+
`* ${this.escapeComment(field.helpText)} `,
|
|
1656
|
+
true
|
|
1657
|
+
);
|
|
1658
|
+
}
|
|
1659
|
+
return property;
|
|
1660
|
+
});
|
|
1661
|
+
return this.factory.createInterfaceDeclaration(
|
|
1662
|
+
void 0,
|
|
1663
|
+
inputTypeName,
|
|
1664
|
+
void 0,
|
|
1665
|
+
void 0,
|
|
1666
|
+
properties
|
|
1667
|
+
);
|
|
1668
|
+
}
|
|
1669
|
+
createActionInterface(appName, actionType, typeActions) {
|
|
1670
|
+
const typeName = `${appName}${this.capitalize(actionType)}Actions`;
|
|
1671
|
+
const methods = typeActions.map((action) => {
|
|
1672
|
+
const actionName = this.sanitizeActionName(action.key);
|
|
1673
|
+
let methodSignature;
|
|
1674
|
+
if (action.inputFields.length > 0) {
|
|
1675
|
+
const inputTypeName = `${appName}${this.capitalize(action.action_type)}${this.capitalize(
|
|
1676
|
+
this.sanitizeActionName(action.key)
|
|
1677
|
+
)}Inputs`;
|
|
1678
|
+
const inputsType = this.factory.createTypeLiteralNode([
|
|
1679
|
+
this.factory.createPropertySignature(
|
|
1680
|
+
void 0,
|
|
1681
|
+
"inputs",
|
|
1682
|
+
void 0,
|
|
1683
|
+
this.factory.createTypeReferenceNode(inputTypeName)
|
|
1684
|
+
)
|
|
1685
|
+
]);
|
|
1686
|
+
const omitType = this.factory.createTypeReferenceNode("Omit", [
|
|
1687
|
+
this.factory.createTypeReferenceNode("ActionExecutionOptions"),
|
|
1688
|
+
this.factory.createLiteralTypeNode(
|
|
1689
|
+
this.factory.createStringLiteral("inputs")
|
|
1690
|
+
)
|
|
1691
|
+
]);
|
|
1692
|
+
const optionsType = this.factory.createIntersectionTypeNode([
|
|
1693
|
+
inputsType,
|
|
1694
|
+
omitType
|
|
1695
|
+
]);
|
|
1696
|
+
methodSignature = this.factory.createMethodSignature(
|
|
1697
|
+
void 0,
|
|
1698
|
+
actionName,
|
|
1699
|
+
void 0,
|
|
1700
|
+
void 0,
|
|
1701
|
+
[
|
|
1702
|
+
this.factory.createParameterDeclaration(
|
|
1703
|
+
void 0,
|
|
1704
|
+
void 0,
|
|
1705
|
+
"options",
|
|
1706
|
+
void 0,
|
|
1707
|
+
optionsType
|
|
1708
|
+
)
|
|
1709
|
+
],
|
|
1710
|
+
this.factory.createTypeReferenceNode("Promise", [
|
|
1711
|
+
this.factory.createTypeReferenceNode("ActionExecutionResult")
|
|
1712
|
+
])
|
|
1713
|
+
);
|
|
1714
|
+
} else {
|
|
1715
|
+
const genericInputsType = this.factory.createTypeLiteralNode([
|
|
1716
|
+
this.factory.createPropertySignature(
|
|
1717
|
+
void 0,
|
|
1718
|
+
"inputs",
|
|
1719
|
+
this.factory.createToken(ts__namespace.SyntaxKind.QuestionToken),
|
|
1720
|
+
this.factory.createTypeReferenceNode("Record", [
|
|
1721
|
+
this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.StringKeyword),
|
|
1722
|
+
this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.AnyKeyword)
|
|
1723
|
+
])
|
|
1724
|
+
)
|
|
1725
|
+
]);
|
|
1726
|
+
const intersectionType = this.factory.createIntersectionTypeNode([
|
|
1727
|
+
genericInputsType,
|
|
1728
|
+
this.factory.createTypeReferenceNode("ActionExecutionOptions")
|
|
1729
|
+
]);
|
|
1730
|
+
methodSignature = this.factory.createMethodSignature(
|
|
1731
|
+
void 0,
|
|
1732
|
+
actionName,
|
|
1733
|
+
void 0,
|
|
1734
|
+
void 0,
|
|
1735
|
+
[
|
|
1736
|
+
this.factory.createParameterDeclaration(
|
|
1737
|
+
void 0,
|
|
1738
|
+
void 0,
|
|
1739
|
+
"options",
|
|
1740
|
+
this.factory.createToken(ts__namespace.SyntaxKind.QuestionToken),
|
|
1741
|
+
intersectionType
|
|
1742
|
+
)
|
|
1743
|
+
],
|
|
1744
|
+
this.factory.createTypeReferenceNode("Promise", [
|
|
1745
|
+
this.factory.createTypeReferenceNode("ActionExecutionResult")
|
|
1746
|
+
])
|
|
1747
|
+
);
|
|
1748
|
+
}
|
|
1749
|
+
if (action.description) {
|
|
1750
|
+
methodSignature = ts__namespace.addSyntheticLeadingComment(
|
|
1751
|
+
methodSignature,
|
|
1752
|
+
ts__namespace.SyntaxKind.MultiLineCommentTrivia,
|
|
1753
|
+
`* ${this.escapeComment(action.description)} `,
|
|
1754
|
+
true
|
|
1755
|
+
);
|
|
1756
|
+
}
|
|
1757
|
+
return methodSignature;
|
|
1758
|
+
});
|
|
1759
|
+
return this.factory.createInterfaceDeclaration(
|
|
1760
|
+
void 0,
|
|
1761
|
+
typeName,
|
|
1762
|
+
void 0,
|
|
1763
|
+
void 0,
|
|
1764
|
+
methods
|
|
1765
|
+
);
|
|
1766
|
+
}
|
|
1767
|
+
createAppProxyInterface(appName, actionsByType) {
|
|
1768
|
+
const properties = [
|
|
1769
|
+
...Object.keys(actionsByType).map(
|
|
1770
|
+
(actionType) => this.factory.createPropertySignature(
|
|
1771
|
+
void 0,
|
|
1772
|
+
actionType,
|
|
1773
|
+
void 0,
|
|
1774
|
+
this.factory.createTypeReferenceNode(
|
|
1775
|
+
`${appName}${this.capitalize(actionType)}Actions`
|
|
1776
|
+
)
|
|
1777
|
+
)
|
|
1778
|
+
),
|
|
1779
|
+
// Always include fetch method for authenticated HTTP requests
|
|
1780
|
+
this.createFetchMethodProperty()
|
|
1781
|
+
];
|
|
1782
|
+
return this.factory.createInterfaceDeclaration(
|
|
1783
|
+
void 0,
|
|
1784
|
+
`${appName}AppProxy`,
|
|
1785
|
+
void 0,
|
|
1786
|
+
void 0,
|
|
1787
|
+
properties
|
|
1788
|
+
);
|
|
1789
|
+
}
|
|
1790
|
+
createFetchMethodProperty() {
|
|
1791
|
+
let property = this.factory.createPropertySignature(
|
|
1792
|
+
void 0,
|
|
1793
|
+
"fetch",
|
|
1794
|
+
void 0,
|
|
1795
|
+
this.factory.createFunctionTypeNode(
|
|
1796
|
+
void 0,
|
|
1797
|
+
[
|
|
1798
|
+
this.factory.createParameterDeclaration(
|
|
1799
|
+
void 0,
|
|
1800
|
+
void 0,
|
|
1801
|
+
"url",
|
|
1802
|
+
void 0,
|
|
1803
|
+
this.factory.createUnionTypeNode([
|
|
1804
|
+
this.factory.createTypeReferenceNode("string"),
|
|
1805
|
+
this.factory.createTypeReferenceNode("URL")
|
|
1806
|
+
])
|
|
1807
|
+
),
|
|
1808
|
+
this.factory.createParameterDeclaration(
|
|
1809
|
+
void 0,
|
|
1810
|
+
void 0,
|
|
1811
|
+
"init",
|
|
1812
|
+
this.factory.createToken(ts__namespace.SyntaxKind.QuestionToken),
|
|
1813
|
+
this.factory.createTypeReferenceNode("ZapierFetchInitOptions")
|
|
1814
|
+
)
|
|
1815
|
+
],
|
|
1816
|
+
this.factory.createTypeReferenceNode("Promise", [
|
|
1817
|
+
this.factory.createTypeReferenceNode("Response")
|
|
1818
|
+
])
|
|
1819
|
+
)
|
|
1820
|
+
);
|
|
1821
|
+
property = ts__namespace.addSyntheticLeadingComment(
|
|
1822
|
+
property,
|
|
1823
|
+
ts__namespace.SyntaxKind.MultiLineCommentTrivia,
|
|
1824
|
+
"* Make authenticated HTTP requests through Zapier's Relay service ",
|
|
1825
|
+
true
|
|
1826
|
+
);
|
|
1827
|
+
return property;
|
|
1828
|
+
}
|
|
1829
|
+
createAppFactoryInterface(appName) {
|
|
1830
|
+
const callSignature = this.factory.createCallSignature(
|
|
1831
|
+
void 0,
|
|
1832
|
+
[
|
|
1833
|
+
this.factory.createParameterDeclaration(
|
|
1834
|
+
void 0,
|
|
1835
|
+
void 0,
|
|
1836
|
+
"options",
|
|
1837
|
+
void 0,
|
|
1838
|
+
this.factory.createTypeLiteralNode([
|
|
1839
|
+
this.factory.createPropertySignature(
|
|
1840
|
+
void 0,
|
|
1841
|
+
"authenticationId",
|
|
1842
|
+
void 0,
|
|
1843
|
+
this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.NumberKeyword)
|
|
1844
|
+
)
|
|
1845
|
+
])
|
|
1846
|
+
)
|
|
1847
|
+
],
|
|
1848
|
+
this.factory.createTypeReferenceNode(`${appName}AppProxy`)
|
|
1849
|
+
);
|
|
1850
|
+
return this.factory.createInterfaceDeclaration(
|
|
1851
|
+
void 0,
|
|
1852
|
+
`${appName}AppFactory`,
|
|
1853
|
+
void 0,
|
|
1854
|
+
void 0,
|
|
1855
|
+
[callSignature]
|
|
1856
|
+
);
|
|
1857
|
+
}
|
|
1858
|
+
createAppWithFactoryType(appName) {
|
|
1859
|
+
return this.factory.createTypeAliasDeclaration(
|
|
1860
|
+
void 0,
|
|
1861
|
+
`${appName}AppWithFactory`,
|
|
1862
|
+
void 0,
|
|
1863
|
+
this.factory.createIntersectionTypeNode([
|
|
1864
|
+
this.factory.createTypeReferenceNode(`${appName}AppFactory`),
|
|
1865
|
+
this.factory.createTypeReferenceNode(`${appName}AppProxy`)
|
|
1866
|
+
])
|
|
1867
|
+
);
|
|
1868
|
+
}
|
|
1869
|
+
createModuleAugmentation(appKey, appName) {
|
|
1870
|
+
return this.factory.createModuleDeclaration(
|
|
1871
|
+
[this.factory.createToken(ts__namespace.SyntaxKind.DeclareKeyword)],
|
|
1872
|
+
this.factory.createStringLiteral("@zapier/zapier-sdk"),
|
|
1873
|
+
this.factory.createModuleBlock([
|
|
1874
|
+
this.factory.createInterfaceDeclaration(
|
|
1875
|
+
void 0,
|
|
1876
|
+
"ZapierSdkApps",
|
|
1877
|
+
void 0,
|
|
1878
|
+
void 0,
|
|
1879
|
+
[
|
|
1880
|
+
this.factory.createPropertySignature(
|
|
1881
|
+
void 0,
|
|
1882
|
+
appKey,
|
|
1883
|
+
void 0,
|
|
1884
|
+
this.factory.createTypeReferenceNode(`${appName}AppWithFactory`)
|
|
1885
|
+
)
|
|
1886
|
+
]
|
|
1887
|
+
)
|
|
1888
|
+
])
|
|
1889
|
+
);
|
|
1890
|
+
}
|
|
1891
|
+
mapFieldTypeToTypeNode(field) {
|
|
1892
|
+
if (field.choices && field.choices.length > 0) {
|
|
1893
|
+
const choiceValues = field.choices.filter(
|
|
1894
|
+
(choice) => choice.value !== void 0 && choice.value !== null && choice.value !== ""
|
|
1895
|
+
).map(
|
|
1896
|
+
(choice) => typeof choice.value === "string" ? this.factory.createLiteralTypeNode(
|
|
1897
|
+
this.factory.createStringLiteral(choice.value)
|
|
1898
|
+
) : this.factory.createLiteralTypeNode(
|
|
1899
|
+
this.factory.createNumericLiteral(String(choice.value))
|
|
1900
|
+
)
|
|
1901
|
+
);
|
|
1902
|
+
if (choiceValues.length > 0) {
|
|
1903
|
+
return this.factory.createUnionTypeNode(choiceValues);
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
switch (field.type?.toLowerCase()) {
|
|
1907
|
+
case "string":
|
|
1908
|
+
case "text":
|
|
1909
|
+
case "email":
|
|
1910
|
+
case "url":
|
|
1911
|
+
case "password":
|
|
1912
|
+
case "datetime":
|
|
1913
|
+
case "date":
|
|
1914
|
+
case "file":
|
|
1915
|
+
return this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.StringKeyword);
|
|
1916
|
+
case "integer":
|
|
1917
|
+
case "number":
|
|
1918
|
+
return this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.NumberKeyword);
|
|
1919
|
+
case "boolean":
|
|
1920
|
+
return this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.BooleanKeyword);
|
|
1921
|
+
case "array":
|
|
1922
|
+
return this.factory.createArrayTypeNode(
|
|
1923
|
+
this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.AnyKeyword)
|
|
1924
|
+
);
|
|
1925
|
+
case "object":
|
|
1926
|
+
return this.factory.createTypeReferenceNode("Record", [
|
|
1927
|
+
this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.StringKeyword),
|
|
1928
|
+
this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.AnyKeyword)
|
|
1929
|
+
]);
|
|
1930
|
+
default:
|
|
1931
|
+
return this.factory.createUnionTypeNode([
|
|
1932
|
+
this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.StringKeyword),
|
|
1933
|
+
this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.NumberKeyword),
|
|
1934
|
+
this.factory.createKeywordTypeNode(ts__namespace.SyntaxKind.BooleanKeyword)
|
|
1935
|
+
]);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
generateEmptyTypesFile(appKey, version) {
|
|
1939
|
+
const appName = this.capitalize(appKey);
|
|
1940
|
+
const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
|
|
1941
|
+
return `/* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any */
|
|
1942
|
+
/**
|
|
1943
|
+
* Auto-generated TypeScript types for Zapier ${appKey} actions
|
|
1944
|
+
${versionComment}
|
|
1945
|
+
* Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
1946
|
+
*
|
|
1947
|
+
* No actions found for this app.
|
|
1948
|
+
*/
|
|
1949
|
+
|
|
1950
|
+
import type { ActionExecutionOptions, ActionExecutionResult, ZapierFetchInitOptions } from '@zapier/zapier-sdk'
|
|
1951
|
+
|
|
1952
|
+
interface ${appName}AppProxy {
|
|
1953
|
+
/** Make authenticated HTTP requests through Zapier's Relay service */
|
|
1954
|
+
fetch: (url: string | URL, init?: ZapierFetchInitOptions) => Promise<Response>
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
interface ${appName}AppFactory {
|
|
1958
|
+
(options: { authenticationId: number }): ${appName}AppProxy
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
|
|
1962
|
+
|
|
1963
|
+
declare module "@zapier/zapier-sdk" {
|
|
1964
|
+
interface ZapierSdkApps {
|
|
1965
|
+
${appKey}: ${appName}AppWithFactory
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
`;
|
|
1969
|
+
}
|
|
1970
|
+
capitalize(str) {
|
|
1971
|
+
return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, "");
|
|
1972
|
+
}
|
|
1973
|
+
sanitizeActionName(actionKey) {
|
|
1974
|
+
let sanitized = actionKey.replace(/[^a-zA-Z0-9_$]/g, "_");
|
|
1975
|
+
if (/^[0-9]/.test(sanitized)) {
|
|
1976
|
+
sanitized = "_" + sanitized;
|
|
1977
|
+
}
|
|
1978
|
+
return sanitized;
|
|
1979
|
+
}
|
|
1980
|
+
sanitizeFieldName(fieldKey) {
|
|
1981
|
+
let sanitized = fieldKey.replace(/[^a-zA-Z0-9_$]/g, "_");
|
|
1982
|
+
if (/^[0-9]/.test(sanitized)) {
|
|
1983
|
+
sanitized = "_" + sanitized;
|
|
1984
|
+
}
|
|
1985
|
+
return sanitized;
|
|
1986
|
+
}
|
|
1987
|
+
escapeComment(comment) {
|
|
1988
|
+
return comment.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
|
|
1989
|
+
}
|
|
1990
|
+
};
|
|
1991
|
+
async function detectTypesOutputDirectory() {
|
|
1992
|
+
const candidates = ["src", "lib"];
|
|
1993
|
+
for (const candidate of candidates) {
|
|
1994
|
+
try {
|
|
1995
|
+
await promises.access(candidate);
|
|
1996
|
+
return path.join(candidate, "zapier", "apps");
|
|
1997
|
+
} catch {
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
return "./zapier/apps/";
|
|
2001
|
+
}
|
|
2002
|
+
var addPlugin = ({ sdk: sdk2, context }) => {
|
|
2003
|
+
const add = zapierSdk.createFunction(async function add2(options) {
|
|
2004
|
+
const {
|
|
2005
|
+
appKeys,
|
|
2006
|
+
authenticationIds,
|
|
2007
|
+
configPath,
|
|
2008
|
+
typesOutput = await detectTypesOutputDirectory()
|
|
2009
|
+
} = options;
|
|
2010
|
+
const resolvedTypesOutput = path.resolve(typesOutput);
|
|
2011
|
+
await promises.mkdir(resolvedTypesOutput, { recursive: true });
|
|
2012
|
+
console.log(`\u{1F4E6} Looking up ${appKeys.length} app(s)...`);
|
|
2013
|
+
const appsIterator = sdk2.listApps({ appKeys }).items();
|
|
2014
|
+
const apps = [];
|
|
2015
|
+
for await (const app of appsIterator) {
|
|
2016
|
+
apps.push(app);
|
|
2017
|
+
}
|
|
2018
|
+
if (apps.length === 0) {
|
|
2019
|
+
console.warn("\u26A0\uFE0F No apps found");
|
|
2020
|
+
return;
|
|
2021
|
+
}
|
|
2022
|
+
let authentications = [];
|
|
2023
|
+
if (authenticationIds && authenticationIds.length > 0) {
|
|
2024
|
+
console.log(
|
|
2025
|
+
`\u{1F510} Looking up ${authenticationIds.length} authentication(s)...`
|
|
2026
|
+
);
|
|
2027
|
+
const authsIterator = sdk2.listAuthentications({ authenticationIds }).items();
|
|
2028
|
+
for await (const auth of authsIterator) {
|
|
2029
|
+
authentications.push(auth);
|
|
2030
|
+
}
|
|
2031
|
+
console.log(`\u{1F510} Found ${authentications.length} authentication(s)`);
|
|
2032
|
+
}
|
|
2033
|
+
for (const app of apps) {
|
|
2034
|
+
console.log(`\u{1F4E6} Adding ${app.key}...`);
|
|
2035
|
+
try {
|
|
2036
|
+
const currentImplementationId = app.current_implementation_id;
|
|
2037
|
+
const [implementationName, version] = currentImplementationId.split("@");
|
|
2038
|
+
if (!implementationName || !version) {
|
|
2039
|
+
console.warn(
|
|
2040
|
+
`\u26A0\uFE0F Invalid implementation ID format for '${app.key}': ${currentImplementationId}. Expected format: <implementationName>@<version>. Skipping...`
|
|
2041
|
+
);
|
|
2042
|
+
continue;
|
|
2043
|
+
}
|
|
2044
|
+
const [manifestKey] = await context.updateManifestEntry(
|
|
2045
|
+
app.key,
|
|
2046
|
+
{
|
|
2047
|
+
implementationName,
|
|
2048
|
+
version
|
|
2049
|
+
},
|
|
2050
|
+
configPath
|
|
2051
|
+
);
|
|
2052
|
+
console.log(
|
|
2053
|
+
`\u{1F4DD} Locked ${app.key} to ${implementationName}@${version} using key '${manifestKey}'`
|
|
2054
|
+
);
|
|
2055
|
+
let authenticationId;
|
|
2056
|
+
if (authentications.length > 0) {
|
|
2057
|
+
const matchingAuth = authentications.find((auth) => {
|
|
2058
|
+
return auth.app_key === app.key;
|
|
2059
|
+
});
|
|
2060
|
+
if (matchingAuth) {
|
|
2061
|
+
authenticationId = matchingAuth.id;
|
|
2062
|
+
console.log(
|
|
2063
|
+
`\u{1F510} Using authentication ${authenticationId} (${matchingAuth.title}) for ${app.key}`
|
|
2064
|
+
);
|
|
2065
|
+
} else {
|
|
2066
|
+
console.warn(`\u26A0\uFE0F No matching authentication found for ${app.key}`);
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
const typesPath = path.join(resolvedTypesOutput, `${manifestKey}.d.ts`);
|
|
2070
|
+
try {
|
|
2071
|
+
const generator = new AstTypeGenerator();
|
|
2072
|
+
const typeDefinitions = await generator.generateTypes({
|
|
2073
|
+
appKey: manifestKey,
|
|
2074
|
+
authenticationId,
|
|
2075
|
+
sdk: sdk2
|
|
2076
|
+
});
|
|
2077
|
+
await promises.writeFile(typesPath, typeDefinitions, "utf8");
|
|
2078
|
+
console.log(`\u{1F527} Generated types for ${manifestKey} at ${typesPath}`);
|
|
2079
|
+
} catch (error) {
|
|
2080
|
+
console.warn(`\u26A0\uFE0F Failed to generate types for ${app.key}: ${error}`);
|
|
2081
|
+
}
|
|
2082
|
+
} catch (error) {
|
|
2083
|
+
console.warn(`\u26A0\uFE0F Failed to process ${app.key}: ${error}`);
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
console.log(`\u2705 Added ${apps.length} app(s) to manifest`);
|
|
2087
|
+
}, AddSchema);
|
|
2088
|
+
return {
|
|
2089
|
+
add,
|
|
1686
2090
|
context: {
|
|
1687
2091
|
meta: {
|
|
1688
|
-
|
|
2092
|
+
add: {
|
|
1689
2093
|
categories: ["utility"],
|
|
1690
|
-
inputSchema:
|
|
2094
|
+
inputSchema: AddSchema
|
|
1691
2095
|
}
|
|
1692
2096
|
}
|
|
1693
2097
|
}
|
|
@@ -1699,9 +2103,9 @@ function createZapierCliSdk(options = {}) {
|
|
|
1699
2103
|
let sdk2 = zapierSdk.createZapierSdkWithoutRegistry({
|
|
1700
2104
|
debug: options.debug
|
|
1701
2105
|
});
|
|
1702
|
-
sdk2 = sdk2.addPlugin(generateTypesPlugin);
|
|
1703
2106
|
sdk2 = sdk2.addPlugin(bundleCodePlugin);
|
|
1704
|
-
sdk2 = sdk2.addPlugin(
|
|
2107
|
+
sdk2 = sdk2.addPlugin(getLoginConfigPathPlugin);
|
|
2108
|
+
sdk2 = sdk2.addPlugin(addPlugin);
|
|
1705
2109
|
sdk2 = sdk2.addPlugin(mcpPlugin);
|
|
1706
2110
|
sdk2 = sdk2.addPlugin(loginPlugin);
|
|
1707
2111
|
sdk2 = sdk2.addPlugin(logoutPlugin);
|
|
@@ -1711,7 +2115,7 @@ function createZapierCliSdk(options = {}) {
|
|
|
1711
2115
|
|
|
1712
2116
|
// package.json
|
|
1713
2117
|
var package_default = {
|
|
1714
|
-
version: "0.
|
|
2118
|
+
version: "0.9.0"};
|
|
1715
2119
|
|
|
1716
2120
|
// src/cli.ts
|
|
1717
2121
|
var program = new commander.Command();
|