@zapier/zapier-sdk-cli 0.42.2 → 0.43.1

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 (54) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cli.cjs +1047 -547
  3. package/dist/cli.d.mts +0 -1
  4. package/dist/cli.d.ts +0 -1
  5. package/dist/cli.mjs +1034 -537
  6. package/dist/index.cjs +1037 -538
  7. package/dist/index.d.mts +395 -23
  8. package/dist/index.d.ts +395 -23
  9. package/dist/index.mjs +1027 -531
  10. package/dist/login.cjs +599 -7
  11. package/dist/login.d.mts +144 -1
  12. package/dist/login.d.ts +144 -1
  13. package/dist/login.mjs +565 -1
  14. package/dist/package.json +5 -2
  15. package/dist/src/login/filesystem-cache.d.ts +25 -0
  16. package/dist/src/login/filesystem-cache.js +195 -0
  17. package/dist/src/login/index.d.ts +115 -0
  18. package/dist/src/login/index.js +442 -0
  19. package/dist/src/login/keychain.d.ts +18 -0
  20. package/dist/src/login/keychain.js +74 -0
  21. package/dist/src/login.d.ts +10 -1
  22. package/dist/src/login.js +10 -1
  23. package/dist/src/plugins/add/index.d.ts +250 -11
  24. package/dist/src/plugins/add/index.js +8 -16
  25. package/dist/src/plugins/buildManifest/index.d.ts +116 -9
  26. package/dist/src/plugins/buildManifest/index.js +14 -23
  27. package/dist/src/plugins/bundleCode/index.d.ts +19 -10
  28. package/dist/src/plugins/bundleCode/index.js +7 -17
  29. package/dist/src/plugins/cliOverrides/index.d.ts +12 -10
  30. package/dist/src/plugins/cliOverrides/index.js +16 -20
  31. package/dist/src/plugins/curl/index.d.ts +69 -10
  32. package/dist/src/plugins/curl/index.js +3 -2
  33. package/dist/src/plugins/feedback/index.d.ts +18 -13
  34. package/dist/src/plugins/feedback/index.js +18 -26
  35. package/dist/src/plugins/generateAppTypes/index.d.ts +261 -9
  36. package/dist/src/plugins/generateAppTypes/index.js +17 -45
  37. package/dist/src/plugins/getLoginConfigPath/index.d.ts +12 -10
  38. package/dist/src/plugins/getLoginConfigPath/index.js +9 -19
  39. package/dist/src/plugins/init/index.d.ts +15 -11
  40. package/dist/src/plugins/init/index.js +9 -17
  41. package/dist/src/plugins/login/index.d.ts +18 -13
  42. package/dist/src/plugins/login/index.js +10 -18
  43. package/dist/src/plugins/logout/index.d.ts +12 -11
  44. package/dist/src/plugins/logout/index.js +11 -17
  45. package/dist/src/plugins/mcp/index.d.ts +18 -15
  46. package/dist/src/plugins/mcp/index.js +9 -21
  47. package/dist/src/sdk.js +1 -1
  48. package/dist/src/utils/auth/login.d.ts +1 -1
  49. package/dist/src/utils/auth/login.js +1 -1
  50. package/dist/src/utils/constants.d.ts +1 -1
  51. package/dist/src/utils/constants.js +1 -1
  52. package/dist/src/utils/version-checker.js +1 -1
  53. package/dist/tsconfig.tsbuildinfo +1 -1
  54. package/package.json +7 -4
package/dist/index.mjs CHANGED
@@ -1,8 +1,14 @@
1
- import * as cliLogin from '@zapier/zapier-sdk-cli-login';
2
- import { logout, getConfigPath, getLoggedInUser, getPkceLoginConfig, AUTH_MODE_HEADER, getLoginStorageMode, updateLogin } from '@zapier/zapier-sdk-cli-login';
3
- import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH, injectCliLogin, createZapierSdk, getOsInfo, getPlatformVersions, getCiPlatform, isCi, ZapierValidationError, ZapierUnknownError, getReleaseId, getCurrentTimestamp, generateEventId, batch, toSnakeCase, buildApplicationLifecycleEvent, ZapierError, isCredentialsObject } from '@zapier/zapier-sdk';
4
- import open from 'open';
1
+ import Conf from 'conf';
2
+ import * as fs from 'fs';
3
+ import { promises, createWriteStream, existsSync, readdirSync, rmSync, mkdirSync, writeFileSync, copyFileSync, readFileSync } from 'fs';
4
+ import * as jwt from 'jsonwebtoken';
5
+ import { getPassword, getKeyring, setPassword, deletePassword } from 'cross-keychain';
5
6
  import crypto, { createHash } from 'crypto';
7
+ import * as path from 'path';
8
+ import { resolve, join, dirname, basename, relative, extname } from 'path';
9
+ import * as lockfile from 'proper-lockfile';
10
+ import { definePlugin, createPluginMethod, buildApplicationLifecycleEvent, OutputPropertySchema, DEFAULT_CONFIG_PATH, ZapierValidationError, ZapierUnknownError, injectCliLogin, isCredentialsObject, batch, toSnakeCase, ZapierError, createZapierSdk, getOsInfo, getPlatformVersions, getCiPlatform, isCi, getReleaseId, getCurrentTimestamp, generateEventId } from '@zapier/zapier-sdk';
11
+ import open from 'open';
6
12
  import express from 'express';
7
13
  import pkceChallenge from 'pkce-challenge';
8
14
  import ora from 'ora';
@@ -11,10 +17,6 @@ import inquirer from 'inquirer';
11
17
  import { z } from 'zod';
12
18
  import { startMcpServer } from '@zapier/zapier-sdk-mcp';
13
19
  import { buildSync } from 'esbuild';
14
- import * as fs from 'fs';
15
- import { promises, createWriteStream, existsSync, readdirSync, rmSync, mkdirSync, writeFileSync, copyFileSync, readFileSync } from 'fs';
16
- import * as path from 'path';
17
- import { resolve, join, dirname, basename, relative, extname } from 'path';
18
20
  import { mkdir, writeFile, access } from 'fs/promises';
19
21
  import * as ts from 'typescript';
20
22
  import 'is-installed-globally';
@@ -22,7 +24,586 @@ import { execSync } from 'child_process';
22
24
  import Handlebars from 'handlebars';
23
25
  import { fileURLToPath } from 'url';
24
26
 
