@zapier/zapier-sdk-cli 0.77.8 → 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.mjs CHANGED
@@ -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';
@@ -9,9 +9,10 @@ import { resolve, join, dirname, basename, relative, extname } from 'path';
9
9
  import * as lockfile from 'proper-lockfile';
10
10
  import { defineMethod, apiPluginRef, resolveCredentialsPluginRef, eventEmissionPluginRef, sdkOptionsPluginRef, declareOptionalProperty, OutputPropertySchema, ZapierBundleError, isZapierBundleError, DEFAULT_CONFIG_PATH, declareMethod, ZapierValidationError, isZapierValidationError, ZapierUnknownError, manifestPluginRef, defineResolver, isPermanentHttpError, isZapierAuthenticationError, ZapierApiError, defineOverride, fetchPlugin, zapierCoreOptions, injectCliLogin, definePlugin, omitExports, zapierSdkPlugin, getConnectionPlugin, invalidateCachedToken, batch, toSnakeCase, ZapierError, isZapierReleaseTriggerMessageSignal, getOrCreateApiClient, isCredentialsObject, createSdk, getRegistryPlugin, createController, ZapierAbortDrainSignal, ZapierReleaseTriggerMessageSignal, buildApplicationLifecycleEvent, AuthMechanism, isCoreCancelledSignal, ZapierAuthenticationError, CORE_OPTIONS_ID, SDK_OPTIONS_ID, addPlugin, getOsInfo, getPlatformVersions, getAgent, getTtyContext, getCiPlatform, isCi, getReleaseId, getCurrentTimestamp, generateEventId, DEPRECATION_NOTICE_EVENT } from '@zapier/zapier-sdk';
11
11
  import { z } from 'zod';
12
- import chalk3 from 'chalk';
12
+ import chalk5 from 'chalk';
13
13
  import { hostname } from 'os';
14
- import inquirer3 from 'inquirer';
14
+ import inquirer4 from 'inquirer';
15
+ import { makeTheme, createPrompt, useState, usePrefix, useMemo, useEffect, useKeypress, isEnterKey, isTabKey, isUpKey, isDownKey, usePagination, Separator } from '@inquirer/core';
15
16
  import express from 'express';
16
17
  import { createInterface } from 'readline/promises';
17
18
  import open from 'open';
@@ -25,7 +26,6 @@ import 'is-installed-globally';
25
26
  import { execSync, spawn } from 'child_process';
26
27
  import Handlebars from 'handlebars';
27
28
  import { fileURLToPath } from 'url';
28
- import { makeTheme, createPrompt, useState, usePrefix, useMemo, useEffect, useKeypress, isEnterKey, isTabKey, isUpKey, isDownKey, usePagination, Separator } from '@inquirer/core';
29
29
  import packageJsonLib, { VersionNotFoundError } from 'package-json';
30
30
  import semver from 'semver';
31
31
  import crossSpawn from 'cross-spawn';
@@ -366,6 +366,10 @@ function getActiveCredentials(options) {
366
366
  if (!name) return void 0;
367
367
  return findEntry(readRegistry(), name, normalizeBaseUrl(options?.baseUrl));
368
368
  }
369
+ function listStoredCredentials(options) {
370
+ const baseUrl = normalizeBaseUrl(options?.baseUrl);
371
+ return readRegistry().filter((entry) => entry.baseUrl === baseUrl).sort((left, right) => right.createdAt - left.createdAt);
372
+ }
369
373
  var MAX_CREDENTIAL_NAME_ATTEMPTS = 500;
