create-brainerce-store 1.23.0 → 1.24.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.
Files changed (2) hide show
  1. package/dist/index.js +59 -13
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ var require_package = __commonJS({
31
31
  "package.json"(exports2, module2) {
32
32
  module2.exports = {
33
33
  name: "create-brainerce-store",
34
- version: "1.22.0",
34
+ version: "1.24.0",
35
35
  description: "Scaffold a production-ready e-commerce storefront connected to Brainerce",
36
36
  bin: {
37
37
  "create-brainerce-store": "dist/index.js"
@@ -44,7 +44,8 @@ var require_package = __commonJS({
44
44
  scripts: {
45
45
  build: "tsup src/index.ts --format cjs --dts --clean",
46
46
  dev: "tsup src/index.ts --format cjs --dts --watch",
47
- clean: "rimraf dist"
47
+ clean: "rimraf dist",
48
+ prepublishOnly: "npm run build"
48
49
  },
49
50
  dependencies: {
50
51
  chalk: "^4.1.2",
@@ -410,7 +411,17 @@ async function copyWithEjs(srcDir, destDir, vars) {
410
411
  }
411
412
 
412
413
  // src/fetch-store-info.ts
413
- async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com") {
414
+ var KNOWN_API_URLS = {
415
+ production: "https://api.brainerce.com",
416
+ staging: "https://api-staging.brainerce.com"
417
+ };
418
+ var ConnectionNotFoundError = class extends Error {
419
+ constructor(connectionId, baseUrl) {
420
+ super(`Connection "${connectionId}" not found at ${baseUrl}`);
421
+ this.code = "NOT_FOUND";
422
+ }
423
+ };
424
+ async function fetchStoreInfo(connectionId, baseUrl = KNOWN_API_URLS.production) {
414
425
  const url = `${baseUrl}/api/vc/${connectionId}/info`;
415
426
  const controller = new AbortController();
416
427
  const timeout = setTimeout(() => controller.abort(), 1e4);
@@ -419,23 +430,23 @@ async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com
419
430
  res = await fetch(url, { signal: controller.signal });
420
431
  } catch (err) {
421
432
  if (err.name === "AbortError") {
422
- throw new Error("Request timed out");
433
+ throw new Error(`Request to ${baseUrl} timed out`);
423
434
  }
424
- throw new Error(`Failed to connect to Brainerce API: ${err.message}`);
435
+ throw new Error(`Failed to connect to ${baseUrl}: ${err.message}`);
425
436
  } finally {
426
437
  clearTimeout(timeout);
427
438
  }
428
439
  if (res.status === 404) {
429
- throw new Error(`Connection ID "${connectionId}" not found. Check your dashboard.`);
440
+ throw new ConnectionNotFoundError(connectionId, baseUrl);
430
441
  }
431
442
  if (!res.ok) {
432
- throw new Error(`API returned status ${res.status}`);
443
+ throw new Error(`${baseUrl} returned status ${res.status}`);
433
444
  }
434
445
  let json;
435
446
  try {
436
447
  json = await res.json();
437
448
  } catch {
438
- throw new Error("Invalid response from API");
449
+ throw new Error(`Invalid response from ${baseUrl}`);
439
450
  }
440
451
  return {
441
452
  name: json.name || json.storeName || "My Store",
@@ -444,6 +455,33 @@ async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com
444
455
  ...json.i18n ? { i18n: json.i18n } : {}
445
456
  };
446
457
  }
458
+ async function resolveStoreInfo(connectionId, candidateUrls) {
459
+ const urls = candidateUrls.filter((u, i) => u && candidateUrls.indexOf(u) === i);
460
+ if (urls.length === 0) {
461
+ throw new Error("No API URLs to try");
462
+ }
463
+ let lastError;
464
+ let allNotFound = true;
465
+ for (let i = 0; i < urls.length; i++) {
466
+ const baseUrl = urls[i];
467
+ try {
468
+ const info = await fetchStoreInfo(connectionId, baseUrl);
469
+ return { info, apiBaseUrl: baseUrl, fellBack: i > 0 };
470
+ } catch (err) {
471
+ lastError = err;
472
+ const isNotFound = err.code === "NOT_FOUND";
473
+ if (!isNotFound) {
474
+ allNotFound = false;
475
+ }
476
+ }
477
+ }
478
+ if (allNotFound) {
479
+ throw new Error(
480
+ `Connection "${connectionId}" not found in any known environment (${urls.join(", ")}). Check your dashboard.`
481
+ );
482
+ }
483
+ throw lastError || new Error("Failed to resolve store info");
484
+ }
447
485
 
448
486
  // src/utils/logger.ts
449
487
  var import_chalk = __toESM(require("chalk"));
@@ -537,7 +575,8 @@ program.name("create-brainerce-store").description("Scaffold a production-ready
537
575
  scaffoldInPlace = true;
538
576
  }
539
577
  let connectionId = options.connectionId;
540
- const apiBaseUrl = (options.apiUrl || process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(/\/$/, "");
578
+ const explicitApiUrl = (options.apiUrl || process.env.BRAINERCE_API_URL || "").replace(/\/$/, "");
579
+ const candidateApiUrls = explicitApiUrl ? [explicitApiUrl] : [KNOWN_API_URLS.production, KNOWN_API_URLS.staging];
541
580
  let language = options.language;
542
581
  let framework = options.framework;
543
582
  let theme = options.theme;
@@ -573,16 +612,23 @@ program.name("create-brainerce-store").description("Scaffold a production-ready
573
612
  const spinner = createSpinner("Fetching store info...");
574
613
  spinner.start();
575
614
  let storeInfo;
615
+ let resolvedApiUrl = candidateApiUrls[0];
576
616
  try {
577
- storeInfo = await fetchStoreInfo(connectionId, apiBaseUrl);
617
+ const resolved = await resolveStoreInfo(connectionId, candidateApiUrls);
618
+ storeInfo = resolved.info;
619
+ resolvedApiUrl = resolved.apiBaseUrl;
620
+ const envLabel = resolved.apiBaseUrl === KNOWN_API_URLS.staging ? " [staging]" : resolved.apiBaseUrl === KNOWN_API_URLS.production ? "" : ` [${resolved.apiBaseUrl}]`;
578
621
  const i18nStatus = storeInfo.i18n?.enabled && storeInfo.i18n.supportedLocales.length > 1 ? ` | i18n: ${storeInfo.i18n.supportedLocales.join(", ")}` : "";
579
622
  spinner.succeed(
580
- `Store: "${storeInfo.name}" | ${storeInfo.currency} | ${storeInfo.language}${i18nStatus}`
623
+ `Store: "${storeInfo.name}" | ${storeInfo.currency} | ${storeInfo.language}${i18nStatus}${envLabel}`
581
624
  );
625
+ if (resolved.fellBack) {
626
+ logger.info(` Detected ${envLabel.trim() || "alternate"} environment \u2014 using ${resolved.apiBaseUrl}`);
627
+ }
582
628
  } catch (err) {
583
629
  spinner.fail("Could not fetch store info");
584
630
  logger.warn(
585
- "Using defaults. Make sure the connection ID is correct and the Brainerce API is reachable."
631
+ err instanceof Error ? err.message : "Using defaults. Make sure the connection ID is correct and the Brainerce API is reachable."
586
632
  );
587
633
  storeInfo = { name: projectName, currency: "USD", language: "en" };
588
634
  }
@@ -594,7 +640,7 @@ program.name("create-brainerce-store").description("Scaffold a production-ready
594
640
  await scaffold({
595
641
  projectName,
596
642
  connectionId,
597
- apiBaseUrl,
643
+ apiBaseUrl: resolvedApiUrl,
598
644
  framework,
599
645
  theme,
600
646
  storeName: storeInfo.name,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-brainerce-store",
3
- "version": "1.23.0",
3
+ "version": "1.24.0",
4
4
  "description": "Scaffold a production-ready e-commerce storefront connected to Brainerce",
5
5
  "bin": {
6
6
  "create-brainerce-store": "dist/index.js"
@@ -13,7 +13,8 @@
13
13
  "scripts": {
14
14
  "build": "tsup src/index.ts --format cjs --dts --clean",
15
15
  "dev": "tsup src/index.ts --format cjs --dts --watch",
16
- "clean": "rimraf dist"
16
+ "clean": "rimraf dist",
17
+ "prepublishOnly": "npm run build"
17
18
  },
18
19
  "dependencies": {
19
20
  "chalk": "^4.1.2",