@zapier/zapier-sdk-cli 0.42.1 → 0.43.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/dist/cli.cjs CHANGED
@@ -9,15 +9,18 @@ var chalk7 = require('chalk');
9
9
  var ora = require('ora');
10
10
  var util = require('util');
11
11
  var wrapAnsi = require('wrap-ansi');
12
- var cliLogin = require('@zapier/zapier-sdk-cli-login');
13
- var open = require('open');
12
+ var Conf = require('conf');
13
+ var fs = require('fs');
14
+ var jwt = require('jsonwebtoken');
15
+ var crossKeychain = require('cross-keychain');
14
16
  var crypto = require('crypto');
17
+ var path = require('path');
18
+ var lockfile = require('proper-lockfile');
19
+ var open = require('open');
15
20
  var express = require('express');
16
21
  var pkceChallenge = require('pkce-challenge');
17
22
  var zapierSdkMcp = require('@zapier/zapier-sdk-mcp');
18
23
  var esbuild = require('esbuild');
19
- var fs = require('fs');
20
- var path = require('path');
21
24
  var promises = require('fs/promises');
22
25
  var ts = require('typescript');
23
26
  var isInstalledGlobally = require('is-installed-globally');
@@ -53,19 +56,26 @@ var chalk7__default = /*#__PURE__*/_interopDefault(chalk7);
53
56
  var ora__default = /*#__PURE__*/_interopDefault(ora);
54
57
  var util__default = /*#__PURE__*/_interopDefault(util);
55
58
  var wrapAnsi__default = /*#__PURE__*/_interopDefault(wrapAnsi);
56
- var cliLogin__namespace = /*#__PURE__*/_interopNamespace(cliLogin);
57
- var open__default = /*#__PURE__*/_interopDefault(open);
59
+ var Conf__default = /*#__PURE__*/_interopDefault(Conf);
60
+ var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
61
+ var jwt__namespace = /*#__PURE__*/_interopNamespace(jwt);
58
62
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
63
+ var path__namespace = /*#__PURE__*/_interopNamespace(path);
64
+ var lockfile__namespace = /*#__PURE__*/_interopNamespace(lockfile);
65
+ var open__default = /*#__PURE__*/_interopDefault(open);
59
66
  var express__default = /*#__PURE__*/_interopDefault(express);
60
67
  var pkceChallenge__default = /*#__PURE__*/_interopDefault(pkceChallenge);
61
- var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
62
- var path__namespace = /*#__PURE__*/_interopNamespace(path);
63
68
  var ts__namespace = /*#__PURE__*/_interopNamespace(ts);
64
69
  var isInstalledGlobally__default = /*#__PURE__*/_interopDefault(isInstalledGlobally);
65
70
  var Handlebars__default = /*#__PURE__*/_interopDefault(Handlebars);
66
71
  var packageJsonLib__default = /*#__PURE__*/_interopDefault(packageJsonLib);
67
72
  var semver__default = /*#__PURE__*/_interopDefault(semver);
68
73
 
74
+ var __defProp = Object.defineProperty;
75
+ var __export = (target, all) => {
76
+ for (var name in all)
77
+ __defProp(target, name, { get: all[name], enumerable: true });
78
+ };
69
79
  var ZapierCliError = class extends zapierSdk.ZapierError {
70
80
  };
71
81
  var ZapierCliUserCancellationError = class extends ZapierCliError {
@@ -1103,7 +1113,7 @@ var SHARED_COMMAND_CLI_OPTIONS = [
1103
1113
 
1104
1114
  // package.json
1105
1115
  var package_default = {
1106
- version: "0.42.1"};
1116
+ version: "0.43.0"};
1107
1117
 
1108
1118
  // src/telemetry/builders.ts
1109
1119
  function createCliBaseEvent(context = {}) {
@@ -1833,8 +1843,8 @@ function generateCliCommands(program2, sdk2) {
1833
1843
  return;
1834
1844
  }
1835
1845
  const cliCommandName = methodNameToCliCommand(fnInfo.name);
1836
- const config = createCommandConfig(cliCommandName, fnInfo, sdk2);
1837
- addCommand(program2, cliCommandName, config);
1846
+ const config2 = createCommandConfig(cliCommandName, fnInfo, sdk2);
1847
+ addCommand(program2, cliCommandName, config2);
1838
1848
  });
