@zapier/zapier-sdk-cli 0.6.3 → 0.6.4

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 (91) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +115 -12
  3. package/bin/{zapier-sdk.js → zapier-sdk.mjs} +1 -1
  4. package/dist/cli.cjs +1711 -0
  5. package/dist/cli.d.mts +1 -0
  6. package/dist/cli.d.ts +1 -0
  7. package/dist/{cli.js → cli.mjs} +204 -456
  8. package/dist/index.cjs +770 -0
  9. package/dist/index.d.mts +12 -0
  10. package/dist/index.d.ts +12 -0
  11. package/dist/index.mjs +739 -0
  12. package/dist/package.json +67 -0
  13. package/dist/src/cli.js +8 -14
  14. package/dist/src/index.d.ts +1 -0
  15. package/dist/src/index.js +1 -1
  16. package/dist/src/plugins/bundleCode/index.d.ts +15 -0
  17. package/dist/src/{commands/bundle-code → plugins/bundleCode}/index.js +19 -1
  18. package/dist/src/{commands/bundle-code → plugins/bundleCode}/schemas.d.ts +8 -8
  19. package/dist/src/{commands/bundle-code → plugins/bundleCode}/schemas.js +4 -4
  20. package/dist/src/plugins/generateTypes/index.d.ts +21 -0
  21. package/dist/src/{commands/generate-types → plugins/generateTypes}/index.js +18 -0
  22. package/dist/src/{commands/generate-types → plugins/generateTypes}/schemas.d.ts +0 -3
  23. package/dist/src/{commands/generate-types → plugins/generateTypes}/schemas.js +1 -2
  24. package/dist/src/plugins/getConfigPath/index.d.ts +15 -0
  25. package/dist/src/plugins/getConfigPath/index.js +19 -0
  26. package/dist/src/plugins/getConfigPath/schemas.d.ts +3 -0
  27. package/dist/src/plugins/getConfigPath/schemas.js +5 -0
  28. package/dist/src/plugins/index.d.ts +6 -0
  29. package/dist/src/plugins/index.js +6 -0
  30. package/dist/src/plugins/login/index.d.ts +15 -0
  31. package/dist/src/plugins/login/index.js +26 -0
  32. package/dist/src/plugins/login/schemas.d.ts +9 -0
  33. package/dist/src/plugins/login/schemas.js +10 -0
  34. package/dist/src/plugins/logout/index.d.ts +15 -0
  35. package/dist/src/plugins/logout/index.js +18 -0
  36. package/dist/src/plugins/logout/schemas.d.ts +3 -0
  37. package/dist/src/plugins/logout/schemas.js +5 -0
  38. package/dist/src/plugins/mcp/index.d.ts +15 -0
  39. package/dist/src/plugins/mcp/index.js +24 -0
  40. package/dist/src/plugins/mcp/schemas.d.ts +9 -0
  41. package/dist/src/plugins/mcp/schemas.js +10 -0
  42. package/dist/src/sdk.d.ts +9 -0
  43. package/dist/src/sdk.js +22 -0
  44. package/dist/src/utils/cli-generator.js +4 -0
  45. package/dist/tsconfig.tsbuildinfo +1 -1
  46. package/package.json +19 -8
  47. package/src/cli.ts +8 -21
  48. package/src/index.ts +2 -0
  49. package/src/{commands/bundle-code → plugins/bundleCode}/index.ts +39 -2
  50. package/src/{commands/bundle-code → plugins/bundleCode}/schemas.ts +4 -4
  51. package/src/{commands/generate-types → plugins/generateTypes}/index.ts +56 -3
  52. package/src/{commands/generate-types → plugins/generateTypes}/schemas.ts +0 -4
  53. package/src/plugins/getConfigPath/index.ts +42 -0
  54. package/src/plugins/getConfigPath/schemas.ts +8 -0
  55. package/src/plugins/index.ts +6 -0
  56. package/src/plugins/login/index.ts +48 -0
  57. package/src/plugins/login/schemas.ts +13 -0
  58. package/src/plugins/logout/index.ts +37 -0
  59. package/src/plugins/logout/schemas.ts +8 -0
  60. package/src/plugins/mcp/index.ts +43 -0
  61. package/src/plugins/mcp/schemas.ts +13 -0
  62. package/src/sdk.ts +43 -0
  63. package/src/utils/cli-generator.ts +5 -0
  64. package/tsconfig.build.json +15 -3
  65. package/tsconfig.json +2 -2
  66. package/tsup.config.ts +10 -4
  67. package/bin/zsdk.js +0 -4
  68. package/dist/index.js +0 -0
  69. package/dist/src/commands/bundle-code/cli.d.ts +0 -2
  70. package/dist/src/commands/bundle-code/cli.js +0 -77
  71. package/dist/src/commands/bundle-code/index.d.ts +0 -5
  72. package/dist/src/commands/configPath.d.ts +0 -2
  73. package/dist/src/commands/configPath.js +0 -9
  74. package/dist/src/commands/generate-types/cli.d.ts +0 -2
  75. package/dist/src/commands/generate-types/cli.js +0 -84
  76. package/dist/src/commands/generate-types/index.d.ts +0 -8
  77. package/dist/src/commands/index.d.ts +0 -6
  78. package/dist/src/commands/index.js +0 -6
  79. package/dist/src/commands/login.d.ts +0 -2
  80. package/dist/src/commands/login.js +0 -25
  81. package/dist/src/commands/logout.d.ts +0 -2
  82. package/dist/src/commands/logout.js +0 -16
  83. package/dist/src/commands/mcp.d.ts +0 -2
  84. package/dist/src/commands/mcp.js +0 -11
  85. package/src/commands/bundle-code/cli.ts +0 -118
  86. package/src/commands/configPath.ts +0 -10
  87. package/src/commands/generate-types/cli.ts +0 -126
  88. package/src/commands/index.ts +0 -6
  89. package/src/commands/login.ts +0 -34
  90. package/src/commands/logout.ts +0 -19
  91. package/src/commands/mcp.ts +0 -14