370
374
  function firstAvailableCredentialName({
371
375
  baseName,
@@ -470,6 +474,29 @@ async function getStoredClientCredentials(options) {
470
474
  scope: [...entry.scopes].sort().join(" ")
471
475
  };
472
476
  }
477
+ async function activateStoredCredentials({
478
+ name,
479
+ baseUrl
480
+ }) {
481
+ const resolvedBaseUrl = normalizeBaseUrl(baseUrl);
482
+ const entry = findEntry(readRegistry(), name, resolvedBaseUrl);
483
+ if (!entry) {
484
+ throw new ZapierCliValidationError(
485
+ `No stored credentials named "${name}" were found.`
486
+ );
487
+ }
488
+ const credentials = await getStoredClientCredentials({
489
+ name,
490
+ baseUrl: resolvedBaseUrl
491
+ });
492
+ if (!credentials) {
493
+ throw new ZapierCliValidationError(
494
+ `Stored credentials "${name}" are missing from the system keychain. Add a new account to recreate them.`
495
+ );
496
+ }
497
+ getConfig().set(CREDENTIALS_KEY, name);
498
+ return entry;
499
+ }
473
500
  function deleteRegistryEntry(registry, name, baseUrl) {
474
501
  const idx = registry.findIndex(
475
502
  (e) => e.name === name && e.baseUrl === baseUrl
@@ -1066,6 +1093,362 @@ async function setupClientCredentials({
1066
1093
  }
1067
1094
  return { clientId };
1068
1095
  }
1096
+ function isSelectable(item) {
1097
+ return !Separator.isSeparator(item) && !item.disabled;
1098
+ }
1099
+ function normalizeChoices(choices) {
1100
+ return choices.map((choice) => {
1101
+ if (Separator.isSeparator(choice)) return choice;
1102
+ const name = choice.name ?? String(choice.value);
1103
+ return {
1104
+ value: choice.value,
1105
+ name,
1106
+ short: choice.short ?? name,
1107
+ disabled: choice.disabled ?? false
1108
+ };
1109
+ });
1110
+ }
1111
+ var theme = makeTheme({
1112
+ icon: { cursor: "\u276F" },
1113
+ style: {
1114
+ disabled: (text) => chalk5.dim(`- ${text}`),
1115
+ searchTerm: (text) => chalk5.cyan(text),
1116
+ keysHelpTip: (keys) => keys.map(([key, action]) => `${chalk5.bold(key)} ${chalk5.dim(action)}`).join(chalk5.dim(" \u2022 "))
1117
+ }
1118
+ });
1119
+ var searchSelect = createPrompt(
1120
+ (config2, done) => {
1121
+ const { pageSize = 7 } = config2;
1122
+ const [status, setStatus] = useState(
1123
+ "loading"
1124
+ );
1125
+ const [searchTerm, setSearchTerm] = useState("");
1126
+ const [searchResults, setSearchResults] = useState([]);
1127
+ const [searchError, setSearchError] = useState();
1128
+ const prefix = usePrefix({ status, theme });
1129
+ const bounds = useMemo(() => {
1130
+ const first = searchResults.findIndex(isSelectable);
1131
+ let last = -1;
1132
+ for (let i = searchResults.length - 1; i >= 0; i--) {
1133
+ if (isSelectable(searchResults[i])) {
1134
+ last = i;
1135
+ break;
1136
+ }
1137
+ }
1138
+ return { first, last };
1139
+ }, [searchResults]);
1140
+ const defaultActive = useMemo(() => {
1141
+ const requested = searchTerm === "" ? config2.initialActive : config2.initialActiveForTerm?.({ term: searchTerm });
1142
+ if (requested !== void 0 && requested >= 0 && requested < searchResults.length && isSelectable(searchResults[requested])) {
1143
+ return requested;
1144
+ }
1145
+ return bounds.first;
1146
+ }, [searchResults, searchTerm, bounds.first]);
1147
+ const [active = defaultActive, setActive] = useState();
1148
+ useEffect(() => {
1149
+ const controller = new AbortController();
1150
+ setStatus("loading");
1151
+ setSearchError(void 0);
1152
+ const fetchResults = async () => {
1153
+ try {
1154
+ const results = await config2.source(searchTerm || void 0);
1155
+ if (!controller.signal.aborted) {
1156
+ setActive(void 0);
1157
+ setSearchError(void 0);
1158
+ setSearchResults(normalizeChoices(results));
1159
+ setStatus("idle");
1160
+ }
1161
+ } catch (error2) {
1162
+ if (!controller.signal.aborted && error2 instanceof Error) {
1163
+ setSearchError(error2.message);
1164
+ }
1165
+ }
1166
+ };
1167
+ void fetchResults();
1168
+ return () => {
1169
+ controller.abort();
1170
+ };
1171
+ }, [searchTerm]);
1172
+ const selectedChoice = searchResults[active];
1173
+ useKeypress((key, rl) => {
1174
+ if (isEnterKey(key)) {
1175
+ if (selectedChoice && isSelectable(selectedChoice)) {
1176
+ setStatus("done");
1177
+ done(selectedChoice.value);
1178
+ } else {
1179
+ rl.write(searchTerm);
1180
+ }
1181
+ } else if (isTabKey(key) && selectedChoice && isSelectable(selectedChoice)) {
1182
+ rl.clearLine(0);
1183
+ rl.write(selectedChoice.name);
1184
+ setSearchTerm(selectedChoice.name);
1185
+ } else if (status !== "loading" && (isUpKey(key) || isDownKey(key))) {
1186
+ rl.clearLine(0);
1187
+ if (isUpKey(key) && active !== bounds.first || isDownKey(key) && active !== bounds.last) {
1188
+ const offset = isUpKey(key) ? -1 : 1;
1189
+ let next = active;
1190
+ do {
1191
+ next = (next + offset + searchResults.length) % searchResults.length;
1192
+ } while (!isSelectable(searchResults[next]));
1193
+ setActive(next);
1194
+ }
1195
+ } else {
1196
+ setSearchTerm(rl.line);
1197
+ }
1198
+ });
1199
+ const page = usePagination({
1200
+ items: searchResults,
1201
+ active,
1202
+ renderItem({ item, isActive }) {
1203
+ if (Separator.isSeparator(item)) {
1204
+ return ` ${item.separator}`;
1205
+ }
1206
+ if (item.disabled) {
1207
+ const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
1208
+ return theme.style.disabled(`${item.name} ${disabledLabel}`);
1209
+ }
1210
+ const color = isActive ? theme.style.highlight : (x) => x;
1211
+ const cursor = isActive ? theme.icon.cursor : ` `;
1212
+ return color(`${cursor} ${item.name}`);
1213
+ },
1214
+ pageSize,
1215
+ loop: false
1216
+ });
1217
+ const message = theme.style.message(config2.message, status);
1218
+ if (status === "done" && selectedChoice && isSelectable(selectedChoice)) {
1219
+ return [prefix, message, theme.style.answer(selectedChoice.short)].filter(Boolean).join(" ").trimEnd();
1220
+ }
1221
+ const searchStr = theme.style.searchTerm(searchTerm);
1222
+ const helpTip = theme.style.keysHelpTip([
1223
+ ["\u2191\u2193", "navigate"],
1224
+ ["\u23CE", "select"]
1225
+ ]);
1226
+ let error;
1227
+ if (searchError) {
1228
+ error = theme.style.error(searchError);
1229
+ } else if (searchResults.length === 0 && searchTerm !== "" && status === "idle") {
1230
+ error = theme.style.error("No results found");
1231
+ }
1232
+ const header = [prefix, message, searchStr].filter(Boolean).join(" ").trimEnd();
1233
+ const body = [error ?? page, " ", helpTip].filter(Boolean).join("\n").trimEnd();
1234
+ return [header, body];
1235
+ }
1236
+ );
1237
+
1238
+ // src/utils/auth/credentials-picker.ts
1239
+ function isSameCredentials(left, right) {
1240
+ return left.name === right.name && left.baseUrl === right.baseUrl;
1241
+ }
1242
+ function createdAtIso(credentials) {
1243
+ return new Date(credentials.createdAt).toISOString();
1244
+ }
1245
+ function searchableFields(credentials) {
1246
+ return [
1247
+ { text: credentials.name.toLowerCase(), weight: 0 },
1248
+ { text: credentials.clientId.toLowerCase(), weight: 1e3 },
1249
+ ...credentials.scopes.map((scope) => ({
1250
+ text: scope.toLowerCase(),
1251
+ weight: 2e3
1252
+ })),
1253
+ {
1254
+ text: createdAtIso(credentials).slice(0, 10).toLowerCase(),
1255
+ weight: 3e3
1256
+ }
1257
+ ];
1258
+ }
1259
+ function textMatchScore(text, query) {
1260
+ if (text === query) return 0;
1261
+ if (text.startsWith(query)) return 100 + text.length - query.length;
1262
+ const index = text.indexOf(query);
1263
+ if (index === -1) return void 0;
1264
+ return 200 + text.length - query.length;
1265
+ }
1266
+ function closestFieldScore(fields, query) {
1267
+ let closest;
1268
+ for (const field of fields) {
1269
+ const textScore = textMatchScore(field.text, query);
1270
+ if (textScore === void 0) continue;
1271
+ const score = field.weight + textScore;
1272
+ closest = closest === void 0 ? score : Math.min(closest, score);
1273
+ }
1274
+ return closest;
1275
+ }
1276
+ function searchScore(credentials, term) {
1277
+ const query = term.trim().toLowerCase();
1278
+ const tokens = query.split(/\s+/).filter(Boolean);
1279
+ const fields = searchableFields(credentials);
1280
+ let tokenScore = 0;
1281
+ for (const token of tokens) {
1282
+ const score = closestFieldScore(fields, token);
1283
+ if (score === void 0) return void 0;
1284
+ tokenScore += score;
1285
+ }
1286
+ const phraseScore = closestFieldScore(fields, query);
1287
+ return phraseScore === void 0 ? 1e4 + tokenScore : phraseScore;
1288
+ }
1289
+ function formatCredentialsChoice({
1290
+ credentials,
1291
+ current
1292
+ }) {
1293
+ const currentLabel = current ? chalk5.cyan(" (current)") : "";
1294
+ const details = [
1295
+ credentials.clientId,
1296
+ credentials.scopes.join(", "),
1297
+ `created ${createdAtIso(credentials).slice(0, 10)}`
1298
+ ].join(" \xB7 ");
1299
+ return {
1300
+ name: `${credentials.name}${currentLabel} ${chalk5.dim(`\xB7 ${details}`)}`,
1301
+ short: credentials.name,
1302
+ value: { action: "switch", credentials }
1303
+ };
1304
+ }
1305
+ function buildCredentialsChoices({
1306
+ credentials,
1307
+ activeCredentials,
1308
+ term = ""
1309
+ }) {
1310
+ const sortedCredentials = [...credentials].sort(
1311
+ (left, right) => right.createdAt - left.createdAt
1312
+ );
1313
+ const current = activeCredentials ? sortedCredentials.find(
1314
+ (entry) => isSameCredentials(entry, activeCredentials)
1315
+ ) : void 0;
1316
+ const rankedCredentials = term ? sortedCredentials.map((credentials2) => ({
1317
+ credentials: credentials2,
1318
+ score: searchScore(credentials2, term)
1319
+ })).filter(
1320
+ (result) => result.score !== void 0
1321
+ ).sort((left, right) => left.score - right.score).map(({ credentials: credentials2 }) => credentials2) : [
1322
+ ...current ? [current] : [],
1323
+ ...sortedCredentials.filter((credentials2) => credentials2 !== current)
1324
+ ];
1325
+ return [
1326
+ {
1327
+ name: "+ Add a new account",
1328
+ short: "Add a new account",
1329
+ value: { action: "create" }
1330
+ },
1331
+ ...rankedCredentials.map(
1332
+ (credentials2) => formatCredentialsChoice({
1333
+ credentials: credentials2,
1334
+ current: credentials2 === current
1335
+ })
1336
+ )
1337
+ ];
1338
+ }
1339
+ async function promptForCredentials({
1340
+ credentials,
1341
+ activeCredentials
1342
+ }) {
1343
+ return searchSelect({
1344
+ message: "Select credentials or add a new account:",
1345
+ source: (term) => buildCredentialsChoices({
1346
+ credentials,
1347
+ activeCredentials,
1348
+ term
1349
+ }),
1350
+ initialActive: credentials.length > 0 ? 1 : 0,
1351
+ initialActiveForTerm: () => 1
1352
+ });
1353
+ }
1354
+
1355
+ // src/utils/auth/stored-login-credentials.ts
1356
+ function authFlowOnlyOptions(options) {
1357
+ return [
1358
+ ...options.timeout === void 0 ? [] : ["--timeout"],
1359
+ ...options.useApprovals === true ? ["--use-approvals"] : [],
1360
+ ...options.headless === true ? ["--headless"] : []
1361
+ ];
1362
+ }
1363
+ function assertCanSwitchCredentials({
1364
+ credentials,
1365
+ options,
1366
+ resolvedCredentials
1367
+ }) {
1368
+ if (resolvedCredentials !== void 0) {
1369
+ throw new ZapierCliValidationError(
1370
+ "Cannot switch stored credentials while credentials are configured through SDK options or environment variables. Remove those credentials before switching accounts."
1371
+ );
1372
+ }
1373
+ const incompatibleOptions = authFlowOnlyOptions(options);
1374
+ if (incompatibleOptions.length === 0) return;
1375
+ throw new ZapierCliValidationError(
1376
+ `Cannot switch to stored credentials "${credentials.name}" while using ${incompatibleOptions.join(
1377
+ ", "
1378
+ )}. These options only apply when logging in to a new account.`
1379
+ );
1380
+ }
1381
+ function findStoredCredentialsByName({
1382
+ name,
1383
+ baseUrl
1384
+ }) {
1385
+ return listStoredCredentials({ baseUrl }).find(
1386
+ (credentials) => credentials.name === name
1387
+ );
1388
+ }
1389
+ async function switchCredentials({
1390
+ credentials,
1391
+ options,
1392
+ resolvedCredentials
1393
+ }) {
1394
+ assertCanSwitchCredentials({ credentials, options, resolvedCredentials });
1395
+ await activateStoredCredentials({
1396
+ name: credentials.name,
1397
+ baseUrl: credentials.baseUrl
1398
+ });
1399
+ process.stderr.write(
1400
+ `\u2705 Credentials "${credentials.name}" are now active.
1401
+ `
1402
+ );
1403
+ }
1404
+ async function chooseStoredLoginCredentialsAtBaseUrl({
1405
+ baseUrl,
1406
+ options,
1407
+ resolvedCredentials
1408
+ }) {
1409
+ if (resolvedCredentials !== void 0 || authFlowOnlyOptions(options).length > 0) {
1410
+ return "none";
1411
+ }
1412
+ const storedCredentials = listStoredCredentials({ baseUrl });
1413
+ if (storedCredentials.length === 0) return "none";
1414
+ const selection = await promptForCredentials({
1415
+ credentials: storedCredentials,
1416
+ activeCredentials: getActiveCredentials({ baseUrl })
1417
+ });
1418
+ if (selection.action === "create") return "create";
1419
+ await switchCredentials({
1420
+ credentials: selection.credentials,
1421
+ options,
1422
+ resolvedCredentials
1423
+ });
1424
+ return "switch";
1425
+ }
1426
+ async function chooseStoredLoginCredentials({
1427
+ imports,
1428
+ options
1429
+ }) {
1430
+ const resolvedCredentials = await imports.resolveCredentials();
1431
+ const credentialsBaseUrl = await resolveCredentialsBaseUrl({
1432
+ options: imports.sdkOptions,
1433
+ resolvedCredentials
1434
+ });
1435
+ return chooseStoredLoginCredentialsAtBaseUrl({
1436
+ baseUrl: credentialsBaseUrl,
1437
+ options,
1438
+ resolvedCredentials
1439
+ });
1440
+ }
1441
+ async function confirmNewCredentialsName(name) {
1442
+ const { confirmed } = await inquirer4.prompt([
1443
+ {
1444
+ type: "confirm",
1445
+ name: "confirmed",
1446
+ default: false,
1447
+ message: `No stored credentials named "${name}" were found. Continue with a new account and save it as "${name}"?`
1448
+ }
1449
+ ]);
1450
+ return confirmed;
1451
+ }
1069
1452
 
1070
1453
  // src/utils/constants.ts
1071
1454
  var LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
@@ -1090,20 +1473,20 @@ var getCallablePromise = () => {
1090
1473
  var getCallablePromise_default = getCallablePromise;
1091
1474
  var log = {
1092
1475
  info: (message, ...args) => {
1093
- console.error(chalk3.blue("\u2139"), message, ...args);
1476
+ console.error(chalk5.blue("\u2139"), message, ...args);
1094
1477
  },
1095
1478
  error: (message, ...args) => {
1096
- console.error(chalk3.red("\u2716"), message, ...args);
1479
+ console.error(chalk5.red("\u2716"), message, ...args);
1097
1480
  },
1098
1481
  success: (message, ...args) => {
1099
- console.error(chalk3.green("\u2713"), message, ...args);
1482
+ console.error(chalk5.green("\u2713"), message, ...args);
1100
1483
  },
1101
1484
  warn: (message, ...args) => {
1102
- console.error(chalk3.yellow("\u26A0"), message, ...args);
1485
+ console.error(chalk5.yellow("\u26A0"), message, ...args);
1103
1486
  },
1104
1487
  debug: (message, ...args) => {
1105
1488
  if (process.env.DEBUG === "true" || process.argv.includes("--debug")) {
1106
- console.error(chalk3.gray("\u{1F41B}"), message, ...args);
1489
+ console.error(chalk5.gray("\u{1F41B}"), message, ...args);
1107
1490
  }
1108
1491
  }
1109
1492
  };
@@ -1950,9 +2333,6 @@ var HEADLESS_SIGNUP_RECOVERY_MESSAGE = "Restart `zapier-sdk signup --headless` t
1950
2333
  function getEntryPointLabel(entryPoint) {
1951
2334
  return entryPoint === "signup" ? "Signup" : "Login";
1952
2335
  }
1953
- function getActiveCredentialsAction(entryPoint) {
1954
- return entryPoint === "signup" ? "continue signup" : "log in again";
1955
- }
1956
2336
  function getCredentialsPromptMessage(entryPoint) {
1957
2337
  return entryPoint === "signup" ? "Enter a name to identify these credentials:" : "Enter a name to identify them:";
1958
2338
  }
@@ -1967,11 +2347,24 @@ function validateCredentialsName(name) {
1967
2347
  if (!trimmedName) throw new ZapierCliValidationError("Name cannot be empty");
1968
2348
  return trimmedName;
1969
2349
  }
2350
+ function validateNewCredentialsName({
2351
+ name,
2352
+ baseUrl
2353
+ }) {
2354
+ const validatedName = validateCredentialsName(name);
2355
+ if (credentialNameExists({ name: validatedName, baseUrl })) {
2356
+ throw new ZapierCliValidationError(
2357
+ `Credentials named "${validatedName}" already exist. Choose a different name.`
2358
+ );
2359
+ }
2360
+ return validatedName;
2361
+ }
1970
2362
  async function promptCredentialsName({
1971
2363
  email,
1972
- promptMessage
2364
+ promptMessage,
2365
+ baseUrl
1973
2366
  }) {
1974
- const { credentialName } = await inquirer3.prompt([
2367
+ const { credentialName } = await inquirer4.prompt([
1975
2368
  {
1976
2369
  type: "input",
1977
2370
  name: "credentialName",
@@ -1979,7 +2372,7 @@ async function promptCredentialsName({
1979
2372
  default: defaultCredentialsName(email),
1980
2373
  validate: (input) => {
1981
2374
  try {
1982
- validateCredentialsName(input);
2375
+ validateNewCredentialsName({ name: input, baseUrl });
1983
2376
  return true;
1984
2377
  } catch (err) {
1985
2378
  return err instanceof Error ? err.message : String(err);
@@ -1987,7 +2380,7 @@ async function promptCredentialsName({
1987
2380
  }
1988
2381
  }
1989
2382
  ]);
1990
- return validateCredentialsName(credentialName);
2383
+ return validateNewCredentialsName({ name: credentialName, baseUrl });
1991
2384
  }
1992
2385
  function resolveDefaultCredentialsName({
1993
2386
  email
@@ -2003,7 +2396,8 @@ async function resolveCredentialName({
2003
2396
  if (interactive) {
2004
2397
  return promptCredentialsName({
2005
2398
  email,
2006
- promptMessage: getCredentialsPromptMessage(entryPoint)
2399
+ promptMessage: getCredentialsPromptMessage(entryPoint),
2400
+ baseUrl
2007
2401
  });
2008
2402
  }
2009
2403
  const baseName = resolveDefaultCredentialsName({ email });
@@ -2034,7 +2428,7 @@ async function promptConfirm({
2034
2428
  message,
2035
2429
  defaultValue
2036
2430
  }) {
2037
- const { confirmed } = await inquirer3.prompt([
2431
+ const { confirmed } = await inquirer4.prompt([
2038
2432
  { type: "confirm", name: "confirmed", message, default: defaultValue }
2039
2433
  ]);
2040
2434
  return confirmed;
@@ -2044,6 +2438,11 @@ function promptlessCredentialResetError(credentials) {
2044
2438
  `Already logged in as "${credentials.name}". Run \`logout\` first or use an interactive terminal to re-authenticate.`
2045
2439
  );
2046
2440
  }
2441
+ function unnamedNonInteractiveLoginError(credentials) {
2442
+ throw new ZapierCliValidationError(
2443
+ `Already logged in as "${credentials.name}". Provide \`--name\` to activate or create named credentials, or run \`logout\` first.`
2444
+ );
2445
+ }
2047
2446
  function promptlessLegacyJwtUpgradeError() {
2048
2447
  throw new ZapierCliValidationError(
2049
2448
  "Legacy JWT login detected. Run `logout` first or use an interactive terminal to migrate to client credentials."
@@ -2053,16 +2452,20 @@ async function clearExistingAuthState({
2053
2452
  imports,
2054
2453
  baseUrl,
2055
2454
  interactive,
2056
- entryPoint
2455
+ entryPoint,
2456
+ preserveExistingCredentials = false
2057
2457
  }) {
2058
2458
  const activeCredentials = getActiveCredentials({ baseUrl });
2059
2459
  const flowLabel = getEntryPointLabel(entryPoint);
2460
+ if (activeCredentials && (entryPoint === "login" || preserveExistingCredentials)) {
2461
+ return true;
2462
+ }
2060
2463
  if (activeCredentials) {
2061
2464
  const confirmed = interactive ? await promptConfirm({
2062
2465
  defaultValue: false,
2063
2466
  message: `You are already logged in as "${activeCredentials.name}".
2064
2467
  Logging out will delete these credentials and may interrupt other Zapier SDK or CLI sessions using them.
2065
- Log out and ${getActiveCredentialsAction(entryPoint)}?`
2468
+ Log out and continue signup?`
2066
2469
  }) : promptlessCredentialResetError(activeCredentials);
2067
2470
  if (!confirmed) {
2068
2471
  process.stderr.write(`${flowLabel} cancelled.
@@ -2277,12 +2680,14 @@ async function provisionAccountCredentials({
2277
2680
  async function runAccountAuth({
2278
2681
  imports,
2279
2682
  options,
2280
- entryPoint
2683
+ entryPoint,
2684
+ storedCredentialsMode = "choose",
2685
+ preserveExistingCredentials = false
2281
2686
  }) {
2282
2687
  if (options.callbackUrl !== void 0) {
2283
2688
  const { callbackUrl } = options;
2284
2689
  const pending = getPendingOauthFlow({ entryPoint });
2285
- const finishName = options.name !== void 0 ? validateCredentialsName(options.name) : void 0;
2690
+ const finishName = options.name === void 0 ? void 0 : validateCredentialsName(options.name);
2286
2691
  if (finishName !== void 0 && finishName !== pending.credentialName) {
2287
2692
  throw new ZapierCliValidationError(
2288
2693
  "Cannot change --name while completing a pending OAuth flow. Start a new non-interactive login with the desired --name."
@@ -2342,7 +2747,6 @@ async function runAccountAuth({
2342
2747
  });
2343
2748
  return;
2344
2749
  }
2345
- const timeoutSeconds = parseTimeoutSeconds(options.timeout);
2346
2750
  const interactive = !resolveNonInteractive(options);
2347
2751
  const resolvedCredentials = await imports.resolveCredentials();
2348
2752
  const pkceCredentials = toPkceCredentials(resolvedCredentials);
@@ -2351,8 +2755,34 @@ async function runAccountAuth({
2351
2755
  options: imports.sdkOptions,
2352
2756
  resolvedCredentials
2353
2757
  });
2354
- const providedName = options.name !== void 0 ? validateCredentialsName(options.name) : void 0;
2355
- if (providedName !== void 0) {
2758
+ const providedName = options.name === void 0 ? void 0 : validateCredentialsName(options.name);
2759
+ if (entryPoint === "login") {
2760
+ if (providedName !== void 0) {
2761
+ const matchingCredentials = findStoredCredentialsByName({
2762
+ name: providedName,
2763
+ baseUrl: credentialsBaseUrl
2764
+ });
2765
+ if (matchingCredentials) {
2766
+ await switchCredentials({
2767
+ credentials: matchingCredentials,
2768
+ options,
2769
+ resolvedCredentials
2770
+ });
2771
+ return;
2772
+ }
2773
+ if (interactive && !await confirmNewCredentialsName(providedName)) {
2774
+ process.stderr.write("Login cancelled.\n");
2775
+ return;
2776
+ }
2777
+ } else if (interactive && storedCredentialsMode === "choose") {
2778
+ const selection = await chooseStoredLoginCredentialsAtBaseUrl({
2779
+ baseUrl: credentialsBaseUrl,
2780
+ options,
2781
+ resolvedCredentials
2782
+ });
2783
+ if (selection === "switch") return;
2784
+ }
2785
+ } else if (providedName !== void 0) {
2356
2786
  const activeCredentials = getActiveCredentials({
2357
2787
  baseUrl: credentialsBaseUrl
2358
2788
  });
@@ -2362,14 +2792,22 @@ async function runAccountAuth({
2362
2792
  );
2363
2793
  }
2364
2794
  }
2795
+ if (entryPoint === "login" && !interactive && providedName === void 0) {
2796
+ const activeCredentials = getActiveCredentials({
2797
+ baseUrl: credentialsBaseUrl
2798
+ });
2799
+ if (activeCredentials) unnamedNonInteractiveLoginError(activeCredentials);
2800
+ }
2365
2801
  if (!await clearExistingAuthState({
2366
2802
  imports,
2367
2803
  baseUrl: credentialsBaseUrl,
2368
2804
  interactive,
2369
- entryPoint
2805
+ entryPoint,
2806
+ preserveExistingCredentials
2370
2807
  })) {
2371
2808
  return;
2372
2809
  }
2810
+ const timeoutSeconds = parseTimeoutSeconds(options.timeout);
2373
2811
  const useApprovals = options.useApprovals === true;
2374
2812
  if (!interactive) {
2375
2813
  await startPendingOauthFlow({
@@ -2406,7 +2844,7 @@ async function runAccountAuth({
2406
2844
  }
2407
2845
  var LoginSchema = z.object({
2408
2846
  name: z.string().optional().describe(
2409
- "Name to identify these credentials (defaults to <email>@<hostname>). Provide this to set a custom name without the interactive prompt."
2847
+ "Activate stored credentials with this name. If none exist, create new credentials with this name; interactive login asks for confirmation first."
2410
2848
  ),
2411
2849
  timeout: z.string().optional().describe("Login timeout in seconds (default: 300)"),
2412
2850
  useApprovals: z.boolean().optional().describe(
@@ -4207,7 +4645,7 @@ async function promptYesNo({
4207
4645
  nonInteractive
4208
4646
  }) {
4209
4647
  if (nonInteractive) return defaultValue;
4210
- const { answer } = await inquirer3.prompt([
4648
+ const { answer } = await inquirer4.prompt([
4211
4649
  { type: "confirm", name: "answer", message, default: defaultValue }
4212
4650
  ]);
4213
4651
  return answer;
@@ -4254,7 +4692,7 @@ function buildTemplateVariables({
4254
4692
  };
4255
4693
  }
4256
4694
  function cleanupProject({ projectDir }) {
4257
- console.log("\n" + chalk3.yellow("!") + " Cleaning up...");
4695
+ console.log("\n" + chalk5.yellow("!") + " Cleaning up...");
4258
4696
  rmSync(projectDir, { recursive: true, force: true });
4259
4697
  }
4260
4698
  async function withInterruptCleanup(cleanup, fn) {
@@ -4464,8 +4902,8 @@ function buildNextSteps({
4464
4902
  }
4465
4903
  function createConsoleDisplayHooks() {
4466
4904
  return {
4467
- onItemComplete: (message) => console.log(" " + chalk3.green("\u2713") + " " + chalk3.dim(message)),
4468
- onWarn: (message) => console.warn(chalk3.yellow("!") + " " + message),
4905
+ onItemComplete: (message) => console.log(" " + chalk5.green("\u2713") + " " + chalk5.dim(message)),
4906
+ onWarn: (message) => console.warn(chalk5.yellow("!") + " " + message),
4469
4907
  onStepStart: ({
4470
4908
  description,
4471
4909
  stepNumber,
@@ -4474,31 +4912,31 @@ function createConsoleDisplayHooks() {
4474
4912
  nonInteractive
4475
4913
  }) => {
4476
4914
  const progressMessage = `${description}...`;
4477
- const stepCounter = chalk3.dim(`${stepNumber}/${totalSteps}`);
4915
+ const stepCounter = chalk5.dim(`${stepNumber}/${totalSteps}`);
4478
4916
  if (nonInteractive) {
4479
4917
  console.log(
4480
- "\n" + chalk3.bold(`\u276F ${progressMessage}`) + " " + stepCounter + "\n"
4918
+ "\n" + chalk5.bold(`\u276F ${progressMessage}`) + " " + stepCounter + "\n"
4481
4919
  );
4482
4920
  } else {
4483
4921
  console.log(
4484
- chalk3.dim("\u2192") + " " + progressMessage + " " + stepCounter
4922
+ chalk5.dim("\u2192") + " " + progressMessage + " " + stepCounter
4485
4923
  );
4486
4924
  }
4487
4925
  if (command) {
4488
- console.log(" " + chalk3.cyan(`$ ${command}`));
4926
+ console.log(" " + chalk5.cyan(`$ ${command}`));
4489
4927
  }
4490
4928
  },
4491
4929
  onStepSuccess: ({ stepNumber, totalSteps }) => console.log(
4492
- "\n" + chalk3.green("\u2713") + " " + chalk3.dim(`Step ${stepNumber}/${totalSteps} complete`) + "\n"
4930
+ "\n" + chalk5.green("\u2713") + " " + chalk5.dim(`Step ${stepNumber}/${totalSteps} complete`) + "\n"
4493
4931
  ),
4494
4932
  onStepError: ({ description, command, err }) => {
4495
4933
  const detail = err instanceof Error && err.message ? `
4496
- ${chalk3.dim(err.message)}` : "";
4934
+ ${chalk5.dim(err.message)}` : "";
4497
4935
  const hint = command ? `
4498
- ${chalk3.dim("run manually:")} ${chalk3.cyan(`$ ${command}`)}` : "";
4936
+ ${chalk5.dim("run manually:")} ${chalk5.cyan(`$ ${command}`)}` : "";
4499
4937
  console.error(
4500
4938
  `
4501
- ${chalk3.red("\u2716")} ${chalk3.bold(description)}${chalk3.dim(" failed")}${detail}${hint}`
4939
+ ${chalk5.red("\u2716")} ${chalk5.bold(description)}${chalk5.dim(" failed")}${detail}${hint}`
4502
4940
  );
4503
4941
  }
4504
4942
  };
@@ -4510,22 +4948,22 @@ function displaySummaryAndNextSteps({
4510
4948
  packageManager
4511
4949
  }) {
4512
4950
  const formatStatus = (complete) => ({
4513
- icon: complete ? chalk3.green("\u2713") : chalk3.yellow("!"),
4514
- text: complete ? chalk3.green("Setup complete") : chalk3.yellow("Setup interrupted")
4951
+ icon: complete ? chalk5.green("\u2713") : chalk5.yellow("!"),
4952
+ text: complete ? chalk5.green("Setup complete") : chalk5.yellow("Setup interrupted")
4515
4953
  });
4516
- const formatNextStep = (step, i) => " " + chalk3.dim(`${i + 1}.`) + " " + chalk3.bold(step.description);
4517
- const formatCommand = (cmd) => " " + chalk3.cyan(`$ ${cmd}`);
4518
- const formatCompletedStep = (step) => " " + chalk3.green("\u2713") + " " + step.description;
4954
+ const formatNextStep = (step, i) => " " + chalk5.dim(`${i + 1}.`) + " " + chalk5.bold(step.description);
4955
+ const formatCommand = (cmd) => " " + chalk5.cyan(`$ ${cmd}`);
4956
+ const formatCompletedStep = (step) => " " + chalk5.green("\u2713") + " " + step.description;
4519
4957
  const { execCmd } = getPackageManagerCommands({ packageManager });
4520
4958
  const leftoverSteps = steps.filter(
4521
4959
  (s) => !completedSetupStepIds.includes(s.id)
4522
4960
  );
4523
4961
  const isComplete = leftoverSteps.length === 0;
4524
4962
  const status = formatStatus(isComplete);
4525
- console.log("\n" + chalk3.bold("\u276F Summary") + "\n");
4526
- console.log(" " + chalk3.dim("Project") + " " + chalk3.bold(projectName));
4963
+ console.log("\n" + chalk5.bold("\u276F Summary") + "\n");
4964
+ console.log(" " + chalk5.dim("Project") + " " + chalk5.bold(projectName));
4527
4965
  console.log(
4528
- " " + chalk3.dim("Status") + " " + status.icon + " " + status.text
4966
+ " " + chalk5.dim("Status") + " " + status.icon + " " + status.text
4529
4967
  );
4530
4968
  const completedSteps = steps.filter(
4531
4969
  (s) => completedSetupStepIds.includes(s.id)
@@ -4535,7 +4973,7 @@ function displaySummaryAndNextSteps({
4535
4973
  for (const step of completedSteps) console.log(formatCompletedStep(step));
4536
4974
  }
4537
4975
  const nextSteps = buildNextSteps({ projectName, leftoverSteps, execCmd });
4538
- console.log("\n" + chalk3.bold("\u276F Next Steps") + "\n");
4976
+ console.log("\n" + chalk5.bold("\u276F Next Steps") + "\n");
4539
4977
  nextSteps.forEach((step, i) => {
4540
4978
  console.log(formatNextStep(step, i));
4541
4979
  if (step.command) console.log(formatCommand(step.command));
@@ -4598,149 +5036,6 @@ var initPlugin = defineMethod({
4598
5036
  });
4599
5037
  }
4600
5038
  });
4601
- function isSelectable(item) {
4602
- return !Separator.isSeparator(item) && !item.disabled;
4603
- }
4604
- function normalizeChoices(choices) {
4605
- return choices.map((choice) => {
4606
- if (Separator.isSeparator(choice)) return choice;
4607
- const name = choice.name ?? String(choice.value);
4608
- return {
4609
- value: choice.value,
4610
- name,
4611
- short: choice.short ?? name,
4612
- disabled: choice.disabled ?? false
4613
- };
4614
- });
4615
- }
4616
- var theme = makeTheme({
4617
- icon: { cursor: "\u276F" },
4618
- style: {
4619
- disabled: (text) => chalk3.dim(`- ${text}`),
4620
- searchTerm: (text) => chalk3.cyan(text),
4621
- keysHelpTip: (keys) => keys.map(([key, action]) => `${chalk3.bold(key)} ${chalk3.dim(action)}`).join(chalk3.dim(" \u2022 "))
4622
- }
4623
- });
4624
- var searchSelect = createPrompt(
4625
- (config2, done) => {
4626
- const { pageSize = 7 } = config2;
4627
- const [status, setStatus] = useState(
4628
- "loading"
4629
- );
4630
- const [searchTerm, setSearchTerm] = useState("");
4631
- const [searchResults, setSearchResults] = useState([]);
4632
- const [searchError, setSearchError] = useState();
4633
- const prefix = usePrefix({ status, theme });
4634
- const bounds = useMemo(() => {
4635
- const first = searchResults.findIndex(isSelectable);
4636
- let last = -1;
4637
- for (let i = searchResults.length - 1; i >= 0; i--) {
4638
- if (isSelectable(searchResults[i])) {
4639
- last = i;
4640
- break;
4641
- }
4642
- }
4643
- return { first, last };
4644
- }, [searchResults]);
4645
- const defaultActive = useMemo(() => {
4646
- const requested = config2.initialActive;
4647
- if (searchTerm === "" && requested !== void 0 && requested >= 0 && requested < searchResults.length && isSelectable(searchResults[requested])) {
4648
- return requested;
4649
- }
4650
- return bounds.first;
4651
- }, [searchResults, searchTerm, bounds.first]);
4652
- const [active = defaultActive, setActive] = useState();
4653
- useEffect(() => {
4654
- const controller = new AbortController();
4655
- setStatus("loading");
4656
- setSearchError(void 0);
4657
- const fetchResults = async () => {
4658
- try {
4659
- const results = await config2.source(searchTerm || void 0);
4660
- if (!controller.signal.aborted) {
4661
- setActive(void 0);
4662
- setSearchError(void 0);
4663
- setSearchResults(normalizeChoices(results));
4664
- setStatus("idle");
4665
- }
4666
- } catch (error2) {
4667
- if (!controller.signal.aborted && error2 instanceof Error) {
4668
- setSearchError(error2.message);
4669
- }
4670
- }
4671
- };
4672
- void fetchResults();
4673
- return () => {
4674
- controller.abort();
4675
- };
4676
- }, [searchTerm]);
4677
- const selectedChoice = searchResults[active];
4678
- useKeypress((key, rl) => {
4679
- if (isEnterKey(key)) {
4680
- if (selectedChoice && isSelectable(selectedChoice)) {
4681
- setStatus("done");
4682
- done(selectedChoice.value);
4683
- } else {
4684
- rl.write(searchTerm);
4685
- }
4686
- } else if (isTabKey(key) && selectedChoice && isSelectable(selectedChoice)) {
4687
- rl.clearLine(0);
4688
- rl.write(selectedChoice.name);
4689
- setSearchTerm(selectedChoice.name);
4690
- } else if (status !== "loading" && (isUpKey(key) || isDownKey(key))) {
4691
- rl.clearLine(0);
4692
- if (isUpKey(key) && active !== bounds.first || isDownKey(key) && active !== bounds.last) {
4693
- const offset = isUpKey(key) ? -1 : 1;
4694
- let next = active;
4695
- do {
4696
- next = (next + offset + searchResults.length) % searchResults.length;
4697
- } while (!isSelectable(searchResults[next]));
4698
- setActive(next);
4699
- }
4700
- } else {
4701
- setSearchTerm(rl.line);
4702
- }
4703
- });
4704
- const page = usePagination({
4705
- items: searchResults,
4706
- active,
4707
- renderItem({ item, isActive }) {
4708
- if (Separator.isSeparator(item)) {
4709
- return ` ${item.separator}`;
4710
- }
4711
- if (item.disabled) {
4712
- const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
4713
- return theme.style.disabled(`${item.name} ${disabledLabel}`);
4714
- }
4715
- const color = isActive ? theme.style.highlight : (x) => x;
4716
- const cursor = isActive ? theme.icon.cursor : ` `;
4717
- return color(`${cursor} ${item.name}`);
4718
- },
4719
- pageSize,
4720
- loop: false
4721
- });
4722
- const message = theme.style.message(config2.message, status);
4723
- if (status === "done" && selectedChoice && isSelectable(selectedChoice)) {
4724
- return [prefix, message, theme.style.answer(selectedChoice.short)].filter(Boolean).join(" ").trimEnd();
4725
- }
4726
- const searchStr = theme.style.searchTerm(searchTerm);
4727
- const helpTip = theme.style.keysHelpTip([
4728
- ["\u2191\u2193", "navigate"],
4729
- ["\u23CE", "select"]
4730
- ]);
4731
- let error;
4732
- if (searchError) {
4733
- error = theme.style.error(searchError);
4734
- } else if (searchResults.length === 0 && searchTerm !== "" && status === "idle") {
4735
- error = theme.style.error("No results found");
4736
- }
4737
- const header = [prefix, message, searchStr].filter(Boolean).join(" ").trimEnd();
4738
- const body = [error ?? page, " ", helpTip].filter(Boolean).join("\n").trimEnd();
4739
- return [header, body];
4740
- }
4741
- );
4742
-
4743
- // src/utils/controller-answer.ts
4744
5039
  function offers(question, action) {
4745
5040
  return question.actions.some((a) => a.action === action);
4746
5041
  }
@@ -4751,7 +5046,7 @@ async function promptText({
4751
5046
  message,
4752
5047
  password
4753
5048
  }) {
4754
- const { value } = await inquirer3.prompt([
5049
+ const { value } = await inquirer4.prompt([
4755
5050
  {
4756
5051
  type: password ? "password" : "input",
4757
5052
  name: "value",
@@ -4761,10 +5056,10 @@ async function promptText({
4761
5056
  ]);
4762
5057
  return value;
4763
5058
  }
4764
- var display = (c) => c.hint ? `${c.label} ${chalk3.dim(`(${c.hint})`)}` : c.label;
5059
+ var display = (c) => c.hint ? `${c.label} ${chalk5.dim(`(${c.hint})`)}` : c.label;
4765
5060
  var HIGH_CONTRAST_PROMPT_THEME = {
4766
5061
  style: {
4767
- answer: (text) => chalk3.inverse.bold(` ${text} `)
5062
+ answer: (text) => chalk5.inverse.bold(` ${text} `)
4768
5063
  }
4769
5064
  };
4770
5065
  function buildSelectRows(question, term) {
@@ -4780,8 +5075,8 @@ function buildSelectRows(question, term) {
4780
5075
  name: display(c),
4781
5076
  value: c.value
4782
5077
  }));
4783
- const skipRow = offers(question, "skip") ? [row(chalk3.dim("Skip (optional)"), "skip")] : [];
4784
- const customRow = offers(question, "custom") ? [row(chalk3.dim("Enter a value manually\u2026"), "custom")] : [];
5078
+ const skipRow = offers(question, "skip") ? [row(chalk5.dim("Skip (optional)"), "skip")] : [];
5079
+ const customRow = offers(question, "custom") ? [row(chalk5.dim("Enter a value manually\u2026"), "custom")] : [];
4785
5080
  const committed = !!t || question.search !== void 0;
4786
5081
  let rows;
4787
5082
  if (!committed) {
@@ -4792,13 +5087,13 @@ function buildSelectRows(question, term) {
4792
5087
  rows = [...customRow, ...skipRow];
4793
5088
  }
4794
5089
  if (offers(question, "search"))
4795
- rows.push(row(chalk3.cyan("Search again\u2026"), "search"));
5090
+ rows.push(row(chalk5.cyan("Search again\u2026"), "search"));
4796
5091
  if (offers(question, "next_page"))
4797
- rows.push(row(chalk3.dim("Load more\u2026"), "next_page"));
4798
- if (offers(question, "retry")) rows.push(row(chalk3.yellow("Retry"), "retry"));
4799
- if (offers(question, "cancel")) rows.push(row(chalk3.dim("Cancel"), "cancel"));
5092
+ rows.push(row(chalk5.dim("Load more\u2026"), "next_page"));
5093
+ if (offers(question, "retry")) rows.push(row(chalk5.yellow("Retry"), "retry"));
5094
+ if (offers(question, "cancel")) rows.push(row(chalk5.dim("Cancel"), "cancel"));
4800
5095
  for (const note of question.notes ?? [])
4801
- rows.push({ name: chalk3.dim(note), value: note, disabled: true });
5096
+ rows.push({ name: chalk5.dim(note), value: note, disabled: true });
4802
5097
  return rows;
4803
5098
  }
4804
5099
  function foldPage(acc, question, field) {
@@ -4839,7 +5134,7 @@ async function answerSelect(question, field, box, failed, mode) {
4839
5134
  const isClosedListPrompt = mode === "closed-list" && !failed && !view.multiple;
4840
5135
  const booleanValues = view.choices.map(({ value: value2 }) => value2);
4841
5136
  if (isClosedListPrompt && booleanValues.length === 2 && booleanValues.includes("true") && booleanValues.includes("false")) {
4842
- const { value: value2 } = await inquirer3.prompt([
5137
+ const { value: value2 } = await inquirer4.prompt([
4843
5138
  {
4844
5139
  type: "confirm",
4845
5140
  name: "value",
@@ -4855,7 +5150,7 @@ async function answerSelect(question, field, box, failed, mode) {
4855
5150
  name: display(choice),
4856
5151
  value: choice.value
4857
5152
  }));
4858
- const { value: value2 } = await inquirer3.prompt([
5153
+ const { value: value2 } = await inquirer4.prompt([
4859
5154
  {
4860
5155
  type: "list",
4861
5156
  name: "value",
@@ -4878,17 +5173,17 @@ async function answerSelect(question, field, box, failed, mode) {
4878
5173
  })),
4879
5174
  ...offers(question, "next_page") ? [
4880
5175
  {
4881
- name: chalk3.dim("Load more\u2026"),
5176
+ name: chalk5.dim("Load more\u2026"),
4882
5177
  value: { action: "next_page" }
4883
5178
  }
4884
5179
  ] : [],
4885
5180
  ...(question.notes ?? []).map((note) => ({
4886
- name: chalk3.dim(note),
5181
+ name: chalk5.dim(note),
4887
5182
  value: note,
4888
5183
  disabled: true
4889
5184
  }))
4890
5185
  ];
4891
- const { values } = await inquirer3.prompt([
5186
+ const { values } = await inquirer4.prompt([
4892
5187
  {
4893
5188
  type: "checkbox",
4894
5189
  name: "values",
@@ -4960,14 +5255,14 @@ async function answerSelect(question, field, box, failed, mode) {
4960
5255
  case "retry":
4961
5256
  return { type: "retry" };
4962
5257
  case "skip":
4963
- printAnswered(view.message, chalk3.dim("(skipped)"));
5258
+ printAnswered(view.message, chalk5.dim("(skipped)"));
4964
5259
  return { type: "skip" };
4965
5260
  case "cancel":
4966
5261
  return { type: "cancel" };
4967
5262
  }
4968
5263
  }
4969
5264
  function printAnswered(message, label) {
4970
- console.log(`${chalk3.green("\u2714")} ${message} ${chalk3.cyan(label)}`);
5265
+ console.log(`${chalk5.green("\u2714")} ${message} ${chalk5.cyan(label)}`);
4971
5266
  }
4972
5267
  async function answerInput(question) {
4973
5268
  const message = question.placeholder ? question.message.replace(/:?\s*$/, ` (${question.placeholder}):`) : question.message;
@@ -4985,7 +5280,7 @@ async function answerCollection(question) {
4985
5280
  return { type: "add" };
4986
5281
  }
4987
5282
  if (question.description) console.log(question.description);
4988
- const { again } = await inquirer3.prompt([
5283
+ const { again } = await inquirer4.prompt([
4989
5284
  {
4990
5285
  type: "confirm",
4991
5286
  name: "again",
@@ -5004,7 +5299,7 @@ function createCliAnswer({
5004
5299
  try {
5005
5300
  if (result.error !== void 0) {
5006
5301
  const message = typeof result.error === "string" ? result.error : result.error.message;
5007
- console.log(chalk3.yellow(`! ${message}`));
5302
+ console.log(chalk5.yellow(`! ${message}`));
5008
5303
  }
5009
5304
  const question = result.question;
5010
5305
  const field = question.path.length ? question.path.join(".") : "value";
@@ -5173,7 +5468,7 @@ var boltFillRanks = new Map(
5173
5468
  );
5174
5469
  var STATUS_ROW_INDEX = Math.floor(boltRows.length / 2);
5175
5470
  function formatPhase({ label, detail }) {
5176
- return detail ? `${chalk3.bold(label)} ${chalk3.dim(detail)}` : chalk3.bold(label);
5471
+ return detail ? `${chalk5.bold(label)} ${chalk5.dim(detail)}` : chalk5.bold(label);
5177
5472
  }
5178
5473
  function formatLoaderFrame({
5179
5474
  phase,
@@ -5185,7 +5480,7 @@ function formatLoaderFrame({
5185
5480
  const cellIndex = rowIndex * row.length + columnIndex;
5186
5481
  const fillRank = boltFillRanks.get(cellIndex);
5187
5482
  const isFilled = fillRank !== void 0 && fillRank < fillStage;
5188
- return isFilled ? chalk3.bold.yellow(cell) : chalk3.dim.yellow(cell);
5483
+ return isFilled ? chalk5.bold.yellow(cell) : chalk5.dim.yellow(cell);
5189
5484
  }).join("");
5190
5485
  const status = rowIndex === STATUS_ROW_INDEX ? ` ${formatPhase(phase)}` : "";
5191
5486
  return `${bolt}${status}`;
@@ -5217,12 +5512,12 @@ async function runWithSetupLoader({
5217
5512
  const result = await promise;
5218
5513
  clearInterval(animationTimer);
5219
5514
  const elapsedSeconds = ((Date.now() - startedAt) / 1e3).toFixed(1);
5220
- loader.succeed(`${formatPhase(phase)} ${chalk3.dim(`${elapsedSeconds}s`)}`);
5515
+ loader.succeed(`${formatPhase(phase)} ${chalk5.dim(`${elapsedSeconds}s`)}`);
5221
5516
  return result;
5222
5517
  } catch (error) {
5223
5518
  clearInterval(animationTimer);
5224
5519
  const elapsedSeconds = ((Date.now() - startedAt) / 1e3).toFixed(1);
5225
- loader.fail(`${formatPhase(phase)} ${chalk3.dim(`${elapsedSeconds}s`)}`);
5520
+ loader.fail(`${formatPhase(phase)} ${chalk5.dim(`${elapsedSeconds}s`)}`);
5226
5521
  throw error;
5227
5522
  }
5228
5523
  }
@@ -5713,7 +6008,7 @@ async function runCommand({
5713
6008
  detail: commandLabel
5714
6009
  });
5715
6010
  }
5716
- console.log(chalk3.dim(commandLabel));
6011
+ console.log(chalk5.dim(commandLabel));
5717
6012
  return await execute;
5718
6013
  } catch (error) {
5719
6014
  const message = error instanceof Error ? error.message : String(error);
@@ -5819,6 +6114,14 @@ function createWizardContext({
5819
6114
  imports,
5820
6115
  createAnswer: () => createCliAnswer({ mode: "closed-list" }),
5821
6116
  setupController: createSetupController(),
6117
+ selectStoredLoginCredentials: () => chooseStoredLoginCredentials({ imports, options: {} }),
6118
+ authenticateNewAccount: ({ entryPoint, headless }) => runAccountAuth({
6119
+ imports,
6120
+ options: { headless },
6121
+ entryPoint,
6122
+ storedCredentialsMode: "fresh",
6123
+ preserveExistingCredentials: true
6124
+ }),
5822
6125
  checkForUpdates,
5823
6126
  openUrl: async (url) => {
5824
6127
  await open(url);
@@ -5852,6 +6155,14 @@ function isCredentialWriteError(error) {
5852
6155
  const message = error instanceof Error ? error.message : String(error);
5853
6156
  return /permission|sandbox|eacces|eperm/i.test(message);
5854
6157
  }
6158
+ async function confirmAuthentication(context) {
6159
+ const { data: profile } = await runWithSetupLoader({
6160
+ promise: context.imports.getProfile({}),
6161
+ label: "Confirming Zapier account"
6162
+ });
6163
+ context.accountEmail = profile.email;
6164
+ console.log(`Authenticated as ${profile.email}.`);
6165
+ }
5855
6166
  async function authenticate(context) {
5856
6167
  const activeProfile = await runWithSetupLoader({
5857
6168
  promise: context.imports.getProfile({}).then(({ data }) => data).catch((error) => {
@@ -5860,7 +6171,12 @@ async function authenticate(context) {
5860
6171
  }),
5861
6172
  label: "Checking Zapier authentication"
5862
6173
  });
5863
- if (activeProfile) {
6174
+ const storedCredentialsSelection = await context.selectStoredLoginCredentials();
6175
+ if (storedCredentialsSelection === "switch") {
6176
+ await confirmAuthentication(context);
6177
+ return;
6178
+ }
6179
+ if (storedCredentialsSelection === "none" && activeProfile) {
5864
6180
  const shouldLogout = await resolveSetupConfirm({
5865
6181
  answer: context.createAnswer(),
5866
6182
  controller: context.setupController,
@@ -5901,10 +6217,14 @@ Log out and use a different account?`,
5901
6217
  ]
5902
6218
  });
5903
6219
  const headless = environment === "headless";
5904
- const runAuth = flow === "login" ? context.imports.login : context.imports.signup;
5905
6220
  printAuthCommand({ context, flow, headless });
5906
6221
  try {
5907
- await runAuth({ headless });
6222
+ if (storedCredentialsSelection === "create") {
6223
+ await context.authenticateNewAccount({ entryPoint: flow, headless });
6224
+ } else {
6225
+ const runAuth = flow === "login" ? context.imports.login : context.imports.signup;
6226
+ await runAuth({ headless });
6227
+ }
5908
6228
  } catch (error) {
5909
6229
  if (isCredentialWriteError(error)) {
5910
6230
  console.error(
@@ -5913,12 +6233,7 @@ Log out and use a different account?`,
5913
6233
  }
5914
6234
  throw error;
5915
6235
  }
5916
- const { data: profile } = await runWithSetupLoader({
5917
- promise: context.imports.getProfile({}),
5918
- label: "Confirming Zapier account"
5919
- });
5920
- context.accountEmail = profile.email;
5921
- console.log(`Authenticated as ${profile.email}.`);
6236
+ await confirmAuthentication(context);
5922
6237
  }
5923
6238
  var agentLabels = {
5924
6239
  claude: "Claude Code",
@@ -5960,7 +6275,7 @@ function printAgentPrompt({
5960
6275
  message
5961
6276
  }) {
5962
6277
  console.log();
5963
- console.log(chalk3.bgYellow.black.bold(message));
6278
+ console.log(chalk5.bgYellow.black.bold(message));
5964
6279
  console.log();
5965
6280
  console.log(buildAgentPrompt({ context }));
5966
6281
  }
@@ -6245,7 +6560,7 @@ var MINIMUM_MESSAGE_WIDTH = 20;
6245
6560
  var MAXIMUM_MESSAGE_WIDTH = 88;
6246
6561
  function showPhase({ number, title }) {
6247
6562
  console.log();
6248
- console.log(chalk3.bgCyan.black.bold(` ${number}/${PHASE_COUNT} ${title} `));
6563
+ console.log(chalk5.bgCyan.black.bold(` ${number}/${PHASE_COUNT} ${title} `));
6249
6564
  }
6250
6565
  function printWrapped(text) {
6251
6566
  const width = Math.max(
@@ -6259,7 +6574,7 @@ function printWrapped(text) {
6259
6574
  }
6260
6575
  function showReadyMessage() {
6261
6576
  console.log();
6262
- console.log(chalk3.bgGreen.black.bold(" \u2713 Zapier SDK setup complete "));
6577
+ console.log(chalk5.bgGreen.black.bold(" \u2713 Zapier SDK setup complete "));
6263
6578
  console.log();
6264
6579
  printWrapped(
6265
6580
  "Use active Zapier connections to access 9,000+ app connectors without managing each app's OAuth, token refresh, or retries."
@@ -6271,7 +6586,7 @@ function showReadyMessage() {
6271
6586
  console.log();
6272
6587
  }
6273
6588
  async function runWizard(context) {
6274
- console.log(chalk3.bold("Zapier SDK setup"));
6589
+ console.log(chalk5.bold("Zapier SDK setup"));
6275
6590
  showPhase({ number: 1, title: "Project directory" });
6276
6591
  await chooseDirectory(context);
6277
6592
  showPhase({ number: 2, title: "Node.js" });
@@ -6286,7 +6601,7 @@ async function runWizard(context) {
6286
6601
  showPhase({ number: 6, title: "Slack demo" });
6287
6602
  await offerSlackTest(context);
6288
6603
  showReadyMessage();
6289
- console.log(chalk3.bgCyan.black.bold(" Next steps "));
6604
+ console.log(chalk5.bgCyan.black.bold(" Next steps "));
6290
6605
  await openAgentHandoff(context);
6291
6606
  }
6292
6607
 
@@ -6301,7 +6616,11 @@ var setupImports = [
6301
6616
  listConnectionsRef2,
6302
6617
  loginRef,
6303
6618
  logoutRef,
6304
- signupRef
6619
+ signupRef,
6620
+ apiPluginRef,
6621
+ resolveCredentialsPluginRef,
6622
+ eventEmissionPluginRef,
6623
+ sdkOptionsPluginRef
6305
6624
  ];
6306
6625
  var setupPlugin = defineMethod({
6307
6626
  name: "setup",
@@ -6342,18 +6661,18 @@ function createInteractiveCallback() {
6342
6661
  const attrs = message.message_attributes;
6343
6662
  console.log(
6344
6663
  `
6345
- ${chalk3.bold(`Message #${messageNumber}`)} ${chalk3.dim(message.id)} ${chalk3.dim(`(lease #${attrs.lease_count})`)}`
6664
+ ${chalk5.bold(`Message #${messageNumber}`)} ${chalk5.dim(message.id)} ${chalk5.dim(`(lease #${attrs.lease_count})`)}`
6346
6665
  );
6347
6666
  if (attrs.error_message) {
6348
- console.log(chalk3.yellow(` upstream error: ${attrs.error_message}`));
6667
+ console.log(chalk5.yellow(` upstream error: ${attrs.error_message}`));
6349
6668
  }
6350
6669
  if (attrs.possible_duplicate_data) {
6351
- console.log(chalk3.yellow(" possible duplicate data"));
6670
+ console.log(chalk5.yellow(" possible duplicate data"));
6352
6671
  }
6353
6672
  while (true) {
6354
6673
  let action;
6355
6674
  try {
6356
- const answer = await inquirer3.prompt([
6675
+ const answer = await inquirer4.prompt([
6357
6676
  {
6358
6677
  type: "list",
6359
6678
  name: "action",
@@ -6378,7 +6697,7 @@ ${chalk3.bold(`Message #${messageNumber}`)} ${chalk3.dim(message.id)} ${chalk3.d
6378
6697
  throw error;
6379
6698
  }
6380
6699
  if (action === "view") {
6381
- console.log(chalk3.dim(JSON.stringify(message.payload, null, 2)));
6700
+ console.log(chalk5.dim(JSON.stringify(message.payload, null, 2)));
6382
6701
  continue;
6383
6702
  }
6384
6703
  if (action === "ack") {
@@ -6481,7 +6800,7 @@ function describeReason(reason) {
6481
6800
  }
6482
6801
  function printDrainError(reason, message) {
6483
6802
  console.error(
6484
- chalk3.red(`Error processing ${message.id}: ${describeReason(reason)}`)
6803
+ chalk5.red(`Error processing ${message.id}: ${describeReason(reason)}`)
6485
6804
  );
6486
6805
  }
6487
6806
  function printDrainSummary(counts) {
@@ -6491,7 +6810,7 @@ function printDrainSummary(counts) {
6491
6810
  if (skipped > 0) parts.push(`${skipped} skipped`);
6492
6811
  parts.push(`${counts.rejected} rejected`);
6493
6812
  console.log(
6494
- chalk3.dim(
6813
+ chalk5.dim(
6495
6814
  `
6496
6815
  Processed ${total} message${total === 1 ? "" : "s"} (${parts.join(", ")}).`
6497
6816
  )
@@ -6499,7 +6818,7 @@ Processed ${total} message${total === 1 ? "" : "s"} (${parts.join(", ")}).`
6499
6818
  }
6500
6819
  function warnInteractiveContinueOnErrorOverride() {
6501
6820
  console.warn(
6502
- chalk3.yellow(
6821
+ chalk5.yellow(
6503
6822
  'Note: continueOnError=false is overridden to true in interactive mode (the "Skip (let lease expire)" choice would otherwise terminate the drain).'
6504
6823
  )
6505
6824
  );
@@ -6820,7 +7139,7 @@ function collectDeprecationNoticeAndForward(event, onEvent) {
6820
7139
  // package.json with { type: 'json' }
6821
7140
  var package_default = {
6822
7141
  name: "@zapier/zapier-sdk-cli",
6823
- version: "0.77.8"};
7142
+ version: "0.78.0"};
6824
7143
 
6825
7144
  // src/sdk.ts
6826
7145
  var warnedDeprecatedMethods = /* @__PURE__ */ new Set();
@@ -6831,9 +7150,9 @@ var cliCoreOptions = {
6831
7150
  warnedDeprecatedMethods.add(methodName);
6832
7151
  console.warn();
6833
7152
  console.warn(
6834
- chalk3.yellow.bold("\u26A0\uFE0F DEPRECATION WARNING") + chalk3.yellow(` - \`${toKebabCase(methodName)}\` is deprecated.`)
7153
+ chalk5.yellow.bold("\u26A0\uFE0F DEPRECATION WARNING") + chalk5.yellow(` - \`${toKebabCase(methodName)}\` is deprecated.`)
6835
7154
  );
6836
- console.warn(chalk3.yellow(` ${deprecation.message}`));
7155
+ console.warn(chalk5.yellow(` ${deprecation.message}`));
6837
7156
  console.warn();
6838
7157
  }
6839
7158
  };
@@ -6904,7 +7223,7 @@ function createZapierCliSdk(options = {}) {
6904
7223
 
6905
7224
  // package.json
6906
7225
  var package_default2 = {
6907
- version: "0.77.8"};
7226
+ version: "0.78.0"};
6908
7227
 
6909
7228
  // src/telemetry/builders.ts
6910
7229
  function createCliBaseEvent(context = {}) {