1839
1849
  program2.configureHelp({
1840
1850
  formatHelp: (cmd, helper) => {
@@ -2091,10 +2101,10 @@ function collect(value, previous = []) {
2091
2101
  previous.push(value);
2092
2102
  return previous;
2093
2103
  }
2094
- function addCommand(program2, commandName, config) {
2095
- const command = program2.command(commandName, { hidden: config.hidden ?? false }).description(config.description);
2104
+ function addCommand(program2, commandName, config2) {
2105
+ const command = program2.command(commandName, { hidden: config2.hidden ?? false }).description(config2.description);
2096
2106
  let hasPositionalArray = false;
2097
- config.parameters.forEach((param) => {
2107
+ config2.parameters.forEach((param) => {
2098
2108
  const kebabName = toKebabCase(param.name);
2099
2109
  if (param.hasResolver && param.required) {
2100
2110
  command.argument(
@@ -2128,7 +2138,7 @@ function addCommand(program2, commandName, config) {
2128
2138
  );
2129
2139
  } else {
2130
2140
  const flags = [];
2131
- const alias = config.aliases?.[param.name];
2141
+ const alias = config2.aliases?.[param.name];
2132
2142
  if (alias && alias.length === 1) {
2133
2143
  flags.push(`-${alias}`);
2134
2144
  }
@@ -2157,13 +2167,13 @@ function addCommand(program2, commandName, config) {
2157
2167
  }
2158
2168
  }
2159
2169
  });
2160
- const paramNames = new Set(config.parameters.map((p) => p.name));
2170
+ const paramNames = new Set(config2.parameters.map((p) => p.name));
2161
2171
  SHARED_COMMAND_CLI_OPTIONS.forEach((opt) => {
2162
2172
  if (paramNames.has(opt.name)) return;
2163
- if (config.supportsJsonOutput === false && opt.name === "json") return;
2173
+ if (config2.supportsJsonOutput === false && opt.name === "json") return;
2164
2174
  command.option(opt.flag, opt.description);
2165
2175
  });
2166
- command.action(config.handler);
2176
+ command.action(config2.handler);
2167
2177
  }
2168
2178
  function convertCliArgsToSdkParams(parameters, positionalArgs, options) {
2169
2179
  const sdkParams = {};
@@ -2235,6 +2245,581 @@ function convertValue(value, type, elementType) {
2235
2245
  return value;
2236
2246
  }
2237
2247
  }
2248
+
2249
+ // src/login.ts
2250
+ var login_exports = {};
2251
+ __export(login_exports, {
2252
+ AUTH_MODE_HEADER: () => AUTH_MODE_HEADER,
2253
+ ZapierAuthenticationError: () => ZapierAuthenticationError,
2254
+ createCache: () => createCache,
2255
+ getAuthAuthorizeUrl: () => getAuthAuthorizeUrl,
2256
+ getAuthTokenUrl: () => getAuthTokenUrl,
2257
+ getConfig: () => getConfig,
2258
+ getConfigPath: () => getConfigPath,
2259
+ getLoggedInUser: () => getLoggedInUser,
2260
+ getLoginStorageMode: () => getLoginStorageMode,
2261
+ getPkceLoginConfig: () => getPkceLoginConfig,
2262
+ getToken: () => getToken,
2263
+ logout: () => logout,
2264
+ unloadConfig: () => unloadConfig,
2265
+ updateLogin: () => updateLogin
2266
+ });
2267
+ var SERVICE = "zapier-sdk-cli";
2268
+ var ACCOUNT = "login";
2269
+ var cachedBackendInfo;
2270
+ async function getBackendInfo() {
2271
+ if (!cachedBackendInfo) {
2272
+ const keyring = await crossKeychain.getKeyring();
2273
+ cachedBackendInfo = `${keyring.name} (${keyring.id})`;
2274
+ }
2275
+ return cachedBackendInfo;
2276
+ }
2277
+ var keychainQueue = Promise.resolve();
2278
+ function enqueue(fn) {
2279
+ const result = keychainQueue.then(fn, fn);
2280
+ keychainQueue = result.then(
2281
+ () => {
2282
+ },
2283
+ () => {
2284
+ }
2285
+ );
2286
+ return result;
2287
+ }
2288
+ async function getTokensFromKeychain({
2289
+ debugLog
2290
+ } = {}) {
2291
+ return enqueue(async () => {
2292
+ const backendInfo = await getBackendInfo();
2293
+ debugLog?.(`Keychain read via ${backendInfo}`);
2294
+ const startTime = Date.now();
2295
+ const raw = await crossKeychain.getPassword(SERVICE, ACCOUNT);
2296
+ debugLog?.(`Keychain read completed in ${Date.now() - startTime}ms`);
2297
+ if (!raw) {
2298
+ debugLog?.("Keychain returned no data");
2299
+ return void 0;
2300
+ }
2301
+ let parsed;
2302
+ try {
2303
+ parsed = JSON.parse(raw);
2304
+ } catch {
2305
+ debugLog?.("Keychain data is not valid JSON");
2306
+ return void 0;
2307
+ }
2308
+ if (typeof parsed.login_jwt === "string" && typeof parsed.login_refresh_token === "string") {
2309
+ return {
2310
+ login_jwt: parsed.login_jwt,
2311
+ login_refresh_token: parsed.login_refresh_token
2312
+ };
2313
+ }
2314
+ debugLog?.("Keychain data has invalid shape", parsed);
2315
+ return void 0;
2316
+ });
2317
+ }
2318
+ async function setTokensInKeychain({
2319
+ data,
2320
+ debugLog
2321
+ }) {
2322
+ return enqueue(async () => {
2323
+ const backendInfo = await getBackendInfo();
2324
+ debugLog?.(`Keychain write via ${backendInfo}`);
2325
+ const startTime = Date.now();
2326
+ await crossKeychain.setPassword(SERVICE, ACCOUNT, JSON.stringify(data));
2327
+ debugLog?.(`Keychain write completed in ${Date.now() - startTime}ms`);
2328
+ });
2329
+ }
2330
+ async function clearTokensFromKeychain({
2331
+ debugLog
2332
+ } = {}) {
2333
+ return enqueue(async () => {
2334
+ try {
2335
+ const backendInfo = await getBackendInfo();
2336
+ debugLog?.(`Keychain clear via ${backendInfo}`);
2337
+ await crossKeychain.deletePassword(SERVICE, ACCOUNT);
2338
+ } catch {
2339
+ }
2340
+ });
2341
+ }
2342
+ var SERVICE2 = "zapier-sdk-cache";
2343
+ var CONFIG_KEY = "cache";
2344
+ var LOCK_UPDATE_MS = 5e3;
2345
+ var LOCK_STALE_MS = 1e4;
2346
+ var LOCK_RETRY_WAIT_MS = 100;
2347
+ var LOCK_RETRY_MAX_WAIT_MS = 1e3;
2348
+ var LOCK_RETRY_COUNT = 120;
2349
+ function keychainAccount(key) {
2350
+ return crypto.createHash("sha256").update(key).digest("hex");
2351
+ }
2352
+ function readConfigMap() {
2353
+ const cfg = getConfig();
2354
+ const stored = cfg.get(CONFIG_KEY);
2355
+ if (stored && typeof stored === "object") {
2356
+ return stored;
2357
+ }
2358
+ return {};
2359
+ }
2360
+ function writeConfigMap(map) {
2361
+ getConfig().set(CONFIG_KEY, map);
2362
+ }
2363
+ function entryIsExpired(entry) {
2364
+ return entry.expires_at !== void 0 && entry.expires_at <= Date.now();
2365
+ }
2366
+ function createCache() {
2367
+ return {
2368
+ async get(key) {
2369
+ const entry = readConfigMap()[key];
2370
+ if (!entry) return void 0;
2371
+ if (entryIsExpired(entry)) return void 0;
2372
+ if (entry.secret) {
2373
+ const stored = await enqueue(async () => {
2374
+ await getBackendInfo();
2375
+ return crossKeychain.getPassword(SERVICE2, keychainAccount(key));
2376
+ });
2377
+ if (!stored) {
2378
+ return void 0;
2379
+ }
2380
+ return { value: stored, expiresAt: entry.expires_at };
2381
+ }
2382
+ if (entry.value === void 0) return void 0;
2383
+ return { value: entry.value, expiresAt: entry.expires_at };
2384
+ },
2385
+ async set(key, value, options) {
2386
+ const secret = options?.secret ?? false;
2387
+ const expiresAt = options?.ttl ? Date.now() + options.ttl * 1e3 : void 0;
2388
+ if (secret) {
2389
+ try {
2390
+ await enqueue(async () => {
2391
+ await getBackendInfo();
2392
+ await crossKeychain.setPassword(SERVICE2, keychainAccount(key), value);
2393
+ });
2394
+ } catch {
2395
+ return;
2396
+ }
2397
+ const map = readConfigMap();
2398
+ map[key] = { secret: true, expires_at: expiresAt };
2399
+ try {
2400
+ writeConfigMap(map);
2401
+ } catch {
2402
+ }
2403
+ } else {
2404
+ const map = readConfigMap();
2405
+ map[key] = { secret: false, value, expires_at: expiresAt };
2406
+ try {
2407
+ writeConfigMap(map);
2408
+ } catch {
2409
+ }
2410
+ }
2411
+ },
2412
+ async delete(key) {
2413
+ const map = readConfigMap();
2414
+ const entry = map[key];
2415
+ if (entry) {
2416
+ delete map[key];
2417
+ try {
2418
+ writeConfigMap(map);
2419
+ } catch {
2420
+ }
2421
+ }
2422
+ if (entry?.secret) {
2423
+ try {
2424
+ await enqueue(async () => {
2425
+ await getBackendInfo();
2426
+ await crossKeychain.deletePassword(SERVICE2, keychainAccount(key));
2427
+ });
2428
+ } catch {
2429
+ }
2430
+ }
2431
+ },
2432
+ async withLock(_key, fn) {
2433
+ const cfg = getConfig();
2434
+ const lockTarget = `${cfg.path}.cache-lock`;
2435
+ try {
2436
+ fs.mkdirSync(path.dirname(lockTarget), { recursive: true });
2437
+ if (!fs.existsSync(lockTarget)) {
2438
+ fs.writeFileSync(lockTarget, "");
2439
+ }
2440
+ } catch {
2441
+ return fn();
2442
+ }
2443
+ let release = null;
2444
+ try {
2445
+ release = await lockfile__namespace.lock(lockTarget, {
2446
+ stale: LOCK_STALE_MS,
2447
+ update: LOCK_UPDATE_MS,
2448
+ retries: {
2449
+ retries: LOCK_RETRY_COUNT,
2450
+ factor: 1.2,
2451
+ minTimeout: LOCK_RETRY_WAIT_MS,
2452
+ maxTimeout: LOCK_RETRY_MAX_WAIT_MS
2453
+ }
2454
+ });
2455
+ } catch {
2456
+ return fn();
2457
+ }
2458
+ try {
2459
+ return await fn();
2460
+ } finally {
2461
+ try {
2462
+ await release();
2463
+ } catch {
2464
+ }
2465
+ }
2466
+ }
2467
+ };
2468
+ }
2469
+
2470
+ // src/login/index.ts
2471
+ var ZapierAuthenticationError = class extends Error {
2472
+ constructor(message) {
2473
+ super(message);
2474
+ this.name = "ZapierAuthenticationError";
2475
+ }
2476
+ };
2477
+ var config = null;
2478
+ var DEFAULT_AUTH_CLIENT_ID = "grwWZD5hUWGvb4V8ODBuOtXer3h0DBEZ2HR8aay6";
2479
+ var TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
2480
+ function createDebugLog(enabled) {
2481
+ if (!enabled) {
2482
+ return () => {
2483
+ };
2484
+ }
2485
+ return (message, data) => {
2486
+ if (data === void 0) {
2487
+ console.log(`[Zapier SDK CLI Login] ${message}`);
2488
+ } else {
2489
+ console.log(`[Zapier SDK CLI Login] ${message}`, data);
2490
+ }
2491
+ };
2492
+ }
2493
+ function censorHeaderValue(value) {
2494
+ if (value.length > 12) {
2495
+ return `${value.substring(0, 4)}...${value.substring(value.length - 4)}`;
2496
+ }
2497
+ return `${value.charAt(0)}...`;
2498
+ }
2499
+ function getAuthClientId(clientId) {
2500
+ return clientId || DEFAULT_AUTH_CLIENT_ID;
2501
+ }
2502
+ var AUTH_MODE_HEADER = "X-Auth";
2503
+ var DEFAULT_AUTH_BASE_URL = "https://zapier.com";
2504
+ function getAuthTokenUrl(options) {
2505
+ const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
2506
+ return `${authBaseUrl}/oauth/token/`;
2507
+ }
2508
+ function getAuthAuthorizeUrl(options) {
2509
+ const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
2510
+ return `${authBaseUrl}/oauth/authorize/`;
2511
+ }
2512
+ function getPkceLoginConfig(options) {
2513
+ return {
2514
+ clientId: getAuthClientId(options?.credentials?.clientId),
2515
+ tokenUrl: getAuthTokenUrl({ baseUrl: options?.credentials?.baseUrl }),
2516
+ authorizeUrl: getAuthAuthorizeUrl({
2517
+ baseUrl: options?.credentials?.baseUrl
2518
+ })
2519
+ };
2520
+ }
2521
+ var cachedLogin;
2522
+ function getConfig() {
2523
+ if (!config) {
2524
+ config = new Conf__default.default({ projectName: "zapier-sdk-cli" });
2525
+ if (!config.has("login_storage_mode")) {
2526
+ config.set(
2527
+ "login_storage_mode",
2528
+ fs.existsSync(config.path) ? "config" : "keychain"
2529
+ );
2530
+ }
2531
+ }
2532
+ return config;
2533
+ }
2534
+ function unloadConfig() {
2535
+ config = null;
2536
+ cachedLogin = void 0;
2537
+ }
2538
+ async function updateLogin(loginData, options = {}) {
2539
+ const debugLog = createDebugLog(options.debug ?? false);
2540
+ const storage = options.storage ?? cachedLogin?.storage ?? "keychain";
2541
+ const expiresAt = Date.now() + loginData.expires_in * 1e3;
2542
+ const cfg = getConfig();
2543
+ cfg.set("login_storage_mode", storage);
2544
+ if (storage === "keychain") {
2545
+ await setTokensInKeychain({
2546
+ data: {
2547
+ login_jwt: loginData.access_token,
2548
+ login_refresh_token: loginData.refresh_token
2549
+ },
2550
+ debugLog
2551
+ });
2552
+ cfg.set("login_expires_at", expiresAt);
2553
+ cfg.delete("login_jwt");
2554
+ cfg.delete("login_refresh_token");
2555
+ } else {
2556
+ cfg.set("login_jwt", loginData.access_token);
2557
+ cfg.set("login_refresh_token", loginData.refresh_token);
2558
+ cfg.set("login_expires_at", expiresAt);
2559
+ await clearTokensFromKeychain({ debugLog });
2560
+ }
2561
+ cachedLogin = {
2562
+ jwt: loginData.access_token,
2563
+ refreshToken: loginData.refresh_token,
2564
+ expiresAt,
2565
+ storage
2566
+ };
2567
+ }
2568
+ function decodeJwtOrThrow(token) {
2569
+ if (typeof token !== "string") {
2570
+ throw new Error("Expected JWT to be a string");
2571
+ }
2572
+ const decodedJwt = jwt__namespace.decode(token, { complete: true });
2573
+ if (!decodedJwt) {
2574
+ throw new Error("Could not decode JWT");
2575
+ }
2576
+ if (typeof decodedJwt.payload === "string") {
2577
+ throw new Error("Did not expect JWT payload to be a string");
2578
+ }
2579
+ return decodedJwt;
2580
+ }
2581
+ async function refreshJwt(refreshToken, options = {}) {
2582
+ const {
2583
+ onEvent,
2584
+ fetch: fetch2 = globalThis.fetch,
2585
+ credentials: credentials2,
2586
+ debug = false
2587
+ } = options;
2588
+ const debugLog = createDebugLog(debug);
2589
+ const tokenUrl = getAuthTokenUrl({ baseUrl: credentials2?.baseUrl });
2590
+ const clientId = getAuthClientId(credentials2?.clientId);
2591
+ const startTime = Date.now();
2592
+ try {
2593
+ onEvent?.({
2594
+ type: "auth_refreshing",
2595
+ payload: {
2596
+ message: "Refreshing your token...",
2597
+ operation: "token_refresh"
2598
+ },
2599
+ timestamp: Date.now()
2600
+ });
2601
+ debugLog(`\u2192 POST ${tokenUrl}`, {
2602
+ headers: {
2603
+ "Content-Type": "application/x-www-form-urlencoded",
2604
+ [AUTH_MODE_HEADER]: "no"
2605
+ },
2606
+ body: {
2607
+ client_id: clientId,
2608
+ refresh_token: censorHeaderValue(refreshToken),
2609
+ grant_type: "refresh_token"
2610
+ }
2611
+ });
2612
+ const response = await fetch2(tokenUrl, {
2613
+ method: "POST",
2614
+ headers: {
2615
+ "Content-Type": "application/x-www-form-urlencoded",
2616
+ [AUTH_MODE_HEADER]: "no"
2617
+ },
2618
+ body: new URLSearchParams({
2619
+ client_id: clientId,
2620
+ refresh_token: refreshToken,
2621
+ grant_type: "refresh_token"
2622
+ })
2623
+ });
2624
+ const duration = Date.now() - startTime;
2625
+ if (!response.ok) {
2626
+ debugLog(`\u2190 ${response.status} ${response.statusText} (${duration}ms)`);
2627
+ throw new Error(
2628
+ `Token refresh failed: ${response.status} ${response.statusText}`
2629
+ );
2630
+ }
2631
+ debugLog(`\u2190 ${response.status} ${response.statusText} (${duration}ms)`);
2632
+ const data = await response.json();
2633
+ await updateLogin(data, { debug });
2634
+ debugLog(
2635
+ `Token refreshed and saved to ${cachedLogin?.storage ?? "keychain"}`
2636
+ );
2637
+ onEvent?.({
2638
+ type: "auth_success",
2639
+ payload: {
2640
+ message: "Token refreshed successfully",
2641
+ operation: "token_refresh"
2642
+ },
2643
+ timestamp: Date.now()
2644
+ });
2645
+ return data.access_token;
2646
+ } catch (error) {
2647
+ const duration = Date.now() - startTime;
2648
+ debugLog(`\u2716 Token refresh failed (${duration}ms)`, {
2649
+ error: error instanceof Error ? error.message : error
2650
+ });
2651
+ cachedLogin = void 0;
2652
+ const errorMessage = `Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`;
2653
+ onEvent?.({
2654
+ type: "auth_error",
2655
+ payload: {
2656
+ message: errorMessage,
2657
+ error: errorMessage,
2658
+ operation: "token_refresh"
2659
+ },
2660
+ timestamp: Date.now()
2661
+ });
2662
+ throw error;
2663
+ }
2664
+ }
2665
+ var pendingRefresh = null;
2666
+ var pendingResolve = null;
2667
+ async function resolveStoredLogin(debugLog) {
2668
+ if (cachedLogin) {
2669
+ debugLog("Using in-memory cached credentials");
2670
+ return cachedLogin;
2671
+ }
2672
+ if (pendingResolve) {
2673
+ debugLog("Waiting for existing keychain read to complete");
2674
+ return pendingResolve;
2675
+ }
2676
+ pendingResolve = resolveStoredLoginFromStorage(debugLog).finally(() => {
2677
+ pendingResolve = null;
2678
+ });
2679
+ return pendingResolve;
2680
+ }
2681
+ async function resolveStoredLoginFromStorage(debugLog) {
2682
+ let cfg;
2683
+ try {
2684
+ cfg = getConfig();
2685
+ } catch (error) {
2686
+ debugLog("Failed to load config", {
2687
+ error: error instanceof Error ? error.message : error
2688
+ });
2689
+ return void 0;
2690
+ }
2691
+ const expiresAt = cfg.get("login_expires_at");
2692
+ const configJwt = cfg.get("login_jwt");
2693
+ const configRefresh = cfg.get("login_refresh_token");
2694
+ if (configJwt && configRefresh && typeof expiresAt === "number") {
2695
+ debugLog("Loaded credentials from config (legacy format)");
2696
+ cachedLogin = {
2697
+ jwt: configJwt,
2698
+ refreshToken: configRefresh,
2699
+ expiresAt,
2700
+ storage: "config"
2701
+ };
2702
+ return cachedLogin;
2703
+ }
2704
+ if (typeof expiresAt !== "number") {
2705
+ debugLog("No stored login credentials found");
2706
+ return void 0;
2707
+ }
2708
+ const keychainData = await getTokensFromKeychain({ debugLog });
2709
+ if (!keychainData) {
2710
+ debugLog("No tokens found in keychain");
2711
+ return void 0;
2712
+ }
2713
+ debugLog("Loaded credentials from keychain");
2714
+ cachedLogin = {
2715
+ jwt: keychainData.login_jwt,
2716
+ refreshToken: keychainData.login_refresh_token,
2717
+ expiresAt,
2718
+ storage: "keychain"
2719
+ };
2720
+ return cachedLogin;
2721
+ }
2722
+ async function resolveOrRefreshToken(options = {}) {
2723
+ const { debug = false } = options;
2724
+ const debugLog = createDebugLog(debug);
2725
+ const stored = await resolveStoredLogin(debugLog);
2726
+ if (!stored) {
2727
+ return void 0;
2728
+ }
2729
+ const { jwt: storedJwt, refreshToken, expiresAt } = stored;
2730
+ if (expiresAt > Date.now() + TOKEN_REFRESH_BUFFER_MS) {
2731
+ debugLog("Using cached token (still valid)");
2732
+ return storedJwt;
2733
+ }
2734
+ debugLog("Token expired, refreshing...");
2735
+ if (pendingRefresh) {
2736
+ debugLog("Waiting for existing refresh to complete");
2737
+ return pendingRefresh;
2738
+ }
2739
+ pendingRefresh = refreshJwt(refreshToken, options).finally(() => {
2740
+ pendingRefresh = null;
2741
+ });
2742
+ return await pendingRefresh;
2743
+ }
2744
+ async function getToken(options = {}) {
2745
+ try {
2746
+ return await resolveOrRefreshToken(options);
2747
+ } catch (error) {
2748
+ const message = error instanceof Error ? error.message : "Token refresh failed";
2749
+ throw new ZapierAuthenticationError(
2750
+ `${message}
2751
+ Please run 'login' to authenticate again.`
2752
+ );
2753
+ }
2754
+ }
2755
+ async function getLoggedInUser(options = {}) {
2756
+ const jwt2 = await getToken(options).catch(() => void 0);
2757
+ if (!jwt2) {
2758
+ throw new Error(
2759
+ "No valid authentication token available. Please login first."
2760
+ );
2761
+ }
2762
+ let decodedJwt = decodeJwtOrThrow(jwt2);
2763
+ if (decodedJwt.payload["sub_type"] == "service") {
2764
+ decodedJwt = decodeJwtOrThrow(decodedJwt.payload["njwt"]);
2765
+ }
2766
+ if (typeof decodedJwt.payload["zap:acc"] !== "string") {
2767
+ throw new Error("JWT payload does not contain accountId");
2768
+ }
2769
+ const accountId = parseInt(decodedJwt.payload["zap:acc"], 10);
2770
+ if (isNaN(accountId)) {
2771
+ throw new Error("JWT accountId is not a number");
2772
+ }
2773
+ if (decodedJwt.payload["sub_type"] !== "customuser" || typeof decodedJwt.payload["sub"] !== "string") {
2774
+ throw new Error("JWT payload does not contain customUserId");
2775
+ }
2776
+ const customUserId = parseInt(decodedJwt.payload["sub"], 10);
2777
+ if (isNaN(customUserId)) {
2778
+ throw new Error("JWT customUserId is not a number");
2779
+ }
2780
+ const email = decodedJwt.payload["zap:uname"];
2781
+ if (typeof email !== "string") {
2782
+ throw new Error("JWT payload does not contain email");
2783
+ }
2784
+ return {
2785
+ accountId,
2786
+ customUserId,
2787
+ email
2788
+ };
2789
+ }
2790
+ function getLoginStorageMode() {
2791
+ const cfg = getConfig();
2792
+ if (typeof cfg.get("login_jwt") === "string") {
2793
+ return "config";
2794
+ }
2795
+ const explicitMode = cfg.get("login_storage_mode");
2796
+ if (explicitMode === "keychain" || explicitMode === "config") {
2797
+ return explicitMode;
2798
+ }
2799
+ return "keychain";
2800
+ }
2801
+ async function logout(options = {}) {
2802
+ const { onEvent } = options;
2803
+ const mode = getLoginStorageMode();
2804
+ cachedLogin = void 0;
2805
+ await clearTokensFromKeychain();
2806
+ const cfg = getConfig();
2807
+ cfg.set("login_storage_mode", mode);
2808
+ cfg.delete("login_expires_at");
2809
+ cfg.delete("login_jwt");
2810
+ cfg.delete("login_refresh_token");
2811
+ onEvent?.({
2812
+ type: "auth_logout",
2813
+ payload: { message: "Logged out successfully", operation: "logout" },
2814
+ timestamp: Date.now()
2815
+ });
2816
+ }
2817
+ function getConfigPath() {
2818
+ const cfg = getConfig();
2819
+ return cfg.path;
2820
+ }
2821
+
2822
+ // src/utils/constants.ts
2238
2823
  var LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
2239
2824
  var LOGIN_TIMEOUT_MS = 3e5;
2240
2825
  var spinPromise = async (promise, text) => {
@@ -2368,13 +2953,13 @@ var login = async ({
2368
2953
  timeoutMs = LOGIN_TIMEOUT_MS,
2369
2954
  credentials: credentials2
2370
2955
  }) => {
2371
- const { clientId, tokenUrl, authorizeUrl } = cliLogin.getPkceLoginConfig({
2956
+ const { clientId, tokenUrl, authorizeUrl } = getPkceLoginConfig({
2372
2957
  credentials: credentials2
2373
2958
  });
2374
2959
  const scope = ensureOfflineAccess(
2375
2960
  credentials2?.scope || "internal credentials"
2376
2961
  );
2377
- await cliLogin.logout();
2962
+ await logout();
2378
2963
  const availablePort = await findAvailablePort();
2379
2964
  const redirectUri = `http://localhost:${availablePort}/oauth`;
2380
2965
  log_default.info(`Using port ${availablePort} for OAuth callback`);
@@ -2462,13 +3047,13 @@ var login = async ({
2462
3047
  },
2463
3048
  {
2464
3049
  headers: {
2465
- [cliLogin.AUTH_MODE_HEADER]: "no",
3050
+ [AUTH_MODE_HEADER]: "no",
2466
3051
  "Content-Type": "application/x-www-form-urlencoded"
2467
3052
  }
2468
3053
  }
2469
3054
  );
2470
3055
  let targetStorage;
2471
- if (cliLogin.getLoginStorageMode() === "config") {
3056
+ if (getLoginStorageMode() === "config") {
2472
3057
  const { upgrade } = await inquirer__default.default.prompt([
2473
3058
  {
2474
3059
  type: "confirm",
@@ -2482,13 +3067,13 @@ var login = async ({
2482
3067
  targetStorage = "keychain";
2483
3068
  }
2484
3069
  try {
2485
- await cliLogin.updateLogin(data, { storage: targetStorage });
3070
+ await updateLogin(data, { storage: targetStorage });
2486
3071
  } catch (err) {
2487
3072
  if (targetStorage === "keychain") {
2488
3073
  log_default.warn(
2489
- `Could not store credentials in system keychain. Storing in plaintext at ${cliLogin.getConfigPath()}.`
3074
+ `Could not store credentials in system keychain. Storing in plaintext at ${getConfigPath()}.`
2490
3075
  );
2491
- await cliLogin.updateLogin(data, { storage: "config" });
3076
+ await updateLogin(data, { storage: "config" });
2492
3077
  } else {
2493
3078
  throw err;
2494
3079
  }
@@ -2525,7 +3110,7 @@ var loginPlugin = (sdk2) => {
2525
3110
  timeoutMs: timeoutSeconds * 1e3,
2526
3111
  credentials: pkceCredentials
2527
3112
  });
2528
- const user = await cliLogin.getLoggedInUser();
3113
+ const user = await getLoggedInUser();
2529
3114
  sdk2.context.eventEmission.emit(
2530
3115
  "platform.sdk.ApplicationLifecycleEvent",
2531
3116
  zapierSdk.buildApplicationLifecycleEvent(
@@ -2552,7 +3137,7 @@ var LogoutSchema = zod.z.object({}).describe("Log out of your Zapier account");
2552
3137
 
2553
3138
  // src/plugins/logout/index.ts
2554
3139
  var logoutWithSdk = zapierSdk.createFunction(async function logoutWithSdk2(_options) {
2555
- await cliLogin.logout();
3140
+ await logout();
2556
3141
  console.log("\u2705 Successfully logged out");
2557
3142
  }, LogoutSchema);
2558
3143
  var logoutPlugin = () => ({
@@ -2687,7 +3272,7 @@ var GetLoginConfigPathSchema = zod.z.object({}).describe("Show the path to the l
2687
3272
  var getLoginConfigPathPlugin = () => {
2688
3273
  const getLoginConfigPathWithSdk = zapierSdk.createFunction(
2689
3274
  async function getLoginConfigPathWithSdk2(_options) {
2690
- return cliLogin.getConfigPath();
3275
+ return getConfigPath();
2691
3276
  },
2692
3277
  GetLoginConfigPathSchema
2693
3278
  );
@@ -3716,7 +4301,7 @@ async function postWithRetry({
3716
4301
  var feedbackPlugin = (sdk2) => {
3717
4302
  const debug = sdk2.context.options?.debug;
3718
4303
  const feedbackWithSdk = zapierSdk.createFunction(async function feedback(options) {
3719
- const user = await cliLogin.getLoggedInUser();
4304
+ const user = await getLoggedInUser();
3720
4305
  const body = JSON.stringify({
3721
4306
  email: user.email,
3722
4307
  customuser_id: user.customUserId,
@@ -4688,10 +5273,10 @@ var initPlugin = () => {
4688
5273
  // package.json with { type: 'json' }
4689
5274
  var package_default2 = {
4690
5275
  name: "@zapier/zapier-sdk-cli",
4691
- version: "0.42.1"};
5276
+ version: "0.43.0"};
4692
5277
 
4693
5278
  // src/sdk.ts
4694
- zapierSdk.injectCliLogin(cliLogin__namespace);
5279
+ zapierSdk.injectCliLogin(login_exports);
4695
5280
  function createZapierCliSdk(options = {}) {
4696
5281
  return zapierSdk.createZapierSdk({
4697
5282
  ...options,
@@ -4710,14 +5295,14 @@ var CACHE_RESET_INTERVAL_MS = (() => {
4710
5295
  })();
4711
5296
  function getVersionCache() {
4712
5297
  try {
4713
- const cache = cliLogin.getConfig().get("version_cache");
5298
+ const cache = getConfig().get("version_cache");
4714
5299
  const now = Date.now();
4715
5300
  if (!cache || !cache.last_reset_timestamp || now - cache.last_reset_timestamp >= CACHE_RESET_INTERVAL_MS) {
4716
5301
  const newCache = {
4717
5302
  last_reset_timestamp: now,
4718
5303
  packages: {}
4719
5304
  };
4720
- cliLogin.getConfig().set("version_cache", newCache);
5305
+ getConfig().set("version_cache", newCache);
4721
5306
  return newCache;
4722
5307
  }
4723
5308
  return cache;
@@ -4736,7 +5321,7 @@ function setCachedPackageInfo(packageName, version, info) {
4736
5321
  cache.packages[packageName] = {};
4737
5322
  }
4738
5323
  cache.packages[packageName][version] = info;
4739
- cliLogin.getConfig().set("version_cache", cache);
5324
+ getConfig().set("version_cache", cache);
4740
5325
  } catch (error) {
4741
5326
  log_default.debug(`Failed to cache package info: ${error}`);
4742
5327
  }