@zapier/zapier-sdk-cli 0.77.9 → 0.78.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/index.cjs CHANGED
@@ -9,9 +9,10 @@ var path = require('path');
9
9
  var lockfile = require('proper-lockfile');
10
10
  var zapierSdk = require('@zapier/zapier-sdk');
11
11
  var zod = require('zod');
12
- var chalk3 = require('chalk');
12
+ var chalk5 = require('chalk');
13
13
  var os = require('os');
14
- var inquirer3 = require('inquirer');
14
+ var inquirer4 = require('inquirer');
15
+ var core = require('@inquirer/core');
15
16
  var express = require('express');
16
17
  var promises$1 = require('readline/promises');
17
18
  var open = require('open');
@@ -25,7 +26,6 @@ require('is-installed-globally');
25
26
  var child_process = require('child_process');
26
27
  var Handlebars = require('handlebars');
27
28
  var url = require('url');
28
- var core = require('@inquirer/core');
29
29
  var packageJsonLib = require('package-json');
30
30
  var semver = require('semver');
31
31
  var crossSpawn = require('cross-spawn');
@@ -61,8 +61,8 @@ var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
61
61
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
62
62
  var path__namespace = /*#__PURE__*/_interopNamespace(path);
63
63
  var lockfile__namespace = /*#__PURE__*/_interopNamespace(lockfile);
64
- var chalk3__default = /*#__PURE__*/_interopDefault(chalk3);
65
- var inquirer3__default = /*#__PURE__*/_interopDefault(inquirer3);
64
+ var chalk5__default = /*#__PURE__*/_interopDefault(chalk5);
65
+ var inquirer4__default = /*#__PURE__*/_interopDefault(inquirer4);
66
66
  var express__default = /*#__PURE__*/_interopDefault(express);
67
67
  var open__default = /*#__PURE__*/_interopDefault(open);
68
68
  var ora__default = /*#__PURE__*/_interopDefault(ora);
@@ -407,6 +407,10 @@ function getActiveCredentials(options) {
407
407
  if (!name) return void 0;
408
408
  return findEntry(readRegistry(), name, normalizeBaseUrl(options?.baseUrl));
409
409
  }
410
+ function listStoredCredentials(options) {
411
+ const baseUrl = normalizeBaseUrl(options?.baseUrl);
412
+ return readRegistry().filter((entry) => entry.baseUrl === baseUrl).sort((left, right) => right.createdAt - left.createdAt);
413
+ }
410
414
  var MAX_CREDENTIAL_NAME_ATTEMPTS = 500;
