@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.
@@ -1,5 +1,5 @@
1
1
  import * as jwt from 'jsonwebtoken';
2
- import { deletePassword, getKeyring, setPassword, getPassword } from 'cross-keychain';
2
+ import { deletePassword, getPassword, getKeyring, setPassword } from 'cross-keychain';
3
3
  import Conf from 'conf';
4
4
  import * as fs from 'fs';
5
5
  import { promises, createWriteStream, existsSync, readdirSync, readFileSync, rmSync, mkdirSync, writeFileSync, copyFileSync } from 'fs';
@@ -11,11 +11,12 @@ import { defineMethod, apiPluginRef, resolveCredentialsPluginRef, eventEmissionP
11
11
  import { z } from 'zod';
12
12
  import { triggerInboxResolver, DrainTriggerInboxSchema, WatchTriggerInboxSchema, injectCliLogin as injectCliLogin$1, definePlugin as definePlugin$1, omitExports as omitExports$1, zapierExperimentalSdkPlugin, createSdk as createSdk$1, CORE_OPTIONS_ID, SDK_OPTIONS_ID, addPlugin } from '@zapier/zapier-sdk/experimental';
13
13
  import { hostname } from 'os';
14
- import inquirer3 from 'inquirer';
14
+ import inquirer4 from 'inquirer';
15
+ import chalk5 from 'chalk';
16
+ import { makeTheme, createPrompt, useState, usePrefix, useMemo, useEffect, useKeypress, isEnterKey, isTabKey, isUpKey, isDownKey, usePagination, Separator } from '@inquirer/core';
15
17
  import express from 'express';
16
18
  import { createInterface } from 'readline/promises';
17
19
  import open from 'open';
18
- import chalk3 from 'chalk';
19
20
  import ora from 'ora';
20
21
  import pkceChallenge from 'pkce-challenge';
21
22
  import { startMcpServer } from '@zapier/zapier-sdk-mcp';
@@ -26,7 +27,6 @@ import 'is-installed-globally';
26
27
  import { execSync, spawn } from 'child_process';
27
28
  import Handlebars from 'handlebars';
28
29
  import { fileURLToPath } from 'url';
29
- import { makeTheme, createPrompt, useState, usePrefix, useMemo, useEffect, useKeypress, isEnterKey, isTabKey, isUpKey, isDownKey, usePagination, Separator } from '@inquirer/core';
30
30
  import packageJsonLib, { VersionNotFoundError } from 'package-json';
31
31
  import semver from 'semver';
32
32
  import crossSpawn from 'cross-spawn';
@@ -365,6 +365,10 @@ function getActiveCredentials(options) {
365
365
  if (!name) return void 0;
366
366
  return findEntry(readRegistry(), name, normalizeBaseUrl(options?.baseUrl));
367
367
  }
368
+ function listStoredCredentials(options) {
369
+ const baseUrl = normalizeBaseUrl(options?.baseUrl);
370
+ return readRegistry().filter((entry) => entry.baseUrl === baseUrl).sort((left, right) => right.createdAt - left.createdAt);
371
+ }
368
372
  var MAX_CREDENTIAL_NAME_ATTEMPTS = 500;
369
373
  function firstAvailableCredentialName({
370
374
  baseName,
@@ -469,6 +473,29 @@ async function getStoredClientCredentials(options) {
469
473
  scope: [...entry.scopes].sort().join(" ")
470
474
  };
471
475
  }
476
+ async function activateStoredCredentials({
477
+ name,
478
+ baseUrl
479
+ }) {
480
+ const resolvedBaseUrl = normalizeBaseUrl(baseUrl);
481
+ const entry = findEntry(readRegistry(), name, resolvedBaseUrl);
482
+ if (!entry) {
483
+ throw new ZapierCliValidationError(
484
+ `No stored credentials named "${name}" were found.`
485
+ );
486
+ }
487
+ const credentials = await getStoredClientCredentials({
488
+ name,
489
+ baseUrl: resolvedBaseUrl
490
+ });
491
+ if (!credentials) {
492
+ throw new ZapierCliValidationError(
493
+ `Stored credentials "${name}" are missing from the system keychain. Add a new account to recreate them.`
494
+ );
495
+ }
496
+ getConfig().set(CREDENTIALS_KEY, name);
497
+ return entry;
498
+ }
472
499
  function deleteRegistryEntry(registry, name, baseUrl) {
473
500
  const idx = registry.findIndex(
474
501
  (e) => e.name === name && e.baseUrl === baseUrl
@@ -1060,6 +1087,362 @@ async function setupClientCredentials({
1060
1087
  }
1061
1088
  return { clientId };
1062
1089
  }
1090
+ function isSelectable(item) {
1091
+ return !Separator.isSeparator(item) && !item.disabled;
1092
+ }
1093
+ function normalizeChoices(choices) {
1094
+ return choices.map((choice) => {
1095
+ if (Separator.isSeparator(choice)) return choice;
1096
+ const name = choice.name ?? String(choice.value);
1097
+ return {
1098
+ value: choice.value,
1099
+ name,
1100
+ short: choice.short ?? name,
1101
+ disabled: choice.disabled ?? false
1102
+ };
1103
+ });
1104
+ }
1105
+ var theme = makeTheme({
1106
+ icon: { cursor: "\u276F" },
1107
+ style: {
1108
+ disabled: (text) => chalk5.dim(`- ${text}`),
1109
+ searchTerm: (text) => chalk5.cyan(text),
1110
+ keysHelpTip: (keys) => keys.map(([key, action]) => `${chalk5.bold(key)} ${chalk5.dim(action)}`).join(chalk5.dim(" \u2022 "))
1111
+ }
1112
+ });
1113
+ var searchSelect = createPrompt(
1114
+ (config2, done) => {
1115
+ const { pageSize = 7 } = config2;
1116
+ const [status, setStatus] = useState(
1117
+ "loading"
1118
+ );
1119
+ const [searchTerm, setSearchTerm] = useState("");
1120
+ const [searchResults, setSearchResults] = useState([]);
1121
+ const [searchError, setSearchError] = useState();
1122
+ const prefix = usePrefix({ status, theme });
1123
+ const bounds = useMemo(() => {
1124
+ const first = searchResults.findIndex(isSelectable);
1125
+ let last = -1;
1126
+ for (let i = searchResults.length - 1; i >= 0; i--) {
1127
+ if (isSelectable(searchResults[i])) {
1128
+ last = i;
1129
+ break;
1130
+ }
1131
+ }
1132
+ return { first, last };
1133
+ }, [searchResults]);
1134
+ const defaultActive = useMemo(() => {
1135
+ const requested = searchTerm === "" ? config2.initialActive : config2.initialActiveForTerm?.({ term: searchTerm });
1136
+ if (requested !== void 0 && requested >= 0 && requested < searchResults.length && isSelectable(searchResults[requested])) {
1137
+ return requested;
1138
+ }
1139
+ return bounds.first;
1140
+ }, [searchResults, searchTerm, bounds.first]);
1141
+ const [active = defaultActive, setActive] = useState();
1142
+ useEffect(() => {
1143
+ const controller = new AbortController();
1144
+ setStatus("loading");
1145
+ setSearchError(void 0);
1146
+ const fetchResults = async () => {
1147
+ try {
1148
+ const results = await config2.source(searchTerm || void 0);
1149
+ if (!controller.signal.aborted) {
1150
+ setActive(void 0);
1151
+ setSearchError(void 0);
1152
+ setSearchResults(normalizeChoices(results));
1153
+ setStatus("idle");
1154
+ }
1155
+ } catch (error2) {
1156
+ if (!controller.signal.aborted && error2 instanceof Error) {
1157
+ setSearchError(error2.message);
1158
+ }
1159
+ }
1160
+ };
1161
+ void fetchResults();
1162
+ return () => {
1163
+ controller.abort();
1164
+ };
1165
+ }, [searchTerm]);
1166
+ const selectedChoice = searchResults[active];
1167
+ useKeypress((key, rl) => {
1168
+ if (isEnterKey(key)) {
1169
+ if (selectedChoice && isSelectable(selectedChoice)) {
1170
+ setStatus("done");
1171
+ done(selectedChoice.value);
1172
+ } else {
1173
+ rl.write(searchTerm);
1174
+ }
1175
+ } else if (isTabKey(key) && selectedChoice && isSelectable(selectedChoice)) {
1176
+ rl.clearLine(0);
1177
+ rl.write(selectedChoice.name);
1178
+ setSearchTerm(selectedChoice.name);
1179
+ } else if (status !== "loading" && (isUpKey(key) || isDownKey(key))) {
1180
+ rl.clearLine(0);
1181
+ if (isUpKey(key) && active !== bounds.first || isDownKey(key) && active !== bounds.last) {
1182
+ const offset = isUpKey(key) ? -1 : 1;
1183
+ let next = active;
1184
+ do {
1185
+ next = (next + offset + searchResults.length) % searchResults.length;
1186
+ } while (!isSelectable(searchResults[next]));
1187
+ setActive(next);
1188
+ }
1189
+ } else {
1190
+ setSearchTerm(rl.line);
1191
+ }
1192
+ });
1193
+ const page = usePagination({
1194
+ items: searchResults,
1195
+ active,
1196
+ renderItem({ item, isActive }) {
1197
+ if (Separator.isSeparator(item)) {
1198
+ return ` ${item.separator}`;
1199
+ }
1200
+ if (item.disabled) {
1201
+ const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
1202
+ return theme.style.disabled(`${item.name} ${disabledLabel}`);
1203
+ }
1204
+ const color = isActive ? theme.style.highlight : (x) => x;
1205
+ const cursor = isActive ? theme.icon.cursor : ` `;
1206
+ return color(`${cursor} ${item.name}`);
1207
+ },
1208
+ pageSize,
1209
+ loop: false
1210
+ });
1211
+ const message = theme.style.message(config2.message, status);
1212
+ if (status === "done" && selectedChoice && isSelectable(selectedChoice)) {
1213
+ return [prefix, message, theme.style.answer(selectedChoice.short)].filter(Boolean).join(" ").trimEnd();
1214
+ }
1215
+ const searchStr = theme.style.searchTerm(searchTerm);
1216
+ const helpTip = theme.style.keysHelpTip([
1217
+ ["\u2191\u2193", "navigate"],
1218
+ ["\u23CE", "select"]
1219
+ ]);
1220
+ let error;
1221
+ if (searchError) {
1222
+ error = theme.style.error(searchError);
1223
+ } else if (searchResults.length === 0 && searchTerm !== "" && status === "idle") {
1224
+ error = theme.style.error("No results found");
1225
+ }
1226
+ const header = [prefix, message, searchStr].filter(Boolean).join(" ").trimEnd();
1227
+ const body = [error ?? page, " ", helpTip].filter(Boolean).join("\n").trimEnd();
1228
+ return [header, body];
1229
+ }
1230
+ );
1231
+
1232
+ // src/utils/auth/credentials-picker.ts
1233
+ function isSameCredentials(left, right) {
1234
+ return left.name === right.name && left.baseUrl === right.baseUrl;
1235
+ }
1236
+ function createdAtIso(credentials) {
1237
+ return new Date(credentials.createdAt).toISOString();
1238
+ }
1239
+ function searchableFields(credentials) {
1240
+ return [
1241
+ { text: credentials.name.toLowerCase(), weight: 0 },
1242
+ { text: credentials.clientId.toLowerCase(), weight: 1e3 },
1243
+ ...credentials.scopes.map((scope) => ({
1244
+ text: scope.toLowerCase(),
1245
+ weight: 2e3
1246
+ })),
1247
+ {
1248
+ text: createdAtIso(credentials).slice(0, 10).toLowerCase(),
1249
+ weight: 3e3
1250
+ }
1251
+ ];
1252
+ }
1253
+ function textMatchScore(text, query) {
1254
+ if (text === query) return 0;
1255
+ if (text.startsWith(query)) return 100 + text.length - query.length;
1256
+ const index = text.indexOf(query);
1257
+ if (index === -1) return void 0;
1258
+ return 200 + text.length - query.length;
1259
+ }
1260
+ function closestFieldScore(fields, query) {
1261
+ let closest;
1262
+ for (const field of fields) {
1263
+ const textScore = textMatchScore(field.text, query);
1264
+ if (textScore === void 0) continue;
1265
+ const score = field.weight + textScore;
1266
+ closest = closest === void 0 ? score : Math.min(closest, score);
1267
+ }
1268
+ return closest;
1269
+ }
1270
+ function searchScore(credentials, term) {
1271
+ const query = term.trim().toLowerCase();
1272
+ const tokens = query.split(/\s+/).filter(Boolean);
1273
+ const fields = searchableFields(credentials);
1274
+ let tokenScore = 0;
1275
+ for (const token of tokens) {
1276
+ const score = closestFieldScore(fields, token);
1277
+ if (score === void 0) return void 0;
1278
+ tokenScore += score;
1279
+ }
1280
+ const phraseScore = closestFieldScore(fields, query);
1281
+ return phraseScore === void 0 ? 1e4 + tokenScore : phraseScore;
1282
+ }
1283
+ function formatCredentialsChoice({
1284
+ credentials,
1285
+ current
1286
+ }) {
1287
+ const currentLabel = current ? chalk5.cyan(" (current)") : "";
1288
+ const details = [
1289
+ credentials.clientId,
1290
+ credentials.scopes.join(", "),
1291
+ `created ${createdAtIso(credentials).slice(0, 10)}`
1292
+ ].join(" \xB7 ");
1293
+ return {
1294
+ name: `${credentials.name}${currentLabel} ${chalk5.dim(`\xB7 ${details}`)}`,
1295
+ short: credentials.name,
1296
+ value: { action: "switch", credentials }
1297
+ };
1298
+ }
1299
+ function buildCredentialsChoices({
1300
+ credentials,
1301
+ activeCredentials,
1302
+ term = ""
1303
+ }) {
1304
+ const sortedCredentials = [...credentials].sort(
1305
+ (left, right) => right.createdAt - left.createdAt
1306
+ );
1307
+ const current = activeCredentials ? sortedCredentials.find(
1308
+ (entry) => isSameCredentials(entry, activeCredentials)
1309
+ ) : void 0;
1310
+ const rankedCredentials = term ? sortedCredentials.map((credentials2) => ({
1311
+ credentials: credentials2,
1312
+ score: searchScore(credentials2, term)
1313
+ })).filter(
1314
+ (result) => result.score !== void 0
1315
+ ).sort((left, right) => left.score - right.score).map(({ credentials: credentials2 }) => credentials2) : [
1316
+ ...current ? [current] : [],
1317
+ ...sortedCredentials.filter((credentials2) => credentials2 !== current)
1318
+ ];
1319
+ return [
1320
+ {
1321
+ name: "+ Add a new account",
1322
+ short: "Add a new account",
1323
+ value: { action: "create" }
1324
+ },
1325
+ ...rankedCredentials.map(
1326
+ (credentials2) => formatCredentialsChoice({
1327
+ credentials: credentials2,
1328
+ current: credentials2 === current
1329
+ })
1330
+ )
1331
+ ];
1332
+ }
1333
+ async function promptForCredentials({
1334
+ credentials,
1335
+ activeCredentials
1336
+ }) {
1337
+ return searchSelect({
1338
+ message: "Select credentials or add a new account:",
1339
+ source: (term) => buildCredentialsChoices({
1340
+ credentials,
1341
+ activeCredentials,
1342
+ term
1343
+ }),
1344
+ initialActive: credentials.length > 0 ? 1 : 0,
1345
+ initialActiveForTerm: () => 1
1346
+ });
1347
+ }
1348
+
1349
+ // src/utils/auth/stored-login-credentials.ts
1350
+ function authFlowOnlyOptions(options) {
1351
+ return [
1352
+ ...options.timeout === void 0 ? [] : ["--timeout"],
1353
+ ...options.useApprovals === true ? ["--use-approvals"] : [],
1354
+ ...options.headless === true ? ["--headless"] : []
1355
+ ];
1356
+ }
1357
+ function assertCanSwitchCredentials({
1358
+ credentials,
1359
+ options,
1360
+ resolvedCredentials
1361
+ }) {
1362
+ if (resolvedCredentials !== void 0) {
1363
+ throw new ZapierCliValidationError(
1364
+ "Cannot switch stored credentials while credentials are configured through SDK options or environment variables. Remove those credentials before switching accounts."
1365
+ );
1366
+ }
1367
+ const incompatibleOptions = authFlowOnlyOptions(options);
1368
+ if (incompatibleOptions.length === 0) return;
1369
+ throw new ZapierCliValidationError(
1370
+ `Cannot switch to stored credentials "${credentials.name}" while using ${incompatibleOptions.join(
1371
+ ", "
1372
+ )}. These options only apply when logging in to a new account.`
1373
+ );
1374
+ }
1375
+ function findStoredCredentialsByName({
1376
+ name,
1377
+ baseUrl
1378
+ }) {
1379
+ return listStoredCredentials({ baseUrl }).find(
1380
+ (credentials) => credentials.name === name
1381
+ );
1382
+ }
1383
+ async function switchCredentials({
1384
+ credentials,
1385
+ options,
1386
+ resolvedCredentials
1387
+ }) {
1388
+ assertCanSwitchCredentials({ credentials, options, resolvedCredentials });
1389
+ await activateStoredCredentials({
1390
+ name: credentials.name,
1391
+ baseUrl: credentials.baseUrl
1392
+ });
1393
+ process.stderr.write(
1394
+ `\u2705 Credentials "${credentials.name}" are now active.
1395
+ `
1396
+ );
1397
+ }
1398
+ async function chooseStoredLoginCredentialsAtBaseUrl({
1399
+ baseUrl,
1400
+ options,
1401
+ resolvedCredentials
1402
+ }) {
1403
+ if (resolvedCredentials !== void 0 || authFlowOnlyOptions(options).length > 0) {
1404
+ return "none";
1405
+ }
1406
+ const storedCredentials = listStoredCredentials({ baseUrl });
1407
+ if (storedCredentials.length === 0) return "none";
1408
+ const selection = await promptForCredentials({
1409
+ credentials: storedCredentials,
1410
+ activeCredentials: getActiveCredentials({ baseUrl })
1411
+ });
1412
+ if (selection.action === "create") return "create";
1413
+ await switchCredentials({
1414
+ credentials: selection.credentials,
1415
+ options,
1416
+ resolvedCredentials
1417
+ });
1418
+ return "switch";
1419
+ }
1420
+ async function chooseStoredLoginCredentials({
1421
+ imports,
1422
+ options
1423
+ }) {
1424
+ const resolvedCredentials = await imports.resolveCredentials();
1425
+ const credentialsBaseUrl = await resolveCredentialsBaseUrl({
1426
+ options: imports.sdkOptions,
1427
+ resolvedCredentials
1428
+ });
1429
+ return chooseStoredLoginCredentialsAtBaseUrl({
1430
+ baseUrl: credentialsBaseUrl,
1431
+ options,
1432
+ resolvedCredentials
1433
+ });
1434
+ }
1435
+ async function confirmNewCredentialsName(name) {
1436
+ const { confirmed } = await inquirer4.prompt([
1437
+ {
1438
+ type: "confirm",
1439
+ name: "confirmed",
1440
+ default: false,
1441
+ message: `No stored credentials named "${name}" were found. Continue with a new account and save it as "${name}"?`
1442
+ }
1443
+ ]);
1444
+ return confirmed;
1445
+ }
1063
1446
 
1064
1447
  // src/utils/constants.ts
1065
1448
  var LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
@@ -1084,20 +1467,20 @@ var getCallablePromise = () => {
1084
1467
  var getCallablePromise_default = getCallablePromise;
1085
1468
  var log = {
1086
1469
  info: (message, ...args) => {
1087
- console.error(chalk3.blue("\u2139"), message, ...args);
1470
+ console.error(chalk5.blue("\u2139"), message, ...args);
1088
1471
  },
1089
1472
  error: (message, ...args) => {
1090
- console.error(chalk3.red("\u2716"), message, ...args);
1473
+ console.error(chalk5.red("\u2716"), message, ...args);
1091
1474
  },
1092
1475
  success: (message, ...args) => {
1093
- console.error(chalk3.green("\u2713"), message, ...args);
1476
+ console.error(chalk5.green("\u2713"), message, ...args);
1094
1477
  },
1095
1478
  warn: (message, ...args) => {
1096
- console.error(chalk3.yellow("\u26A0"), message, ...args);
1479
+ console.error(chalk5.yellow("\u26A0"), message, ...args);
1097
1480
  },
1098
1481
  debug: (message, ...args) => {
1099
1482
  if (process.env.DEBUG === "true" || process.argv.includes("--debug")) {
1100
- console.error(chalk3.gray("\u{1F41B}"), message, ...args);
1483
+ console.error(chalk5.gray("\u{1F41B}"), message, ...args);
1101
1484
  }
1102
1485
  }
1103
1486
  };
@@ -1944,9 +2327,6 @@ var HEADLESS_SIGNUP_RECOVERY_MESSAGE = "Restart `zapier-sdk signup --headless` t
1944
2327
  function getEntryPointLabel(entryPoint) {
1945
2328
  return entryPoint === "signup" ? "Signup" : "Login";
1946
2329
  }
1947
- function getActiveCredentialsAction(entryPoint) {
1948
- return entryPoint === "signup" ? "continue signup" : "log in again";
1949
- }
1950
2330
  function getCredentialsPromptMessage(entryPoint) {
1951
2331
  return entryPoint === "signup" ? "Enter a name to identify these credentials:" : "Enter a name to identify them:";
1952
2332
  }
@@ -1961,11 +2341,24 @@ function validateCredentialsName(name) {
1961
2341
  if (!trimmedName) throw new ZapierCliValidationError("Name cannot be empty");
1962
2342
  return trimmedName;
1963
2343
  }
2344
+ function validateNewCredentialsName({
2345
+ name,
2346
+ baseUrl
2347
+ }) {
2348
+ const validatedName = validateCredentialsName(name);
2349
+ if (credentialNameExists({ name: validatedName, baseUrl })) {
2350
+ throw new ZapierCliValidationError(
2351
+ `Credentials named "${validatedName}" already exist. Choose a different name.`
2352
+ );
2353
+ }
2354
+ return validatedName;
2355
+ }
1964
2356
  async function promptCredentialsName({
1965
2357
  email,
1966
- promptMessage
2358
+ promptMessage,
2359
+ baseUrl
1967
2360
  }) {
1968
- const { credentialName } = await inquirer3.prompt([
2361
+ const { credentialName } = await inquirer4.prompt([
1969
2362
  {
1970
2363
  type: "input",
1971
2364
  name: "credentialName",
@@ -1973,7 +2366,7 @@ async function promptCredentialsName({
1973
2366
  default: defaultCredentialsName(email),
1974
2367
  validate: (input) => {
1975
2368
  try {
1976
- validateCredentialsName(input);
2369
+ validateNewCredentialsName({ name: input, baseUrl });
1977
2370
  return true;
1978
2371
  } catch (err) {
1979
2372
  return err instanceof Error ? err.message : String(err);
@@ -1981,7 +2374,7 @@ async function promptCredentialsName({
1981
2374
  }
1982
2375
  }
1983
2376
  ]);
1984
- return validateCredentialsName(credentialName);
2377
+ return validateNewCredentialsName({ name: credentialName, baseUrl });
1985
2378
  }
1986
2379
  function resolveDefaultCredentialsName({
1987
2380
  email
@@ -1997,7 +2390,8 @@ async function resolveCredentialName({
1997
2390
  if (interactive) {
1998
2391
  return promptCredentialsName({
1999
2392
  email,
2000
- promptMessage: getCredentialsPromptMessage(entryPoint)
2393
+ promptMessage: getCredentialsPromptMessage(entryPoint),
2394
+ baseUrl
2001
2395
  });
2002
2396
  }
2003
2397
  const baseName = resolveDefaultCredentialsName({ email });
@@ -2028,7 +2422,7 @@ async function promptConfirm({
2028
2422
  message,
2029
2423
  defaultValue
2030
2424
  }) {
2031
- const { confirmed } = await inquirer3.prompt([
2425
+ const { confirmed } = await inquirer4.prompt([
2032
2426
  { type: "confirm", name: "confirmed", message, default: defaultValue }
2033
2427
  ]);
2034
2428
  return confirmed;
@@ -2038,6 +2432,11 @@ function promptlessCredentialResetError(credentials) {
2038
2432
  `Already logged in as "${credentials.name}". Run \`logout\` first or use an interactive terminal to re-authenticate.`
2039
2433
  );
2040
2434
  }
2435
+ function unnamedNonInteractiveLoginError(credentials) {
2436
+ throw new ZapierCliValidationError(
2437
+ `Already logged in as "${credentials.name}". Provide \`--name\` to activate or create named credentials, or run \`logout\` first.`
2438
+ );
2439
+ }
2041
2440
  function promptlessLegacyJwtUpgradeError() {
2042
2441
  throw new ZapierCliValidationError(
2043
2442
  "Legacy JWT login detected. Run `logout` first or use an interactive terminal to migrate to client credentials."
@@ -2047,16 +2446,20 @@ async function clearExistingAuthState({
2047
2446
  imports,
2048
2447
  baseUrl,
2049
2448
  interactive,
2050
- entryPoint
2449
+ entryPoint,
2450
+ preserveExistingCredentials = false
2051
2451
  }) {
2052
2452
  const activeCredentials = getActiveCredentials({ baseUrl });
2053
2453
  const flowLabel = getEntryPointLabel(entryPoint);
2454
+ if (activeCredentials && (entryPoint === "login" || preserveExistingCredentials)) {
2455
+ return true;
2456
+ }
2054
2457
  if (activeCredentials) {
2055
2458
  const confirmed = interactive ? await promptConfirm({
2056
2459
  defaultValue: false,
2057
2460
  message: `You are already logged in as "${activeCredentials.name}".
2058
2461
  Logging out will delete these credentials and may interrupt other Zapier SDK or CLI sessions using them.
2059
- Log out and ${getActiveCredentialsAction(entryPoint)}?`
2462
+ Log out and continue signup?`
2060
2463
  }) : promptlessCredentialResetError(activeCredentials);
2061
2464
  if (!confirmed) {
2062
2465
  process.stderr.write(`${flowLabel} cancelled.
@@ -2271,12 +2674,14 @@ async function provisionAccountCredentials({
2271
2674
  async function runAccountAuth({
2272
2675
  imports,
2273
2676
  options,
2274
- entryPoint
2677
+ entryPoint,
2678
+ storedCredentialsMode = "choose",
2679
+ preserveExistingCredentials = false
2275
2680
  }) {
2276
2681
  if (options.callbackUrl !== void 0) {
2277
2682
  const { callbackUrl } = options;
2278
2683
  const pending = getPendingOauthFlow({ entryPoint });
2279
- const finishName = options.name !== void 0 ? validateCredentialsName(options.name) : void 0;
2684
+ const finishName = options.name === void 0 ? void 0 : validateCredentialsName(options.name);
2280
2685
  if (finishName !== void 0 && finishName !== pending.credentialName) {
2281
2686
  throw new ZapierCliValidationError(
2282
2687
  "Cannot change --name while completing a pending OAuth flow. Start a new non-interactive login with the desired --name."
@@ -2336,7 +2741,6 @@ async function runAccountAuth({
2336
2741
  });
2337
2742
  return;
2338
2743
  }
2339
- const timeoutSeconds = parseTimeoutSeconds(options.timeout);
2340
2744
  const interactive = !resolveNonInteractive(options);
2341
2745
  const resolvedCredentials = await imports.resolveCredentials();
2342
2746
  const pkceCredentials = toPkceCredentials(resolvedCredentials);
@@ -2345,8 +2749,34 @@ async function runAccountAuth({
2345
2749
  options: imports.sdkOptions,
2346
2750
  resolvedCredentials
2347
2751
  });
2348
- const providedName = options.name !== void 0 ? validateCredentialsName(options.name) : void 0;
2349
- if (providedName !== void 0) {
2752
+ const providedName = options.name === void 0 ? void 0 : validateCredentialsName(options.name);
2753
+ if (entryPoint === "login") {
2754
+ if (providedName !== void 0) {
2755
+ const matchingCredentials = findStoredCredentialsByName({
2756
+ name: providedName,
2757
+ baseUrl: credentialsBaseUrl
2758
+ });
2759
+ if (matchingCredentials) {
2760
+ await switchCredentials({
2761
+ credentials: matchingCredentials,
2762
+ options,
2763
+ resolvedCredentials
2764
+ });
2765
+ return;
2766
+ }
2767
+ if (interactive && !await confirmNewCredentialsName(providedName)) {
2768
+ process.stderr.write("Login cancelled.\n");
2769
+ return;
2770
+ }
2771
+ } else if (interactive && storedCredentialsMode === "choose") {
2772
+ const selection = await chooseStoredLoginCredentialsAtBaseUrl({
2773
+ baseUrl: credentialsBaseUrl,
2774
+ options,
2775
+ resolvedCredentials
2776
+ });
2777
+ if (selection === "switch") return;
2778
+ }
2779
+ } else if (providedName !== void 0) {
2350
2780
  const activeCredentials = getActiveCredentials({
2351
2781
  baseUrl: credentialsBaseUrl
2352
2782
  });
@@ -2356,14 +2786,22 @@ async function runAccountAuth({
2356
2786
  );
2357
2787
  }
2358
2788
  }
2789
+ if (entryPoint === "login" && !interactive && providedName === void 0) {
2790
+ const activeCredentials = getActiveCredentials({
2791
+ baseUrl: credentialsBaseUrl
2792
+ });
2793
+ if (activeCredentials) unnamedNonInteractiveLoginError(activeCredentials);
2794
+ }
2359
2795
  if (!await clearExistingAuthState({
2360
2796
  imports,
2361
2797
  baseUrl: credentialsBaseUrl,
2362
2798
  interactive,
2363
- entryPoint
2799
+ entryPoint,
2800
+ preserveExistingCredentials
2364
2801
  })) {
2365
2802
  return;
2366
2803
  }
2804
+ const timeoutSeconds = parseTimeoutSeconds(options.timeout);
2367
2805
  const useApprovals = options.useApprovals === true;
2368
2806
  if (!interactive) {
2369
2807
  await startPendingOauthFlow({
@@ -2400,7 +2838,7 @@ async function runAccountAuth({
2400
2838
  }
2401
2839
  var LoginSchema = z.object({
2402
2840
  name: z.string().optional().describe(
2403
- "Name to identify these credentials (defaults to <email>@<hostname>). Provide this to set a custom name without the interactive prompt."
2841
+ "Activate stored credentials with this name. If none exist, create new credentials with this name; interactive login asks for confirmation first."
2404
2842
  ),
2405
2843
  timeout: z.string().optional().describe("Login timeout in seconds (default: 300)"),
2406
2844
  useApprovals: z.boolean().optional().describe(
@@ -4201,7 +4639,7 @@ async function promptYesNo({
4201
4639
  nonInteractive
4202
4640
  }) {
4203
4641
  if (nonInteractive) return defaultValue;
4204
- const { answer } = await inquirer3.prompt([
4642
+ const { answer } = await inquirer4.prompt([
4205
4643
  { type: "confirm", name: "answer", message, default: defaultValue }
4206
4644
  ]);
4207
4645
  return answer;
@@ -4248,7 +4686,7 @@ function buildTemplateVariables({
4248
4686
  };
4249
4687
  }
4250
4688
  function cleanupProject({ projectDir }) {
4251
- console.log("\n" + chalk3.yellow("!") + " Cleaning up...");
4689
+ console.log("\n" + chalk5.yellow("!") + " Cleaning up...");
4252
4690
  rmSync(projectDir, { recursive: true, force: true });
4253
4691
  }
4254
4692
  async function withInterruptCleanup(cleanup, fn) {
@@ -4458,8 +4896,8 @@ function buildNextSteps({
4458
4896
  }
4459
4897
  function createConsoleDisplayHooks() {
4460
4898
  return {
4461
- onItemComplete: (message) => console.log(" " + chalk3.green("\u2713") + " " + chalk3.dim(message)),
4462
- onWarn: (message) => console.warn(chalk3.yellow("!") + " " + message),
4899
+ onItemComplete: (message) => console.log(" " + chalk5.green("\u2713") + " " + chalk5.dim(message)),
4900
+ onWarn: (message) => console.warn(chalk5.yellow("!") + " " + message),
4463
4901
  onStepStart: ({
4464
4902
  description,
4465
4903
  stepNumber,
@@ -4468,31 +4906,31 @@ function createConsoleDisplayHooks() {
4468
4906
  nonInteractive
4469
4907
  }) => {
4470
4908
  const progressMessage = `${description}...`;
4471
- const stepCounter = chalk3.dim(`${stepNumber}/${totalSteps}`);
4909
+ const stepCounter = chalk5.dim(`${stepNumber}/${totalSteps}`);
4472
4910
  if (nonInteractive) {
4473
4911
  console.log(
4474
- "\n" + chalk3.bold(`\u276F ${progressMessage}`) + " " + stepCounter + "\n"
4912
+ "\n" + chalk5.bold(`\u276F ${progressMessage}`) + " " + stepCounter + "\n"
4475
4913
  );
4476
4914
  } else {
4477
4915
  console.log(
4478
- chalk3.dim("\u2192") + " " + progressMessage + " " + stepCounter
4916
+ chalk5.dim("\u2192") + " " + progressMessage + " " + stepCounter
4479
4917
  );
4480
4918
  }
4481
4919
  if (command) {
4482
- console.log(" " + chalk3.cyan(`$ ${command}`));
4920
+ console.log(" " + chalk5.cyan(`$ ${command}`));
4483
4921
  }
4484
4922
  },
4485
4923
  onStepSuccess: ({ stepNumber, totalSteps }) => console.log(
4486
- "\n" + chalk3.green("\u2713") + " " + chalk3.dim(`Step ${stepNumber}/${totalSteps} complete`) + "\n"
4924
+ "\n" + chalk5.green("\u2713") + " " + chalk5.dim(`Step ${stepNumber}/${totalSteps} complete`) + "\n"
4487
4925
  ),
4488
4926
  onStepError: ({ description, command, err }) => {
4489
4927
  const detail = err instanceof Error && err.message ? `
4490
- ${chalk3.dim(err.message)}` : "";
4928
+ ${chalk5.dim(err.message)}` : "";
4491
4929
  const hint = command ? `
4492
- ${chalk3.dim("run manually:")} ${chalk3.cyan(`$ ${command}`)}` : "";
4930
+ ${chalk5.dim("run manually:")} ${chalk5.cyan(`$ ${command}`)}` : "";
4493
4931
  console.error(
4494
4932
  `
4495
- ${chalk3.red("\u2716")} ${chalk3.bold(description)}${chalk3.dim(" failed")}${detail}${hint}`
4933
+ ${chalk5.red("\u2716")} ${chalk5.bold(description)}${chalk5.dim(" failed")}${detail}${hint}`
4496
4934
  );
4497
4935
  }
4498
4936
  };
@@ -4504,22 +4942,22 @@ function displaySummaryAndNextSteps({
4504
4942
  packageManager
4505
4943
  }) {
4506
4944
  const formatStatus = (complete) => ({
4507
- icon: complete ? chalk3.green("\u2713") : chalk3.yellow("!"),
4508
- text: complete ? chalk3.green("Setup complete") : chalk3.yellow("Setup interrupted")
4945
+ icon: complete ? chalk5.green("\u2713") : chalk5.yellow("!"),
4946
+ text: complete ? chalk5.green("Setup complete") : chalk5.yellow("Setup interrupted")
4509
4947
  });
4510
- const formatNextStep = (step, i) => " " + chalk3.dim(`${i + 1}.`) + " " + chalk3.bold(step.description);
4511
- const formatCommand = (cmd) => " " + chalk3.cyan(`$ ${cmd}`);
4512
- const formatCompletedStep = (step) => " " + chalk3.green("\u2713") + " " + step.description;
4948
+ const formatNextStep = (step, i) => " " + chalk5.dim(`${i + 1}.`) + " " + chalk5.bold(step.description);
4949
+ const formatCommand = (cmd) => " " + chalk5.cyan(`$ ${cmd}`);
4950
+ const formatCompletedStep = (step) => " " + chalk5.green("\u2713") + " " + step.description;
4513
4951
  const { execCmd } = getPackageManagerCommands({ packageManager });
4514
4952
  const leftoverSteps = steps.filter(
4515
4953
  (s) => !completedSetupStepIds.includes(s.id)
4516
4954
  );
4517
4955
  const isComplete = leftoverSteps.length === 0;
4518
4956
  const status = formatStatus(isComplete);
4519
- console.log("\n" + chalk3.bold("\u276F Summary") + "\n");
4520
- console.log(" " + chalk3.dim("Project") + " " + chalk3.bold(projectName));
4957
+ console.log("\n" + chalk5.bold("\u276F Summary") + "\n");
4958
+ console.log(" " + chalk5.dim("Project") + " " + chalk5.bold(projectName));
4521
4959
  console.log(
4522
- " " + chalk3.dim("Status") + " " + status.icon + " " + status.text
4960
+ " " + chalk5.dim("Status") + " " + status.icon + " " + status.text
4523
4961
  );
4524
4962
  const completedSteps = steps.filter(
4525
4963
  (s) => completedSetupStepIds.includes(s.id)
@@ -4529,7 +4967,7 @@ function displaySummaryAndNextSteps({
4529
4967
  for (const step of completedSteps) console.log(formatCompletedStep(step));
4530
4968
  }
4531
4969
  const nextSteps = buildNextSteps({ projectName, leftoverSteps, execCmd });
4532
- console.log("\n" + chalk3.bold("\u276F Next Steps") + "\n");
4970
+ console.log("\n" + chalk5.bold("\u276F Next Steps") + "\n");
4533
4971
  nextSteps.forEach((step, i) => {
4534
4972
  console.log(formatNextStep(step, i));
4535
4973
  if (step.command) console.log(formatCommand(step.command));
@@ -4592,149 +5030,6 @@ var initPlugin = defineMethod({
4592
5030
  });
4593
5031
  }
4594
5032
  });
4595
- function isSelectable(item) {
4596
- return !Separator.isSeparator(item) && !item.disabled;
4597
- }
4598
- function normalizeChoices(choices) {
4599
- return choices.map((choice) => {
4600
- if (Separator.isSeparator(choice)) return choice;
4601
- const name = choice.name ?? String(choice.value);
4602
- return {
4603
- value: choice.value,
4604
- name,
4605
- short: choice.short ?? name,
4606
- disabled: choice.disabled ?? false
4607
- };
4608
- });
4609
- }
4610
- var theme = makeTheme({
4611
- icon: { cursor: "\u276F" },
4612
- style: {
4613
- disabled: (text) => chalk3.dim(`- ${text}`),
4614
- searchTerm: (text) => chalk3.cyan(text),
4615
- keysHelpTip: (keys) => keys.map(([key, action]) => `${chalk3.bold(key)} ${chalk3.dim(action)}`).join(chalk3.dim(" \u2022 "))
4616
- }
4617
- });
4618
- var searchSelect = createPrompt(
4619
- (config2, done) => {
4620
- const { pageSize = 7 } = config2;
4621
- const [status, setStatus] = useState(
4622
- "loading"
4623
- );
4624
- const [searchTerm, setSearchTerm] = useState("");
4625
- const [searchResults, setSearchResults] = useState([]);
4626
- const [searchError, setSearchError] = useState();
4627
- const prefix = usePrefix({ status, theme });
4628
- const bounds = useMemo(() => {
4629
- const first = searchResults.findIndex(isSelectable);
4630
- let last = -1;
4631
- for (let i = searchResults.length - 1; i >= 0; i--) {
4632
- if (isSelectable(searchResults[i])) {
4633
- last = i;
4634
- break;
4635
- }
4636
- }
4637
- return { first, last };
4638
- }, [searchResults]);
4639
- const defaultActive = useMemo(() => {
4640
- const requested = config2.initialActive;
4641
- if (searchTerm === "" && requested !== void 0 && requested >= 0 && requested < searchResults.length && isSelectable(searchResults[requested])) {
4642
- return requested;
4643
- }
4644
- return bounds.first;
4645
- }, [searchResults, searchTerm, bounds.first]);
4646
- const [active = defaultActive, setActive] = useState();
4647
- useEffect(() => {
4648
- const controller = new AbortController();
4649
- setStatus("loading");
4650
- setSearchError(void 0);
4651
- const fetchResults = async () => {
4652
- try {
4653
- const results = await config2.source(searchTerm || void 0);
4654
- if (!controller.signal.aborted) {
4655
- setActive(void 0);
4656
- setSearchError(void 0);
4657
- setSearchResults(normalizeChoices(results));
4658
- setStatus("idle");
4659
- }
4660
- } catch (error2) {
4661
- if (!controller.signal.aborted && error2 instanceof Error) {
4662
- setSearchError(error2.message);
4663
- }
4664
- }
4665
- };
4666
- void fetchResults();
4667
- return () => {
4668
- controller.abort();
4669
- };
4670
- }, [searchTerm]);
4671
- const selectedChoice = searchResults[active];
4672
- useKeypress((key, rl) => {
4673
- if (isEnterKey(key)) {
4674
- if (selectedChoice && isSelectable(selectedChoice)) {
4675
- setStatus("done");
4676
- done(selectedChoice.value);
4677
- } else {
4678
- rl.write(searchTerm);
4679
- }
4680
- } else if (isTabKey(key) && selectedChoice && isSelectable(selectedChoice)) {
4681
- rl.clearLine(0);
4682
- rl.write(selectedChoice.name);
4683
- setSearchTerm(selectedChoice.name);
4684
- } else if (status !== "loading" && (isUpKey(key) || isDownKey(key))) {
4685
- rl.clearLine(0);
4686
- if (isUpKey(key) && active !== bounds.first || isDownKey(key) && active !== bounds.last) {
4687
- const offset = isUpKey(key) ? -1 : 1;
4688
- let next = active;
4689
- do {
4690
- next = (next + offset + searchResults.length) % searchResults.length;
4691
- } while (!isSelectable(searchResults[next]));
4692
- setActive(next);
4693
- }
4694
- } else {
4695
- setSearchTerm(rl.line);
4696
- }
4697
- });
4698
- const page = usePagination({
4699
- items: searchResults,
4700
- active,
4701
- renderItem({ item, isActive }) {
4702
- if (Separator.isSeparator(item)) {
4703
- return ` ${item.separator}`;
4704
- }
4705
- if (item.disabled) {
4706
- const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
4707
- return theme.style.disabled(`${item.name} ${disabledLabel}`);
4708
- }
4709
- const color = isActive ? theme.style.highlight : (x) => x;
4710
- const cursor = isActive ? theme.icon.cursor : ` `;
4711
- return color(`${cursor} ${item.name}`);
4712
- },
4713
- pageSize,
4714
- loop: false
4715
- });
4716
- const message = theme.style.message(config2.message, status);
4717
- if (status === "done" && selectedChoice && isSelectable(selectedChoice)) {
4718
- return [prefix, message, theme.style.answer(selectedChoice.short)].filter(Boolean).join(" ").trimEnd();
4719
- }
4720
- const searchStr = theme.style.searchTerm(searchTerm);
4721
- const helpTip = theme.style.keysHelpTip([
4722
- ["\u2191\u2193", "navigate"],
4723
- ["\u23CE", "select"]
4724
- ]);
4725
- let error;
4726
- if (searchError) {
4727
- error = theme.style.error(searchError);
4728
- } else if (searchResults.length === 0 && searchTerm !== "" && status === "idle") {
4729
- error = theme.style.error("No results found");
4730
- }
4731
- const header = [prefix, message, searchStr].filter(Boolean).join(" ").trimEnd();
4732
- const body = [error ?? page, " ", helpTip].filter(Boolean).join("\n").trimEnd();
4733
- return [header, body];
4734
- }
4735
- );
4736
-
4737
- // src/utils/controller-answer.ts
4738
5033
  function offers(question, action) {
4739
5034
  return question.actions.some((a) => a.action === action);
4740
5035
  }
@@ -4745,7 +5040,7 @@ async function promptText({
4745
5040
  message,
4746
5041
  password
4747
5042
  }) {
4748
- const { value } = await inquirer3.prompt([
5043
+ const { value } = await inquirer4.prompt([
4749
5044
  {
4750
5045
  type: password ? "password" : "input",
4751
5046
  name: "value",
@@ -4755,10 +5050,10 @@ async function promptText({
4755
5050
  ]);
4756
5051
  return value;
4757
5052
  }
4758
- var display = (c) => c.hint ? `${c.label} ${chalk3.dim(`(${c.hint})`)}` : c.label;
5053
+ var display = (c) => c.hint ? `${c.label} ${chalk5.dim(`(${c.hint})`)}` : c.label;
4759
5054
  var HIGH_CONTRAST_PROMPT_THEME = {
4760
5055
  style: {
4761
- answer: (text) => chalk3.inverse.bold(` ${text} `)
5056
+ answer: (text) => chalk5.inverse.bold(` ${text} `)
4762
5057
  }
4763
5058
  };
4764
5059
  function buildSelectRows(question, term) {
@@ -4774,8 +5069,8 @@ function buildSelectRows(question, term) {
4774
5069
  name: display(c),
4775
5070
  value: c.value
4776
5071
  }));
4777
- const skipRow = offers(question, "skip") ? [row(chalk3.dim("Skip (optional)"), "skip")] : [];
4778
- const customRow = offers(question, "custom") ? [row(chalk3.dim("Enter a value manually\u2026"), "custom")] : [];
5072
+ const skipRow = offers(question, "skip") ? [row(chalk5.dim("Skip (optional)"), "skip")] : [];
5073
+ const customRow = offers(question, "custom") ? [row(chalk5.dim("Enter a value manually\u2026"), "custom")] : [];
4779
5074
  const committed = !!t || question.search !== void 0;
4780
5075
  let rows;
4781
5076
  if (!committed) {
@@ -4786,13 +5081,13 @@ function buildSelectRows(question, term) {
4786
5081
  rows = [...customRow, ...skipRow];
4787
5082
  }
4788
5083
  if (offers(question, "search"))
4789
- rows.push(row(chalk3.cyan("Search again\u2026"), "search"));
5084
+ rows.push(row(chalk5.cyan("Search again\u2026"), "search"));
4790
5085
  if (offers(question, "next_page"))
4791
- rows.push(row(chalk3.dim("Load more\u2026"), "next_page"));
4792
- if (offers(question, "retry")) rows.push(row(chalk3.yellow("Retry"), "retry"));
4793
- if (offers(question, "cancel")) rows.push(row(chalk3.dim("Cancel"), "cancel"));
5086
+ rows.push(row(chalk5.dim("Load more\u2026"), "next_page"));
5087
+ if (offers(question, "retry")) rows.push(row(chalk5.yellow("Retry"), "retry"));
5088
+ if (offers(question, "cancel")) rows.push(row(chalk5.dim("Cancel"), "cancel"));
4794
5089
  for (const note of question.notes ?? [])
4795
- rows.push({ name: chalk3.dim(note), value: note, disabled: true });
5090
+ rows.push({ name: chalk5.dim(note), value: note, disabled: true });
4796
5091
  return rows;
4797
5092
  }
4798
5093
  function foldPage(acc, question, field) {
@@ -4833,7 +5128,7 @@ async function answerSelect(question, field, box, failed, mode) {
4833
5128
  const isClosedListPrompt = mode === "closed-list" && !failed && !view.multiple;
4834
5129
  const booleanValues = view.choices.map(({ value: value2 }) => value2);
4835
5130
  if (isClosedListPrompt && booleanValues.length === 2 && booleanValues.includes("true") && booleanValues.includes("false")) {
4836
- const { value: value2 } = await inquirer3.prompt([
5131
+ const { value: value2 } = await inquirer4.prompt([
4837
5132
  {
4838
5133
  type: "confirm",
4839
5134
  name: "value",
@@ -4849,7 +5144,7 @@ async function answerSelect(question, field, box, failed, mode) {
4849
5144
  name: display(choice),
4850
5145
  value: choice.value
4851
5146
  }));
4852
- const { value: value2 } = await inquirer3.prompt([
5147
+ const { value: value2 } = await inquirer4.prompt([
4853
5148
  {
4854
5149
  type: "list",
4855
5150
  name: "value",
@@ -4872,17 +5167,17 @@ async function answerSelect(question, field, box, failed, mode) {
4872
5167
  })),
4873
5168
  ...offers(question, "next_page") ? [
4874
5169
  {
4875
- name: chalk3.dim("Load more\u2026"),
5170
+ name: chalk5.dim("Load more\u2026"),
4876
5171
  value: { action: "next_page" }
4877
5172
  }
4878
5173
  ] : [],
4879
5174
  ...(question.notes ?? []).map((note) => ({
4880
- name: chalk3.dim(note),
5175
+ name: chalk5.dim(note),
4881
5176
  value: note,
4882
5177
  disabled: true
4883
5178
  }))
4884
5179
  ];
4885
- const { values } = await inquirer3.prompt([
5180
+ const { values } = await inquirer4.prompt([
4886
5181
  {
4887
5182
  type: "checkbox",
4888
5183
  name: "values",
@@ -4954,14 +5249,14 @@ async function answerSelect(question, field, box, failed, mode) {
4954
5249
  case "retry":
4955
5250
  return { type: "retry" };
4956
5251
  case "skip":
4957
- printAnswered(view.message, chalk3.dim("(skipped)"));
5252
+ printAnswered(view.message, chalk5.dim("(skipped)"));
4958
5253
  return { type: "skip" };
4959
5254
  case "cancel":
4960
5255
  return { type: "cancel" };
4961
5256
  }
4962
5257
  }
4963
5258
  function printAnswered(message, label) {
4964
- console.log(`${chalk3.green("\u2714")} ${message} ${chalk3.cyan(label)}`);
5259
+ console.log(`${chalk5.green("\u2714")} ${message} ${chalk5.cyan(label)}`);
4965
5260
  }
4966
5261
  async function answerInput(question) {
4967
5262
  const message = question.placeholder ? question.message.replace(/:?\s*$/, ` (${question.placeholder}):`) : question.message;
@@ -4979,7 +5274,7 @@ async function answerCollection(question) {
4979
5274
  return { type: "add" };
4980
5275
  }
4981
5276
  if (question.description) console.log(question.description);
4982
- const { again } = await inquirer3.prompt([
5277
+ const { again } = await inquirer4.prompt([
4983
5278
  {
4984
5279
  type: "confirm",
4985
5280
  name: "again",
@@ -4998,7 +5293,7 @@ function createCliAnswer({
4998
5293
  try {
4999
5294
  if (result.error !== void 0) {
5000
5295
  const message = typeof result.error === "string" ? result.error : result.error.message;
5001
- console.log(chalk3.yellow(`! ${message}`));
5296
+ console.log(chalk5.yellow(`! ${message}`));
5002
5297
  }
5003
5298
  const question = result.question;
5004
5299
  const field = question.path.length ? question.path.join(".") : "value";
@@ -5167,7 +5462,7 @@ var boltFillRanks = new Map(
5167
5462
  );
5168
5463
  var STATUS_ROW_INDEX = Math.floor(boltRows.length / 2);
5169
5464
  function formatPhase({ label, detail }) {
5170
- return detail ? `${chalk3.bold(label)} ${chalk3.dim(detail)}` : chalk3.bold(label);
5465
+ return detail ? `${chalk5.bold(label)} ${chalk5.dim(detail)}` : chalk5.bold(label);
5171
5466
  }
5172
5467
  function formatLoaderFrame({
5173
5468
  phase,
@@ -5179,7 +5474,7 @@ function formatLoaderFrame({
5179
5474
  const cellIndex = rowIndex * row.length + columnIndex;
5180
5475
  const fillRank = boltFillRanks.get(cellIndex);
5181
5476
  const isFilled = fillRank !== void 0 && fillRank < fillStage;
5182
- return isFilled ? chalk3.bold.yellow(cell) : chalk3.dim.yellow(cell);
5477
+ return isFilled ? chalk5.bold.yellow(cell) : chalk5.dim.yellow(cell);
5183
5478
  }).join("");
5184
5479
  const status = rowIndex === STATUS_ROW_INDEX ? ` ${formatPhase(phase)}` : "";
5185
5480
  return `${bolt}${status}`;
@@ -5211,12 +5506,12 @@ async function runWithSetupLoader({
5211
5506
  const result = await promise;
5212
5507
  clearInterval(animationTimer);
5213
5508
  const elapsedSeconds = ((Date.now() - startedAt) / 1e3).toFixed(1);
5214
- loader.succeed(`${formatPhase(phase)} ${chalk3.dim(`${elapsedSeconds}s`)}`);
5509
+ loader.succeed(`${formatPhase(phase)} ${chalk5.dim(`${elapsedSeconds}s`)}`);
5215
5510
  return result;
5216
5511
  } catch (error) {
5217
5512
  clearInterval(animationTimer);
5218
5513
  const elapsedSeconds = ((Date.now() - startedAt) / 1e3).toFixed(1);
5219
- loader.fail(`${formatPhase(phase)} ${chalk3.dim(`${elapsedSeconds}s`)}`);
5514
+ loader.fail(`${formatPhase(phase)} ${chalk5.dim(`${elapsedSeconds}s`)}`);
5220
5515
  throw error;
5221
5516
  }
5222
5517
  }
@@ -5707,7 +6002,7 @@ async function runCommand({
5707
6002
  detail: commandLabel
5708
6003
  });
5709
6004
  }
5710
- console.log(chalk3.dim(commandLabel));
6005
+ console.log(chalk5.dim(commandLabel));
5711
6006
  return await execute;
5712
6007
  } catch (error) {
5713
6008
  const message = error instanceof Error ? error.message : String(error);
@@ -5813,6 +6108,14 @@ function createWizardContext({
5813
6108
  imports,
5814
6109
  createAnswer: () => createCliAnswer({ mode: "closed-list" }),
5815
6110
  setupController: createSetupController(),
6111
+ selectStoredLoginCredentials: () => chooseStoredLoginCredentials({ imports, options: {} }),
6112
+ authenticateNewAccount: ({ entryPoint, headless }) => runAccountAuth({
6113
+ imports,
6114
+ options: { headless },
6115
+ entryPoint,
6116
+ storedCredentialsMode: "fresh",
6117
+ preserveExistingCredentials: true
6118
+ }),
5816
6119
  checkForUpdates,
5817
6120
  openUrl: async (url) => {
5818
6121
  await open(url);
@@ -5846,6 +6149,14 @@ function isCredentialWriteError(error) {
5846
6149
  const message = error instanceof Error ? error.message : String(error);
5847
6150
  return /permission|sandbox|eacces|eperm/i.test(message);
5848
6151
  }
6152
+ async function confirmAuthentication(context) {
6153
+ const { data: profile } = await runWithSetupLoader({
6154
+ promise: context.imports.getProfile({}),
6155
+ label: "Confirming Zapier account"
6156
+ });
6157
+ context.accountEmail = profile.email;
6158
+ console.log(`Authenticated as ${profile.email}.`);
6159
+ }
5849
6160
  async function authenticate(context) {
5850
6161
  const activeProfile = await runWithSetupLoader({
5851
6162
  promise: context.imports.getProfile({}).then(({ data }) => data).catch((error) => {
@@ -5854,7 +6165,12 @@ async function authenticate(context) {
5854
6165
  }),
5855
6166
  label: "Checking Zapier authentication"
5856
6167
  });
5857
- if (activeProfile) {
6168
+ const storedCredentialsSelection = await context.selectStoredLoginCredentials();
6169
+ if (storedCredentialsSelection === "switch") {
6170
+ await confirmAuthentication(context);
6171
+ return;
6172
+ }
6173
+ if (storedCredentialsSelection === "none" && activeProfile) {
5858
6174
  const shouldLogout = await resolveSetupConfirm({
5859
6175
  answer: context.createAnswer(),
5860
6176
  controller: context.setupController,
@@ -5895,10 +6211,14 @@ Log out and use a different account?`,
5895
6211
  ]
5896
6212
  });
5897
6213
  const headless = environment === "headless";
5898
- const runAuth = flow === "login" ? context.imports.login : context.imports.signup;
5899
6214
  printAuthCommand({ context, flow, headless });
5900
6215
  try {
5901
- await runAuth({ headless });
6216
+ if (storedCredentialsSelection === "create") {
6217
+ await context.authenticateNewAccount({ entryPoint: flow, headless });
6218
+ } else {
6219
+ const runAuth = flow === "login" ? context.imports.login : context.imports.signup;
6220
+ await runAuth({ headless });
6221
+ }
5902
6222
  } catch (error) {
5903
6223
  if (isCredentialWriteError(error)) {
5904
6224
  console.error(
@@ -5907,12 +6227,7 @@ Log out and use a different account?`,
5907
6227
  }
5908
6228
  throw error;
5909
6229
  }
5910
- const { data: profile } = await runWithSetupLoader({
5911
- promise: context.imports.getProfile({}),
5912
- label: "Confirming Zapier account"
5913
- });
5914
- context.accountEmail = profile.email;
5915
- console.log(`Authenticated as ${profile.email}.`);
6230
+ await confirmAuthentication(context);
5916
6231
  }
5917
6232
  var agentLabels = {
5918
6233
  claude: "Claude Code",
@@ -5954,7 +6269,7 @@ function printAgentPrompt({
5954
6269
  message
5955
6270
  }) {
5956
6271
  console.log();
5957
- console.log(chalk3.bgYellow.black.bold(message));
6272
+ console.log(chalk5.bgYellow.black.bold(message));
5958
6273
  console.log();
5959
6274
  console.log(buildAgentPrompt({ context }));
5960
6275
  }
@@ -6239,7 +6554,7 @@ var MINIMUM_MESSAGE_WIDTH = 20;
6239
6554
  var MAXIMUM_MESSAGE_WIDTH = 88;
6240
6555
  function showPhase({ number, title }) {
6241
6556
  console.log();
6242
- console.log(chalk3.bgCyan.black.bold(` ${number}/${PHASE_COUNT} ${title} `));
6557
+ console.log(chalk5.bgCyan.black.bold(` ${number}/${PHASE_COUNT} ${title} `));
6243
6558
  }
6244
6559
  function printWrapped(text) {
6245
6560
  const width = Math.max(
@@ -6253,7 +6568,7 @@ function printWrapped(text) {
6253
6568
  }
6254
6569
  function showReadyMessage() {
6255
6570
  console.log();
6256
- console.log(chalk3.bgGreen.black.bold(" \u2713 Zapier SDK setup complete "));
6571
+ console.log(chalk5.bgGreen.black.bold(" \u2713 Zapier SDK setup complete "));
6257
6572
  console.log();
6258
6573
  printWrapped(
6259
6574
  "Use active Zapier connections to access 9,000+ app connectors without managing each app's OAuth, token refresh, or retries."
@@ -6265,7 +6580,7 @@ function showReadyMessage() {
6265
6580
  console.log();
6266
6581
  }
6267
6582
  async function runWizard(context) {
6268
- console.log(chalk3.bold("Zapier SDK setup"));
6583
+ console.log(chalk5.bold("Zapier SDK setup"));
6269
6584
  showPhase({ number: 1, title: "Project directory" });
6270
6585
  await chooseDirectory(context);
6271
6586
  showPhase({ number: 2, title: "Node.js" });
@@ -6280,7 +6595,7 @@ async function runWizard(context) {
6280
6595
  showPhase({ number: 6, title: "Slack demo" });
6281
6596
  await offerSlackTest(context);
6282
6597
  showReadyMessage();
6283
- console.log(chalk3.bgCyan.black.bold(" Next steps "));
6598
+ console.log(chalk5.bgCyan.black.bold(" Next steps "));
6284
6599
  await openAgentHandoff(context);
6285
6600
  }
6286
6601
 
@@ -6295,7 +6610,11 @@ var setupImports = [
6295
6610
  listConnectionsRef2,
6296
6611
  loginRef,
6297
6612
  logoutRef,
6298
- signupRef
6613
+ signupRef,
6614
+ apiPluginRef,
6615
+ resolveCredentialsPluginRef,
6616
+ eventEmissionPluginRef,
6617
+ sdkOptionsPluginRef
6299
6618
  ];
6300
6619
  var setupPlugin = defineMethod({
6301
6620
  name: "setup",
@@ -6341,18 +6660,18 @@ function createInteractiveCallback() {
6341
6660
  const attrs = message.message_attributes;
6342
6661
  console.log(
6343
6662
  `
6344
- ${chalk3.bold(`Message #${messageNumber}`)} ${chalk3.dim(message.id)} ${chalk3.dim(`(lease #${attrs.lease_count})`)}`
6663
+ ${chalk5.bold(`Message #${messageNumber}`)} ${chalk5.dim(message.id)} ${chalk5.dim(`(lease #${attrs.lease_count})`)}`
6345
6664
  );
6346
6665
  if (attrs.error_message) {
6347
- console.log(chalk3.yellow(` upstream error: ${attrs.error_message}`));
6666
+ console.log(chalk5.yellow(` upstream error: ${attrs.error_message}`));
6348
6667
  }
6349
6668
  if (attrs.possible_duplicate_data) {
6350
- console.log(chalk3.yellow(" possible duplicate data"));
6669
+ console.log(chalk5.yellow(" possible duplicate data"));
6351
6670
  }
6352
6671
  while (true) {
6353
6672
  let action;
6354
6673
  try {
6355
- const answer = await inquirer3.prompt([
6674
+ const answer = await inquirer4.prompt([
6356
6675
  {
6357
6676
  type: "list",
6358
6677
  name: "action",
@@ -6377,7 +6696,7 @@ ${chalk3.bold(`Message #${messageNumber}`)} ${chalk3.dim(message.id)} ${chalk3.d
6377
6696
  throw error;
6378
6697
  }
6379
6698
  if (action === "view") {
6380
- console.log(chalk3.dim(JSON.stringify(message.payload, null, 2)));
6699
+ console.log(chalk5.dim(JSON.stringify(message.payload, null, 2)));
6381
6700
  continue;
6382
6701
  }
6383
6702
  if (action === "ack") {
@@ -6480,7 +6799,7 @@ function describeReason(reason) {
6480
6799
  }
6481
6800
  function printDrainError(reason, message) {
6482
6801
  console.error(
6483
- chalk3.red(`Error processing ${message.id}: ${describeReason(reason)}`)
6802
+ chalk5.red(`Error processing ${message.id}: ${describeReason(reason)}`)
6484
6803
  );
6485
6804
  }
6486
6805
  function printDrainSummary(counts) {
@@ -6490,7 +6809,7 @@ function printDrainSummary(counts) {
6490
6809
  if (skipped > 0) parts.push(`${skipped} skipped`);
6491
6810
  parts.push(`${counts.rejected} rejected`);
6492
6811
  console.log(
6493
- chalk3.dim(
6812
+ chalk5.dim(
6494
6813
  `
6495
6814
  Processed ${total} message${total === 1 ? "" : "s"} (${parts.join(", ")}).`
6496
6815
  )
@@ -6498,7 +6817,7 @@ Processed ${total} message${total === 1 ? "" : "s"} (${parts.join(", ")}).`
6498
6817
  }
6499
6818
  function warnInteractiveContinueOnErrorOverride() {
6500
6819
  console.warn(
6501
- chalk3.yellow(
6820
+ chalk5.yellow(
6502
6821
  'Note: continueOnError=false is overridden to true in interactive mode (the "Skip (let lease expire)" choice would otherwise terminate the drain).'
6503
6822
  )
6504
6823
  );
@@ -6819,7 +7138,7 @@ function collectDeprecationNoticeAndForward(event, onEvent) {
6819
7138
  // package.json with { type: 'json' }
6820
7139
  var package_default = {
6821
7140
  name: "@zapier/zapier-sdk-cli",
6822
- version: "0.77.9"};
7141
+ version: "0.78.0"};
6823
7142
 
6824
7143
  // src/sdk.ts
6825
7144
  var warnedDeprecatedMethods = /* @__PURE__ */ new Set();
@@ -6830,9 +7149,9 @@ var cliCoreOptions = {
6830
7149
  warnedDeprecatedMethods.add(methodName);
6831
7150
  console.warn();
6832
7151
  console.warn(
6833
- chalk3.yellow.bold("\u26A0\uFE0F DEPRECATION WARNING") + chalk3.yellow(` - \`${toKebabCase(methodName)}\` is deprecated.`)
7152
+ chalk5.yellow.bold("\u26A0\uFE0F DEPRECATION WARNING") + chalk5.yellow(` - \`${toKebabCase(methodName)}\` is deprecated.`)
6834
7153
  );
6835
- console.warn(chalk3.yellow(` ${deprecation.message}`));
7154
+ console.warn(chalk5.yellow(` ${deprecation.message}`));
6836
7155
  console.warn();
6837
7156
  }
6838
7157
  };