package/dist/index.cjs ADDED
@@ -0,0 +1,770 @@
1
+ 'use strict';
2
+
3
+ var zapierSdk = require('@zapier/zapier-sdk');
4
+ var open = require('open');
5
+ var crypto = require('crypto');
6
+ var express = require('express');
7
+ var pkceChallenge = require('pkce-challenge');
8
+ var ora = require('ora');
9
+ var chalk = require('chalk');
10
+ var zapierSdkCliLogin = require('@zapier/zapier-sdk-cli-login');
11
+ var zod = require('zod');
12
+ var zapierSdkMcp = require('@zapier/zapier-sdk-mcp');
13
+ var fs = require('fs');
14
+ var path = require('path');
15
+ var esbuild = require('esbuild');
16
+
17
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
18
+
19
+ function _interopNamespace(e) {
20
+ if (e && e.__esModule) return e;
21
+ var n = Object.create(null);
22
+ if (e) {
23
+ Object.keys(e).forEach(function (k) {
24
+ if (k !== 'default') {
25
+ var d = Object.getOwnPropertyDescriptor(e, k);
26
+ Object.defineProperty(n, k, d.get ? d : {
27
+ enumerable: true,
28
+ get: function () { return e[k]; }
29
+ });
30
+ }
31
+ });
32
+ }
33
+ n.default = e;
34
+ return Object.freeze(n);
35
+ }
36
+
37
+ var open__default = /*#__PURE__*/_interopDefault(open);
38
+ var crypto__default = /*#__PURE__*/_interopDefault(crypto);
39
+ var express__default = /*#__PURE__*/_interopDefault(express);
40
+ var pkceChallenge__default = /*#__PURE__*/_interopDefault(pkceChallenge);
41
+ var ora__default = /*#__PURE__*/_interopDefault(ora);
42
+ var chalk__default = /*#__PURE__*/_interopDefault(chalk);
43
+ var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
44
+ var path__namespace = /*#__PURE__*/_interopNamespace(path);
45
+
46
+ // src/sdk.ts
47
+
48
+ // src/utils/constants.ts
49
+ var ZAPIER_BASE = "https://zapier.com";
50
+ var LOGIN_CLIENT_ID = "K5eEnRE9TTmSFATdkkWhKF8NOKwoiOnYAyIqJjae";
51
+ var LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
52
+ var LOGIN_TIMEOUT_MS = 3e5;
53
+ var AUTH_MODE_HEADER = "X-Auth";
54
+ var spinPromise = async (promise, text) => {
55
+ const spinner = ora__default.default(text).start();
56
+ try {
57
+ const result = await promise;
58
+ spinner.succeed();
59
+ return result;
60
+ } catch (error) {
61
+ spinner.fail();
62
+ throw error;
63
+ }
64
+ };
65
+ var log = {
66
+ info: (message, ...args) => {
67
+ console.log(chalk__default.default.blue("\u2139"), message, ...args);
68
+ },
69
+ error: (message, ...args) => {
70
+ console.error(chalk__default.default.red("\u2716"), message, ...args);
71
+ },
72
+ success: (message, ...args) => {
73
+ console.log(chalk__default.default.green("\u2713"), message, ...args);
74
+ },
75
+ warn: (message, ...args) => {
76
+ console.log(chalk__default.default.yellow("\u26A0"), message, ...args);
77
+ }
78
+ };
79
+ var log_default = log;
80
+
81
+ // src/utils/api/client.ts
82
+ var createApiClient = () => {
83
+ const post = async (url, data, options = {}) => {
84
+ const { headers = {} } = options;
85
+ const response = await fetch(url, {
86
+ method: "POST",
87
+ headers: {
88
+ "Content-Type": "application/x-www-form-urlencoded",
89
+ Connection: "close",
90
+ ...headers
91
+ },
92
+ body: new URLSearchParams(data)
93
+ });
94
+ if (!response.ok) {
95
+ throw new Error(`${response.status} ${response.statusText}`);
96
+ }
97
+ const responseData = await response.json();
98
+ return {
99
+ data: responseData,
100
+ status: response.status
101
+ };
102
+ };
103
+ return {
104
+ post
105
+ };
106
+ };
107
+ var api = createApiClient();
108
+ var client_default = api;
109
+
110
+ // src/utils/getCallablePromise.ts
111
+ var getCallablePromise = () => {
112
+ let resolve2 = () => {
113
+ };
114
+ let reject = () => {
115
+ };
116
+ const promise = new Promise((_resolve, _reject) => {
117
+ resolve2 = _resolve;
118
+ reject = _reject;
119
+ });
120
+ return {
121
+ promise,
122
+ resolve: resolve2,
123
+ reject
124
+ };
125
+ };
126
+ var getCallablePromise_default = getCallablePromise;
127
+ var findAvailablePort = () => {
128
+ return new Promise((resolve2, reject) => {
129
+ let portIndex = 0;
130
+ const tryPort = (port) => {
131
+ const server = express__default.default().listen(port, () => {
132
+ server.close();
133
+ resolve2(port);
134
+ });
135
+ server.on("error", (err) => {
136
+ if (err.code === "EADDRINUSE") {
137
+ if (portIndex < LOGIN_PORTS.length) {
138
+ tryPort(LOGIN_PORTS[portIndex++]);
139
+ } else {
140
+ reject(
141
+ new Error(
142
+ `All configured OAuth callback ports are busy: ${LOGIN_PORTS.join(", ")}. Please try again later or close applications using these ports.`
143
+ )
144
+ );
145
+ }
146
+ } else {
147
+ reject(err);
148
+ }
149
+ });
150
+ };
151
+ if (LOGIN_PORTS.length > 0) {
152
+ tryPort(LOGIN_PORTS[portIndex++]);
153
+ } else {
154
+ reject(new Error("No OAuth callback ports configured"));
155
+ }
156
+ });
157
+ };
158
+ var generateRandomString = () => {
159
+ const array = new Uint32Array(28);
160
+ crypto__default.default.getRandomValues(array);
161
+ return Array.from(
162
+ array,
163
+ (dec) => ("0" + dec.toString(16)).substring(-2)
164
+ ).join("");
165
+ };
166
+ var login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
167
+ zapierSdkCliLogin.logout();
168
+ const availablePort = await findAvailablePort();
169
+ const redirectUri = `http://localhost:${availablePort}/oauth`;
170
+ log_default.info(`Using port ${availablePort} for OAuth callback`);
171
+ const { promise: promisedCode, resolve: setCode } = getCallablePromise_default();
172
+ const app = express__default.default();
173
+ app.get("/oauth", (req, res) => {
174
+ setCode(String(req.query.code));
175
+ res.setHeader("Connection", "close");
176
+ res.end("You can now close this tab and return to the CLI.");
177
+ });
178
+ const server = app.listen(availablePort);
179
+ const connections = /* @__PURE__ */ new Set();
180
+ server.on("connection", (conn) => {
181
+ connections.add(conn);
182
+ conn.on("close", () => connections.delete(conn));
183
+ });
184
+ const cleanup = () => {
185
+ server.close();
186
+ log_default.info("\n\u274C Login cancelled by user");
187
+ process.exit(0);
188
+ };
189
+ process.on("SIGINT", cleanup);
190
+ process.on("SIGTERM", cleanup);
191
+ const { code_verifier: codeVerifier, code_challenge: codeChallenge } = await pkceChallenge__default.default();
192
+ const authUrl = `${ZAPIER_BASE}/oauth/authorize/?${new URLSearchParams({
193
+ response_type: "code",
194
+ client_id: LOGIN_CLIENT_ID,
195
+ redirect_uri: redirectUri,
196
+ scope: "internal offline_access",
197
+ state: generateRandomString(),
198
+ code_challenge: codeChallenge,
199
+ code_challenge_method: "S256"
200
+ }).toString()}`;
201
+ log_default.info("Opening your browser to log in.");
202
+ log_default.info("If it doesn't open, visit:", authUrl);
203
+ open__default.default(authUrl);
204
+ try {
205
+ await spinPromise(
206
+ Promise.race([
207
+ promisedCode,
208
+ new Promise(
209
+ (_resolve, reject) => setTimeout(() => {
210
+ reject(
211
+ new Error(
212
+ `Login timed out after ${Math.round(timeoutMs / 1e3)} seconds.`
213
+ )
214
+ );
215
+ }, timeoutMs)
216
+ )
217
+ ]),
218
+ "Waiting for you to login and authorize"
219
+ );
220
+ } finally {
221
+ process.off("SIGINT", cleanup);
222
+ process.off("SIGTERM", cleanup);
223
+ await new Promise((resolve2) => {
224
+ const timeout = setTimeout(() => {
225
+ log_default.info("Server close timed out, forcing connection shutdown...");
226
+ connections.forEach((conn) => conn.destroy());
227
+ resolve2();
228
+ }, 1e3);
229
+ server.close(() => {
230
+ clearTimeout(timeout);
231
+ resolve2();
232
+ });
233
+ });
234
+ }
235
+ log_default.info("Exchanging authorization code for tokens...");
236
+ const { data } = await client_default.post(
237
+ `${ZAPIER_BASE}/oauth/token/`,
238
+ {
239
+ grant_type: "authorization_code",
240
+ code: await promisedCode,
241
+ redirect_uri: redirectUri,
242
+ client_id: LOGIN_CLIENT_ID,
243
+ code_verifier: codeVerifier
244
+ },
245
+ {
246
+ headers: {
247
+ [AUTH_MODE_HEADER]: "no",
248
+ "Content-Type": "application/x-www-form-urlencoded"
249
+ }
250
+ }
251
+ );
252
+ zapierSdkCliLogin.updateLogin(data);
253
+ log_default.info("Token exchange completed successfully");
254
+ return data.access_token;
255
+ };
256
+ var login_default = login;
257
+ var LoginSchema = zod.z.object({
258
+ timeout: zod.z.string().optional().describe("Login timeout in seconds (default: 300)")
259
+ }).describe("Log in to Zapier to access your account");
260
+
261
+ // src/plugins/login/index.ts
262
+ var loginWithSdk = zapierSdk.createFunction(async function loginWithSdk2(options) {
263
+ const timeoutSeconds = options.timeout ? parseInt(options.timeout, 10) : 300;
264
+ if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
265
+ throw new Error("Timeout must be a positive number");
266
+ }
267
+ await login_default(timeoutSeconds * 1e3);
268
+ const user = await zapierSdkCliLogin.getLoggedInUser();
269
+ console.log(`\u2705 Successfully logged in as ${user.email}`);
270
+ setTimeout(() => process.exit(0), 100);
271
+ }, LoginSchema);
272
+ var loginPlugin = () => ({
273
+ login: loginWithSdk,
274
+ context: {
275
+ meta: {
276
+ login: {
277
+ categories: ["account"],
278
+ inputSchema: LoginSchema
279
+ }
280
+ }
281
+ }
282
+ });
283
+ var LogoutSchema = zod.z.object({}).describe("Log out of your Zapier account");
284
+
285
+ // src/plugins/logout/index.ts
286
+ var logoutWithSdk = zapierSdk.createFunction(async function logoutWithSdk2(_options) {
287
+ zapierSdkCliLogin.logout();
288
+ console.log("\u2705 Successfully logged out");
289
+ }, LogoutSchema);
290
+ var logoutPlugin = () => ({
291
+ logout: logoutWithSdk,
292
+ context: {
293
+ meta: {
294
+ logout: {
295
+ categories: ["account"],
296
+ inputSchema: LogoutSchema
297
+ }
298
+ }
299
+ }
300
+ });
301
+ var McpSchema = zod.z.object({
302
+ port: zod.z.string().optional().describe("Port to listen on (for future HTTP transport)")
303
+ }).describe("Start MCP server for Zapier SDK");
304
+
305
+ // src/plugins/mcp/index.ts
306
+ var mcpPlugin = ({ context }) => {
307
+ const mcpWithSdk = zapierSdk.createFunction(async function mcpWithSdk2(options) {
308
+ const mcpOptions = {
309
+ ...options,
310
+ debug: context.options.debug
311
+ };
312
+ return await zapierSdkMcp.startMcpServerAsProcess(mcpOptions);
313
+ }, McpSchema);
314
+ return {
315
+ mcp: mcpWithSdk,
316
+ context: {
317
+ meta: {
318
+ mcp: {
319
+ categories: ["utility"],
320
+ inputSchema: McpSchema
321
+ }
322
+ }
323
+ }
324
+ };
325
+ };
326
+ var GenerateTypesSchema = zod.z.object({
327
+ appKey: zapierSdk.AppKeyPropertySchema.describe("App key to generate SDK code for"),
328
+ authenticationId: zapierSdk.AuthenticationIdPropertySchema.optional(),
329
+ output: zapierSdk.OutputPropertySchema.optional().describe(
330
+ "Output file path (defaults to generated/<appKey>.ts)"
331
+ ),
332
+ lockFilePath: zod.z.string().optional().describe("Path to the .zapierrc lock file (defaults to .zapierrc)")
333
+ }).describe("Generate TypeScript SDK code for a specific app");
334
+ var generateTypesPlugin = ({ sdk }) => {
335
+ const generateTypesWithSdk = zapierSdk.createFunction(
336
+ async function generateTypesWithSdk2(options) {
337
+ return await generateTypes({ ...options, sdk });
338
+ },
339
+ GenerateTypesSchema
340
+ );
341
+ return {
342
+ generateTypes: generateTypesWithSdk,
343
+ context: {
344
+ meta: {
345
+ generateTypes: {
346
+ categories: ["utility"],
347
+ inputSchema: GenerateTypesSchema
348
+ }
349
+ }
350
+ }
351
+ };
352
+ };
353
+ function generateFetchMethodSignature() {
354
+ return ` /** Make authenticated HTTP requests through Zapier's Relay service */
355
+ fetch: (options: Omit<z.infer<typeof RelayFetchSchema>, 'authenticationId'>) => Promise<Response>`;
356
+ }
357
+ async function generateTypes(options) {
358
+ const {
359
+ appKey,
360
+ authenticationId,
361
+ output = `./types/${appKey}.d.ts`,
362
+ sdk
363
+ } = options;
364
+ const { app, version } = parseAppIdentifier(appKey);
365
+ const actionsResult = await sdk.listActions({
366
+ appKey: app
367
+ });
368
+ const actions = actionsResult.data;
369
+ if (actions.length === 0) {
370
+ const typeDefinitions2 = generateEmptyTypesFile(app, version);
371
+ if (output) {
372
+ fs__namespace.mkdirSync(path__namespace.dirname(output), { recursive: true });
373
+ fs__namespace.writeFileSync(output, typeDefinitions2, "utf8");
374
+ }
375
+ return typeDefinitions2;
376
+ }
377
+ const actionsWithFields = [];
378
+ if (authenticationId) {
379
+ for (const action of actions) {
380
+ try {
381
+ const manifestEntry = sdk.getContext().getManifestEntry(appKey);
382
+ const fieldsResult = await sdk.listInputFields({
383
+ // 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
384
+ appKey: manifestEntry ? appKey : action.app_key,
385
+ actionKey: action.key,
386
+ actionType: action.action_type,
387
+ authenticationId
388
+ });
389
+ const fields = fieldsResult.data.map((field) => {
390
+ const fieldObj = field;
391
+ return {
392
+ ...fieldObj,
393
+ required: fieldObj.is_required || fieldObj.required || false
394
+ };
395
+ });
396
+ actionsWithFields.push({
397
+ ...action,
398
+ inputFields: fields,
399
+ name: action.title || action.key
400
+ });
401
+ } catch {
402
+ actionsWithFields.push({
403
+ ...action,
404
+ inputFields: [],
405
+ name: action.title || action.key
406
+ });
407
+ }
408
+ }
409
+ } else {
410
+ actions.forEach((action) => {
411
+ actionsWithFields.push({
412
+ ...action,
413
+ inputFields: [],
414
+ name: action.title || action.key
415
+ });
416
+ });
417
+ }
418
+ const typeDefinitions = generateTypeDefinitions(
419
+ app,
420
+ actionsWithFields,
421
+ version
422
+ );
423
+ if (output) {
424
+ fs__namespace.mkdirSync(path__namespace.dirname(output), { recursive: true });
425
+ fs__namespace.writeFileSync(output, typeDefinitions, "utf8");
426
+ }
427
+ return typeDefinitions;
428
+ }
429
+ function parseAppIdentifier(identifier) {
430
+ const parts = identifier.split("@");
431
+ return {
432
+ app: parts[0],
433
+ version: parts[1]
434
+ };
435
+ }
436
+ function generateTypeDefinitions(appKey, actions, version) {
437
+ if (actions.length === 0) {
438
+ return generateEmptyTypesFile(appKey, version);
439
+ }
440
+ const actionsByType = actions.reduce(
441
+ (acc, action) => {
442
+ if (!acc[action.action_type]) {
443
+ acc[action.action_type] = [];
444
+ }
445
+ acc[action.action_type].push(action);
446
+ return acc;
447
+ },
448
+ {}
449
+ );
450
+ const appName = capitalize(appKey);
451
+ const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
452
+ let output = `/* eslint-disable @typescript-eslint/naming-convention */
453
+ /**
454
+ * Auto-generated TypeScript types for Zapier ${appKey} actions
455
+ ${versionComment}
456
+ * Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
457
+ *
458
+ * Usage:
459
+ * import type { ${appName}Sdk } from './path/to/this/file'
460
+ * const sdk = createZapierSdk() as unknown as ${appName}Sdk
461
+ *
462
+ * // Direct usage (per-call auth):
463
+ * await sdk.apps.${appKey}.search.user_by_email({ authenticationId: 123, inputs: { email } })
464
+ *
465
+ * // Factory usage (pinned auth):
466
+ * const my${appName} = sdk.apps.${appKey}({ authenticationId: 123 })
467
+ * await my${appName}.search.user_by_email({ inputs: { email } })
468
+ */
469
+
470
+ import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/zapier-sdk'
471
+ import { z } from 'zod'
472
+ import { RelayFetchSchema } from '@zapier/zapier-sdk'
473
+
474
+ `;
475
+ actions.forEach((action) => {
476
+ if (action.inputFields.length > 0) {
477
+ const inputTypeName = `${appName}${capitalize(action.action_type)}${capitalize(
478
+ sanitizeActionName(action.key)
479
+ )}Inputs`;
480
+ output += `interface ${inputTypeName} {
481
+ `;
482
+ action.inputFields.forEach((field) => {
483
+ const isOptional = !field.required;
484
+ const fieldType = mapFieldTypeToTypeScript(field);
485
+ const description = field.helpText ? ` /** ${escapeComment(field.helpText)} */
486
+ ` : "";
487
+ output += `${description} ${sanitizeFieldName(field.key)}${isOptional ? "?" : ""}: ${fieldType}
488
+ `;
489
+ });
490
+ output += `}
491
+
492
+ `;
493
+ }
494
+ });
495
+ Object.entries(actionsByType).forEach(([actionType, typeActions]) => {
496
+ const typeName = `${appName}${capitalize(actionType)}Actions`;
497
+ output += `interface ${typeName} {
498
+ `;
499
+ typeActions.forEach((action) => {
500
+ const actionName = sanitizeActionName(action.key);
501
+ const description = action.description ? ` /** ${escapeComment(action.description)} */
502
+ ` : "";
503
+ if (action.inputFields.length > 0) {
504
+ const inputTypeName = `${appName}${capitalize(action.action_type)}${capitalize(
505
+ sanitizeActionName(action.key)
506
+ )}Inputs`;
507
+ output += `${description} ${actionName}: (options: { inputs: ${inputTypeName} } & Omit<ActionExecutionOptions, 'inputs'>) => Promise<ActionExecutionResult>
508
+ `;
509
+ } else {
510
+ output += `${description} ${actionName}: (options?: { inputs?: Record<string, any> } & ActionExecutionOptions) => Promise<ActionExecutionResult>
511
+ `;
512
+ }
513
+ });
514
+ output += `}
515
+
516
+ `;
517
+ });
518
+ output += `interface ${appName}AppProxy {
519
+ `;
520
+ Object.keys(actionsByType).forEach((actionType) => {
521
+ const typeName = `${appName}${capitalize(actionType)}Actions`;
522
+ output += ` ${actionType}: ${typeName}
523
+ `;
524
+ });
525
+ output += generateFetchMethodSignature() + "\n";
526
+ output += `}
527
+
528
+ `;
529
+ output += `interface ${appName}AppFactory {
530
+ `;
531
+ output += ` (options: { authenticationId: number }): ${appName}AppProxy
532
+ `;
533
+ output += `}
534
+
535
+ `;
536
+ output += `type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
537
+
538
+ `;
539
+ output += `export interface ${appName}Sdk {
540
+ `;
541
+ output += ` apps: {
542
+ `;
543
+ output += ` ${appKey}: ${appName}AppWithFactory
544
+ `;
545
+ output += ` }
546
+ `;
547
+ output += `}
548
+ `;
549
+ return output;
550
+ }
551
+ function generateEmptyTypesFile(appKey, version) {
552
+ const appName = capitalize(appKey);
553
+ const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
554
+ return `/* eslint-disable @typescript-eslint/naming-convention */
555
+ /**
556
+ * Auto-generated TypeScript types for Zapier ${appKey} actions
557
+ ${versionComment}
558
+ * Generated on: ${(/* @__PURE__ */ new Date()).toISOString()}
559
+ *
560
+ * No actions found for this app.
561
+ */
562
+
563
+ import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/zapier-sdk'
564
+ import { z } from 'zod'
565
+ import { RelayFetchSchema } from '@zapier/zapier-sdk'
566
+
567
+ interface ${appName}AppProxy {
568
+ // No actions available
569
+ ${generateFetchMethodSignature()}
570
+ }
571
+
572
+ interface ${appName}AppFactory {
573
+ (options: { authenticationId: number }): ${appName}AppProxy
574
+ }
575
+
576
+ type ${appName}AppWithFactory = ${appName}AppFactory & ${appName}AppProxy
577
+
578
+ export interface ${appName}Sdk {
579
+ apps: {
580
+ ${appKey}: ${appName}AppWithFactory
581
+ }
582
+ }
583
+ `;
584
+ }
585
+ function capitalize(str) {
586
+ return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, "");
587
+ }
588
+ function sanitizeActionName(actionKey) {
589
+ let sanitized = actionKey.replace(/[^a-zA-Z0-9_$]/g, "_");
590
+ if (/^[0-9]/.test(sanitized)) {
591
+ sanitized = "_" + sanitized;
592
+ }
593
+ return sanitized;
594
+ }
595
+ function sanitizeFieldName(fieldKey) {
596
+ let sanitized = fieldKey.replace(/[^a-zA-Z0-9_$]/g, "_");
597
+ if (/^[0-9]/.test(sanitized)) {
598
+ sanitized = "_" + sanitized;
599
+ }
600
+ return sanitized;
601
+ }
602
+ function escapeComment(comment) {
603
+ return comment.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
604
+ }
605
+ function mapFieldTypeToTypeScript(field) {
606
+ if (field.choices && field.choices.length > 0) {
607
+ const choiceValues = field.choices.filter(
608
+ (choice) => choice.value !== void 0 && choice.value !== null && choice.value !== ""
609
+ ).map(
610
+ (choice) => typeof choice.value === "string" ? `"${choice.value}"` : choice.value
611
+ );
612
+ if (choiceValues.length > 0) {
613
+ return choiceValues.join(" | ");
614
+ }
615
+ }
616
+ switch (field.type?.toLowerCase()) {
617
+ case "string":
618
+ case "text":
619
+ case "email":
620
+ case "url":
621
+ case "password":
622
+ return "string";
623
+ case "integer":
624
+ case "number":
625
+ return "number";
626
+ case "boolean":
627
+ return "boolean";
628
+ case "datetime":
629
+ case "date":
630
+ return "string";
631
+ // ISO date strings
632
+ case "file":
633
+ return "string";
634
+ // File URL or content
635
+ case "array":
636
+ return "any[]";
637
+ case "object":
638
+ return "Record<string, any>";
639
+ default:
640
+ return "string | number | boolean";
641
+ }
642
+ }
643
+ var BundleCodeSchema = zod.z.object({
644
+ input: zod.z.string().min(1).describe("Input TypeScript file path to bundle"),
645
+ output: zapierSdk.OutputPropertySchema.optional().describe(
646
+ "Output file path (defaults to input with .js extension)"
647
+ ),
648
+ string: zod.z.boolean().optional().describe("Return bundled code as string instead of writing to file"),
649
+ minify: zod.z.boolean().optional().describe("Minify the bundled output"),
650
+ target: zod.z.string().optional().describe("ECMAScript target version"),
651
+ cjs: zod.z.boolean().optional().describe("Output CommonJS format instead of ESM")
652
+ }).describe("Bundle TypeScript code into executable JavaScript");
653
+ var bundleCodePlugin = () => {
654
+ const bundleCodeWithSdk = zapierSdk.createFunction(async function bundleCodeWithSdk2(options) {
655
+ return await bundleCode(options);
656
+ }, BundleCodeSchema);
657
+ return {
658
+ bundleCode: bundleCodeWithSdk,
659
+ context: {
660
+ meta: {
661
+ bundleCode: {
662
+ categories: ["utility"],
663
+ inputSchema: BundleCodeSchema
664
+ }
665
+ }
666
+ }
667
+ };
668
+ };
669
+ var ZapierBundleError = class extends Error {
670
+ constructor(message, details, originalError) {
671
+ super(message);
672
+ this.code = "ZAPIER_BUNDLE_ERROR";
673
+ this.name = "ZapierBundleError";
674
+ this.details = details;
675
+ this.originalError = originalError;
676
+ }
677
+ };
678
+ async function bundleCode(options) {
679
+ const {
680
+ input,
681
+ output,
682
+ target = "es2020",
683
+ cjs = false,
684
+ minify = false,
685
+ string: returnString = false
686
+ } = options;
687
+ const resolvedInput = path__namespace.resolve(process.cwd(), input);
688
+ try {
689
+ const result = esbuild.buildSync({
690
+ entryPoints: [resolvedInput],
691
+ bundle: true,
692
+ platform: "node",
693
+ target,
694
+ format: cjs ? "cjs" : "esm",
695
+ minify,
696
+ write: false,
697
+ external: [],
698
+ // Bundle everything
699
+ banner: {
700
+ js: "#!/usr/bin/env node"
701
+ }
702
+ });
703
+ if (result.errors.length > 0) {
704
+ const errorMessages = result.errors.map((e) => e.text);
705
+ throw new ZapierBundleError(
706
+ `Bundle failed: ${errorMessages.join(", ")}`,
707
+ errorMessages
708
+ );
709
+ }
710
+ const bundledCode = result.outputFiles?.[0]?.text;
711
+ if (!bundledCode) {
712
+ throw new ZapierBundleError("No output generated");
713
+ }
714
+ let finalOutput = bundledCode;
715
+ if (returnString) {
716
+ finalOutput = JSON.stringify(bundledCode);
717
+ }
718
+ if (output) {
719
+ fs__namespace.mkdirSync(path__namespace.dirname(output), { recursive: true });
720
+ fs__namespace.writeFileSync(output, finalOutput, "utf8");
721
+ }
722
+ return finalOutput;
723
+ } catch (error) {
724
+ if (error instanceof ZapierBundleError) {
725
+ throw error;
726
+ }
727
+ throw new ZapierBundleError(
728
+ `Bundle failed: ${error instanceof Error ? error.message : "Unknown error"}`,
729
+ void 0,
730
+ error instanceof Error ? error : void 0
731
+ );
732
+ }
733
+ }
734
+ var GetConfigPathSchema = zod.z.object({}).describe("Show the path to the configuration file");
735
+ var getConfigPathPlugin = () => {
736
+ const getConfigPathWithSdk = zapierSdk.createFunction(
737
+ async function getConfigPathWithSdk2(_options) {
738
+ return zapierSdkCliLogin.getConfigPath();
739
+ },
740
+ GetConfigPathSchema
741
+ );
742
+ return {
743
+ getConfigPath: getConfigPathWithSdk,
744
+ context: {
745
+ meta: {
746
+ getConfigPath: {
747
+ categories: ["utility"],
748
+ inputSchema: GetConfigPathSchema
749
+ }
750
+ }
751
+ }
752
+ };
753
+ };
754
+
755
+ // src/sdk.ts
756
+ function createZapierCliSdk(options = {}) {
757
+ let sdk = zapierSdk.createZapierSdkWithoutRegistry({
758
+ debug: options.debug
759
+ });
760
+ sdk = sdk.addPlugin(generateTypesPlugin);
761
+ sdk = sdk.addPlugin(bundleCodePlugin);
762
+ sdk = sdk.addPlugin(getConfigPathPlugin);
763
+ sdk = sdk.addPlugin(mcpPlugin);
764
+ sdk = sdk.addPlugin(loginPlugin);
765
+ sdk = sdk.addPlugin(logoutPlugin);
766
+ const finalSdk = sdk.addPlugin(zapierSdk.registryPlugin);
767
+ return finalSdk;
768
+ }
769
+
770
+ exports.createZapierCliSdk = createZapierCliSdk;