411
415
  function firstAvailableCredentialName({
412
416
  baseName,
@@ -511,6 +515,29 @@ async function getStoredClientCredentials(options) {
511
515
  scope: [...entry.scopes].sort().join(" ")
512
516
  };
513
517
  }
518
+ async function activateStoredCredentials({
519
+ name,
520
+ baseUrl
521
+ }) {
522
+ const resolvedBaseUrl = normalizeBaseUrl(baseUrl);
523
+ const entry = findEntry(readRegistry(), name, resolvedBaseUrl);
524
+ if (!entry) {
525
+ throw new ZapierCliValidationError(
526
+ `No stored credentials named "${name}" were found.`
527
+ );
528
+ }
529
+ const credentials = await getStoredClientCredentials({
530
+ name,
531
+ baseUrl: resolvedBaseUrl
532
+ });
533
+ if (!credentials) {
534
+ throw new ZapierCliValidationError(
535
+ `Stored credentials "${name}" are missing from the system keychain. Add a new account to recreate them.`
536
+ );
537
+ }
538
+ getConfig().set(CREDENTIALS_KEY, name);
539
+ return entry;
540
+ }
514
541
  function deleteRegistryEntry(registry, name, baseUrl) {
515
542
  const idx = registry.findIndex(
516
543
  (e) => e.name === name && e.baseUrl === baseUrl
@@ -1107,6 +1134,362 @@ async function setupClientCredentials({
1107
1134
  }
1108
1135
  return { clientId };
1109
1136
  }
1137
+ function isSelectable(item) {
1138
+ return !core.Separator.isSeparator(item) && !item.disabled;
1139
+ }
1140
+ function normalizeChoices(choices) {
1141
+ return choices.map((choice) => {
1142
+ if (core.Separator.isSeparator(choice)) return choice;
1143
+ const name = choice.name ?? String(choice.value);
1144
+ return {
1145
+ value: choice.value,
1146
+ name,
1147
+ short: choice.short ?? name,
1148
+ disabled: choice.disabled ?? false
1149
+ };
1150
+ });
1151
+ }
1152
+ var theme = core.makeTheme({
1153
+ icon: { cursor: "\u276F" },
1154
+ style: {
1155
+ disabled: (text) => chalk5__default.default.dim(`- ${text}`),
1156
+ searchTerm: (text) => chalk5__default.default.cyan(text),
1157
+ keysHelpTip: (keys) => keys.map(([key, action]) => `${chalk5__default.default.bold(key)} ${chalk5__default.default.dim(action)}`).join(chalk5__default.default.dim(" \u2022 "))
1158
+ }
1159
+ });
1160
+ var searchSelect = core.createPrompt(
1161
+ (config2, done) => {
1162
+ const { pageSize = 7 } = config2;
1163
+ const [status, setStatus] = core.useState(
1164
+ "loading"
1165
+ );
1166
+ const [searchTerm, setSearchTerm] = core.useState("");
1167
+ const [searchResults, setSearchResults] = core.useState([]);
1168
+ const [searchError, setSearchError] = core.useState();
1169
+ const prefix = core.usePrefix({ status, theme });
1170
+ const bounds = core.useMemo(() => {
1171
+ const first = searchResults.findIndex(isSelectable);
1172
+ let last = -1;
1173
+ for (let i = searchResults.length - 1; i >= 0; i--) {
1174
+ if (isSelectable(searchResults[i])) {
1175
+ last = i;
1176
+ break;
1177
+ }
1178
+ }
1179
+ return { first, last };
1180
+ }, [searchResults]);
1181
+ const defaultActive = core.useMemo(() => {
1182
+ const requested = searchTerm === "" ? config2.initialActive : config2.initialActiveForTerm?.({ term: searchTerm });
1183
+ if (requested !== void 0 && requested >= 0 && requested < searchResults.length && isSelectable(searchResults[requested])) {
1184
+ return requested;
1185
+ }
1186
+ return bounds.first;
1187
+ }, [searchResults, searchTerm, bounds.first]);
1188
+ const [active = defaultActive, setActive] = core.useState();
1189
+ core.useEffect(() => {
1190
+ const controller = new AbortController();
1191
+ setStatus("loading");
1192
+ setSearchError(void 0);
1193
+ const fetchResults = async () => {
1194
+ try {
1195
+ const results = await config2.source(searchTerm || void 0);
1196
+ if (!controller.signal.aborted) {
1197
+ setActive(void 0);
1198
+ setSearchError(void 0);
1199
+ setSearchResults(normalizeChoices(results));
1200
+ setStatus("idle");
1201
+ }
1202
+ } catch (error2) {
1203
+ if (!controller.signal.aborted && error2 instanceof Error) {
1204
+ setSearchError(error2.message);
1205
+ }
1206
+ }
1207
+ };
1208
+ void fetchResults();
1209
+ return () => {
1210
+ controller.abort();
1211
+ };
1212
+ }, [searchTerm]);
1213
+ const selectedChoice = searchResults[active];
1214
+ core.useKeypress((key, rl) => {
1215
+ if (core.isEnterKey(key)) {
1216
+ if (selectedChoice && isSelectable(selectedChoice)) {
1217
+ setStatus("done");
1218
+ done(selectedChoice.value);
1219
+ } else {
1220
+ rl.write(searchTerm);
1221
+ }
1222
+ } else if (core.isTabKey(key) && selectedChoice && isSelectable(selectedChoice)) {
1223
+ rl.clearLine(0);
1224
+ rl.write(selectedChoice.name);
1225
+ setSearchTerm(selectedChoice.name);
1226
+ } else if (status !== "loading" && (core.isUpKey(key) || core.isDownKey(key))) {
1227
+ rl.clearLine(0);
1228
+ if (core.isUpKey(key) && active !== bounds.first || core.isDownKey(key) && active !== bounds.last) {
1229
+ const offset = core.isUpKey(key) ? -1 : 1;
1230
+ let next = active;
1231
+ do {
1232
+ next = (next + offset + searchResults.length) % searchResults.length;
1233
+ } while (!isSelectable(searchResults[next]));
1234
+ setActive(next);
1235
+ }
1236
+ } else {
1237
+ setSearchTerm(rl.line);
1238
+ }
1239
+ });
1240
+ const page = core.usePagination({
1241
+ items: searchResults,
1242
+ active,
1243
+ renderItem({ item, isActive }) {
1244
+ if (core.Separator.isSeparator(item)) {
1245
+ return ` ${item.separator}`;
1246
+ }
1247
+ if (item.disabled) {
1248
+ const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
1249
+ return theme.style.disabled(`${item.name} ${disabledLabel}`);
1250
+ }
1251
+ const color = isActive ? theme.style.highlight : (x) => x;
1252
+ const cursor = isActive ? theme.icon.cursor : ` `;
1253
+ return color(`${cursor} ${item.name}`);
1254
+ },
1255
+ pageSize,
1256
+ loop: false
1257
+ });
1258
+ const message = theme.style.message(config2.message, status);
1259
+ if (status === "done" && selectedChoice && isSelectable(selectedChoice)) {
1260
+ return [prefix, message, theme.style.answer(selectedChoice.short)].filter(Boolean).join(" ").trimEnd();
1261
+ }
1262
+ const searchStr = theme.style.searchTerm(searchTerm);
1263
+ const helpTip = theme.style.keysHelpTip([
1264
+ ["\u2191\u2193", "navigate"],
1265
+ ["\u23CE", "select"]
1266
+ ]);
1267
+ let error;
1268
+ if (searchError) {
1269
+ error = theme.style.error(searchError);
1270
+ } else if (searchResults.length === 0 && searchTerm !== "" && status === "idle") {
1271
+ error = theme.style.error("No results found");
1272
+ }
1273
+ const header = [prefix, message, searchStr].filter(Boolean).join(" ").trimEnd();
1274
+ const body = [error ?? page, " ", helpTip].filter(Boolean).join("\n").trimEnd();
1275
+ return [header, body];
1276
+ }
1277
+ );
1278
+
1279
+ // src/utils/auth/credentials-picker.ts
1280
+ function isSameCredentials(left, right) {
1281
+ return left.name === right.name && left.baseUrl === right.baseUrl;
1282
+ }
1283
+ function createdAtIso(credentials) {
1284
+ return new Date(credentials.createdAt).toISOString();
1285
+ }
1286
+ function searchableFields(credentials) {
1287
+ return [
1288
+ { text: credentials.name.toLowerCase(), weight: 0 },
1289
+ { text: credentials.clientId.toLowerCase(), weight: 1e3 },
1290
+ ...credentials.scopes.map((scope) => ({
1291
+ text: scope.toLowerCase(),
1292
+ weight: 2e3
1293
+ })),
1294
+ {
1295
+ text: createdAtIso(credentials).slice(0, 10).toLowerCase(),
1296
+ weight: 3e3
1297
+ }
1298
+ ];
1299
+ }
1300
+ function textMatchScore(text, query) {
1301
+ if (text === query) return 0;
1302
+ if (text.startsWith(query)) return 100 + text.length - query.length;
1303
+ const index = text.indexOf(query);
1304
+ if (index === -1) return void 0;
1305
+ return 200 + text.length - query.length;
1306
+ }
1307
+ function closestFieldScore(fields, query) {
1308
+ let closest;
1309
+ for (const field of fields) {
1310
+ const textScore = textMatchScore(field.text, query);
1311
+ if (textScore === void 0) continue;
1312
+ const score = field.weight + textScore;
1313
+ closest = closest === void 0 ? score : Math.min(closest, score);
1314
+ }
1315
+ return closest;
1316
+ }
1317
+ function searchScore(credentials, term) {
1318
+ const query = term.trim().toLowerCase();
1319
+ const tokens = query.split(/\s+/).filter(Boolean);
1320
+ const fields = searchableFields(credentials);
1321
+ let tokenScore = 0;
1322
+ for (const token of tokens) {
1323
+ const score = closestFieldScore(fields, token);
1324
+ if (score === void 0) return void 0;
1325
+ tokenScore += score;
1326
+ }
1327
+ const phraseScore = closestFieldScore(fields, query);
1328
+ return phraseScore === void 0 ? 1e4 + tokenScore : phraseScore;
1329
+ }
1330
+ function formatCredentialsChoice({
1331
+ credentials,
1332
+ current
1333
+ }) {
1334
+ const currentLabel = current ? chalk5__default.default.cyan(" (current)") : "";
1335
+ const details = [
1336
+ credentials.clientId,
1337
+ credentials.scopes.join(", "),
1338
+ `created ${createdAtIso(credentials).slice(0, 10)}`
1339
+ ].join(" \xB7 ");
1340
+ return {
1341
+ name: `${credentials.name}${currentLabel} ${chalk5__default.default.dim(`\xB7 ${details}`)}`,
1342
+ short: credentials.name,
1343
+ value: { action: "switch", credentials }
1344
+ };
1345
+ }
1346
+ function buildCredentialsChoices({
1347
+ credentials,
1348
+ activeCredentials,
1349
+ term = ""
1350
+ }) {
1351
+ const sortedCredentials = [...credentials].sort(
1352
+ (left, right) => right.createdAt - left.createdAt
1353
+ );
1354
+ const current = activeCredentials ? sortedCredentials.find(
1355
+ (entry) => isSameCredentials(entry, activeCredentials)
1356
+ ) : void 0;
1357
+ const rankedCredentials = term ? sortedCredentials.map((credentials2) => ({
1358
+ credentials: credentials2,
1359
+ score: searchScore(credentials2, term)
1360
+ })).filter(
1361
+ (result) => result.score !== void 0
1362
+ ).sort((left, right) => left.score - right.score).map(({ credentials: credentials2 }) => credentials2) : [
1363
+ ...current ? [current] : [],
1364
+ ...sortedCredentials.filter((credentials2) => credentials2 !== current)
1365
+ ];
1366
+ return [
1367
+ {
1368
+ name: "+ Add a new account",
1369
+ short: "Add a new account",
1370
+ value: { action: "create" }
1371
+ },
1372
+ ...rankedCredentials.map(
1373
+ (credentials2) => formatCredentialsChoice({
1374
+ credentials: credentials2,
1375
+ current: credentials2 === current
1376
+ })
1377
+ )
1378
+ ];
1379
+ }
1380
+ async function promptForCredentials({
1381
+ credentials,
1382
+ activeCredentials
1383
+ }) {
1384
+ return searchSelect({
1385
+ message: "Select credentials or add a new account:",
1386
+ source: (term) => buildCredentialsChoices({
1387
+ credentials,
1388
+ activeCredentials,
1389
+ term
1390
+ }),
1391
+ initialActive: credentials.length > 0 ? 1 : 0,
1392
+ initialActiveForTerm: () => 1
1393
+ });
1394
+ }
1395
+
1396
+ // src/utils/auth/stored-login-credentials.ts
1397
+ function authFlowOnlyOptions(options) {
1398
+ return [
1399
+ ...options.timeout === void 0 ? [] : ["--timeout"],
1400
+ ...options.useApprovals === true ? ["--use-approvals"] : [],
1401
+ ...options.headless === true ? ["--headless"] : []
1402
+ ];
1403
+ }
1404
+ function assertCanSwitchCredentials({
1405
+ credentials,
1406
+ options,
1407
+ resolvedCredentials
1408
+ }) {
1409
+ if (resolvedCredentials !== void 0) {
1410
+ throw new ZapierCliValidationError(
1411
+ "Cannot switch stored credentials while credentials are configured through SDK options or environment variables. Remove those credentials before switching accounts."
1412
+ );
1413
+ }
1414
+ const incompatibleOptions = authFlowOnlyOptions(options);
1415
+ if (incompatibleOptions.length === 0) return;
1416
+ throw new ZapierCliValidationError(
1417
+ `Cannot switch to stored credentials "${credentials.name}" while using ${incompatibleOptions.join(
1418
+ ", "
1419
+ )}. These options only apply when logging in to a new account.`
1420
+ );
1421
+ }
1422
+ function findStoredCredentialsByName({
1423
+ name,
1424
+ baseUrl
1425
+ }) {
1426
+ return listStoredCredentials({ baseUrl }).find(
1427
+ (credentials) => credentials.name === name
1428
+ );
1429
+ }
1430
+ async function switchCredentials({
1431
+ credentials,
1432
+ options,
1433
+ resolvedCredentials
1434
+ }) {
1435
+ assertCanSwitchCredentials({ credentials, options, resolvedCredentials });
1436
+ await activateStoredCredentials({
1437
+ name: credentials.name,
1438
+ baseUrl: credentials.baseUrl
1439
+ });
1440
+ process.stderr.write(
1441
+ `\u2705 Credentials "${credentials.name}" are now active.
1442
+ `
1443
+ );
1444
+ }
1445
+ async function chooseStoredLoginCredentialsAtBaseUrl({
1446
+ baseUrl,
1447
+ options,
1448
+ resolvedCredentials
1449
+ }) {
1450
+ if (resolvedCredentials !== void 0 || authFlowOnlyOptions(options).length > 0) {
1451
+ return "none";
1452
+ }
1453
+ const storedCredentials = listStoredCredentials({ baseUrl });
1454
+ if (storedCredentials.length === 0) return "none";
1455
+ const selection = await promptForCredentials({
1456
+ credentials: storedCredentials,
1457
+ activeCredentials: getActiveCredentials({ baseUrl })
1458
+ });
1459
+ if (selection.action === "create") return "create";
1460
+ await switchCredentials({
1461
+ credentials: selection.credentials,
1462
+ options,
1463
+ resolvedCredentials
1464
+ });
1465
+ return "switch";
1466
+ }
1467
+ async function chooseStoredLoginCredentials({
1468
+ imports,
1469
+ options
1470
+ }) {
1471
+ const resolvedCredentials = await imports.resolveCredentials();
1472
+ const credentialsBaseUrl = await resolveCredentialsBaseUrl({
1473
+ options: imports.sdkOptions,
1474
+ resolvedCredentials
1475
+ });
1476
+ return chooseStoredLoginCredentialsAtBaseUrl({
1477
+ baseUrl: credentialsBaseUrl,
1478
+ options,
1479
+ resolvedCredentials
1480
+ });
1481
+ }
1482
+ async function confirmNewCredentialsName(name) {
1483
+ const { confirmed } = await inquirer4__default.default.prompt([
1484
+ {
1485
+ type: "confirm",
1486
+ name: "confirmed",
1487
+ default: false,
1488
+ message: `No stored credentials named "${name}" were found. Continue with a new account and save it as "${name}"?`
1489
+ }
1490
+ ]);
1491
+ return confirmed;
1492
+ }
1110
1493
 
1111
1494
  // src/utils/constants.ts
1112
1495
  var LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
@@ -1131,20 +1514,20 @@ var getCallablePromise = () => {
1131
1514
  var getCallablePromise_default = getCallablePromise;
1132
1515
  var log = {
1133
1516
  info: (message, ...args) => {
1134
- console.error(chalk3__default.default.blue("\u2139"), message, ...args);
1517
+ console.error(chalk5__default.default.blue("\u2139"), message, ...args);
1135
1518
  },
1136
1519
  error: (message, ...args) => {
1137
- console.error(chalk3__default.default.red("\u2716"), message, ...args);
1520
+ console.error(chalk5__default.default.red("\u2716"), message, ...args);
1138
1521
  },
1139
1522
  success: (message, ...args) => {
1140
- console.error(chalk3__default.default.green("\u2713"), message, ...args);
1523
+ console.error(chalk5__default.default.green("\u2713"), message, ...args);
1141
1524
  },
1142
1525
  warn: (message, ...args) => {
1143
- console.error(chalk3__default.default.yellow("\u26A0"), message, ...args);
1526
+ console.error(chalk5__default.default.yellow("\u26A0"), message, ...args);
1144
1527
  },
1145
1528
  debug: (message, ...args) => {
1146
1529
  if (process.env.DEBUG === "true" || process.argv.includes("--debug")) {
1147
- console.error(chalk3__default.default.gray("\u{1F41B}"), message, ...args);
1530
+ console.error(chalk5__default.default.gray("\u{1F41B}"), message, ...args);
1148
1531
  }
1149
1532
  }
1150
1533
  };
@@ -1991,9 +2374,6 @@ var HEADLESS_SIGNUP_RECOVERY_MESSAGE = "Restart `zapier-sdk signup --headless` t
1991
2374
  function getEntryPointLabel(entryPoint) {
1992
2375
  return entryPoint === "signup" ? "Signup" : "Login";
1993
2376
  }
1994
- function getActiveCredentialsAction(entryPoint) {
1995
- return entryPoint === "signup" ? "continue signup" : "log in again";
1996
- }
1997
2377
  function getCredentialsPromptMessage(entryPoint) {
1998
2378
  return entryPoint === "signup" ? "Enter a name to identify these credentials:" : "Enter a name to identify them:";
1999
2379
  }
@@ -2008,11 +2388,24 @@ function validateCredentialsName(name) {
2008
2388
  if (!trimmedName) throw new ZapierCliValidationError("Name cannot be empty");
2009
2389
  return trimmedName;
2010
2390
  }
2391
+ function validateNewCredentialsName({
2392
+ name,
2393
+ baseUrl
2394
+ }) {
2395
+ const validatedName = validateCredentialsName(name);
2396
+ if (credentialNameExists({ name: validatedName, baseUrl })) {
2397
+ throw new ZapierCliValidationError(
2398
+ `Credentials named "${validatedName}" already exist. Choose a different name.`
2399
+ );
2400
+ }
2401
+ return validatedName;
2402
+ }
2011
2403
  async function promptCredentialsName({
2012
2404
  email,
2013
- promptMessage
2405
+ promptMessage,
2406
+ baseUrl
2014
2407
  }) {
2015
- const { credentialName } = await inquirer3__default.default.prompt([
2408
+ const { credentialName } = await inquirer4__default.default.prompt([
2016
2409
  {
2017
2410
  type: "input",
2018
2411
  name: "credentialName",
@@ -2020,7 +2413,7 @@ async function promptCredentialsName({
2020
2413
  default: defaultCredentialsName(email),
2021
2414
  validate: (input) => {
2022
2415
  try {
2023
- validateCredentialsName(input);
2416
+ validateNewCredentialsName({ name: input, baseUrl });
2024
2417
  return true;
2025
2418
  } catch (err) {
2026
2419
  return err instanceof Error ? err.message : String(err);
@@ -2028,7 +2421,7 @@ async function promptCredentialsName({
2028
2421
  }
2029
2422
  }
2030
2423
  ]);
2031
- return validateCredentialsName(credentialName);
2424
+ return validateNewCredentialsName({ name: credentialName, baseUrl });
2032
2425
  }
2033
2426
  function resolveDefaultCredentialsName({
2034
2427
  email
@@ -2044,7 +2437,8 @@ async function resolveCredentialName({
2044
2437
  if (interactive) {
2045
2438
  return promptCredentialsName({
2046
2439
  email,
2047
- promptMessage: getCredentialsPromptMessage(entryPoint)
2440
+ promptMessage: getCredentialsPromptMessage(entryPoint),
2441
+ baseUrl
2048
2442
  });
2049
2443
  }
2050
2444
  const baseName = resolveDefaultCredentialsName({ email });
@@ -2075,7 +2469,7 @@ async function promptConfirm({
2075
2469
  message,
2076
2470
  defaultValue
2077
2471
  }) {
2078
- const { confirmed } = await inquirer3__default.default.prompt([
2472
+ const { confirmed } = await inquirer4__default.default.prompt([
2079
2473
  { type: "confirm", name: "confirmed", message, default: defaultValue }
2080
2474
  ]);
2081
2475
  return confirmed;
@@ -2085,6 +2479,11 @@ function promptlessCredentialResetError(credentials) {
2085
2479
  `Already logged in as "${credentials.name}". Run \`logout\` first or use an interactive terminal to re-authenticate.`
2086
2480
  );
2087
2481
  }
2482
+ function unnamedNonInteractiveLoginError(credentials) {
2483
+ throw new ZapierCliValidationError(
2484
+ `Already logged in as "${credentials.name}". Provide \`--name\` to activate or create named credentials, or run \`logout\` first.`
2485
+ );
2486
+ }
2088
2487
  function promptlessLegacyJwtUpgradeError() {
2089
2488
  throw new ZapierCliValidationError(
2090
2489
  "Legacy JWT login detected. Run `logout` first or use an interactive terminal to migrate to client credentials."
@@ -2094,16 +2493,20 @@ async function clearExistingAuthState({
2094
2493
  imports,
2095
2494
  baseUrl,
2096
2495
  interactive,
2097
- entryPoint
2496
+ entryPoint,
2497
+ preserveExistingCredentials = false
2098
2498
  }) {
2099
2499
  const activeCredentials = getActiveCredentials({ baseUrl });
2100
2500
  const flowLabel = getEntryPointLabel(entryPoint);
2501
+ if (activeCredentials && (entryPoint === "login" || preserveExistingCredentials)) {
2502
+ return true;
2503
+ }
2101
2504
  if (activeCredentials) {
2102
2505
  const confirmed = interactive ? await promptConfirm({
2103
2506
  defaultValue: false,
2104
2507
  message: `You are already logged in as "${activeCredentials.name}".
2105
2508
  Logging out will delete these credentials and may interrupt other Zapier SDK or CLI sessions using them.
2106
- Log out and ${getActiveCredentialsAction(entryPoint)}?`
2509
+ Log out and continue signup?`
2107
2510
  }) : promptlessCredentialResetError(activeCredentials);
2108
2511
  if (!confirmed) {
2109
2512
  process.stderr.write(`${flowLabel} cancelled.
@@ -2318,12 +2721,14 @@ async function provisionAccountCredentials({
2318
2721
  async function runAccountAuth({
2319
2722
  imports,
2320
2723
  options,
2321
- entryPoint
2724
+ entryPoint,
2725
+ storedCredentialsMode = "choose",
2726
+ preserveExistingCredentials = false
2322
2727
  }) {
2323
2728
  if (options.callbackUrl !== void 0) {
2324
2729
  const { callbackUrl } = options;
2325
2730
  const pending = getPendingOauthFlow({ entryPoint });
2326
- const finishName = options.name !== void 0 ? validateCredentialsName(options.name) : void 0;
2731
+ const finishName = options.name === void 0 ? void 0 : validateCredentialsName(options.name);
2327
2732
  if (finishName !== void 0 && finishName !== pending.credentialName) {
2328
2733
  throw new ZapierCliValidationError(
2329
2734
  "Cannot change --name while completing a pending OAuth flow. Start a new non-interactive login with the desired --name."
@@ -2383,7 +2788,6 @@ async function runAccountAuth({
2383
2788
  });
2384
2789
  return;
2385
2790
  }
2386
- const timeoutSeconds = parseTimeoutSeconds(options.timeout);
2387
2791
  const interactive = !resolveNonInteractive(options);
2388
2792
  const resolvedCredentials = await imports.resolveCredentials();
2389
2793
  const pkceCredentials = toPkceCredentials(resolvedCredentials);
@@ -2392,8 +2796,34 @@ async function runAccountAuth({
2392
2796
  options: imports.sdkOptions,
2393
2797
  resolvedCredentials
2394
2798
  });
2395
- const providedName = options.name !== void 0 ? validateCredentialsName(options.name) : void 0;
2396
- if (providedName !== void 0) {
2799
+ const providedName = options.name === void 0 ? void 0 : validateCredentialsName(options.name);
2800
+ if (entryPoint === "login") {
2801
+ if (providedName !== void 0) {
2802
+ const matchingCredentials = findStoredCredentialsByName({
2803
+ name: providedName,
2804
+ baseUrl: credentialsBaseUrl
2805
+ });
2806
+ if (matchingCredentials) {
2807
+ await switchCredentials({
2808
+ credentials: matchingCredentials,
2809
+ options,
2810
+ resolvedCredentials
2811
+ });
2812
+ return;
2813
+ }
2814
+ if (interactive && !await confirmNewCredentialsName(providedName)) {
2815
+ process.stderr.write("Login cancelled.\n");
2816
+ return;
2817
+ }
2818
+ } else if (interactive && storedCredentialsMode === "choose") {
2819
+ const selection = await chooseStoredLoginCredentialsAtBaseUrl({
2820
+ baseUrl: credentialsBaseUrl,
2821
+ options,
2822
+ resolvedCredentials
2823
+ });
2824
+ if (selection === "switch") return;
2825
+ }
2826
+ } else if (providedName !== void 0) {
2397
2827
  const activeCredentials = getActiveCredentials({
2398
2828
  baseUrl: credentialsBaseUrl
2399
2829
  });
@@ -2403,14 +2833,22 @@ async function runAccountAuth({
2403
2833
  );
2404
2834
  }
2405
2835
  }
2836
+ if (entryPoint === "login" && !interactive && providedName === void 0) {
2837
+ const activeCredentials = getActiveCredentials({
2838
+ baseUrl: credentialsBaseUrl
2839
+ });
2840
+ if (activeCredentials) unnamedNonInteractiveLoginError(activeCredentials);
2841
+ }
2406
2842
  if (!await clearExistingAuthState({
2407
2843
  imports,
2408
2844
  baseUrl: credentialsBaseUrl,
2409
2845
  interactive,
2410
- entryPoint
2846
+ entryPoint,
2847
+ preserveExistingCredentials
2411
2848
  })) {
2412
2849
  return;
2413
2850
  }
2851
+ const timeoutSeconds = parseTimeoutSeconds(options.timeout);
2414
2852
  const useApprovals = options.useApprovals === true;
2415
2853
  if (!interactive) {
2416
2854
  await startPendingOauthFlow({
@@ -2447,7 +2885,7 @@ async function runAccountAuth({
2447
2885
  }
2448
2886
  var LoginSchema = zod.z.object({
2449
2887
  name: zod.z.string().optional().describe(
2450
- "Name to identify these credentials (defaults to <email>@<hostname>). Provide this to set a custom name without the interactive prompt."
2888
+ "Activate stored credentials with this name. If none exist, create new credentials with this name; interactive login asks for confirmation first."
2451
2889
  ),
2452
2890
  timeout: zod.z.string().optional().describe("Login timeout in seconds (default: 300)"),
2453
2891
  useApprovals: zod.z.boolean().optional().describe(
@@ -4248,7 +4686,7 @@ async function promptYesNo({
4248
4686
  nonInteractive
4249
4687
  }) {
4250
4688
  if (nonInteractive) return defaultValue;
4251
- const { answer } = await inquirer3__default.default.prompt([
4689
+ const { answer } = await inquirer4__default.default.prompt([
4252
4690
  { type: "confirm", name: "answer", message, default: defaultValue }
4253
4691
  ]);
4254
4692
  return answer;
@@ -4295,7 +4733,7 @@ function buildTemplateVariables({
4295
4733
  };
4296
4734
  }
4297
4735
  function cleanupProject({ projectDir }) {
4298
- console.log("\n" + chalk3__default.default.yellow("!") + " Cleaning up...");
4736
+ console.log("\n" + chalk5__default.default.yellow("!") + " Cleaning up...");
4299
4737
  fs.rmSync(projectDir, { recursive: true, force: true });
4300
4738
  }
4301
4739
  async function withInterruptCleanup(cleanup, fn) {
@@ -4505,8 +4943,8 @@ function buildNextSteps({
4505
4943
  }
4506
4944
  function createConsoleDisplayHooks() {
4507
4945
  return {
4508
- onItemComplete: (message) => console.log(" " + chalk3__default.default.green("\u2713") + " " + chalk3__default.default.dim(message)),
4509
- onWarn: (message) => console.warn(chalk3__default.default.yellow("!") + " " + message),
4946
+ onItemComplete: (message) => console.log(" " + chalk5__default.default.green("\u2713") + " " + chalk5__default.default.dim(message)),
4947
+ onWarn: (message) => console.warn(chalk5__default.default.yellow("!") + " " + message),
4510
4948
  onStepStart: ({
4511
4949
  description,
4512
4950
  stepNumber,
@@ -4515,31 +4953,31 @@ function createConsoleDisplayHooks() {
4515
4953
  nonInteractive
4516
4954
  }) => {
4517
4955
  const progressMessage = `${description}...`;
4518
- const stepCounter = chalk3__default.default.dim(`${stepNumber}/${totalSteps}`);
4956
+ const stepCounter = chalk5__default.default.dim(`${stepNumber}/${totalSteps}`);
4519
4957
  if (nonInteractive) {
4520
4958
  console.log(
4521
- "\n" + chalk3__default.default.bold(`\u276F ${progressMessage}`) + " " + stepCounter + "\n"
4959
+ "\n" + chalk5__default.default.bold(`\u276F ${progressMessage}`) + " " + stepCounter + "\n"
4522
4960
  );
4523
4961
  } else {
4524
4962
  console.log(
4525
- chalk3__default.default.dim("\u2192") + " " + progressMessage + " " + stepCounter
4963
+ chalk5__default.default.dim("\u2192") + " " + progressMessage + " " + stepCounter
4526
4964
  );
4527
4965
  }
4528
4966
  if (command) {
4529
- console.log(" " + chalk3__default.default.cyan(`$ ${command}`));
4967
+ console.log(" " + chalk5__default.default.cyan(`$ ${command}`));
4530
4968
  }
4531
4969
  },
4532
4970
  onStepSuccess: ({ stepNumber, totalSteps }) => console.log(
4533
- "\n" + chalk3__default.default.green("\u2713") + " " + chalk3__default.default.dim(`Step ${stepNumber}/${totalSteps} complete`) + "\n"
4971
+ "\n" + chalk5__default.default.green("\u2713") + " " + chalk5__default.default.dim(`Step ${stepNumber}/${totalSteps} complete`) + "\n"
4534
4972
  ),
4535
4973
  onStepError: ({ description, command, err }) => {
4536
4974
  const detail = err instanceof Error && err.message ? `
4537
- ${chalk3__default.default.dim(err.message)}` : "";
4975
+ ${chalk5__default.default.dim(err.message)}` : "";
4538
4976
  const hint = command ? `
4539
- ${chalk3__default.default.dim("run manually:")} ${chalk3__default.default.cyan(`$ ${command}`)}` : "";
4977
+ ${chalk5__default.default.dim("run manually:")} ${chalk5__default.default.cyan(`$ ${command}`)}` : "";
4540
4978
  console.error(
4541
4979
  `
4542
- ${chalk3__default.default.red("\u2716")} ${chalk3__default.default.bold(description)}${chalk3__default.default.dim(" failed")}${detail}${hint}`
4980
+ ${chalk5__default.default.red("\u2716")} ${chalk5__default.default.bold(description)}${chalk5__default.default.dim(" failed")}${detail}${hint}`
4543
4981
  );
4544
4982
  }
4545
4983
  };
@@ -4551,22 +4989,22 @@ function displaySummaryAndNextSteps({
4551
4989
  packageManager
4552
4990
  }) {
4553
4991
  const formatStatus = (complete) => ({
4554
- icon: complete ? chalk3__default.default.green("\u2713") : chalk3__default.default.yellow("!"),
4555
- text: complete ? chalk3__default.default.green("Setup complete") : chalk3__default.default.yellow("Setup interrupted")
4992
+ icon: complete ? chalk5__default.default.green("\u2713") : chalk5__default.default.yellow("!"),
4993
+ text: complete ? chalk5__default.default.green("Setup complete") : chalk5__default.default.yellow("Setup interrupted")
4556
4994
  });
4557
- const formatNextStep = (step, i) => " " + chalk3__default.default.dim(`${i + 1}.`) + " " + chalk3__default.default.bold(step.description);
4558
- const formatCommand = (cmd) => " " + chalk3__default.default.cyan(`$ ${cmd}`);
4559
- const formatCompletedStep = (step) => " " + chalk3__default.default.green("\u2713") + " " + step.description;
4995
+ const formatNextStep = (step, i) => " " + chalk5__default.default.dim(`${i + 1}.`) + " " + chalk5__default.default.bold(step.description);
4996
+ const formatCommand = (cmd) => " " + chalk5__default.default.cyan(`$ ${cmd}`);
4997
+ const formatCompletedStep = (step) => " " + chalk5__default.default.green("\u2713") + " " + step.description;
4560
4998
  const { execCmd } = getPackageManagerCommands({ packageManager });
4561
4999
  const leftoverSteps = steps.filter(
4562
5000
  (s) => !completedSetupStepIds.includes(s.id)
4563
5001
  );
4564
5002
  const isComplete = leftoverSteps.length === 0;
4565
5003
  const status = formatStatus(isComplete);
4566
- console.log("\n" + chalk3__default.default.bold("\u276F Summary") + "\n");
4567
- console.log(" " + chalk3__default.default.dim("Project") + " " + chalk3__default.default.bold(projectName));
5004
+ console.log("\n" + chalk5__default.default.bold("\u276F Summary") + "\n");
5005
+ console.log(" " + chalk5__default.default.dim("Project") + " " + chalk5__default.default.bold(projectName));
4568
5006
  console.log(
4569
- " " + chalk3__default.default.dim("Status") + " " + status.icon + " " + status.text
5007
+ " " + chalk5__default.default.dim("Status") + " " + status.icon + " " + status.text
4570
5008
  );
4571
5009
  const completedSteps = steps.filter(
4572
5010
  (s) => completedSetupStepIds.includes(s.id)
@@ -4576,7 +5014,7 @@ function displaySummaryAndNextSteps({
4576
5014
  for (const step of completedSteps) console.log(formatCompletedStep(step));
4577
5015
  }
4578
5016
  const nextSteps = buildNextSteps({ projectName, leftoverSteps, execCmd });
4579
- console.log("\n" + chalk3__default.default.bold("\u276F Next Steps") + "\n");
5017
+ console.log("\n" + chalk5__default.default.bold("\u276F Next Steps") + "\n");
4580
5018
  nextSteps.forEach((step, i) => {
4581
5019
  console.log(formatNextStep(step, i));
4582
5020
  if (step.command) console.log(formatCommand(step.command));
@@ -4639,149 +5077,6 @@ var initPlugin = zapierSdk.defineMethod({
4639
5077
  });
4640
5078
  }
4641
5079
  });
4642
- function isSelectable(item) {
4643
- return !core.Separator.isSeparator(item) && !item.disabled;
4644
- }
4645
- function normalizeChoices(choices) {
4646
- return choices.map((choice) => {
4647
- if (core.Separator.isSeparator(choice)) return choice;
4648
- const name = choice.name ?? String(choice.value);
4649
- return {
4650
- value: choice.value,
4651
- name,
4652
- short: choice.short ?? name,
4653
- disabled: choice.disabled ?? false
4654
- };
4655
- });
4656
- }
4657
- var theme = core.makeTheme({
4658
- icon: { cursor: "\u276F" },
4659
- style: {
4660
- disabled: (text) => chalk3__default.default.dim(`- ${text}`),
4661
- searchTerm: (text) => chalk3__default.default.cyan(text),
4662
- keysHelpTip: (keys) => keys.map(([key, action]) => `${chalk3__default.default.bold(key)} ${chalk3__default.default.dim(action)}`).join(chalk3__default.default.dim(" \u2022 "))
4663
- }
4664
- });
4665
- var searchSelect = core.createPrompt(
4666
- (config2, done) => {
4667
- const { pageSize = 7 } = config2;
4668
- const [status, setStatus] = core.useState(
4669
- "loading"
4670
- );
4671
- const [searchTerm, setSearchTerm] = core.useState("");
4672
- const [searchResults, setSearchResults] = core.useState([]);
4673
- const [searchError, setSearchError] = core.useState();
4674
- const prefix = core.usePrefix({ status, theme });
4675
- const bounds = core.useMemo(() => {
4676
- const first = searchResults.findIndex(isSelectable);
4677
- let last = -1;
4678
- for (let i = searchResults.length - 1; i >= 0; i--) {
4679
- if (isSelectable(searchResults[i])) {
4680
- last = i;
4681
- break;
4682
- }
4683
- }
4684
- return { first, last };
4685
- }, [searchResults]);
4686
- const defaultActive = core.useMemo(() => {
4687
- const requested = config2.initialActive;
4688
- if (searchTerm === "" && requested !== void 0 && requested >= 0 && requested < searchResults.length && isSelectable(searchResults[requested])) {
4689
- return requested;
4690
- }
4691
- return bounds.first;
4692
- }, [searchResults, searchTerm, bounds.first]);
4693
- const [active = defaultActive, setActive] = core.useState();
4694
- core.useEffect(() => {
4695
- const controller = new AbortController();
4696
- setStatus("loading");
4697
- setSearchError(void 0);
4698
- const fetchResults = async () => {
4699
- try {
4700
- const results = await config2.source(searchTerm || void 0);
4701
- if (!controller.signal.aborted) {
4702
- setActive(void 0);
4703
- setSearchError(void 0);
4704
- setSearchResults(normalizeChoices(results));
4705
- setStatus("idle");
4706
- }
4707
- } catch (error2) {
4708
- if (!controller.signal.aborted && error2 instanceof Error) {
4709
- setSearchError(error2.message);
4710
- }
4711
- }
4712
- };
4713
- void fetchResults();
4714
- return () => {
4715
- controller.abort();
4716
- };
4717
- }, [searchTerm]);
4718
- const selectedChoice = searchResults[active];
4719
- core.useKeypress((key, rl) => {
4720
- if (core.isEnterKey(key)) {
4721
- if (selectedChoice && isSelectable(selectedChoice)) {
4722
- setStatus("done");
4723
- done(selectedChoice.value);
4724
- } else {
4725
- rl.write(searchTerm);
4726
- }
4727
- } else if (core.isTabKey(key) && selectedChoice && isSelectable(selectedChoice)) {
4728
- rl.clearLine(0);
4729
- rl.write(selectedChoice.name);
4730
- setSearchTerm(selectedChoice.name);
4731
- } else if (status !== "loading" && (core.isUpKey(key) || core.isDownKey(key))) {
4732
- rl.clearLine(0);
4733
- if (core.isUpKey(key) && active !== bounds.first || core.isDownKey(key) && active !== bounds.last) {
4734
- const offset = core.isUpKey(key) ? -1 : 1;
4735
- let next = active;
4736
- do {
4737
- next = (next + offset + searchResults.length) % searchResults.length;
4738
- } while (!isSelectable(searchResults[next]));
4739
- setActive(next);
4740
- }
4741
- } else {
4742
- setSearchTerm(rl.line);
4743
- }
4744
- });
4745
- const page = core.usePagination({
4746
- items: searchResults,
4747
- active,
4748
- renderItem({ item, isActive }) {
4749
- if (core.Separator.isSeparator(item)) {
4750
- return ` ${item.separator}`;
4751
- }
4752
- if (item.disabled) {
4753
- const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
4754
- return theme.style.disabled(`${item.name} ${disabledLabel}`);
4755
- }
4756
- const color = isActive ? theme.style.highlight : (x) => x;
4757
- const cursor = isActive ? theme.icon.cursor : ` `;
4758
- return color(`${cursor} ${item.name}`);
4759
- },
4760
- pageSize,
4761
- loop: false
4762
- });
4763
- const message = theme.style.message(config2.message, status);
4764
- if (status === "done" && selectedChoice && isSelectable(selectedChoice)) {
4765
- return [prefix, message, theme.style.answer(selectedChoice.short)].filter(Boolean).join(" ").trimEnd();
4766
- }
4767
- const searchStr = theme.style.searchTerm(searchTerm);
4768
- const helpTip = theme.style.keysHelpTip([
4769
- ["\u2191\u2193", "navigate"],
4770
- ["\u23CE", "select"]
4771
- ]);
4772
- let error;
4773
- if (searchError) {
4774
- error = theme.style.error(searchError);
4775
- } else if (searchResults.length === 0 && searchTerm !== "" && status === "idle") {
4776
- error = theme.style.error("No results found");
4777
- }
4778
- const header = [prefix, message, searchStr].filter(Boolean).join(" ").trimEnd();
4779
- const body = [error ?? page, " ", helpTip].filter(Boolean).join("\n").trimEnd();
4780
- return [header, body];
4781
- }
4782
- );
4783
-
4784
- // src/utils/controller-answer.ts
4785
5080
  function offers(question, action) {
4786
5081
  return question.actions.some((a) => a.action === action);
4787
5082
  }
@@ -4792,7 +5087,7 @@ async function promptText({
4792
5087
  message,
4793
5088
  password
4794
5089
  }) {
4795
- const { value } = await inquirer3__default.default.prompt([
5090
+ const { value } = await inquirer4__default.default.prompt([
4796
5091
  {
4797
5092
  type: password ? "password" : "input",
4798
5093
  name: "value",
@@ -4802,10 +5097,10 @@ async function promptText({
4802
5097
  ]);
4803
5098
  return value;
4804
5099
  }
4805
- var display = (c) => c.hint ? `${c.label} ${chalk3__default.default.dim(`(${c.hint})`)}` : c.label;
5100
+ var display = (c) => c.hint ? `${c.label} ${chalk5__default.default.dim(`(${c.hint})`)}` : c.label;
4806
5101
  var HIGH_CONTRAST_PROMPT_THEME = {
4807
5102
  style: {
4808
- answer: (text) => chalk3__default.default.inverse.bold(` ${text} `)
5103
+ answer: (text) => chalk5__default.default.inverse.bold(` ${text} `)
4809
5104
  }
4810
5105
  };
4811
5106
  function buildSelectRows(question, term) {
@@ -4821,8 +5116,8 @@ function buildSelectRows(question, term) {
4821
5116
  name: display(c),
4822
5117
  value: c.value
4823
5118
  }));
4824
- const skipRow = offers(question, "skip") ? [row(chalk3__default.default.dim("Skip (optional)"), "skip")] : [];
4825
- const customRow = offers(question, "custom") ? [row(chalk3__default.default.dim("Enter a value manually\u2026"), "custom")] : [];
5119
+ const skipRow = offers(question, "skip") ? [row(chalk5__default.default.dim("Skip (optional)"), "skip")] : [];
5120
+ const customRow = offers(question, "custom") ? [row(chalk5__default.default.dim("Enter a value manually\u2026"), "custom")] : [];
4826
5121
  const committed = !!t || question.search !== void 0;
4827
5122
  let rows;
4828
5123
  if (!committed) {
@@ -4833,13 +5128,13 @@ function buildSelectRows(question, term) {
4833
5128
  rows = [...customRow, ...skipRow];
4834
5129
  }
4835
5130
  if (offers(question, "search"))
4836
- rows.push(row(chalk3__default.default.cyan("Search again\u2026"), "search"));
5131
+ rows.push(row(chalk5__default.default.cyan("Search again\u2026"), "search"));
4837
5132
  if (offers(question, "next_page"))
4838
- rows.push(row(chalk3__default.default.dim("Load more\u2026"), "next_page"));
4839
- if (offers(question, "retry")) rows.push(row(chalk3__default.default.yellow("Retry"), "retry"));
4840
- if (offers(question, "cancel")) rows.push(row(chalk3__default.default.dim("Cancel"), "cancel"));
5133
+ rows.push(row(chalk5__default.default.dim("Load more\u2026"), "next_page"));
5134
+ if (offers(question, "retry")) rows.push(row(chalk5__default.default.yellow("Retry"), "retry"));
5135
+ if (offers(question, "cancel")) rows.push(row(chalk5__default.default.dim("Cancel"), "cancel"));
4841
5136
  for (const note of question.notes ?? [])
4842
- rows.push({ name: chalk3__default.default.dim(note), value: note, disabled: true });
5137
+ rows.push({ name: chalk5__default.default.dim(note), value: note, disabled: true });
4843
5138
  return rows;
4844
5139
  }
4845
5140
  function foldPage(acc, question, field) {
@@ -4880,7 +5175,7 @@ async function answerSelect(question, field, box, failed, mode) {
4880
5175
  const isClosedListPrompt = mode === "closed-list" && !failed && !view.multiple;
4881
5176
  const booleanValues = view.choices.map(({ value: value2 }) => value2);
4882
5177
  if (isClosedListPrompt && booleanValues.length === 2 && booleanValues.includes("true") && booleanValues.includes("false")) {
4883
- const { value: value2 } = await inquirer3__default.default.prompt([
5178
+ const { value: value2 } = await inquirer4__default.default.prompt([
4884
5179
  {
4885
5180
  type: "confirm",
4886
5181
  name: "value",
@@ -4896,7 +5191,7 @@ async function answerSelect(question, field, box, failed, mode) {
4896
5191
  name: display(choice),
4897
5192
  value: choice.value
4898
5193
  }));
4899
- const { value: value2 } = await inquirer3__default.default.prompt([
5194
+ const { value: value2 } = await inquirer4__default.default.prompt([
4900
5195
  {
4901
5196
  type: "list",
4902
5197
  name: "value",
@@ -4919,17 +5214,17 @@ async function answerSelect(question, field, box, failed, mode) {
4919
5214
  })),
4920
5215
  ...offers(question, "next_page") ? [
4921
5216
  {
4922
- name: chalk3__default.default.dim("Load more\u2026"),
5217
+ name: chalk5__default.default.dim("Load more\u2026"),
4923
5218
  value: { action: "next_page" }
4924
5219
  }
4925
5220
  ] : [],
4926
5221
  ...(question.notes ?? []).map((note) => ({
4927
- name: chalk3__default.default.dim(note),
5222
+ name: chalk5__default.default.dim(note),
4928
5223
  value: note,
4929
5224
  disabled: true
4930
5225
  }))
4931
5226
  ];
4932
- const { values } = await inquirer3__default.default.prompt([
5227
+ const { values } = await inquirer4__default.default.prompt([
4933
5228
  {
4934
5229
  type: "checkbox",
4935
5230
  name: "values",
@@ -5001,14 +5296,14 @@ async function answerSelect(question, field, box, failed, mode) {
5001
5296
  case "retry":
5002
5297
  return { type: "retry" };
5003
5298
  case "skip":
5004
- printAnswered(view.message, chalk3__default.default.dim("(skipped)"));
5299
+ printAnswered(view.message, chalk5__default.default.dim("(skipped)"));
5005
5300
  return { type: "skip" };
5006
5301
  case "cancel":
5007
5302
  return { type: "cancel" };
5008
5303
  }
5009
5304
  }
5010
5305
  function printAnswered(message, label) {
5011
- console.log(`${chalk3__default.default.green("\u2714")} ${message} ${chalk3__default.default.cyan(label)}`);
5306
+ console.log(`${chalk5__default.default.green("\u2714")} ${message} ${chalk5__default.default.cyan(label)}`);
5012
5307
  }
5013
5308
  async function answerInput(question) {
5014
5309
  const message = question.placeholder ? question.message.replace(/:?\s*$/, ` (${question.placeholder}):`) : question.message;
@@ -5026,7 +5321,7 @@ async function answerCollection(question) {
5026
5321
  return { type: "add" };
5027
5322
  }
5028
5323
  if (question.description) console.log(question.description);
5029
- const { again } = await inquirer3__default.default.prompt([
5324
+ const { again } = await inquirer4__default.default.prompt([
5030
5325
  {
5031
5326
  type: "confirm",
5032
5327
  name: "again",
@@ -5045,7 +5340,7 @@ function createCliAnswer({
5045
5340
  try {
5046
5341
  if (result.error !== void 0) {
5047
5342
  const message = typeof result.error === "string" ? result.error : result.error.message;
5048
- console.log(chalk3__default.default.yellow(`! ${message}`));
5343
+ console.log(chalk5__default.default.yellow(`! ${message}`));
5049
5344
  }
5050
5345
  const question = result.question;
5051
5346
  const field = question.path.length ? question.path.join(".") : "value";
@@ -5214,7 +5509,7 @@ var boltFillRanks = new Map(
5214
5509
  );
5215
5510
  var STATUS_ROW_INDEX = Math.floor(boltRows.length / 2);
5216
5511
  function formatPhase({ label, detail }) {
5217
- return detail ? `${chalk3__default.default.bold(label)} ${chalk3__default.default.dim(detail)}` : chalk3__default.default.bold(label);
5512
+ return detail ? `${chalk5__default.default.bold(label)} ${chalk5__default.default.dim(detail)}` : chalk5__default.default.bold(label);
5218
5513
  }
5219
5514
  function formatLoaderFrame({
5220
5515
  phase,
@@ -5226,7 +5521,7 @@ function formatLoaderFrame({
5226
5521
  const cellIndex = rowIndex * row.length + columnIndex;
5227
5522
  const fillRank = boltFillRanks.get(cellIndex);
5228
5523
  const isFilled = fillRank !== void 0 && fillRank < fillStage;
5229
- return isFilled ? chalk3__default.default.bold.yellow(cell) : chalk3__default.default.dim.yellow(cell);
5524
+ return isFilled ? chalk5__default.default.bold.yellow(cell) : chalk5__default.default.dim.yellow(cell);
5230
5525
  }).join("");
5231
5526
  const status = rowIndex === STATUS_ROW_INDEX ? ` ${formatPhase(phase)}` : "";
5232
5527
  return `${bolt}${status}`;
@@ -5258,12 +5553,12 @@ async function runWithSetupLoader({
5258
5553
  const result = await promise;
5259
5554
  clearInterval(animationTimer);
5260
5555
  const elapsedSeconds = ((Date.now() - startedAt) / 1e3).toFixed(1);
5261
- loader.succeed(`${formatPhase(phase)} ${chalk3__default.default.dim(`${elapsedSeconds}s`)}`);
5556
+ loader.succeed(`${formatPhase(phase)} ${chalk5__default.default.dim(`${elapsedSeconds}s`)}`);
5262
5557
  return result;
5263
5558
  } catch (error) {
5264
5559
  clearInterval(animationTimer);
5265
5560
  const elapsedSeconds = ((Date.now() - startedAt) / 1e3).toFixed(1);
5266
- loader.fail(`${formatPhase(phase)} ${chalk3__default.default.dim(`${elapsedSeconds}s`)}`);
5561
+ loader.fail(`${formatPhase(phase)} ${chalk5__default.default.dim(`${elapsedSeconds}s`)}`);
5267
5562
  throw error;
5268
5563
  }
5269
5564
  }
@@ -5754,7 +6049,7 @@ async function runCommand({
5754
6049
  detail: commandLabel
5755
6050
  });
5756
6051
  }
5757
- console.log(chalk3__default.default.dim(commandLabel));
6052
+ console.log(chalk5__default.default.dim(commandLabel));
5758
6053
  return await execute;
5759
6054
  } catch (error) {
5760
6055
  const message = error instanceof Error ? error.message : String(error);
@@ -5860,6 +6155,14 @@ function createWizardContext({
5860
6155
  imports,
5861
6156
  createAnswer: () => createCliAnswer({ mode: "closed-list" }),
5862
6157
  setupController: createSetupController(),
6158
+ selectStoredLoginCredentials: () => chooseStoredLoginCredentials({ imports, options: {} }),
6159
+ authenticateNewAccount: ({ entryPoint, headless }) => runAccountAuth({
6160
+ imports,
6161
+ options: { headless },
6162
+ entryPoint,
6163
+ storedCredentialsMode: "fresh",
6164
+ preserveExistingCredentials: true
6165
+ }),
5863
6166
  checkForUpdates,
5864
6167
  openUrl: async (url) => {
5865
6168
  await open__default.default(url);
@@ -5893,6 +6196,14 @@ function isCredentialWriteError(error) {
5893
6196
  const message = error instanceof Error ? error.message : String(error);
5894
6197
  return /permission|sandbox|eacces|eperm/i.test(message);
5895
6198
  }
6199
+ async function confirmAuthentication(context) {
6200
+ const { data: profile } = await runWithSetupLoader({
6201
+ promise: context.imports.getProfile({}),
6202
+ label: "Confirming Zapier account"
6203
+ });
6204
+ context.accountEmail = profile.email;
6205
+ console.log(`Authenticated as ${profile.email}.`);
6206
+ }
5896
6207
  async function authenticate(context) {
5897
6208
  const activeProfile = await runWithSetupLoader({
5898
6209
  promise: context.imports.getProfile({}).then(({ data }) => data).catch((error) => {
@@ -5901,7 +6212,12 @@ async function authenticate(context) {
5901
6212
  }),
5902
6213
  label: "Checking Zapier authentication"
5903
6214
  });
5904
- if (activeProfile) {
6215
+ const storedCredentialsSelection = await context.selectStoredLoginCredentials();
6216
+ if (storedCredentialsSelection === "switch") {
6217
+ await confirmAuthentication(context);
6218
+ return;
6219
+ }
6220
+ if (storedCredentialsSelection === "none" && activeProfile) {
5905
6221
  const shouldLogout = await resolveSetupConfirm({
5906
6222
  answer: context.createAnswer(),
5907
6223
  controller: context.setupController,
@@ -5942,10 +6258,14 @@ Log out and use a different account?`,
5942
6258
  ]
5943
6259
  });
5944
6260
  const headless = environment === "headless";
5945
- const runAuth = flow === "login" ? context.imports.login : context.imports.signup;
5946
6261
  printAuthCommand({ context, flow, headless });
5947
6262
  try {
5948
- await runAuth({ headless });
6263
+ if (storedCredentialsSelection === "create") {
6264
+ await context.authenticateNewAccount({ entryPoint: flow, headless });
6265
+ } else {
6266
+ const runAuth = flow === "login" ? context.imports.login : context.imports.signup;
6267
+ await runAuth({ headless });
6268
+ }
5949
6269
  } catch (error) {
5950
6270
  if (isCredentialWriteError(error)) {
5951
6271
  console.error(
@@ -5954,12 +6274,7 @@ Log out and use a different account?`,
5954
6274
  }
5955
6275
  throw error;
5956
6276
  }
5957
- const { data: profile } = await runWithSetupLoader({
5958
- promise: context.imports.getProfile({}),
5959
- label: "Confirming Zapier account"
5960
- });
5961
- context.accountEmail = profile.email;
5962
- console.log(`Authenticated as ${profile.email}.`);
6277
+ await confirmAuthentication(context);
5963
6278
  }
5964
6279
  var agentLabels = {
5965
6280
  claude: "Claude Code",
@@ -6001,7 +6316,7 @@ function printAgentPrompt({
6001
6316
  message
6002
6317
  }) {
6003
6318
  console.log();
6004
- console.log(chalk3__default.default.bgYellow.black.bold(message));
6319
+ console.log(chalk5__default.default.bgYellow.black.bold(message));
6005
6320
  console.log();
6006
6321
  console.log(buildAgentPrompt({ context }));
6007
6322
  }
@@ -6286,7 +6601,7 @@ var MINIMUM_MESSAGE_WIDTH = 20;
6286
6601
  var MAXIMUM_MESSAGE_WIDTH = 88;
6287
6602
  function showPhase({ number, title }) {
6288
6603
  console.log();
6289
- console.log(chalk3__default.default.bgCyan.black.bold(` ${number}/${PHASE_COUNT} ${title} `));
6604
+ console.log(chalk5__default.default.bgCyan.black.bold(` ${number}/${PHASE_COUNT} ${title} `));
6290
6605
  }
6291
6606
  function printWrapped(text) {
6292
6607
  const width = Math.max(
@@ -6300,7 +6615,7 @@ function printWrapped(text) {
6300
6615
  }
6301
6616
  function showReadyMessage() {
6302
6617
  console.log();
6303
- console.log(chalk3__default.default.bgGreen.black.bold(" \u2713 Zapier SDK setup complete "));
6618
+ console.log(chalk5__default.default.bgGreen.black.bold(" \u2713 Zapier SDK setup complete "));
6304
6619
  console.log();
6305
6620
  printWrapped(
6306
6621
  "Use active Zapier connections to access 9,000+ app connectors without managing each app's OAuth, token refresh, or retries."
@@ -6312,7 +6627,7 @@ function showReadyMessage() {
6312
6627
  console.log();
6313
6628
  }
6314
6629
  async function runWizard(context) {
6315
- console.log(chalk3__default.default.bold("Zapier SDK setup"));
6630
+ console.log(chalk5__default.default.bold("Zapier SDK setup"));
6316
6631
  showPhase({ number: 1, title: "Project directory" });
6317
6632
  await chooseDirectory(context);
6318
6633
  showPhase({ number: 2, title: "Node.js" });
@@ -6327,7 +6642,7 @@ async function runWizard(context) {
6327
6642
  showPhase({ number: 6, title: "Slack demo" });
6328
6643
  await offerSlackTest(context);
6329
6644
  showReadyMessage();
6330
- console.log(chalk3__default.default.bgCyan.black.bold(" Next steps "));
6645
+ console.log(chalk5__default.default.bgCyan.black.bold(" Next steps "));
6331
6646
  await openAgentHandoff(context);
6332
6647
  }
6333
6648
 
@@ -6342,7 +6657,11 @@ var setupImports = [
6342
6657
  listConnectionsRef2,
6343
6658
  loginRef,
6344
6659
  logoutRef,
6345
- signupRef
6660
+ signupRef,
6661
+ zapierSdk.apiPluginRef,
6662
+ zapierSdk.resolveCredentialsPluginRef,
6663
+ zapierSdk.eventEmissionPluginRef,
6664
+ zapierSdk.sdkOptionsPluginRef
6346
6665
  ];
6347
6666
  var setupPlugin = zapierSdk.defineMethod({
6348
6667
  name: "setup",
@@ -6383,18 +6702,18 @@ function createInteractiveCallback() {
6383
6702
  const attrs = message.message_attributes;
6384
6703
  console.log(
6385
6704
  `
6386
- ${chalk3__default.default.bold(`Message #${messageNumber}`)} ${chalk3__default.default.dim(message.id)} ${chalk3__default.default.dim(`(lease #${attrs.lease_count})`)}`
6705
+ ${chalk5__default.default.bold(`Message #${messageNumber}`)} ${chalk5__default.default.dim(message.id)} ${chalk5__default.default.dim(`(lease #${attrs.lease_count})`)}`
6387
6706
  );
6388
6707
  if (attrs.error_message) {
6389
- console.log(chalk3__default.default.yellow(` upstream error: ${attrs.error_message}`));
6708
+ console.log(chalk5__default.default.yellow(` upstream error: ${attrs.error_message}`));
6390
6709
  }
6391
6710
  if (attrs.possible_duplicate_data) {
6392
- console.log(chalk3__default.default.yellow(" possible duplicate data"));
6711
+ console.log(chalk5__default.default.yellow(" possible duplicate data"));
6393
6712
  }
6394
6713
  while (true) {
6395
6714
  let action;
6396
6715
  try {
6397
- const answer = await inquirer3__default.default.prompt([
6716
+ const answer = await inquirer4__default.default.prompt([
6398
6717
  {
6399
6718
  type: "list",
6400
6719
  name: "action",
@@ -6419,7 +6738,7 @@ ${chalk3__default.default.bold(`Message #${messageNumber}`)} ${chalk3__default.d
6419
6738
  throw error;
6420
6739
  }
6421
6740
  if (action === "view") {
6422
- console.log(chalk3__default.default.dim(JSON.stringify(message.payload, null, 2)));
6741
+ console.log(chalk5__default.default.dim(JSON.stringify(message.payload, null, 2)));
6423
6742
  continue;
6424
6743
  }
6425
6744
  if (action === "ack") {
@@ -6522,7 +6841,7 @@ function describeReason(reason) {
6522
6841
  }
6523
6842
  function printDrainError(reason, message) {
6524
6843
  console.error(
6525
- chalk3__default.default.red(`Error processing ${message.id}: ${describeReason(reason)}`)
6844
+ chalk5__default.default.red(`Error processing ${message.id}: ${describeReason(reason)}`)
6526
6845
  );
6527
6846
  }
6528
6847
  function printDrainSummary(counts) {
@@ -6532,7 +6851,7 @@ function printDrainSummary(counts) {
6532
6851
  if (skipped > 0) parts.push(`${skipped} skipped`);
6533
6852
  parts.push(`${counts.rejected} rejected`);
6534
6853
  console.log(
6535
- chalk3__default.default.dim(
6854
+ chalk5__default.default.dim(
6536
6855
  `
6537
6856
  Processed ${total} message${total === 1 ? "" : "s"} (${parts.join(", ")}).`
6538
6857
  )
@@ -6540,7 +6859,7 @@ Processed ${total} message${total === 1 ? "" : "s"} (${parts.join(", ")}).`
6540
6859
  }
6541
6860
  function warnInteractiveContinueOnErrorOverride() {
6542
6861
  console.warn(
6543
- chalk3__default.default.yellow(
6862
+ chalk5__default.default.yellow(
6544
6863
  'Note: continueOnError=false is overridden to true in interactive mode (the "Skip (let lease expire)" choice would otherwise terminate the drain).'
6545
6864
  )
6546
6865
  );
@@ -6861,7 +7180,7 @@ function collectDeprecationNoticeAndForward(event, onEvent) {
6861
7180
  // package.json with { type: 'json' }
6862
7181
  var package_default = {
6863
7182
  name: "@zapier/zapier-sdk-cli",
6864
- version: "0.77.9"};
7183
+ version: "0.78.0"};
6865
7184
 
6866
7185
  // src/sdk.ts
6867
7186
  var warnedDeprecatedMethods = /* @__PURE__ */ new Set();
@@ -6872,9 +7191,9 @@ var cliCoreOptions = {
6872
7191
  warnedDeprecatedMethods.add(methodName);
6873
7192
  console.warn();
6874
7193
  console.warn(
6875
- chalk3__default.default.yellow.bold("\u26A0\uFE0F DEPRECATION WARNING") + chalk3__default.default.yellow(` - \`${toKebabCase(methodName)}\` is deprecated.`)
7194
+ chalk5__default.default.yellow.bold("\u26A0\uFE0F DEPRECATION WARNING") + chalk5__default.default.yellow(` - \`${toKebabCase(methodName)}\` is deprecated.`)
6876
7195
  );
6877
- console.warn(chalk3__default.default.yellow(` ${deprecation.message}`));
7196
+ console.warn(chalk5__default.default.yellow(` ${deprecation.message}`));
6878
7197
  console.warn();
6879
7198
  }
6880
7199
  };
@@ -6945,7 +7264,7 @@ function createZapierCliSdk(options = {}) {
6945
7264
 
6946
7265
  // package.json
6947
7266
  var package_default2 = {
6948
- version: "0.77.9"};
7267
+ version: "0.78.0"};
6949
7268
 
6950
7269
  // src/telemetry/builders.ts
6951
7270
  function createCliBaseEvent(context = {}) {