25
- // src/sdk.ts
27
+ var __defProp = Object.defineProperty;
28
+ var __export = (target, all) => {
29
+ for (var name in all)
30
+ __defProp(target, name, { get: all[name], enumerable: true });
31
+ };
32
+
33
+ // src/login.ts
34
+ var login_exports = {};
35
+ __export(login_exports, {
36
+ AUTH_MODE_HEADER: () => AUTH_MODE_HEADER,
37
+ ZapierAuthenticationError: () => ZapierAuthenticationError,
38
+ createCache: () => createCache,
39
+ getAuthAuthorizeUrl: () => getAuthAuthorizeUrl,
40
+ getAuthTokenUrl: () => getAuthTokenUrl,
41
+ getConfig: () => getConfig,
42
+ getConfigPath: () => getConfigPath,
43
+ getLoggedInUser: () => getLoggedInUser,
44
+ getLoginStorageMode: () => getLoginStorageMode,
45
+ getPkceLoginConfig: () => getPkceLoginConfig,
46
+ getToken: () => getToken,
47
+ logout: () => logout,
48
+ unloadConfig: () => unloadConfig,
49
+ updateLogin: () => updateLogin
50
+ });
51
+ var SERVICE = "zapier-sdk-cli";
52
+ var ACCOUNT = "login";
53
+ var cachedBackendInfo;
54
+ async function getBackendInfo() {
55
+ if (!cachedBackendInfo) {
56
+ const keyring = await getKeyring();
57
+ cachedBackendInfo = `${keyring.name} (${keyring.id})`;
58
+ }
59
+ return cachedBackendInfo;
60
+ }
61
+ var keychainQueue = Promise.resolve();
62
+ function enqueue(fn) {
63
+ const result = keychainQueue.then(fn, fn);
64
+ keychainQueue = result.then(
65
+ () => {
66
+ },
67
+ () => {
68
+ }
69
+ );
70
+ return result;
71
+ }
72
+ async function getTokensFromKeychain({
73
+ debugLog
74
+ } = {}) {
75
+ return enqueue(async () => {
76
+ const backendInfo = await getBackendInfo();
77
+ debugLog?.(`Keychain read via ${backendInfo}`);
78
+ const startTime = Date.now();
79
+ const raw = await getPassword(SERVICE, ACCOUNT);
80
+ debugLog?.(`Keychain read completed in ${Date.now() - startTime}ms`);
81
+ if (!raw) {
82
+ debugLog?.("Keychain returned no data");
83
+ return void 0;
84
+ }
85
+ let parsed;
86
+ try {
87
+ parsed = JSON.parse(raw);
88
+ } catch {
89
+ debugLog?.("Keychain data is not valid JSON");
90
+ return void 0;
91
+ }
92
+ if (typeof parsed.login_jwt === "string" && typeof parsed.login_refresh_token === "string") {
93
+ return {
94
+ login_jwt: parsed.login_jwt,
95
+ login_refresh_token: parsed.login_refresh_token
96
+ };
97
+ }
98
+ debugLog?.("Keychain data has invalid shape", parsed);
99
+ return void 0;
100
+ });
101
+ }
102
+ async function setTokensInKeychain({
103
+ data,
104
+ debugLog
105
+ }) {
106
+ return enqueue(async () => {
107
+ const backendInfo = await getBackendInfo();
108
+ debugLog?.(`Keychain write via ${backendInfo}`);
109
+ const startTime = Date.now();
110
+ await setPassword(SERVICE, ACCOUNT, JSON.stringify(data));
111
+ debugLog?.(`Keychain write completed in ${Date.now() - startTime}ms`);
112
+ });
113
+ }
114
+ async function clearTokensFromKeychain({
115
+ debugLog
116
+ } = {}) {
117
+ return enqueue(async () => {
118
+ try {
119
+ const backendInfo = await getBackendInfo();
120
+ debugLog?.(`Keychain clear via ${backendInfo}`);
121
+ await deletePassword(SERVICE, ACCOUNT);
122
+ } catch {
123
+ }
124
+ });
125
+ }
126
+ var SERVICE2 = "zapier-sdk-cache";
127
+ var CONFIG_KEY = "cache";
128
+ var LOCK_UPDATE_MS = 5e3;
129
+ var LOCK_STALE_MS = 1e4;
130
+ var LOCK_RETRY_WAIT_MS = 100;
131
+ var LOCK_RETRY_MAX_WAIT_MS = 1e3;
132
+ var LOCK_RETRY_COUNT = 120;
133
+ function keychainAccount(key) {
134
+ return createHash("sha256").update(key).digest("hex");
135
+ }
136
+ function readConfigMap() {
137
+ const cfg = getConfig();
138
+ const stored = cfg.get(CONFIG_KEY);
139
+ if (stored && typeof stored === "object") {
140
+ return stored;
141
+ }
142
+ return {};
143
+ }
144
+ function writeConfigMap(map) {
145
+ getConfig().set(CONFIG_KEY, map);
146
+ }
147
+ function entryIsExpired(entry) {
148
+ return entry.expires_at !== void 0 && entry.expires_at <= Date.now();
149
+ }
150
+ function createCache() {
151
+ return {
152
+ async get(key) {
153
+ const entry = readConfigMap()[key];
154
+ if (!entry) return void 0;
155
+ if (entryIsExpired(entry)) return void 0;
156
+ if (entry.secret) {
157
+ const stored = await enqueue(async () => {
158
+ await getBackendInfo();
159
+ return getPassword(SERVICE2, keychainAccount(key));
160
+ });
161
+ if (!stored) {
162
+ return void 0;
163
+ }
164
+ return { value: stored, expiresAt: entry.expires_at };
165
+ }
166
+ if (entry.value === void 0) return void 0;
167
+ return { value: entry.value, expiresAt: entry.expires_at };
168
+ },
169
+ async set(key, value, options) {
170
+ const secret = options?.secret ?? false;
171
+ const expiresAt = options?.ttl ? Date.now() + options.ttl * 1e3 : void 0;
172
+ if (secret) {
173
+ try {
174
+ await enqueue(async () => {
175
+ await getBackendInfo();
176
+ await setPassword(SERVICE2, keychainAccount(key), value);
177
+ });
178
+ } catch {
179
+ return;
180
+ }
181
+ const map = readConfigMap();
182
+ map[key] = { secret: true, expires_at: expiresAt };
183
+ try {
184
+ writeConfigMap(map);
185
+ } catch {
186
+ }
187
+ } else {
188
+ const map = readConfigMap();
189
+ map[key] = { secret: false, value, expires_at: expiresAt };
190
+ try {
191
+ writeConfigMap(map);
192
+ } catch {
193
+ }
194
+ }
195
+ },
196
+ async delete(key) {
197
+ const map = readConfigMap();
198
+ const entry = map[key];
199
+ if (entry) {
200
+ delete map[key];
201
+ try {
202
+ writeConfigMap(map);
203
+ } catch {
204
+ }
205
+ }
206
+ if (entry?.secret) {
207
+ try {
208
+ await enqueue(async () => {
209
+ await getBackendInfo();
210
+ await deletePassword(SERVICE2, keychainAccount(key));
211
+ });
212
+ } catch {
213
+ }
214
+ }
215
+ },
216
+ async withLock(_key, fn) {
217
+ const cfg = getConfig();
218
+ const lockTarget = `${cfg.path}.cache-lock`;
219
+ try {
220
+ mkdirSync(dirname(lockTarget), { recursive: true });
221
+ if (!existsSync(lockTarget)) {
222
+ writeFileSync(lockTarget, "");
223
+ }
224
+ } catch {
225
+ return fn();
226
+ }
227
+ let release = null;
228
+ try {
229
+ release = await lockfile.lock(lockTarget, {
230
+ stale: LOCK_STALE_MS,
231
+ update: LOCK_UPDATE_MS,
232
+ retries: {
233
+ retries: LOCK_RETRY_COUNT,
234
+ factor: 1.2,
235
+ minTimeout: LOCK_RETRY_WAIT_MS,
236
+ maxTimeout: LOCK_RETRY_MAX_WAIT_MS
237
+ }
238
+ });
239
+ } catch {
240
+ return fn();
241
+ }
242
+ try {
243
+ return await fn();
244
+ } finally {
245
+ try {
246
+ await release();
247
+ } catch {
248
+ }
249
+ }
250
+ }
251
+ };
252
+ }
253
+
254
+ // src/login/index.ts
255
+ var ZapierAuthenticationError = class extends Error {
256
+ constructor(message) {
257
+ super(message);
258
+ this.name = "ZapierAuthenticationError";
259
+ }
260
+ };
261
+ var config = null;
262
+ var DEFAULT_AUTH_CLIENT_ID = "grwWZD5hUWGvb4V8ODBuOtXer3h0DBEZ2HR8aay6";
263
+ var TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
264
+ function createDebugLog(enabled) {
265
+ if (!enabled) {
266
+ return () => {
267
+ };
268
+ }
269
+ return (message, data) => {
270
+ if (data === void 0) {
271
+ console.log(`[Zapier SDK CLI Login] ${message}`);
272
+ } else {
273
+ console.log(`[Zapier SDK CLI Login] ${message}`, data);
274
+ }
275
+ };
276
+ }
277
+ function censorHeaderValue(value) {
278
+ if (value.length > 12) {
279
+ return `${value.substring(0, 4)}...${value.substring(value.length - 4)}`;
280
+ }
281
+ return `${value.charAt(0)}...`;
282
+ }
283
+ function getAuthClientId(clientId) {
284
+ return clientId || DEFAULT_AUTH_CLIENT_ID;
285
+ }
286
+ var AUTH_MODE_HEADER = "X-Auth";
287
+ var DEFAULT_AUTH_BASE_URL = "https://zapier.com";
288
+ function getAuthTokenUrl(options) {
289
+ const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
290
+ return `${authBaseUrl}/oauth/token/`;
291
+ }
292
+ function getAuthAuthorizeUrl(options) {
293
+ const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
294
+ return `${authBaseUrl}/oauth/authorize/`;
295
+ }
296
+ function getPkceLoginConfig(options) {
297
+ return {
298
+ clientId: getAuthClientId(options?.credentials?.clientId),
299
+ tokenUrl: getAuthTokenUrl({ baseUrl: options?.credentials?.baseUrl }),
300
+ authorizeUrl: getAuthAuthorizeUrl({
301
+ baseUrl: options?.credentials?.baseUrl
302
+ })
303
+ };
304
+ }
305
+ var cachedLogin;
306
+ function getConfig() {
307
+ if (!config) {
308
+ config = new Conf({ projectName: "zapier-sdk-cli" });
309
+ if (!config.has("login_storage_mode")) {
310
+ config.set(
311
+ "login_storage_mode",
312
+ existsSync(config.path) ? "config" : "keychain"
313
+ );
314
+ }
315
+ }
316
+ return config;
317
+ }
318
+ function unloadConfig() {
319
+ config = null;
320
+ cachedLogin = void 0;
321
+ }
322
+ async function updateLogin(loginData, options = {}) {
323
+ const debugLog = createDebugLog(options.debug ?? false);
324
+ const storage = options.storage ?? cachedLogin?.storage ?? "keychain";
325
+ const expiresAt = Date.now() + loginData.expires_in * 1e3;
326
+ const cfg = getConfig();
327
+ cfg.set("login_storage_mode", storage);
328
+ if (storage === "keychain") {
329
+ await setTokensInKeychain({
330
+ data: {
331
+ login_jwt: loginData.access_token,
332
+ login_refresh_token: loginData.refresh_token
333
+ },
334
+ debugLog
335
+ });
336
+ cfg.set("login_expires_at", expiresAt);
337
+ cfg.delete("login_jwt");
338
+ cfg.delete("login_refresh_token");
339
+ } else {
340
+ cfg.set("login_jwt", loginData.access_token);
341
+ cfg.set("login_refresh_token", loginData.refresh_token);
342
+ cfg.set("login_expires_at", expiresAt);
343
+ await clearTokensFromKeychain({ debugLog });
344
+ }
345
+ cachedLogin = {
346
+ jwt: loginData.access_token,
347
+ refreshToken: loginData.refresh_token,
348
+ expiresAt,
349
+ storage
350
+ };
351
+ }
352
+ function decodeJwtOrThrow(token) {
353
+ if (typeof token !== "string") {
354
+ throw new Error("Expected JWT to be a string");
355
+ }
356
+ const decodedJwt = jwt.decode(token, { complete: true });
357
+ if (!decodedJwt) {
358
+ throw new Error("Could not decode JWT");
359
+ }
360
+ if (typeof decodedJwt.payload === "string") {
361
+ throw new Error("Did not expect JWT payload to be a string");
362
+ }
363
+ return decodedJwt;
364
+ }
365
+ async function refreshJwt(refreshToken, options = {}) {
366
+ const {
367
+ onEvent,
368
+ fetch: fetch2 = globalThis.fetch,
369
+ credentials,
370
+ debug = false
371
+ } = options;
372
+ const debugLog = createDebugLog(debug);
373
+ const tokenUrl = getAuthTokenUrl({ baseUrl: credentials?.baseUrl });
374
+ const clientId = getAuthClientId(credentials?.clientId);
375
+ const startTime = Date.now();
376
+ try {
377
+ onEvent?.({
378
+ type: "auth_refreshing",
379
+ payload: {
380
+ message: "Refreshing your token...",
381
+ operation: "token_refresh"
382
+ },
383
+ timestamp: Date.now()
384
+ });
385
+ debugLog(`\u2192 POST ${tokenUrl}`, {
386
+ headers: {
387
+ "Content-Type": "application/x-www-form-urlencoded",
388
+ [AUTH_MODE_HEADER]: "no"
389
+ },
390
+ body: {
391
+ client_id: clientId,
392
+ refresh_token: censorHeaderValue(refreshToken),
393
+ grant_type: "refresh_token"
394
+ }
395
+ });
396
+ const response = await fetch2(tokenUrl, {
397
+ method: "POST",
398
+ headers: {
399
+ "Content-Type": "application/x-www-form-urlencoded",
400
+ [AUTH_MODE_HEADER]: "no"
401
+ },
402
+ body: new URLSearchParams({
403
+ client_id: clientId,
404
+ refresh_token: refreshToken,
405
+ grant_type: "refresh_token"
406
+ })
407
+ });
408
+ const duration = Date.now() - startTime;
409
+ if (!response.ok) {
410
+ debugLog(`\u2190 ${response.status} ${response.statusText} (${duration}ms)`);
411
+ throw new Error(
412
+ `Token refresh failed: ${response.status} ${response.statusText}`
413
+ );
414
+ }
415
+ debugLog(`\u2190 ${response.status} ${response.statusText} (${duration}ms)`);
416
+ const data = await response.json();
417
+ await updateLogin(data, { debug });
418
+ debugLog(
419
+ `Token refreshed and saved to ${cachedLogin?.storage ?? "keychain"}`
420
+ );
421
+ onEvent?.({
422
+ type: "auth_success",
423
+ payload: {
424
+ message: "Token refreshed successfully",
425
+ operation: "token_refresh"
426
+ },
427
+ timestamp: Date.now()
428
+ });
429
+ return data.access_token;
430
+ } catch (error) {
431
+ const duration = Date.now() - startTime;
432
+ debugLog(`\u2716 Token refresh failed (${duration}ms)`, {
433
+ error: error instanceof Error ? error.message : error
434
+ });
435
+ cachedLogin = void 0;
436
+ const errorMessage = `Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`;
437
+ onEvent?.({
438
+ type: "auth_error",
439
+ payload: {
440
+ message: errorMessage,
441
+ error: errorMessage,
442
+ operation: "token_refresh"
443
+ },
444
+ timestamp: Date.now()
445
+ });
446
+ throw error;
447
+ }
448
+ }
449
+ var pendingRefresh = null;
450
+ var pendingResolve = null;
451
+ async function resolveStoredLogin(debugLog) {
452
+ if (cachedLogin) {
453
+ debugLog("Using in-memory cached credentials");
454
+ return cachedLogin;
455
+ }
456
+ if (pendingResolve) {
457
+ debugLog("Waiting for existing keychain read to complete");
458
+ return pendingResolve;
459
+ }
460
+ pendingResolve = resolveStoredLoginFromStorage(debugLog).finally(() => {
461
+ pendingResolve = null;
462
+ });
463
+ return pendingResolve;
464
+ }
465
+ async function resolveStoredLoginFromStorage(debugLog) {
466
+ let cfg;
467
+ try {
468
+ cfg = getConfig();
469
+ } catch (error) {
470
+ debugLog("Failed to load config", {
471
+ error: error instanceof Error ? error.message : error
472
+ });
473
+ return void 0;
474
+ }
475
+ const expiresAt = cfg.get("login_expires_at");
476
+ const configJwt = cfg.get("login_jwt");
477
+ const configRefresh = cfg.get("login_refresh_token");
478
+ if (configJwt && configRefresh && typeof expiresAt === "number") {
479
+ debugLog("Loaded credentials from config (legacy format)");
480
+ cachedLogin = {
481
+ jwt: configJwt,
482
+ refreshToken: configRefresh,
483
+ expiresAt,
484
+ storage: "config"
485
+ };
486
+ return cachedLogin;
487
+ }
488
+ if (typeof expiresAt !== "number") {
489
+ debugLog("No stored login credentials found");
490
+ return void 0;
491
+ }
492
+ const keychainData = await getTokensFromKeychain({ debugLog });
493
+ if (!keychainData) {
494
+ debugLog("No tokens found in keychain");
495
+ return void 0;
496
+ }
497
+ debugLog("Loaded credentials from keychain");
498
+ cachedLogin = {
499
+ jwt: keychainData.login_jwt,
500
+ refreshToken: keychainData.login_refresh_token,
501
+ expiresAt,
502
+ storage: "keychain"
503
+ };
504
+ return cachedLogin;
505
+ }
506
+ async function resolveOrRefreshToken(options = {}) {
507
+ const { debug = false } = options;
508
+ const debugLog = createDebugLog(debug);
509
+ const stored = await resolveStoredLogin(debugLog);
510
+ if (!stored) {
511
+ return void 0;
512
+ }
513
+ const { jwt: storedJwt, refreshToken, expiresAt } = stored;
514
+ if (expiresAt > Date.now() + TOKEN_REFRESH_BUFFER_MS) {
515
+ debugLog("Using cached token (still valid)");
516
+ return storedJwt;
517
+ }
518
+ debugLog("Token expired, refreshing...");
519
+ if (pendingRefresh) {
520
+ debugLog("Waiting for existing refresh to complete");
521
+ return pendingRefresh;
522
+ }
523
+ pendingRefresh = refreshJwt(refreshToken, options).finally(() => {
524
+ pendingRefresh = null;
525
+ });
526
+ return await pendingRefresh;
527
+ }
528
+ async function getToken(options = {}) {
529
+ try {
530
+ return await resolveOrRefreshToken(options);
531
+ } catch (error) {
532
+ const message = error instanceof Error ? error.message : "Token refresh failed";
533
+ throw new ZapierAuthenticationError(
534
+ `${message}
535
+ Please run 'login' to authenticate again.`
536
+ );
537
+ }
538
+ }
539
+ async function getLoggedInUser(options = {}) {
540
+ const jwt2 = await getToken(options).catch(() => void 0);
541
+ if (!jwt2) {
542
+ throw new Error(
543
+ "No valid authentication token available. Please login first."
544
+ );
545
+ }
546
+ let decodedJwt = decodeJwtOrThrow(jwt2);
547
+ if (decodedJwt.payload["sub_type"] == "service") {
548
+ decodedJwt = decodeJwtOrThrow(decodedJwt.payload["njwt"]);
549
+ }
550
+ if (typeof decodedJwt.payload["zap:acc"] !== "string") {
551
+ throw new Error("JWT payload does not contain accountId");
552
+ }
553
+ const accountId = parseInt(decodedJwt.payload["zap:acc"], 10);
554
+ if (isNaN(accountId)) {
555
+ throw new Error("JWT accountId is not a number");
556
+ }
557
+ if (decodedJwt.payload["sub_type"] !== "customuser" || typeof decodedJwt.payload["sub"] !== "string") {
558
+ throw new Error("JWT payload does not contain customUserId");
559
+ }
560
+ const customUserId = parseInt(decodedJwt.payload["sub"], 10);
561
+ if (isNaN(customUserId)) {
562
+ throw new Error("JWT customUserId is not a number");
563
+ }
564
+ const email = decodedJwt.payload["zap:uname"];
565
+ if (typeof email !== "string") {
566
+ throw new Error("JWT payload does not contain email");
567
+ }
568
+ return {
569
+ accountId,
570
+ customUserId,
571
+ email
572
+ };
573
+ }
574
+ function getLoginStorageMode() {
575
+ const cfg = getConfig();
576
+ if (typeof cfg.get("login_jwt") === "string") {
577
+ return "config";
578
+ }
579
+ const explicitMode = cfg.get("login_storage_mode");
580
+ if (explicitMode === "keychain" || explicitMode === "config") {
581
+ return explicitMode;
582
+ }
583
+ return "keychain";
584
+ }
585
+ async function logout(options = {}) {
586
+ const { onEvent } = options;
587
+ const mode = getLoginStorageMode();
588
+ cachedLogin = void 0;
589
+ await clearTokensFromKeychain();
590
+ const cfg = getConfig();
591
+ cfg.set("login_storage_mode", mode);
592
+ cfg.delete("login_expires_at");
593
+ cfg.delete("login_jwt");
594
+ cfg.delete("login_refresh_token");
595
+ onEvent?.({
596
+ type: "auth_logout",
597
+ payload: { message: "Logged out successfully", operation: "logout" },
598
+ timestamp: Date.now()
599
+ });
600
+ }
601
+ function getConfigPath() {
602
+ const cfg = getConfig();
603
+ return cfg.path;
604
+ }
605
+
606
+ // src/utils/constants.ts
26
607
  var LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
