@bigcommerce/catalyst 1.0.0-alpha.5 → 1.0.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -28,7 +28,7 @@ import { randomBytes, randomUUID } from "crypto";
28
28
  // package.json
29
29
  var package_default = {
30
30
  name: "@bigcommerce/catalyst",
31
- version: "1.0.0-alpha.5",
31
+ version: "1.0.0-alpha.6",
32
32
  type: "module",
33
33
  bin: {
34
34
  catalyst: "dist/cli.js"
@@ -197,7 +197,7 @@ function getTelemetry() {
197
197
  // src/cli/program.ts
198
198
  import { Option as Option9 } from "@commander-js/extra-typings";
199
199
  import { Command as Command12 } from "commander";
200
- import { colorize as colorize8 } from "consola/utils";
200
+ import { colorize as colorize9 } from "consola/utils";
201
201
  import { config } from "dotenv";
202
202
  import { existsSync as existsSync5 } from "fs";
203
203
  import { resolve } from "path";
@@ -207,7 +207,7 @@ import { Command, Option as Option2 } from "commander";
207
207
  import { z as z4 } from "zod";
208
208
 
209
209
  // src/cli/lib/login.ts
210
- import { password } from "@inquirer/prompts";
210
+ import { confirm, input, password } from "@inquirer/prompts";
211
211
  import { colorize } from "consola/utils";
212
212
  import open from "open";
213
213
  import yoctoSpinner from "yocto-spinner";
@@ -337,8 +337,8 @@ async function manualLogin(apiHost) {
337
337
  Settings \u2192 API \u2192 Store-level API accounts \u2192 Create API account
338
338
  Grant these OAuth scopes: ${DEVICE_OAUTH_SCOPES}`
339
339
  );
340
- const storeHashInput = await consola.prompt("Store hash:", { type: "text" });
341
- const storeHash = String(storeHashInput).trim();
340
+ const storeHashInput = await input({ message: "Store hash:" });
341
+ const storeHash = storeHashInput.trim();
342
342
  if (!storeHash) {
343
343
  throw new Error("Store hash is required.");
344
344
  }
@@ -366,10 +366,10 @@ async function login(loginUrl, apiHost) {
366
366
  } catch (error) {
367
367
  const message = error instanceof Error ? error.message : String(error);
368
368
  consola.warn(`Browser login didn't work (${message}).`);
369
- const shouldFallback = await consola.prompt(
370
- "Try logging in manually with a store hash and access token instead?",
371
- { type: "confirm", initial: true }
372
- );
369
+ const shouldFallback = await confirm({
370
+ message: "Try logging in manually with a store hash and access token instead?",
371
+ default: true
372
+ });
373
373
  if (!shouldFallback) {
374
374
  throw new LoginAbortedError();
375
375
  }
@@ -783,12 +783,17 @@ function getProjectState(cwd = process.cwd()) {
783
783
  }
784
784
 
785
785
  // src/cli/lib/wrangler-config.ts
786
+ function getCompatibilityDate(now = /* @__PURE__ */ new Date()) {
787
+ const date = new Date(now);
788
+ date.setUTCMonth(date.getUTCMonth() - 1);
789
+ return date.toISOString().slice(0, 10);
790
+ }
786
791
  function getWranglerConfig(projectUuid) {
787
792
  return {
788
793
  $schema: "node_modules/wrangler/config-schema.json",
789
794
  main: "../.open-next/worker.js",
790
795
  name: `project-${projectUuid}`,
791
- compatibility_date: "2025-09-15",
796
+ compatibility_date: getCompatibilityDate(),
792
797
  compatibility_flags: ["nodejs_compat", "global_fetch_strictly_public"],
793
798
  observability: {
794
799
  enabled: true,
@@ -935,7 +940,14 @@ Examples:
935
940
  });
936
941
 
937
942
  // src/cli/commands/channel.ts
938
- import { Command as Command3, Option as Option4 } from "commander";
943
+ import { select as select3 } from "@inquirer/prompts";
944
+ import { Command as Command3, InvalidArgumentError, Option as Option4 } from "commander";
945
+ import { colorize as colorize3 } from "consola/utils";
946
+ import { outputFileSync } from "fs-extra/esm";
947
+ import { join as join6 } from "path";
948
+
949
+ // src/cli/lib/channel-site-flow.ts
950
+ import { select as select2 } from "@inquirer/prompts";
939
951
 
940
952
  // src/cli/lib/channels.ts
941
953
  import { z as z6 } from "zod";
@@ -958,6 +970,20 @@ var channelSchema = z6.object({
958
970
  var channelsResponseSchema = z6.object({
959
971
  data: z6.array(channelSchema)
960
972
  });
973
+ var CHANNEL_PLATFORM_ORDER = ["catalyst", "next", "bigcommerce"];
974
+ function sortChannelsByPlatform(channels) {
975
+ return [...channels].sort((a, b) => {
976
+ const aIndex = CHANNEL_PLATFORM_ORDER.indexOf(a.platform);
977
+ const bIndex = CHANNEL_PLATFORM_ORDER.indexOf(b.platform);
978
+ if (aIndex === -1 && bIndex === -1) return 0;
979
+ if (aIndex === -1) return 1;
980
+ if (bIndex === -1) return -1;
981
+ return aIndex - bIndex;
982
+ });
983
+ }
984
+ function channelPlatformLabel(platform) {
985
+ return platform === "bigcommerce" ? "Stencil" : platform.charAt(0).toUpperCase() + platform.slice(1);
986
+ }
961
987
  var initResponseSchema = z6.object({
962
988
  data: z6.object({
963
989
  storefront_api_token: z6.string(),
@@ -1078,7 +1104,7 @@ async function updateChannelSiteUrl(channelId, siteUrl, storeHash, accessToken,
1078
1104
  }
1079
1105
 
1080
1106
  // src/cli/lib/commerce-hosting.ts
1081
- import { input, select, Separator } from "@inquirer/prompts";
1107
+ import { confirm as confirm2, input as input2, select, Separator } from "@inquirer/prompts";
1082
1108
  import { colorize as colorize2 } from "consola/utils";
1083
1109
  import {
1084
1110
  existsSync as existsSync2,
@@ -1159,11 +1185,10 @@ var cleanupCloudflareIncompatibilities = async (projectDir) => {
1159
1185
  );
1160
1186
  return;
1161
1187
  }
1162
- const shouldRemove = await consola.prompt(
1163
- 'Catalyst found core/instrumentation.ts, which is incompatible with the Cloudflare Workers bundle when it uses @vercel/otel (causes "Failed to prepare server" at cold start). Remove it and drop @vercel/otel from core/package.json?',
1164
- { type: "confirm", initial: true }
1165
- );
1166
- consola.log("");
1188
+ const shouldRemove = await confirm2({
1189
+ message: 'Catalyst found core/instrumentation.ts, which is incompatible with the Cloudflare Workers bundle when it uses @vercel/otel (causes "Failed to prepare server" at cold start). Remove it and drop @vercel/otel from core/package.json?',
1190
+ default: true
1191
+ });
1167
1192
  if (!shouldRemove) {
1168
1193
  consola.info(
1169
1194
  'Leaving core/instrumentation.ts in place. The Cloudflare worker will continue to log "Failed to prepare server" at cold start until this is resolved manually.'
@@ -1214,15 +1239,8 @@ var NoLinkedProjectError = class extends Error {
1214
1239
  }
1215
1240
  };
1216
1241
  async function promptForNewProjectName(api) {
1217
- const newProjectName = await consola.prompt("Enter a name for the new project:", {
1218
- type: "text"
1219
- });
1220
- const data = await createProject(
1221
- String(newProjectName),
1222
- api.storeHash,
1223
- api.accessToken,
1224
- api.apiHost
1225
- );
1242
+ const newProjectName = await input2({ message: "Enter a name for the new project:" });
1243
+ const data = await createProject(newProjectName, api.storeHash, api.accessToken, api.apiHost);
1226
1244
  consola.success(`Project "${data.name}" created successfully.`);
1227
1245
  return { uuid: data.uuid, name: data.name, deployment_hostnames: [] };
1228
1246
  }
@@ -1231,31 +1249,31 @@ async function selectOrCreateInfrastructureProject(api, linkedProjectUuid) {
1231
1249
  const existingProjects = await fetchProjects(api.storeHash, api.accessToken, api.apiHost);
1232
1250
  consola.success("Projects fetched.");
1233
1251
  if (existingProjects.length === 0) {
1234
- const shouldCreate = await consola.prompt(
1235
- "There are not any hosting projects that you can link to yet. Would you like to create one?",
1236
- { type: "confirm", initial: true }
1237
- );
1252
+ const shouldCreate = await confirm2({
1253
+ message: "There are not any hosting projects that you can link to yet. Would you like to create one?",
1254
+ default: true
1255
+ });
1238
1256
  if (!shouldCreate) {
1239
1257
  throw new NoLinkedProjectError();
1240
1258
  }
1241
1259
  return promptForNewProjectName(api);
1242
1260
  }
1243
- const promptOptions = [
1261
+ const choices = [
1244
1262
  ...existingProjects.map((p) => ({
1245
- label: p.uuid === linkedProjectUuid ? `${p.name} ${colorize2("green", "[linked]")}` : p.name,
1263
+ name: p.uuid === linkedProjectUuid ? `${p.name} ${colorize2("green", "[linked]")}` : p.name,
1246
1264
  value: p.uuid,
1247
- hint: p.uuid
1265
+ description: p.uuid
1248
1266
  })),
1249
1267
  {
1250
- label: "Create a new project",
1268
+ name: "Create a new project",
1251
1269
  value: "create",
1252
- hint: "Create a new hosting project for this Catalyst storefront."
1270
+ description: "Create a new hosting project for this Catalyst storefront."
1253
1271
  }
1254
1272
  ];
1255
- const selected = await consola.prompt(
1256
- "Select a project or create a new project (Press <enter> to select).",
1257
- { type: "select", options: promptOptions, cancel: "reject" }
1258
- );
1273
+ const selected = await select({
1274
+ message: "Select a project or create a new project (Press <enter> to select).",
1275
+ choices
1276
+ });
1259
1277
  if (selected === "create") {
1260
1278
  return promptForNewProjectName(api);
1261
1279
  }
@@ -1325,7 +1343,7 @@ async function promptForCommerceHostingProject(api, defaultName, autoUseDefaultN
1325
1343
  return selected;
1326
1344
  }
1327
1345
  async function promptAndCreateCommerceHostingProject(api, takenNames, defaultName) {
1328
- const projectName = await input({
1346
+ const projectName = await input2({
1329
1347
  message: "What would you like to name your Commerce Hosting project?",
1330
1348
  default: defaultName,
1331
1349
  validate: (value) => {
@@ -1439,16 +1457,14 @@ async function resolveChannel(options) {
1439
1457
  "No Catalyst channels found on this store. Create one with `catalyst create` and try again."
1440
1458
  );
1441
1459
  }
1442
- const selectedId = await consola.prompt("Select the channel to update.", {
1443
- type: "select",
1444
- options: catalystChannels.map((c) => ({
1445
- label: c.name,
1446
- value: String(c.id),
1447
- hint: `id: ${c.id}`
1448
- })),
1449
- cancel: "reject"
1460
+ const id = await select2({
1461
+ message: "Select the channel to update.",
1462
+ choices: catalystChannels.map((c) => ({
1463
+ name: c.name,
1464
+ value: c.id,
1465
+ description: `id: ${c.id}`
1466
+ }))
1450
1467
  });
1451
- const id = Number(selectedId);
1452
1468
  const matched = catalystChannels.find((c) => c.id === id);
1453
1469
  return { id, name: matched?.name };
1454
1470
  }
@@ -1465,12 +1481,11 @@ async function resolveHostname(project2, options) {
1465
1481
  ...project2.deployment_hostnames.filter((h) => h === options.preferHostname),
1466
1482
  ...project2.deployment_hostnames.filter((h) => h !== options.preferHostname)
1467
1483
  ] : project2.deployment_hostnames;
1468
- const selected = await consola.prompt("Select the hostname to point the channel at.", {
1469
- type: "select",
1470
- options: ordered.map((h) => ({ label: h, value: h })),
1471
- cancel: "reject"
1484
+ const selected = await select2({
1485
+ message: "Select the hostname to point the channel at.",
1486
+ choices: ordered.map((h) => ({ name: h, value: h }))
1472
1487
  });
1473
- return String(selected);
1488
+ return selected;
1474
1489
  }
1475
1490
  async function runChannelSiteUrlFlow(options) {
1476
1491
  const project2 = await resolveProject(options);
@@ -1488,6 +1503,38 @@ async function runChannelSiteUrlFlow(options) {
1488
1503
  consola.success(`Updated channel ${channelLabel} site URL to ${siteUrl}.`);
1489
1504
  }
1490
1505
 
1506
+ // src/cli/lib/env-config.ts
1507
+ var ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
1508
+ var parseEnvAssignment = (input5) => {
1509
+ const separatorIndex = input5.indexOf("=");
1510
+ if (separatorIndex === -1) {
1511
+ throw new Error(`Invalid env var format: ${input5}. Expected format: KEY=VALUE`);
1512
+ }
1513
+ const key = input5.slice(0, separatorIndex).trim();
1514
+ const value = input5.slice(separatorIndex + 1).trim();
1515
+ if (!key || !value) {
1516
+ throw new Error(`Invalid env var format: ${input5}. Expected format: KEY=VALUE`);
1517
+ }
1518
+ if (!ENV_KEY_PATTERN.test(key)) {
1519
+ throw new Error(
1520
+ `Invalid env var name: ${key}. Names must start with a letter or underscore and contain only letters, numbers, and underscores.`
1521
+ );
1522
+ }
1523
+ return { key, value };
1524
+ };
1525
+ var getStoredEnv = (config2) => {
1526
+ return config2.get("env") ?? {};
1527
+ };
1528
+ var toDeploymentSecrets = (envVars) => {
1529
+ return Object.entries(envVars).map(([key, value]) => ({ type: "secret", key, value }));
1530
+ };
1531
+ var mergeDeploymentSecrets = (persisted, flagSecrets) => {
1532
+ const byKey = /* @__PURE__ */ new Map();
1533
+ persisted.forEach((secret) => byKey.set(secret.key, secret));
1534
+ flagSecrets.forEach((secret) => byKey.set(secret.key, secret));
1535
+ return Array.from(byKey.values());
1536
+ };
1537
+
1491
1538
  // src/cli/lib/resolve-credentials.ts
1492
1539
  function resolveCredentials(options, config2) {
1493
1540
  const storeHash = options.storeHash ?? config2.get("storeHash");
@@ -1504,6 +1551,31 @@ function resolveCredentials(options, config2) {
1504
1551
  }
1505
1552
 
1506
1553
  // src/cli/commands/channel.ts
1554
+ var parseChannelId = (value) => {
1555
+ const parsed = Number.parseInt(value, 10);
1556
+ if (Number.isNaN(parsed)) {
1557
+ throw new InvalidArgumentError(`"${value}" is not a valid channel ID (expected a number).`);
1558
+ }
1559
+ return parsed;
1560
+ };
1561
+ async function resolveCredentialsWithLogin(options, config2) {
1562
+ const storeHash = options.storeHash ?? config2.get("storeHash");
1563
+ const accessToken = options.accessToken ?? config2.get("accessToken");
1564
+ if (storeHash && accessToken) {
1565
+ return { storeHash, accessToken };
1566
+ }
1567
+ try {
1568
+ const credentials = await login(options.loginUrl, options.apiHost);
1569
+ config2.set("storeHash", credentials.storeHash);
1570
+ config2.set("accessToken", credentials.accessToken);
1571
+ return credentials;
1572
+ } catch (error) {
1573
+ if (error instanceof LoginAbortedError) {
1574
+ return null;
1575
+ }
1576
+ throw error;
1577
+ }
1578
+ }
1507
1579
  var update = new Command3("update").configureHelp({ showGlobalOptions: true }).description(
1508
1580
  "Update a BigCommerce channel's site URL to point at one of your project's deployment hostnames."
1509
1581
  ).addHelpText(
@@ -1550,33 +1622,111 @@ Examples:
1550
1622
  }
1551
1623
  process.exit(0);
1552
1624
  });
1553
- var channel = new Command3("channel").configureHelp({ showGlobalOptions: true }).description("Manage BigCommerce channels.").addCommand(update);
1625
+ var link = new Command3("link").configureHelp({ showGlobalOptions: true }).description(
1626
+ "Link this Catalyst project to a BigCommerce channel and write its credentials to .env.local."
1627
+ ).addHelpText(
1628
+ "after",
1629
+ `
1630
+ Examples:
1631
+ # Pick a channel interactively (logs you in if needed)
1632
+ $ catalyst channel link
1633
+
1634
+ # Non-interactive
1635
+ $ catalyst channel link --store-hash <hash> --access-token <token> --channel-id 123
1636
+
1637
+ # Append extra environment variables to .env.local
1638
+ $ catalyst channel link --channel-id 123 --env MY_FLAG=1`
1639
+ ).addOption(storeHashOption()).addOption(accessTokenOption()).addOption(apiHostOption()).addOption(loginUrlOption()).addOption(
1640
+ new Option4("--channel-id <id>", "Link this channel directly, skipping the picker.").argParser(
1641
+ parseChannelId
1642
+ )
1643
+ ).option(
1644
+ "--env <vars...>",
1645
+ "Arbitrary environment variables to set in .env.local. Format: KEY=VALUE (repeatable)."
1646
+ ).addOption(
1647
+ new Option4("--cli-api-origin <origin>", "Catalyst CLI API origin").default("https://cxm-prd.bigcommerceapp.com").hideHelp()
1648
+ ).action(async (options) => {
1649
+ const config2 = getProjectConfig();
1650
+ const credentials = await resolveCredentialsWithLogin(options, config2);
1651
+ if (!credentials) {
1652
+ consola.info(
1653
+ "Login aborted. Re-run `catalyst channel link` when you have your credentials ready."
1654
+ );
1655
+ process.exit(0);
1656
+ return;
1657
+ }
1658
+ const { storeHash, accessToken } = credentials;
1659
+ await getTelemetry().identify(storeHash);
1660
+ let channelId = options.channelId;
1661
+ let channelName;
1662
+ if (channelId === void 0) {
1663
+ const channels = await fetchAvailableChannels(storeHash, accessToken, options.apiHost);
1664
+ if (channels.length === 0) {
1665
+ consola.info(
1666
+ "No storefront channels found on this store. Create one with `catalyst create` and try again."
1667
+ );
1668
+ process.exit(0);
1669
+ return;
1670
+ }
1671
+ channelId = await select3({
1672
+ message: "Which channel would you like to link?",
1673
+ choices: sortChannelsByPlatform(channels).map((c) => ({
1674
+ name: c.name,
1675
+ value: c.id,
1676
+ description: channelPlatformLabel(c.platform)
1677
+ }))
1678
+ });
1679
+ channelName = channels.find((c) => c.id === channelId)?.name;
1680
+ }
1681
+ const initData = await getChannelInit(channelId, storeHash, accessToken, options.cliApiOrigin);
1682
+ const envVars = { ...initData.envVars };
1683
+ if (options.env) {
1684
+ options.env.forEach((entry) => {
1685
+ const { key, value } = parseEnvAssignment(entry);
1686
+ envVars[key] = value;
1687
+ });
1688
+ }
1689
+ outputFileSync(
1690
+ join6(process.cwd(), ".env.local"),
1691
+ `${Object.entries(envVars).map(([key, value]) => `${key}=${value}`).join("\n")}
1692
+ `
1693
+ );
1694
+ const label = channelName ? `"${channelName}" (${channelId})` : `${channelId}`;
1695
+ consola.success(
1696
+ `Linked to channel ${label} and wrote ${colorize3("cyanBright", ".env.local")}.`
1697
+ );
1698
+ consola.log(`Next steps:
1699
+
1700
+ ${colorize3("yellow", "pnpm run dev")}`);
1701
+ process.exit(0);
1702
+ });
1703
+ var channel = new Command3("channel").configureHelp({ showGlobalOptions: true }).description("Manage BigCommerce channels.").addCommand(link).addCommand(update);
1554
1704
 
1555
1705
  // src/cli/commands/create.ts
1556
- import { Command as Command4, InvalidArgumentError, Option as Option5 } from "@commander-js/extra-typings";
1557
- import { input as input2, select as select2 } from "@inquirer/prompts";
1706
+ import { Command as Command4, InvalidArgumentError as InvalidArgumentError2, Option as Option5 } from "@commander-js/extra-typings";
1707
+ import { checkbox, input as input3, select as select4 } from "@inquirer/prompts";
1558
1708
  import { execSync as execSync4 } from "child_process";
1559
- import { colorize as colorize3 } from "consola/utils";
1709
+ import { colorize as colorize4 } from "consola/utils";
1560
1710
  import { pathExistsSync } from "fs-extra/esm";
1561
1711
  import kebabCase from "lodash.kebabcase";
1562
- import { join as join9 } from "path";
1712
+ import { join as join10 } from "path";
1563
1713
 
1564
1714
  // src/cli/lib/build-workspace-packages.ts
1565
1715
  import { execSync } from "child_process";
1566
1716
  import { existsSync as existsSync3 } from "fs";
1567
- import { join as join6 } from "path";
1717
+ import { join as join7 } from "path";
1568
1718
  import yoctoSpinner2 from "yocto-spinner";
1569
1719
  var WORKSPACE_PACKAGES = ["packages/catalyst", "packages/client"];
1570
1720
  var buildWorkspacePackages = (projectDir) => {
1571
- const hasCore = existsSync3(join6(projectDir, "core"));
1721
+ const hasCore = existsSync3(join7(projectDir, "core"));
1572
1722
  const hasAllWorkspacePackages = WORKSPACE_PACKAGES.every(
1573
- (pkg) => existsSync3(join6(projectDir, pkg))
1723
+ (pkg) => existsSync3(join7(projectDir, pkg))
1574
1724
  );
1575
1725
  if (!hasCore || !hasAllWorkspacePackages) return;
1576
1726
  WORKSPACE_PACKAGES.forEach((pkg) => {
1577
1727
  const spinner = yoctoSpinner2().start(`Building ${pkg}...`);
1578
1728
  try {
1579
- execSync("pnpm build", { cwd: join6(projectDir, pkg), stdio: "ignore" });
1729
+ execSync("pnpm build", { cwd: join7(projectDir, pkg), stdio: "ignore" });
1580
1730
  spinner.success(`Built ${pkg}.`);
1581
1731
  } catch (error) {
1582
1732
  const message = error instanceof Error ? error.message : "unknown error";
@@ -1758,7 +1908,7 @@ var getAvailableLocales = async (storeHash, accessToken, apiHost) => {
1758
1908
 
1759
1909
  // src/cli/lib/setup-core-project.ts
1760
1910
  import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
1761
- import { dirname as dirname3, join as join7 } from "path";
1911
+ import { dirname as dirname3, join as join8 } from "path";
1762
1912
  import { z as z9 } from "zod";
1763
1913
  var corePackageJsonSchema2 = z9.looseObject({
1764
1914
  scripts: z9.record(z9.string(), z9.string()).optional(),
@@ -1770,7 +1920,7 @@ var writeJson2 = (path, value) => {
1770
1920
  `);
1771
1921
  };
1772
1922
  var setupCoreProject = (projectDir) => {
1773
- const corePackageJsonPath = join7(projectDir, "core", "package.json");
1923
+ const corePackageJsonPath = join8(projectDir, "core", "package.json");
1774
1924
  const pkg = corePackageJsonSchema2.parse(JSON.parse(readFileSync3(corePackageJsonPath, "utf-8")));
1775
1925
  pkg.scripts = {
1776
1926
  ...pkg.scripts,
@@ -1786,11 +1936,11 @@ var setupCoreProject = (projectDir) => {
1786
1936
  };
1787
1937
 
1788
1938
  // src/cli/lib/write-env.ts
1789
- import { outputFileSync } from "fs-extra/esm";
1790
- import { join as join8 } from "path";
1939
+ import { outputFileSync as outputFileSync2 } from "fs-extra/esm";
1940
+ import { join as join9 } from "path";
1791
1941
  var writeEnv = (projectDir, envVars) => {
1792
- outputFileSync(
1793
- join8(projectDir, "core", ".env.local"),
1942
+ outputFileSync2(
1943
+ join9(projectDir, "core", ".env.local"),
1794
1944
  `${Object.entries(envVars).map(([key, value]) => `${key}=${value}`).join("\n")}
1795
1945
  `
1796
1946
  );
@@ -1801,41 +1951,41 @@ function getPlatformCheckCommand(command) {
1801
1951
  const isWindows = process.platform === "win32";
1802
1952
  return isWindows ? `where.exe ${command}` : `which ${command}`;
1803
1953
  }
1804
- function parseChannelId(value) {
1954
+ function parseChannelId2(value) {
1805
1955
  const parsed = parseInt(value, 10);
1806
1956
  if (Number.isNaN(parsed)) {
1807
- throw new InvalidArgumentError(`"${value}" is not a valid channel ID (expected a number).`);
1957
+ throw new InvalidArgumentError2(`"${value}" is not a valid channel ID (expected a number).`);
1808
1958
  }
1809
1959
  return parsed;
1810
1960
  }
1811
1961
  function parseEnvFlag(value, previous = {}) {
1812
1962
  const eqIdx = value.indexOf("=");
1813
1963
  if (eqIdx <= 0) {
1814
- throw new InvalidArgumentError(`Expected KEY=VALUE, got "${value}".`);
1964
+ throw new InvalidArgumentError2(`Expected KEY=VALUE, got "${value}".`);
1815
1965
  }
1816
1966
  const key = value.substring(0, eqIdx);
1817
1967
  const val = value.substring(eqIdx + 1);
1818
1968
  if (!val) {
1819
- throw new InvalidArgumentError(`Expected KEY=VALUE with non-empty value, got "${value}".`);
1969
+ throw new InvalidArgumentError2(`Expected KEY=VALUE with non-empty value, got "${value}".`);
1820
1970
  }
1821
1971
  return { ...previous, [key]: val };
1822
1972
  }
1823
1973
  async function handleChannelCreation(storeHash, accessToken, apiHost, cliApiOrigin) {
1824
- const newChannelName = await input2({
1974
+ const newChannelName = await input3({
1825
1975
  message: "What would you like to name your new channel?"
1826
1976
  });
1827
1977
  const availableLocales = await getAvailableLocales(storeHash, accessToken, apiHost);
1828
- const storefrontLocale = await select2({
1978
+ const storefrontLocale = await select4({
1829
1979
  message: "Which default language would you like to set for your channel?",
1830
1980
  default: "en",
1831
1981
  choices: availableLocales,
1832
1982
  theme: {
1833
1983
  style: {
1834
- help: () => colorize3("dim", "(Select locale from the list or start typing the name)")
1984
+ help: () => colorize4("dim", "(Select locale from the list or start typing the name)")
1835
1985
  }
1836
1986
  }
1837
1987
  });
1838
- const shouldAddAdditionalLocales = await select2({
1988
+ const shouldAddAdditionalLocales = await select4({
1839
1989
  message: "Would you like to add additional languages?",
1840
1990
  choices: [
1841
1991
  { name: "Yes", value: true },
@@ -1844,21 +1994,14 @@ async function handleChannelCreation(storeHash, accessToken, apiHost, cliApiOrig
1844
1994
  });
1845
1995
  let additionalLocales = [];
1846
1996
  if (shouldAddAdditionalLocales) {
1847
- const localeOptions = availableLocales.filter(({ value }) => value !== storefrontLocale).map(({ name, value }) => ({ label: name, value, hint: value }));
1848
- const pickLocales = async () => {
1849
- const selected = await consola.prompt(
1850
- "Which additional languages would you like to add to your channel?",
1851
- { type: "multiselect", options: localeOptions, cancel: "reject" }
1852
- );
1853
- if (selected.length > 4) {
1854
- consola.warn("You can only select up to 4 additional languages. Please try again.");
1855
- return pickLocales();
1856
- }
1857
- return selected;
1858
- };
1859
- additionalLocales = await pickLocales();
1997
+ const localeChoices = availableLocales.filter(({ value }) => value !== storefrontLocale).map(({ name, value }) => ({ name, value, description: value }));
1998
+ additionalLocales = await checkbox({
1999
+ message: "Which additional languages would you like to add to your channel?",
2000
+ choices: localeChoices,
2001
+ validate: (items) => items.length <= 4 || "You can only select up to 4 additional languages."
2002
+ });
1860
2003
  }
1861
- const shouldInstallSampleData = await select2({
2004
+ const shouldInstallSampleData = await select4({
1862
2005
  message: "Would you like to install sample data?",
1863
2006
  choices: [
1864
2007
  { name: "Yes", value: true },
@@ -1876,23 +2019,13 @@ async function handleChannelCreation(storeHash, accessToken, apiHost, cliApiOrig
1876
2019
  );
1877
2020
  }
1878
2021
  async function handleChannelSelection(storeHash, accessToken, apiHost) {
1879
- const channelSortOrder = ["catalyst", "next", "bigcommerce"];
1880
2022
  const channels = await fetchAvailableChannels(storeHash, accessToken, apiHost);
1881
- const existingChannel = await select2({
2023
+ const existingChannel = await select4({
1882
2024
  message: "Which channel would you like to use?",
1883
- choices: channels.sort((a, b) => {
1884
- const aIndex = channelSortOrder.indexOf(a.platform);
1885
- const bIndex = channelSortOrder.indexOf(b.platform);
1886
- if (aIndex === -1 && bIndex === -1) {
1887
- return 0;
1888
- }
1889
- if (aIndex === -1) return 1;
1890
- if (bIndex === -1) return -1;
1891
- return aIndex - bIndex;
1892
- }).map((ch) => ({
2025
+ choices: sortChannelsByPlatform(channels).map((ch) => ({
1893
2026
  name: ch.name,
1894
2027
  value: ch,
1895
- description: `Channel Platform: ${ch.platform === "bigcommerce" ? "Stencil" : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)}`
2028
+ description: `Channel Platform: ${channelPlatformLabel(ch.platform)}`
1896
2029
  }))
1897
2030
  });
1898
2031
  return existingChannel.id;
@@ -1905,7 +2038,7 @@ async function setupProject(options) {
1905
2038
  }
1906
2039
  if (projectName) {
1907
2040
  projectName = kebabCase(projectName);
1908
- projectDir = join9(options.projectDir, projectName);
2041
+ projectDir = join10(options.projectDir, projectName);
1909
2042
  if (pathExistsSync(projectDir)) {
1910
2043
  consola.error(`${projectDir} already exists`);
1911
2044
  process.exit(1);
@@ -1915,13 +2048,13 @@ async function setupProject(options) {
1915
2048
  const validateProjectName = (i) => {
1916
2049
  const formatted = kebabCase(i);
1917
2050
  if (!formatted) return "Project name is required";
1918
- const targetDir = join9(options.projectDir, formatted);
2051
+ const targetDir = join10(options.projectDir, formatted);
1919
2052
  if (pathExistsSync(targetDir)) return `Destination '${targetDir}' already exists`;
1920
2053
  projectName = formatted;
1921
2054
  projectDir = targetDir;
1922
2055
  return true;
1923
2056
  };
1924
- await input2({
2057
+ await input3({
1925
2058
  message: "What do you want to name your project directory?",
1926
2059
  default: "my-catalyst-app",
1927
2060
  validate: validateProjectName
@@ -1959,7 +2092,7 @@ Examples:
1959
2092
 
1960
2093
  # Eagerly set up Commerce Hosting at create time
1961
2094
  $ catalyst create --project-name my-store --hosting commerce`
1962
- ).option("--project-name <name>", "Name of your Catalyst project").option("--project-dir <dir>", "Directory in which to create your project", process.cwd()).addOption(storeHashOption()).addOption(accessTokenOption()).option("--channel-id <id>", "BigCommerce channel ID", parseChannelId).option("--storefront-token <token>", "BigCommerce storefront token").option(
2095
+ ).option("--project-name <name>", "Name of your Catalyst project").option("--project-dir <dir>", "Directory in which to create your project", process.cwd()).addOption(storeHashOption()).addOption(accessTokenOption()).option("--channel-id <id>", "BigCommerce channel ID", parseChannelId2).option("--storefront-token <token>", "BigCommerce storefront token").option(
1963
2096
  "--gh-ref <ref>",
1964
2097
  "Clone a specific ref from the source repository",
1965
2098
  "@bigcommerce/catalyst-core@latest"
@@ -2034,7 +2167,7 @@ Examples:
2034
2167
  }
2035
2168
  let shouldCreateChannel;
2036
2169
  if (eligibility.eligible) {
2037
- shouldCreateChannel = await select2({
2170
+ shouldCreateChannel = await select4({
2038
2171
  message: "Would you like to create a new channel?",
2039
2172
  choices: [
2040
2173
  { name: "Yes", value: true },
@@ -2116,24 +2249,26 @@ Examples:
2116
2249
  throw error;
2117
2250
  }
2118
2251
  consola.success(`Created '${projectName}' at '${projectDir}'`);
2119
- consola.info("Next steps:");
2120
- consola.info(colorize3("yellow", ` cd ${projectName}/core && pnpm run dev`));
2252
+ const steps = [`cd ${projectName}/core && pnpm run dev`];
2121
2253
  if (useCommerceHosting) {
2122
- consola.info(
2123
- colorize3(
2124
- "yellow",
2125
- ` Run 'cd ${projectName}/core && pnpm run deploy' when ready to deploy to Commerce Hosting.`
2126
- )
2254
+ steps.push(
2255
+ `Run 'cd ${projectName}/core && pnpm run deploy' when ready to deploy to Commerce Hosting.`
2127
2256
  );
2128
2257
  }
2258
+ consola.log(
2259
+ `Next steps:
2260
+
2261
+ ${steps.map((step) => ` ${colorize4("yellow", step)}`).join("\n")}`
2262
+ );
2129
2263
  });
2130
2264
 
2131
2265
  // src/cli/commands/deploy.ts
2266
+ import { confirm as confirm3 } from "@inquirer/prompts";
2132
2267
  import AdmZip from "adm-zip";
2133
2268
  import { Command as Command5, Option as Option6 } from "commander";
2134
- import { colorize as colorize4 } from "consola/utils";
2269
+ import { colorize as colorize5 } from "consola/utils";
2135
2270
  import { access, readdir, readFile } from "fs/promises";
2136
- import { dirname as dirname4, join as join10 } from "path";
2271
+ import { dirname as dirname4, join as join11 } from "path";
2137
2272
  import yoctoSpinner4 from "yocto-spinner";
2138
2273
  import { z as z10 } from "zod";
2139
2274
 
@@ -2153,38 +2288,6 @@ function getDeploymentErrorMessage(code) {
2153
2288
  return ERROR_MESSAGES[code] ?? `Deployment failed with an unexpected error (code: ${code}). Please try again. If the issue persists, contact support.`;
2154
2289
  }
2155
2290
 
2156
- // src/cli/lib/env-config.ts
2157
- var ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
2158
- var parseEnvAssignment = (input3) => {
2159
- const separatorIndex = input3.indexOf("=");
2160
- if (separatorIndex === -1) {
2161
- throw new Error(`Invalid env var format: ${input3}. Expected format: KEY=VALUE`);
2162
- }
2163
- const key = input3.slice(0, separatorIndex).trim();
2164
- const value = input3.slice(separatorIndex + 1).trim();
2165
- if (!key || !value) {
2166
- throw new Error(`Invalid env var format: ${input3}. Expected format: KEY=VALUE`);
2167
- }
2168
- if (!ENV_KEY_PATTERN.test(key)) {
2169
- throw new Error(
2170
- `Invalid env var name: ${key}. Names must start with a letter or underscore and contain only letters, numbers, and underscores.`
2171
- );
2172
- }
2173
- return { key, value };
2174
- };
2175
- var getStoredEnv = (config2) => {
2176
- return config2.get("env") ?? {};
2177
- };
2178
- var toDeploymentSecrets = (envVars) => {
2179
- return Object.entries(envVars).map(([key, value]) => ({ type: "secret", key, value }));
2180
- };
2181
- var mergeDeploymentSecrets = (persisted, flagSecrets) => {
2182
- const byKey = /* @__PURE__ */ new Map();
2183
- persisted.forEach((secret) => byKey.set(secret.key, secret));
2184
- flagSecrets.forEach((secret) => byKey.set(secret.key, secret));
2185
- return Array.from(byKey.values());
2186
- };
2187
-
2188
2291
  // src/cli/commands/deploy.ts
2189
2292
  var stepsEnum = z10.enum([
2190
2293
  "initializing",
@@ -2237,8 +2340,8 @@ var DeploymentStatusSchema = z10.object({
2237
2340
  });
2238
2341
  var generateBundleZip = async () => {
2239
2342
  consola.info("Generating bundle...");
2240
- const bigcommerceDir = join10(process.cwd(), ".bigcommerce");
2241
- const distDir = join10(process.cwd(), ".bigcommerce", "dist");
2343
+ const bigcommerceDir = join11(process.cwd(), ".bigcommerce");
2344
+ const distDir = join11(process.cwd(), ".bigcommerce", "dist");
2242
2345
  try {
2243
2346
  await access(distDir);
2244
2347
  } catch {
@@ -2248,7 +2351,7 @@ var generateBundleZip = async () => {
2248
2351
  if (buildDirContents.length === 0) {
2249
2352
  throw new Error(`Dist directory is empty: ${distDir}`);
2250
2353
  }
2251
- const outputZip = join10(bigcommerceDir, "bundle.zip");
2354
+ const outputZip = join11(bigcommerceDir, "bundle.zip");
2252
2355
  const zip = new AdmZip();
2253
2356
  zip.addLocalFolder(distDir, "output");
2254
2357
  zip.writeZip(outputZip);
@@ -2280,7 +2383,7 @@ var generateUploadSignature = async (storeHash, accessToken, apiHost) => {
2280
2383
  };
2281
2384
  var uploadBundleZip = async (uploadUrl) => {
2282
2385
  consola.info("Uploading bundle...");
2283
- const zipPath = join10(process.cwd(), ".bigcommerce", "bundle.zip");
2386
+ const zipPath = join11(process.cwd(), ".bigcommerce", "bundle.zip");
2284
2387
  const fileBuffer = await readFile(zipPath);
2285
2388
  const response = await fetch(uploadUrl, {
2286
2389
  method: "PUT",
@@ -2391,7 +2494,7 @@ var getDeploymentStatus = async (deploymentUuid, storeHash, accessToken, apiHost
2391
2494
  spinner.success("Deployment completed successfully.");
2392
2495
  if (deploymentHostname) {
2393
2496
  consola.success(
2394
- `View your deployment at: ${colorize4("blue", `https://${deploymentHostname}`)}`
2497
+ `View your deployment at: ${colorize5("blue", `https://${deploymentHostname}`)}`
2395
2498
  );
2396
2499
  }
2397
2500
  return deploymentHostname;
@@ -2488,10 +2591,10 @@ Example:
2488
2591
  consola.success(`Linked project "${selected.name}".`);
2489
2592
  }
2490
2593
  if (!getProjectState().isTransformed) {
2491
- const shouldSetup = await consola.prompt(
2492
- "Your project is not yet set up for Commerce Hosting deployments. Would you like to run the Commerce Hosting setup now?",
2493
- { type: "confirm", initial: true }
2494
- );
2594
+ const shouldSetup = await confirm3({
2595
+ message: "Your project is not yet set up for Commerce Hosting deployments. Would you like to run the Commerce Hosting setup now?",
2596
+ default: true
2597
+ });
2495
2598
  if (!shouldSetup) {
2496
2599
  consola.info("When you're ready to deploy, re-run `catalyst deploy` to complete setup.");
2497
2600
  process.exit(0);
@@ -2504,7 +2607,7 @@ Example:
2504
2607
  await cleanupCloudflareIncompatibilities(dirname4(process.cwd()));
2505
2608
  }
2506
2609
  if (options.prebuilt) {
2507
- const distDir = join10(process.cwd(), ".bigcommerce", "dist");
2610
+ const distDir = join11(process.cwd(), ".bigcommerce", "dist");
2508
2611
  try {
2509
2612
  await access(distDir);
2510
2613
  } catch {
@@ -2646,7 +2749,7 @@ var env = new Command6("env").configureHelp({ showGlobalOptions: true }).descrip
2646
2749
 
2647
2750
  // src/cli/commands/logs.ts
2648
2751
  import { Command as Command7, Option as Option7 } from "commander";
2649
- import { colorize as colorize5 } from "consola/utils";
2752
+ import { colorize as colorize6 } from "consola/utils";
2650
2753
  import { z as z11 } from "zod";
2651
2754
  var telemetry = new Telemetry();
2652
2755
  var DEFAULT_CONNECTION_TTL_MS = 1 * 60 * 1e3;
@@ -2688,7 +2791,7 @@ var formatLogEvent = (event, format) => {
2688
2791
  logEntries.forEach((entry) => {
2689
2792
  const msg = formatMessages(entry.messages);
2690
2793
  const level = entry.level.toUpperCase();
2691
- const coloredLevel = colorize5(LEVEL_COLORS[level] ?? "white", level);
2794
+ const coloredLevel = colorize6(LEVEL_COLORS[level] ?? "white", level);
2692
2795
  switch (format) {
2693
2796
  case "short":
2694
2797
  consola.log(msg);
@@ -2870,8 +2973,9 @@ Example:
2870
2973
  var logs = new Command7("logs").configureHelp({ showGlobalOptions: true }).description("View logs from your deployed application.").addCommand(tail, { isDefault: true }).addCommand(query);
2871
2974
 
2872
2975
  // src/cli/commands/project.ts
2976
+ import { confirm as confirm4, input as input4, select as select5 } from "@inquirer/prompts";
2873
2977
  import { Command as Command8 } from "commander";
2874
- import { colorize as colorize6 } from "consola/utils";
2978
+ import { colorize as colorize7 } from "consola/utils";
2875
2979
  import { dirname as dirname5 } from "path";
2876
2980
  async function offerCommerceHostingSetup(projectUuid, credentials) {
2877
2981
  const projectDir = dirname5(process.cwd());
@@ -2879,10 +2983,10 @@ async function offerCommerceHostingSetup(projectUuid, credentials) {
2879
2983
  await cleanupCloudflareIncompatibilities(projectDir);
2880
2984
  return;
2881
2985
  }
2882
- const shouldSetup = await consola.prompt(
2883
- "Your project has been linked, but is not fully set up for Commerce Hosting deployments yet. Would you like to run the setup now?",
2884
- { type: "confirm", initial: true }
2885
- );
2986
+ const shouldSetup = await confirm4({
2987
+ message: "Your project has been linked, but is not fully set up for Commerce Hosting deployments yet. Would you like to run the setup now?",
2988
+ default: true
2989
+ });
2886
2990
  if (!shouldSetup) return;
2887
2991
  await setupCommerceHosting({
2888
2992
  projectDir,
@@ -2911,18 +3015,14 @@ Example:
2911
3015
  return;
2912
3016
  }
2913
3017
  const linkedProjectUuid = config2.get("projectUuid");
2914
- projects.forEach((p) => {
2915
- const marker = p.uuid === linkedProjectUuid ? ` ${colorize6("green", "[linked]")}` : "";
2916
- consola.log(`${p.name} (${p.uuid})${marker}`);
2917
- if (p.deployment_hostnames.length === 0) {
2918
- consola.log(" (not deployed)");
2919
- } else {
2920
- p.deployment_hostnames.forEach((hostname) => {
2921
- consola.log(` ${colorize6("blue", `https://${hostname}`)}`);
2922
- });
2923
- }
2924
- consola.log("");
3018
+ const projectList = projects.map((p) => {
3019
+ const marker = p.uuid === linkedProjectUuid ? ` ${colorize7("green", "[linked]")}` : "";
3020
+ const hostnames = p.deployment_hostnames.length === 0 ? [" (not deployed)"] : p.deployment_hostnames.map(
3021
+ (hostname) => ` ${colorize7("blue", `https://${hostname}`)}`
3022
+ );
3023
+ return [`${p.name} (${p.uuid})${marker}`, ...hostnames].join("\n");
2925
3024
  });
3025
+ consola.log(projectList.join("\n\n"));
2926
3026
  process.exit(0);
2927
3027
  });
2928
3028
  var create2 = new Command8("create").configureHelp({ showGlobalOptions: true }).description(
@@ -2959,9 +3059,7 @@ Example:
2959
3059
  }
2960
3060
  }
2961
3061
  await getTelemetry().identify(storeHash);
2962
- const newProjectName = await consola.prompt("Enter a name for the new project:", {
2963
- type: "text"
2964
- });
3062
+ const newProjectName = await input4({ message: "Enter a name for the new project:" });
2965
3063
  const data = await createProject(newProjectName, storeHash, accessToken, options.apiHost);
2966
3064
  consola.success(`Project "${data.name}" created successfully.`);
2967
3065
  consola.start("Writing project UUID to .bigcommerce/project.json...");
@@ -2971,7 +3069,7 @@ Example:
2971
3069
  consola.success("Project UUID written to .bigcommerce/project.json.");
2972
3070
  process.exit(0);
2973
3071
  });
2974
- var link = new Command8("link").configureHelp({ showGlobalOptions: true }).description(
3072
+ var link2 = new Command8("link").configureHelp({ showGlobalOptions: true }).description(
2975
3073
  "Link your local Catalyst project to a BigCommerce infrastructure project. You can provide a project UUID directly, or fetch and select from available projects using your store credentials."
2976
3074
  ).addHelpText(
2977
3075
  "after",
@@ -3051,21 +3149,17 @@ Examples:
3051
3149
  return;
3052
3150
  }
3053
3151
  const linkedProjectUuid = config2.get("projectUuid");
3054
- const selected = await consola.prompt(
3055
- "Select a project to delete (Press <enter> to select).",
3056
- {
3057
- type: "select",
3058
- options: [
3059
- ...projects.map((p) => ({
3060
- label: p.uuid === linkedProjectUuid ? `${p.name} ${colorize6("green", "[linked]")}` : p.name,
3061
- value: p.uuid,
3062
- hint: p.uuid
3063
- })),
3064
- { label: "Cancel", value: "cancel", hint: "Exit without deleting any project." }
3065
- ],
3066
- cancel: "reject"
3067
- }
3068
- );
3152
+ const selected = await select5({
3153
+ message: "Select a project to delete (Press <enter> to select).",
3154
+ choices: [
3155
+ ...projects.map((p) => ({
3156
+ name: p.uuid === linkedProjectUuid ? `${p.name} ${colorize7("green", "[linked]")}` : p.name,
3157
+ value: p.uuid,
3158
+ description: p.uuid
3159
+ })),
3160
+ { name: "Cancel", value: "cancel", description: "Exit without deleting any project." }
3161
+ ]
3162
+ });
3069
3163
  if (selected === "cancel") {
3070
3164
  consola.info("Aborted. No project was deleted.");
3071
3165
  process.exit(0);
@@ -3080,10 +3174,10 @@ Examples:
3080
3174
  }
3081
3175
  if (!options.force) {
3082
3176
  const label = targetName ? `"${targetName}" (${targetUuid})` : targetUuid;
3083
- const confirmed = await consola.prompt(
3084
- `Are you sure you want to delete project ${label}? This action is irreversible and will permanently destroy the project and all of its data.`,
3085
- { type: "confirm", initial: false }
3086
- );
3177
+ const confirmed = await confirm4({
3178
+ message: `Are you sure you want to delete project ${label}? This action is irreversible and will permanently destroy the project and all of its data.`,
3179
+ default: false
3180
+ });
3087
3181
  if (!confirmed) {
3088
3182
  consola.info("Aborted. No project was deleted.");
3089
3183
  process.exit(0);
@@ -3099,13 +3193,13 @@ Examples:
3099
3193
  }
3100
3194
  process.exit(0);
3101
3195
  });
3102
- var project = new Command8("project").configureHelp({ showGlobalOptions: true }).description("Manage your BigCommerce infrastructure project.").addCommand(create2).addCommand(list2).addCommand(link).addCommand(del);
3196
+ var project = new Command8("project").configureHelp({ showGlobalOptions: true }).description("Manage your BigCommerce infrastructure project.").addCommand(create2).addCommand(list2).addCommand(link2).addCommand(del);
3103
3197
 
3104
3198
  // src/cli/commands/start.ts
3105
3199
  import { Command as Command9 } from "commander";
3106
3200
  import { execa as execa2 } from "execa";
3107
3201
  import { existsSync as existsSync4, lstatSync as lstatSync2, symlinkSync as symlinkSync2 } from "fs";
3108
- import { join as join11, relative } from "path";
3202
+ import { join as join12, relative } from "path";
3109
3203
  var start = new Command9("start").configureHelp({ showGlobalOptions: true }).description(
3110
3204
  "Start a local preview of your Catalyst storefront using the OpenNext Cloudflare adapter."
3111
3205
  ).addHelpText(
@@ -3123,11 +3217,11 @@ Example:
3123
3217
  });
3124
3218
  return;
3125
3219
  }
3126
- const envLocal = join11(process.cwd(), ".env.local");
3127
- const devVars = join11(process.cwd(), ".bigcommerce", ".dev.vars");
3220
+ const envLocal = join12(process.cwd(), ".env.local");
3221
+ const devVars = join12(process.cwd(), ".bigcommerce", ".dev.vars");
3128
3222
  if (existsSync4(envLocal)) {
3129
3223
  if (!existsSync4(devVars)) {
3130
- const target = relative(join11(process.cwd(), ".bigcommerce"), envLocal);
3224
+ const target = relative(join12(process.cwd(), ".bigcommerce"), envLocal);
3131
3225
  symlinkSync2(target, devVars);
3132
3226
  consola.success("Symlinked .bigcommerce/.dev.vars \u2192 .env.local");
3133
3227
  } else if (!lstatSync2(devVars).isSymbolicLink()) {
@@ -3147,7 +3241,7 @@ Example:
3147
3241
  "opennextjs-cloudflare",
3148
3242
  "preview",
3149
3243
  "--config",
3150
- join11(".bigcommerce", "wrangler.jsonc")
3244
+ join12(".bigcommerce", "wrangler.jsonc")
3151
3245
  ],
3152
3246
  {
3153
3247
  stdio: "inherit",
@@ -3158,7 +3252,7 @@ Example:
3158
3252
 
3159
3253
  // src/cli/commands/telemetry.ts
3160
3254
  import { Argument, Command as Command10, Option as Option8 } from "commander";
3161
- import { colorize as colorize7 } from "consola/utils";
3255
+ import { colorize as colorize8 } from "consola/utils";
3162
3256
  var telemetryService = getTelemetry();
3163
3257
  var isEnabled = telemetryService.isEnabled();
3164
3258
  var telemetry2 = new Command10("telemetry").configureHelp({ showGlobalOptions: true }).description(
@@ -3192,7 +3286,7 @@ Examples:
3192
3286
  consola.info("Catalyst CLI Telemetry\n");
3193
3287
  }
3194
3288
  consola.info(
3195
- `Status: ${colorize7("bold", isEnabled ? colorize7("green", "Enabled") : colorize7("red", "Disabled"))}`
3289
+ `Status: ${colorize8("bold", isEnabled ? colorize8("green", "Enabled") : colorize8("red", "Disabled"))}`
3196
3290
  );
3197
3291
  if (!isEnabled) {
3198
3292
  consola.info(
@@ -3272,7 +3366,7 @@ if (!process.env.CATALYST_STORE_HASH && process.env.BIGCOMMERCE_STORE_HASH) {
3272
3366
  process.env.CATALYST_STORE_HASH = process.env.BIGCOMMERCE_STORE_HASH;
3273
3367
  }
3274
3368
  var program = new Command12();
3275
- consola.log(colorize8("cyanBright", `\u25E2 ${package_default.name} v${package_default.version}
3369
+ consola.log(colorize9("cyanBright", `\u25E2 ${package_default.name} v${package_default.version}
3276
3370
  `));
3277
3371
  program.name(package_default.name).version(package_default.version).summary("CLI tool for Catalyst development").description(
3278
3372
  "CLI tool for Catalyst development.\n\nConfiguration priority: flags > env file (--env-path) > process.env > .env.local (auto-loaded from cwd) > .bigcommerce/project.json.\n\nCATALYST_STORE_HASH falls back to BIGCOMMERCE_STORE_HASH if unset.\n\nRun `catalyst <command> --help` for details on a specific command."
@@ -3293,7 +3387,7 @@ program.name(package_default.name).version(package_default.version).summary("CLI
3293
3387
  const message = errCode === "ENOENT" ? `Env file not found: ${envFilePath}` : `Failed to load --env-path ${value}: ${result.error.message}`;
3294
3388
  throw new Error(message);
3295
3389
  }
3296
- consola.log(colorize8("cyanBright", `Loaded environment variables from ${envFilePath}
3390
+ consola.log(colorize9("cyanBright", `Loaded environment variables from ${envFilePath}
3297
3391
  `));
3298
3392
  }
3299
3393
  return value;