@zapier/zapier-sdk-cli 0.42.2 → 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/CHANGELOG.md +12 -0
- package/dist/cli.cjs +619 -34
- package/dist/cli.d.mts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.mjs +601 -19
- package/dist/index.cjs +607 -23
- package/dist/index.mjs +592 -11
- package/dist/login.cjs +599 -7
- package/dist/login.d.mts +144 -1
- package/dist/login.d.ts +144 -1
- package/dist/login.mjs +565 -1
- package/dist/package.json +5 -2
- package/dist/src/login/filesystem-cache.d.ts +25 -0
- package/dist/src/login/filesystem-cache.js +195 -0
- package/dist/src/login/index.d.ts +115 -0
- package/dist/src/login/index.js +442 -0
- package/dist/src/login/keychain.d.ts +18 -0
- package/dist/src/login/keychain.js +74 -0
- package/dist/src/login.d.ts +10 -1
- package/dist/src/login.js +10 -1
- package/dist/src/plugins/feedback/index.js +1 -1
- package/dist/src/plugins/getLoginConfigPath/index.js +1 -1
- package/dist/src/plugins/login/index.js +1 -1
- package/dist/src/plugins/logout/index.js +1 -1
- package/dist/src/sdk.js +1 -1
- package/dist/src/utils/auth/login.d.ts +1 -1
- package/dist/src/utils/auth/login.js +1 -1
- package/dist/src/utils/constants.d.ts +1 -1
- package/dist/src/utils/constants.js +1 -1
- package/dist/src/utils/version-checker.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -4
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
|
|
13
|
-
var
|
|
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
|
|
57
|
-
var
|
|
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.
|
|
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
|
|
1837
|
-
addCommand(program2, cliCommandName,
|
|
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,
|
|
2095
|
-
const command = program2.command(commandName, { hidden:
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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 (
|
|
2173
|
+
if (config2.supportsJsonOutput === false && opt.name === "json") return;
|
|
2164
2174
|
command.option(opt.flag, opt.description);
|
|
2165
2175
|
});
|
|
2166
|
-
command.action(
|
|
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 } =
|
|
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
|
|
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
|
-
[
|
|
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 (
|
|
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
|
|
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 ${
|
|
3074
|
+
`Could not store credentials in system keychain. Storing in plaintext at ${getConfigPath()}.`
|
|
2490
3075
|
);
|
|
2491
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
5276
|
+
version: "0.43.0"};
|
|
4692
5277
|
|
|
4693
5278
|
// src/sdk.ts
|
|
4694
|
-
zapierSdk.injectCliLogin(
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
5324
|
+
getConfig().set("version_cache", cache);
|
|
4740
5325
|
} catch (error) {
|
|
4741
5326
|
log_default.debug(`Failed to cache package info: ${error}`);
|
|
4742
5327
|
}
|