27
608
  var LOGIN_TIMEOUT_MS = 3e5;
28
609
  var ZapierCliError = class extends ZapierError {
@@ -321,85 +902,65 @@ function toPkceCredentials(credentials) {
321
902
  }
322
903
  return void 0;
323
904
  }
324
- var loginPlugin = (sdk) => {
325
- const loginFn = async (options) => {
326
- const timeoutSeconds = options.timeout ? parseInt(options.timeout, 10) : 300;
327
- if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
328
- throw new Error("Timeout must be a positive number");
329
- }
330
- const resolvedCredentials = await sdk.context.resolveCredentials();
331
- const pkceCredentials = toPkceCredentials(resolvedCredentials);
332
- await login_default({
333
- timeoutMs: timeoutSeconds * 1e3,
334
- credentials: pkceCredentials
335
- });
336
- const user = await getLoggedInUser();
337
- sdk.context.eventEmission.emit(
338
- "platform.sdk.ApplicationLifecycleEvent",
339
- buildApplicationLifecycleEvent(
340
- { lifecycle_event_type: "login_success" },
341
- { customuser_id: user.customUserId, account_id: user.accountId }
342
- )
343
- );
344
- console.log(`\u2705 Successfully logged in as ${user.email}`);
345
- };
346
- return {
347
- login: loginFn,
348
- context: {
349
- meta: {
350
- login: {
351
- categories: ["account"],
352
- inputSchema: LoginSchema,
353
- supportsJsonOutput: false
354
- }
905
+ var loginPlugin = definePlugin(
906
+ (sdk) => createPluginMethod(sdk, {
907
+ name: "login",
908
+ categories: ["account"],
909
+ inputSchema: LoginSchema,
910
+ supportsJsonOutput: false,
911
+ handler: async ({ sdk: sdk2, options }) => {
912
+ const timeoutSeconds = options.timeout ? parseInt(options.timeout, 10) : 300;
913
+ if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
914
+ throw new Error("Timeout must be a positive number");
355
915
  }
916
+ const resolvedCredentials = await sdk2.context.resolveCredentials();
917
+ const pkceCredentials = toPkceCredentials(resolvedCredentials);
918
+ await login_default({
919
+ timeoutMs: timeoutSeconds * 1e3,
920
+ credentials: pkceCredentials
921
+ });
922
+ const user = await getLoggedInUser();
923
+ sdk2.context.eventEmission.emit(
924
+ "platform.sdk.ApplicationLifecycleEvent",
925
+ buildApplicationLifecycleEvent(
926
+ { lifecycle_event_type: "login_success" },
927
+ { customuser_id: user.customUserId, account_id: user.accountId }
928
+ )
929
+ );
930
+ console.log(`\u2705 Successfully logged in as ${user.email}`);
356
931
  }
357
- };
358
- };
932
+ })
933
+ );
359
934
  var LogoutSchema = z.object({}).describe("Log out of your Zapier account");
360
935
 
361
936
  // src/plugins/logout/index.ts
362
- var logoutWithSdk = createFunction(async function logoutWithSdk2(_options) {
363
- await logout();
364
- console.log("\u2705 Successfully logged out");
365
- }, LogoutSchema);
366
- var logoutPlugin = () => ({
367
- logout: logoutWithSdk,
368
- context: {
369
- meta: {
370
- logout: {
371
- categories: ["account"],
372
- inputSchema: LogoutSchema,
373
- supportsJsonOutput: false
374
- }
375
- }
376
- }
377
- });
937
+ var logoutPlugin = definePlugin(
938
+ (sdk) => createPluginMethod(sdk, {
939
+ name: "logout",
940
+ categories: ["account"],
941
+ inputSchema: LogoutSchema,
942
+ supportsJsonOutput: false,
943
+ handler: async () => {
944
+ await logout();
945
+ console.log("\u2705 Successfully logged out");
946
+ }
947
+ })
948
+ );
378
949
  var McpSchema = z.object({
379
950
  port: z.string().optional().describe("Port to listen on (for future HTTP transport)")
380
951
  }).describe("Start MCP server for Zapier SDK");
381
952
 
382
953
  // src/plugins/mcp/index.ts
383
- var mcpPlugin = (sdk) => {
384
- const mcpWithSdk = createFunction(async function mcpWithSdk2(options) {
385
- const mcpOptions = {
386
- ...options,
387
- debug: sdk.context.options?.debug
388
- };
389
- return await startMcpServer(mcpOptions);
390
- }, McpSchema);
391
- return {
392
- mcp: mcpWithSdk,
393
- context: {
394
- meta: {
395
- mcp: {
396
- categories: ["utility"],
397
- inputSchema: McpSchema
398
- }
399
- }
400
- }
401
- };
402
- };
954
+ var mcpPlugin = definePlugin(
955
+ (sdk) => createPluginMethod(sdk, {
956
+ name: "mcp",
957
+ categories: ["utility"],
958
+ inputSchema: McpSchema,
959
+ handler: async ({ sdk: sdk2, options }) => {
960
+ await startMcpServer({ ...options, debug: sdk2.context.options?.debug });
961
+ }
962
+ })
963
+ );
403
964
  var BundleCodeSchema = z.object({
404
965
  input: z.string().min(1).describe("Input TypeScript file path to bundle"),
405
966
  output: OutputPropertySchema.optional().describe(
@@ -410,22 +971,14 @@ var BundleCodeSchema = z.object({
410
971
  target: z.string().optional().describe("ECMAScript target version"),
411
972
  cjs: z.boolean().optional().describe("Output CommonJS format instead of ESM")
412
973
  }).describe("Bundle TypeScript code into executable JavaScript");
413
- var bundleCodePlugin = () => {
414
- const bundleCodeWithSdk = createFunction(async function bundleCodeWithSdk2(options) {
415
- return await bundleCode(options);
416
- }, BundleCodeSchema);
417
- return {
418
- bundleCode: bundleCodeWithSdk,
419
- context: {
420
- meta: {
421
- bundleCode: {
422
- categories: ["utility", "deprecated"],
423
- inputSchema: BundleCodeSchema
424
- }
425
- }
426
- }
427
- };
428
- };
974
+ var bundleCodePlugin = definePlugin(
975
+ (sdk) => createPluginMethod(sdk, {
976
+ name: "bundleCode",
977
+ categories: ["utility", "deprecated"],
978
+ inputSchema: BundleCodeSchema,
979
+ handler: async ({ options }) => bundleCode(options)
980
+ })
981
+ );
429
982
  var ZapierBundleError = class extends Error {
430
983
  constructor(message, details, originalError) {
431
984
  super(message);
@@ -492,25 +1045,14 @@ async function bundleCode(options) {
492
1045
  }
493
1046
  }
494
1047
  var GetLoginConfigPathSchema = z.object({}).describe("Show the path to the login configuration file");
495
- var getLoginConfigPathPlugin = () => {
496
- const getLoginConfigPathWithSdk = createFunction(
497
- async function getLoginConfigPathWithSdk2(_options) {
498
- return getConfigPath();
499
- },
500
- GetLoginConfigPathSchema
501
- );
502
- return {
503
- getLoginConfigPath: getLoginConfigPathWithSdk,
504
- context: {
505
- meta: {
506
- getLoginConfigPath: {
507
- categories: ["utility"],
508
- inputSchema: GetLoginConfigPathSchema
509
- }
510
- }
511
- }
512
- };
513
- };
1048
+ var getLoginConfigPathPlugin = definePlugin(
1049
+ (sdk) => createPluginMethod(sdk, {
1050
+ name: "getLoginConfigPath",
1051
+ categories: ["utility"],
1052
+ inputSchema: GetLoginConfigPathSchema,
1053
+ handler: async () => getConfigPath()
1054
+ })
1055
+ );
514
1056
  var AddSchema = z.object({
515
1057
  apps: z.array(z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required").describe(
516
1058
  "One or more app keys to add (e.g., 'slack', 'github', 'trello')"
@@ -538,111 +1080,105 @@ async function detectTypesOutputDirectory() {
538
1080
  }
539
1081
  return "./zapier/apps/";
540
1082
  }
541
- var addPlugin = (sdk) => {
542
- const add = createFunction(async function add2(options) {
543
- const {
544
- apps: appKeys,
545
- connections: connectionIds,
546
- configPath,
547
- typesOutput = await detectTypesOutputDirectory()
548
- } = options;
549
- const resolvedTypesOutput = resolve(typesOutput);
550
- console.log(`\u{1F4E6} Adding ${appKeys.length} app(s)...`);
551
- const appSlugAndKeyMap = /* @__PURE__ */ new Map();
552
- const handleManifestProgress = (event) => {
553
- switch (event.type) {
554
- case "apps_lookup_start":
555
- console.log(`\u{1F4E6} Looking up ${event.count} app(s)...`);
556
- break;
557
- case "app_found":
558
- const displayName = event.app.slug ? `${event.app.slug} (${event.app.key})` : event.app.key;
559
- appSlugAndKeyMap.set(event.app.key, displayName);
560
- break;
561
- case "apps_lookup_complete":
562
- if (event.count === 0) {
563
- console.warn("\u26A0\uFE0F No apps found");
564
- }
565
- break;
566
- case "app_processing_start":
567
- const appName = event.slug ? `${event.slug} (${event.app})` : event.app;
568
- console.log(`\u{1F4E6} Adding ${appName}...`);
569
- break;
570
- case "manifest_updated":
571
- const appDisplay = appSlugAndKeyMap.get(event.app) || event.app;
572
- console.log(
573
- `\u{1F4DD} Locked ${appDisplay} to ${event.app}@${event.version} using key '${event.manifestKey}'`
574
- );
575
- break;
576
- case "app_processing_error":
577
- const errorApp = appSlugAndKeyMap.get(event.app) || event.app;
578
- console.warn(`\u26A0\uFE0F ${event.error} for ${errorApp}`);
579
- break;
580
- }
581
- };
582
- const handleTypesProgress = (event) => {
583
- switch (event.type) {
584
- case "connections_lookup_start":
585
- console.log(`\u{1F510} Looking up ${event.count} connection(s)...`);
586
- break;
587
- case "connections_lookup_complete":
588
- console.log(`\u{1F510} Found ${event.count} connection(s)`);
589
- break;
590
- case "connection_matched":
591
- const appWithConnection = appSlugAndKeyMap.get(event.app) || event.app;
592
- console.log(
593
- `\u{1F510} Using connection ${event.connectionId} (${event.connectionTitle}) for ${appWithConnection}`
594
- );
595
- break;
596
- case "connection_not_matched":
597
- const appWithoutConnection = appSlugAndKeyMap.get(event.app) || event.app;
598
- console.warn(
599
- `\u26A0\uFE0F No matching connection found for ${appWithoutConnection}`
600
- );
601
- break;
602
- case "file_written":
603
- console.log(
604
- `\u{1F527} Generated types for ${event.manifestKey} at ${event.filePath}`
605
- );
606
- break;
607
- case "app_processing_error":
608
- const errorApp = appSlugAndKeyMap.get(event.app) || event.app;
609
- console.warn(`\u26A0\uFE0F ${event.error} for ${errorApp}`);
610
- break;
611
- }
612
- };
613
- const manifestResult = await sdk.buildManifest({
614
- apps: appKeys,
615
- skipWrite: false,
616
- configPath,
617
- onProgress: handleManifestProgress
618
- });
619
- const typesResult = await sdk.generateAppTypes({
620
- apps: appKeys,
621
- connections: connectionIds,
622
- skipWrite: false,
623
- typesOutputDirectory: resolvedTypesOutput,
624
- onProgress: handleTypesProgress
625
- });
626
- const results = manifestResult.manifest?.apps || {};
627
- const successfulApps = Object.keys(results).filter(
628
- (manifestKey) => typesResult.writtenFiles?.[manifestKey]
629
- );
630
- if (successfulApps.length > 0) {
631
- console.log(`\u2705 Added ${successfulApps.length} app(s) to manifest`);
632
- }
633
- }, AddSchema);
634
- return {
635
- add,
636
- context: {
637
- meta: {
638
- add: {
639
- categories: ["utility"],
640
- inputSchema: AddSchema
1083
+ var addPlugin = definePlugin(
1084
+ (sdk) => createPluginMethod(sdk, {
1085
+ name: "add",
1086
+ categories: ["utility"],
1087
+ inputSchema: AddSchema,
1088
+ handler: async ({ sdk: sdk2, options }) => {
1089
+ const {
1090
+ apps: appKeys,
1091
+ connections: connectionIds,
1092
+ configPath,
1093
+ typesOutput = await detectTypesOutputDirectory()
1094
+ } = options;
1095
+ const resolvedTypesOutput = resolve(typesOutput);
1096
+ console.log(`\u{1F4E6} Adding ${appKeys.length} app(s)...`);
1097
+ const appSlugAndKeyMap = /* @__PURE__ */ new Map();
1098
+ const handleManifestProgress = (event) => {
1099
+ switch (event.type) {
1100
+ case "apps_lookup_start":
1101
+ console.log(`\u{1F4E6} Looking up ${event.count} app(s)...`);
1102
+ break;
1103
+ case "app_found":
1104
+ const displayName = event.app.slug ? `${event.app.slug} (${event.app.key})` : event.app.key;
1105
+ appSlugAndKeyMap.set(event.app.key, displayName);
1106
+ break;
1107
+ case "apps_lookup_complete":
1108
+ if (event.count === 0) {
1109
+ console.warn("\u26A0\uFE0F No apps found");
1110
+ }
1111
+ break;
1112
+ case "app_processing_start":
1113
+ const appName = event.slug ? `${event.slug} (${event.app})` : event.app;
1114
+ console.log(`\u{1F4E6} Adding ${appName}...`);
1115
+ break;
1116
+ case "manifest_updated":
1117
+ const appDisplay = appSlugAndKeyMap.get(event.app) || event.app;
1118
+ console.log(
1119
+ `\u{1F4DD} Locked ${appDisplay} to ${event.app}@${event.version} using key '${event.manifestKey}'`
1120
+ );
1121
+ break;
1122
+ case "app_processing_error":
1123
+ const errorApp = appSlugAndKeyMap.get(event.app) || event.app;
1124
+ console.warn(`\u26A0\uFE0F ${event.error} for ${errorApp}`);
1125
+ break;
1126
+ }
1127
+ };
1128
+ const handleTypesProgress = (event) => {
1129
+ switch (event.type) {
1130
+ case "connections_lookup_start":
1131
+ console.log(`\u{1F510} Looking up ${event.count} connection(s)...`);
1132
+ break;
1133
+ case "connections_lookup_complete":
1134
+ console.log(`\u{1F510} Found ${event.count} connection(s)`);
1135
+ break;
1136
+ case "connection_matched":
1137
+ const appWithConnection = appSlugAndKeyMap.get(event.app) || event.app;
1138
+ console.log(
1139
+ `\u{1F510} Using connection ${event.connectionId} (${event.connectionTitle}) for ${appWithConnection}`
1140
+ );
1141
+ break;
1142
+ case "connection_not_matched":
1143
+ const appWithoutConnection = appSlugAndKeyMap.get(event.app) || event.app;
1144
+ console.warn(
1145
+ `\u26A0\uFE0F No matching connection found for ${appWithoutConnection}`
1146
+ );
1147
+ break;
1148
+ case "file_written":
1149
+ console.log(
1150
+ `\u{1F527} Generated types for ${event.manifestKey} at ${event.filePath}`
1151
+ );
1152
+ break;
1153
+ case "app_processing_error":
1154
+ const errorApp = appSlugAndKeyMap.get(event.app) || event.app;
1155
+ console.warn(`\u26A0\uFE0F ${event.error} for ${errorApp}`);
1156
+ break;
641
1157
  }
1158
+ };
1159
+ const manifestResult = await sdk2.buildManifest({
1160
+ apps: appKeys,
1161
+ skipWrite: false,
1162
+ configPath,
1163
+ onProgress: handleManifestProgress
1164
+ });
1165
+ const typesResult = await sdk2.generateAppTypes({
1166
+ apps: appKeys,
1167
+ connections: connectionIds,
1168
+ skipWrite: false,
1169
+ typesOutputDirectory: resolvedTypesOutput,
1170
+ onProgress: handleTypesProgress
1171
+ });
1172
+ const results = manifestResult.manifest?.apps || {};
1173
+ const successfulApps = Object.keys(results).filter(
1174
+ (manifestKey) => typesResult.writtenFiles?.[manifestKey]
1175
+ );
1176
+ if (successfulApps.length > 0) {
1177
+ console.log(`\u2705 Added ${successfulApps.length} app(s) to manifest`);
642
1178
  }
643
1179
  }
644
- };
645
- };
1180
+ })
1181
+ );
646
1182
  var GenerateAppTypesSchema = z.object({
647
1183
  apps: z.array(z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required").describe(
648
1184
  "One or more app keys to generate types for (e.g., 'slack', 'github', 'trello')"
@@ -1249,150 +1785,133 @@ function createManifestEntry(app) {
1249
1785
  version: app.version
1250
1786
  };
1251
1787
  }
1252
- var generateAppTypesPlugin = (sdk) => {
1253
- const generateAppTypes = createFunction(async function generateAppTypes2(options) {
1254
- const {
1255
- apps: appKeys,
1256
- connections: connectionIds,
1257
- skipWrite = false,
1258
- typesOutputDirectory = await detectTypesOutputDirectory(),
1259
- onProgress
1260
- } = options;
1261
- const resolvedTypesOutput = resolve(typesOutputDirectory);
1262
- const result = {
1263
- typeDefinitions: {}
1264
- };
1265
- onProgress?.({ type: "apps_lookup_start", count: appKeys.length });
1266
- const appsIterable = sdk.listApps({ apps: appKeys }).items();
1267
- const apps = [];
1268
- for await (const app of appsIterable) {
1269
- apps.push(app);
1270
- onProgress?.({ type: "app_found", app });
1271
- }
1272
- onProgress?.({ type: "apps_lookup_complete", count: apps.length });
1273
- if (apps.length === 0) {
1274
- return result;
1275
- }
1276
- const connections = [];
1277
- if (connectionIds && connectionIds.length > 0) {
1278
- onProgress?.({
1279
- type: "connections_lookup_start",
1280
- count: connectionIds.length
1281
- });
1282
- const connectionsIterable = sdk.listConnections({ connections: connectionIds }).items();
1283
- for await (const connection of connectionsIterable) {
1284
- connections.push(connection);
1788
+ var generateAppTypesPlugin = definePlugin(
1789
+ (sdk) => createPluginMethod(sdk, {
1790
+ name: "generateAppTypes",
1791
+ categories: ["utility"],
1792
+ // Cast: schema validates JSON fields only; GenerateAppTypesOptions adds
1793
+ // the runtime-only `onProgress` callback (passthrough via createFunction).
1794
+ inputSchema: GenerateAppTypesSchema,
1795
+ handler: async ({ sdk: sdk2, options }) => {
1796
+ const {
1797
+ apps: appKeys,
1798
+ connections: connectionIds,
1799
+ skipWrite = false,
1800
+ typesOutputDirectory = await detectTypesOutputDirectory(),
1801
+ onProgress
1802
+ } = options;
1803
+ const resolvedTypesOutput = resolve(typesOutputDirectory);
1804
+ const result = { typeDefinitions: {} };
1805
+ onProgress?.({ type: "apps_lookup_start", count: appKeys.length });
1806
+ const appsIterable = sdk2.listApps({ apps: appKeys }).items();
1807
+ const apps = [];
1808
+ for await (const app of appsIterable) {
1809
+ apps.push(app);
1810
+ onProgress?.({ type: "app_found", app });
1285
1811
  }
1286
- onProgress?.({
1287
- type: "connections_lookup_complete",
1288
- count: connections.length
1289
- });
1290
- }
1291
- if (!skipWrite && resolvedTypesOutput) {
1292
- await mkdir(resolvedTypesOutput, { recursive: true });
1293
- }
1294
- if (!skipWrite) {
1295
- result.writtenFiles = {};
1296
- }
1297
- for (const app of apps) {
1298
- onProgress?.({
1299
- type: "app_processing_start",
1300
- app: app.key,
1301
- slug: app.slug
1302
- });
1303
- try {
1304
- if (!app.version) {
1305
- const errorMessage = `Invalid implementation ID format: ${app.implementation_id}. Expected format: <implementationName>@<version>`;
1306
- onProgress?.({
1307
- type: "app_processing_error",
1308
- app: app.key,
1309
- error: errorMessage
1310
- });
1311
- throw new ZapierValidationError(errorMessage, {
1312
- details: {
1313
- appKey: app.key,
1314
- implementationId: app.implementation_id
1315
- }
1316
- });
1812
+ onProgress?.({ type: "apps_lookup_complete", count: apps.length });
1813
+ if (apps.length === 0) {
1814
+ return result;
1815
+ }
1816
+ const connections = [];
1817
+ if (connectionIds && connectionIds.length > 0) {
1818
+ onProgress?.({
1819
+ type: "connections_lookup_start",
1820
+ count: connectionIds.length
1821
+ });
1822
+ const connectionsIterable = sdk2.listConnections({ connections: connectionIds }).items();
1823
+ for await (const connection of connectionsIterable) {
1824
+ connections.push(connection);
1317
1825
  }
1318
- let connectionId;
1319
- if (connections.length > 0) {
1320
- const matchingConnection = connections.find((conn) => {
1321
- return conn.app_key === app.key;
1322
- });
1323
- if (matchingConnection) {
1324
- connectionId = matchingConnection.id;
1826
+ onProgress?.({
1827
+ type: "connections_lookup_complete",
1828
+ count: connections.length
1829
+ });
1830
+ }
1831
+ if (!skipWrite && resolvedTypesOutput) {
1832
+ await mkdir(resolvedTypesOutput, { recursive: true });
1833
+ }
1834
+ if (!skipWrite) {
1835
+ result.writtenFiles = {};
1836
+ }
1837
+ for (const app of apps) {
1838
+ onProgress?.({
1839
+ type: "app_processing_start",
1840
+ app: app.key,
1841
+ slug: app.slug
1842
+ });
1843
+ try {
1844
+ if (!app.version) {
1845
+ const errorMessage = `Invalid implementation ID format: ${app.implementation_id}. Expected format: <implementationName>@<version>`;
1325
1846
  onProgress?.({
1326
- type: "connection_matched",
1847
+ type: "app_processing_error",
1327
1848
  app: app.key,
1328
- connectionId: matchingConnection.id,
1329
- connectionTitle: matchingConnection.title || ""
1849
+ error: errorMessage
1330
1850
  });
1331
- } else {
1332
- onProgress?.({
1333
- type: "connection_not_matched",
1334
- app: app.key
1851
+ throw new ZapierValidationError(errorMessage, {
1852
+ details: {
1853
+ appKey: app.key,
1854
+ implementationId: app.implementation_id
1855
+ }
1335
1856
  });
1336
1857
  }
1337
- }
1338
- const manifestKey = getManifestKey(app);
1339
- const generator = new AstTypeGenerator();
1340
- const typeDefinitionString = await generator.generateTypes({
1341
- app,
1342
- connectionId,
1343
- sdk
1344
- });
1345
- result.typeDefinitions[manifestKey] = typeDefinitionString;
1346
- onProgress?.({
1347
- type: "type_generated",
1348
- manifestKey,
1349
- sizeBytes: typeDefinitionString.length
1350
- });
1351
- if (!skipWrite && resolvedTypesOutput && result.writtenFiles) {
1352
- const filePath = join(resolvedTypesOutput, `${manifestKey}.d.ts`);
1353
- await writeFile(filePath, typeDefinitionString, "utf8");
1354
- result.writtenFiles[manifestKey] = filePath;
1858
+ let connectionId;
1859
+ if (connections.length > 0) {
1860
+ const matchingConnection = connections.find(
1861
+ (conn) => conn.app_key === app.key
1862
+ );
1863
+ if (matchingConnection) {
1864
+ connectionId = matchingConnection.id;
1865
+ onProgress?.({
1866
+ type: "connection_matched",
1867
+ app: app.key,
1868
+ connectionId: matchingConnection.id,
1869
+ connectionTitle: matchingConnection.title || ""
1870
+ });
1871
+ } else {
1872
+ onProgress?.({
1873
+ type: "connection_not_matched",
1874
+ app: app.key
1875
+ });
1876
+ }
1877
+ }
1878
+ const manifestKey = getManifestKey(app);
1879
+ const generator = new AstTypeGenerator();
1880
+ const typeDefinitionString = await generator.generateTypes({
1881
+ app,
1882
+ connectionId,
1883
+ sdk: sdk2
1884
+ });
1885
+ result.typeDefinitions[manifestKey] = typeDefinitionString;
1355
1886
  onProgress?.({
1356
- type: "file_written",
1887
+ type: "type_generated",
1357
1888
  manifestKey,
1358
- filePath
1889
+ sizeBytes: typeDefinitionString.length
1359
1890
  });
1360
- }
1361
- onProgress?.({
1362
- type: "app_processing_complete",
1363
- app: app.key
1364
- });
1365
- } catch (error) {
1366
- const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
1367
- onProgress?.({
1368
- type: "app_processing_error",
1369
- app: app.key,
1370
- error: errorMessage
1371
- });
1372
- if (error instanceof ZapierValidationError) {
1373
- throw error;
1374
- } else {
1375
- throw new ZapierUnknownError(errorMessage, {
1376
- cause: error
1377
- // Works for both Error and non-Error
1891
+ if (!skipWrite && resolvedTypesOutput && result.writtenFiles) {
1892
+ const filePath = join(resolvedTypesOutput, `${manifestKey}.d.ts`);
1893
+ await writeFile(filePath, typeDefinitionString, "utf8");
1894
+ result.writtenFiles[manifestKey] = filePath;
1895
+ onProgress?.({ type: "file_written", manifestKey, filePath });
1896
+ }
1897
+ onProgress?.({ type: "app_processing_complete", app: app.key });
1898
+ } catch (error) {
1899
+ const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
1900
+ onProgress?.({
1901
+ type: "app_processing_error",
1902
+ app: app.key,
1903
+ error: errorMessage
1378
1904
  });
1905
+ if (error instanceof ZapierValidationError) {
1906
+ throw error;
1907
+ }
1908
+ throw new ZapierUnknownError(errorMessage, { cause: error });
1379
1909
  }
1380
1910
  }
1911
+ return result;
1381
1912
  }
1382
- return result;
1383
- }, GenerateAppTypesSchema);
1384
- return {
1385
- generateAppTypes,
1386
- context: {
1387
- meta: {
1388
- generateAppTypes: {
1389
- categories: ["utility"],
1390
- inputSchema: GenerateAppTypesSchema
1391
- }
1392
- }
1393
- }
1394
- };
1395
- };
1913
+ })
1914
+ );
1396
1915
  var BuildManifestSchema = z.object({
1397
1916
  apps: z.array(z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required").describe(
1398
1917
  "One or more app keys to build manifest entries for (e.g., 'slack', 'github', 'trello')"
@@ -1408,86 +1927,80 @@ var BuildManifestSchema = z.object({
1408
1927
  );
1409
1928
 
1410
1929
  // src/plugins/buildManifest/index.ts
1411
- var buildManifestPlugin = (sdk) => {
1412
- const buildManifest = createFunction(async function buildManifest2(options) {
1413
- const {
1414
- apps: appKeys,
1415
- skipWrite = false,
1416
- configPath,
1417
- onProgress
1418
- } = options;
1419
- onProgress?.({ type: "apps_lookup_start", count: appKeys.length });
1420
- const appsIterable = sdk.listApps({ apps: appKeys }).items();
1421
- const apps = [];
1422
- for await (const app of appsIterable) {
1423
- apps.push(app);
1424
- onProgress?.({ type: "app_found", app });
1425
- }
1426
- onProgress?.({ type: "apps_lookup_complete", count: apps.length });
1427
- if (apps.length === 0) {
1428
- return {};
1429
- }
1430
- let updatedManifest;
1431
- for (const app of apps) {
1432
- onProgress?.({
1433
- type: "app_processing_start",
1434
- app: app.key,
1435
- slug: app.slug
1436
- });
1437
- try {
1438
- const manifestEntry = createManifestEntry(app);
1439
- onProgress?.({
1440
- type: "manifest_entry_built",
1441
- app: app.key,
1442
- manifestKey: manifestEntry.implementationName,
1443
- version: manifestEntry.version || ""
1444
- });
1445
- const { key: updatedManifestKey, manifest } = await sdk.context.updateManifestEntry({
1446
- appKey: app.key,
1447
- entry: manifestEntry,
1448
- configPath,
1449
- skipWrite,
1450
- manifest: updatedManifest
1451
- });
1452
- updatedManifest = manifest;
1453
- onProgress?.({
1454
- type: "manifest_updated",
1455
- app: app.key,
1456
- manifestKey: updatedManifestKey,
1457
- version: manifestEntry.version || ""
1458
- });
1459
- onProgress?.({ type: "app_processing_complete", app: app.key });
1460
- } catch (error) {
1461
- const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
1930
+ var buildManifestPlugin = definePlugin(
1931
+ (sdk) => createPluginMethod(sdk, {
1932
+ name: "buildManifest",
1933
+ categories: ["utility"],
1934
+ // Cast: BuildManifestSchema validates JSON-serializable fields only.
1935
+ // BuildManifestOptions adds an `onProgress` callback that rides through
1936
+ // `createFunction`'s passthrough spread at runtime; this widens TInput
1937
+ // so the handler can read it.
1938
+ inputSchema: BuildManifestSchema,
1939
+ handler: async ({ sdk: sdk2, options }) => {
1940
+ const {
1941
+ apps: appKeys,
1942
+ skipWrite = false,
1943
+ configPath,
1944
+ onProgress
1945
+ } = options;
1946
+ onProgress?.({ type: "apps_lookup_start", count: appKeys.length });
1947
+ const appsIterable = sdk2.listApps({ apps: appKeys }).items();
1948
+ const apps = [];
1949
+ for await (const app of appsIterable) {
1950
+ apps.push(app);
1951
+ onProgress?.({ type: "app_found", app });
1952
+ }
1953
+ onProgress?.({ type: "apps_lookup_complete", count: apps.length });
1954
+ if (apps.length === 0) {
1955
+ return {};
1956
+ }
1957
+ let updatedManifest;
1958
+ for (const app of apps) {
1462
1959
  onProgress?.({
1463
- type: "app_processing_error",
1960
+ type: "app_processing_start",
1464
1961
  app: app.key,
1465
- error: errorMessage
1962
+ slug: app.slug
1466
1963
  });
1467
- if (error instanceof ZapierValidationError) {
1468
- throw error;
1469
- } else {
1470
- throw new ZapierUnknownError(errorMessage, {
1471
- cause: error
1472
- // Works for both Error and non-Error
1964
+ try {
1965
+ const manifestEntry = createManifestEntry(app);
1966
+ onProgress?.({
1967
+ type: "manifest_entry_built",
1968
+ app: app.key,
1969
+ manifestKey: manifestEntry.implementationName,
1970
+ version: manifestEntry.version || ""
1473
1971
  });
1972
+ const { key: updatedManifestKey, manifest } = await sdk2.context.updateManifestEntry({
1973
+ appKey: app.key,
1974
+ entry: manifestEntry,
1975
+ configPath,
1976
+ skipWrite,
1977
+ manifest: updatedManifest
1978
+ });
1979
+ updatedManifest = manifest;
1980
+ onProgress?.({
1981
+ type: "manifest_updated",
1982
+ app: app.key,
1983
+ manifestKey: updatedManifestKey,
1984
+ version: manifestEntry.version || ""
1985
+ });
1986
+ onProgress?.({ type: "app_processing_complete", app: app.key });
1987
+ } catch (error) {
1988
+ const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
1989
+ onProgress?.({
1990
+ type: "app_processing_error",
1991
+ app: app.key,
1992
+ error: errorMessage
1993
+ });
1994
+ if (error instanceof ZapierValidationError) {
1995
+ throw error;
1996
+ }
1997
+ throw new ZapierUnknownError(errorMessage, { cause: error });
1474
1998
  }
1475
1999
  }
2000
+ return { manifest: updatedManifest };
1476
2001
  }
1477
- return { manifest: updatedManifest };
1478
- }, BuildManifestSchema);
1479
- return {
1480
- buildManifest,
1481
- context: {
1482
- meta: {
1483
- buildManifest: {
1484
- categories: ["utility"],
1485
- inputSchema: BuildManifestSchema
1486
- }
1487
- }
1488
- }
1489
- };
1490
- };
2002
+ })
2003
+ );
1491
2004
  var FeedbackSchema = z.object({
1492
2005
  feedback: z.string().describe(
1493
2006
  "Your feedback on the Zapier SDK. Describe what worked well, what was frustrating, or any suggestions."
@@ -1521,37 +2034,31 @@ async function postWithRetry({
1521
2034
  }
1522
2035
  return response;
1523
2036
  }
1524
- var feedbackPlugin = (sdk) => {
1525
- const debug = sdk.context.options?.debug;
1526
- const feedbackWithSdk = createFunction(async function feedback(options) {
1527
- const user = await getLoggedInUser();
1528
- const body = JSON.stringify({
1529
- email: user.email,
1530
- customuser_id: user.customUserId,
1531
- feedback: options.feedback
1532
- });
1533
- const response = await postWithRetry({ body, attemptsLeft: MAX_RETRIES });
1534
- if (debug) {
1535
- const text = await response.text();
1536
- console.error("[debug] Webhook response:", text);
1537
- }
1538
- return "Thank you for your feedback!";
1539
- }, FeedbackSchema);
1540
- return {
1541
- feedback: feedbackWithSdk,
1542
- context: {
1543
- meta: {
1544
- feedback: {
1545
- categories: ["utility"],
1546
- inputSchema: FeedbackSchema,
1547
- resolvers: {
1548
- feedback: feedbackResolver
1549
- }
1550
- }
2037
+ var feedbackPlugin = definePlugin(
2038
+ (sdk) => createPluginMethod(sdk, {
2039
+ name: "feedback",
2040
+ categories: ["utility"],
2041
+ inputSchema: FeedbackSchema,
2042
+ resolvers: { feedback: feedbackResolver },
2043
+ handler: async ({ sdk: sdk2, options }) => {
2044
+ const user = await getLoggedInUser();
2045
+ const body = JSON.stringify({
2046
+ email: user.email,
2047
+ customuser_id: user.customUserId,
2048
+ feedback: options.feedback
2049
+ });
2050
+ const response = await postWithRetry({
2051
+ body,
2052
+ attemptsLeft: MAX_RETRIES
2053
+ });
2054
+ if (sdk2.context.options?.debug) {
2055
+ const text = await response.text();
2056
+ console.error("[debug] Webhook response:", text);
1551
2057
  }
2058
+ return "Thank you for your feedback!";
1552
2059
  }
1553
- };
1554
- };
2060
+ })
2061
+ );
1555
2062
  var CurlSchema = z.object({
1556
2063
  url: z.string().describe("Request URL"),
1557
2064
  request: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).optional().describe("HTTP method (defaults to GET, or POST if data is provided)"),
@@ -1727,7 +2234,7 @@ async function buildFormData(formArgs, formStringArgs) {
1727
2234
  }
1728
2235
 
1729
2236
  // src/plugins/curl/index.ts
1730
- var curlPlugin = (sdk) => {
2237
+ var curlPlugin = definePlugin((sdk) => {
1731
2238
  async function curl(options) {
1732
2239
  const {
1733
2240
  url: rawUrl,
@@ -1970,30 +2477,25 @@ ${Array.from(
1970
2477
  }
1971
2478
  }
1972
2479
  };
1973
- };
1974
-
1975
- // src/plugins/cliOverrides/index.ts
1976
- var cliOverridesPlugin = (sdk) => {
1977
- if (!sdk.context.meta.fetch) {
1978
- return { context: { meta: {} } };
1979
- }
1980
- return {
1981
- context: {
1982
- meta: {
1983
- fetch: {
1984
- ...sdk.context.meta.fetch,
1985
- categories: [
1986
- ...sdk.context.meta.fetch.categories || [],
1987
- "deprecated"
1988
- ],
1989
- deprecation: {
1990
- message: "This command is deprecated and will be removed soon. Use `curl` instead. Learn more: https://docs.zapier.com/sdk/cli-reference#curl"
1991
- }
2480
+ });
2481
+ var cliOverridesPlugin = definePlugin(
2482
+ (sdk) => {
2483
+ const meta = {};
2484
+ if (sdk.context.meta.fetch) {
2485
+ meta.fetch = {
2486
+ ...sdk.context.meta.fetch,
2487
+ categories: [
2488
+ ...sdk.context.meta.fetch.categories || [],
2489
+ "deprecated"
2490
+ ],
2491
+ deprecation: {
2492
+ message: "This command is deprecated and will be removed soon. Use `curl` instead. Learn more: https://docs.zapier.com/sdk/cli-reference#curl"
1992
2493
  }
1993
- }
2494
+ };
1994
2495
  }
1995
- };
1996
- };
2496
+ return { context: { meta } };
2497
+ }
2498
+ );
1997
2499
  var TEMPLATES = ["basic"];
1998
2500
  var InitSchema = z.object({
1999
2501
  projectName: z.string().min(1).describe("Name of the project directory to create"),
@@ -2405,74 +2907,68 @@ function displaySummaryAndNextSteps({
2405
2907
  }
2406
2908
 
2407
2909
  // src/plugins/init/index.ts
2408
- var initPlugin = () => {
2409
- const init = createFunction(async function init2(options) {
2410
- const { projectName: rawName, skipPrompts = false } = options;
2411
- const cwd = process.cwd();
2412
- const { projectName, projectDir } = validateInitOptions({ rawName, cwd });
2413
- const displayHooks = createConsoleDisplayHooks();
2414
- const packageManagerInfo = detectPackageManager(cwd);
2415
- if (packageManagerInfo.name === "unknown") {
2416
- displayHooks.onWarn(
2417
- "Could not detect package manager, defaulting to npm."
2418
- );
2419
- }
2420
- const packageManager = packageManagerInfo.name === "unknown" ? "npm" : packageManagerInfo.name;
2421
- const steps = getInitSteps({
2422
- projectDir,
2423
- projectName,
2424
- packageManager,
2425
- displayHooks
2426
- });
2427
- const completedSetupStepIds = [];
2428
- for (let i = 0; i < steps.length; i++) {
2429
- const step = steps[i];
2430
- const succeeded = await withInterruptCleanup(
2431
- step.cleanup,
2432
- () => runStep({
2433
- step,
2434
- stepNumber: i + 1,
2435
- totalSteps: steps.length,
2436
- skipPrompts,
2437
- displayHooks
2438
- })
2439
- );
2440
- if (!succeeded) break;
2441
- completedSetupStepIds.push(step.id);
2442
- }
2443
- if (completedSetupStepIds.length === 0) {
2444
- throw new ZapierCliExitError(
2445
- "Project setup failed \u2014 no steps completed."
2446
- );
2447
- }
2448
- displaySummaryAndNextSteps({
2449
- projectName,
2450
- steps,
2451
- completedSetupStepIds,
2452
- packageManager
2453
- });
2454
- }, InitSchema);
2455
- return {
2456
- init,
2457
- context: {
2458
- meta: {
2459
- init: {
2460
- categories: ["utility"],
2461
- inputSchema: InitSchema,
2462
- supportsJsonOutput: false
2463
- }
2910
+ var initPlugin = definePlugin(
2911
+ (sdk) => createPluginMethod(sdk, {
2912
+ name: "init",
2913
+ categories: ["utility"],
2914
+ inputSchema: InitSchema,
2915
+ supportsJsonOutput: false,
2916
+ handler: async ({ options }) => {
2917
+ const { projectName: rawName, skipPrompts = false } = options;
2918
+ const cwd = process.cwd();
2919
+ const { projectName, projectDir } = validateInitOptions({ rawName, cwd });
2920
+ const displayHooks = createConsoleDisplayHooks();
2921
+ const packageManagerInfo = detectPackageManager(cwd);
2922
+ if (packageManagerInfo.name === "unknown") {
2923
+ displayHooks.onWarn(
2924
+ "Could not detect package manager, defaulting to npm."
2925
+ );
2464
2926
  }
2927
+ const packageManager = packageManagerInfo.name === "unknown" ? "npm" : packageManagerInfo.name;
2928
+ const steps = getInitSteps({
2929
+ projectDir,
2930
+ projectName,
2931
+ packageManager,
2932
+ displayHooks
2933
+ });
2934
+ const completedSetupStepIds = [];
2935
+ for (let i = 0; i < steps.length; i++) {
2936
+ const step = steps[i];
2937
+ const succeeded = await withInterruptCleanup(
2938
+ step.cleanup,
2939
+ () => runStep({
2940
+ step,
2941
+ stepNumber: i + 1,
2942
+ totalSteps: steps.length,
2943
+ skipPrompts,
2944
+ displayHooks
2945
+ })
2946
+ );
2947
+ if (!succeeded) break;
2948
+ completedSetupStepIds.push(step.id);
2949
+ }
2950
+ if (completedSetupStepIds.length === 0) {
2951
+ throw new ZapierCliExitError(
2952
+ "Project setup failed \u2014 no steps completed."
2953
+ );
2954
+ }
2955
+ displaySummaryAndNextSteps({
2956
+ projectName,
2957
+ steps,
2958
+ completedSetupStepIds,
2959
+ packageManager
2960
+ });
2465
2961
  }
2466
- };
2467
- };
2962
+ })
2963
+ );
2468
2964
 
2469
2965
  // package.json with { type: 'json' }
2470
2966
  var package_default = {
2471
2967
  name: "@zapier/zapier-sdk-cli",
2472
- version: "0.42.2"};
2968
+ version: "0.43.1"};
2473
2969
 
2474
2970
  // src/sdk.ts
2475
- injectCliLogin(cliLogin);
2971
+ injectCliLogin(login_exports);
2476
2972
  function createZapierCliSdk(options = {}) {
2477
2973
  return createZapierSdk({
2478
2974
  ...options,
@@ -2483,7 +2979,7 @@ function createZapierCliSdk(options = {}) {
2483
2979
 
2484
2980
  // package.json
2485
2981
  var package_default2 = {
2486
- version: "0.42.2"};
2982
+ version: "0.43.1"};
2487
2983
 
2488
2984
  // src/telemetry/builders.ts
2489
2985
  function createCliBaseEvent(context = {}) {