@tokenoftrust/storefront-runner 2.3.0 → 2.3.1

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.
@@ -26,6 +26,7 @@
26
26
  * tenancy-resolver-fence — the concrete registry stays behind the config boundary.
27
27
  */
28
28
  import type { DeepPartial, TenantConfig, ThemeTokens } from "@tot/public-runtime";
29
+ import { SHARED_DEMO_CHECKOUT } from "@tot/public-runtime";
29
30
  import { rootPublicationSpaceConfig } from "./publicationSpaceConfig";
30
31
  import { loadTenantAnalyticsDeclarations } from "@/lib/integration/tenantAnalyticsDeclarations";
31
32
 
@@ -94,12 +95,14 @@ export function synthesizeDevTenant(
94
95
  ...(euUkVisitors ? { euUkVisitors } : {}),
95
96
  };
96
97
  // Cart wires to the shared ToT demo checkout store (test mode, no secret), the
97
- // same as the bundled demo tenants. A marketing tenant never resolves it (the
98
+ // same as the bundled demo tenants — and the SAME constant the hosted QA/test
99
+ // tier's demo-checkout fallback reuses (checkoutCommerce.ts), so both surfaces
100
+ // stay wired to one definition. A marketing tenant never resolves it (the
98
101
  // render chain gates on features.catalog); a commerce one gets its cart
99
102
  // affordance and /cart on localhost whether or not it has catalog files yet.
100
103
  return {
101
104
  ...base,
102
- commerce: { checkout: { storeSubDomain: "tot-preview", mode: "unsigned-demo" } },
105
+ commerce: { checkout: SHARED_DEMO_CHECKOUT },
103
106
  };
104
107
  }
105
108
 
@@ -11,19 +11,31 @@
11
11
  * - `FOXY_CART_SECRET` is the cart-validation secret used only in `signed`
12
12
  * mode; the `unsigned-demo` mode never reads it (validation is OFF), which
13
13
  * is what lets a developer run the whole cart locally with zero secrets.
14
+ *
15
+ * `COMMERCE_DEMO_CHECKOUT_TIER` gates a FALLBACK for a commerce tenant that has
16
+ * no `commerce.checkout` of its own (e.g. a staff-provisioned store —
17
+ * buildStaffTenantConfig projects a minimal record with none). Declared-tier
18
+ * config, not a tenant check: "test" reuses the exact SHARED_DEMO_CHECKOUT the
19
+ * local dev loop wires (synthesizeDevTenant), so a staff-provisioned store's
20
+ * cart renders on hosted QA preview the same as it does under `tot dev`. Any
21
+ * other value — including unset, the PRODUCTION default — fails CLOSED to no
22
+ * cart: an unpaid production store's preview IS its public site, so a demo
23
+ * checkout must never appear there. A tenant's own declared checkout always
24
+ * wins; this only fills in when `commerce.checkout` is absent.
14
25
  */
15
26
  import type { TenantConfig, ResolvedManagedCheckout } from "@tot/public-runtime";
16
- import { resolveManagedCheckout } from "@tot/public-runtime";
27
+ import { resolveManagedCheckout, SHARED_DEMO_CHECKOUT } from "@tot/public-runtime";
17
28
  import { readEnv } from "@/lib/runtimeEnv";
18
29
 
19
30
  /**
20
31
  * Resolve the effective checkout facts for a tenant, or null when the tenant has
21
- * no store configured. Applies the checkout env overrides.
32
+ * no store configured (its own, or the QA/test-tier demo fallback). Applies the
33
+ * checkout env overrides.
22
34
  */
23
35
  export async function resolveTenantCommerce(
24
36
  tenant: TenantConfig,
25
37
  ): Promise<ResolvedManagedCheckout | null> {
26
- const checkout = tenant.commerce?.checkout;
38
+ const checkout = tenant.commerce?.checkout ?? (await demoCheckoutFallback());
27
39
  if (!checkout) return null;
28
40
  // Per-environment overrides so the SAME tenant can point at different stores /
29
41
  // checkout hosts by env: FOXY_STORE_SUBDOMAIN picks the checkout store;
@@ -38,6 +50,17 @@ export async function resolveTenantCommerce(
38
50
  return resolveManagedCheckout({ ...checkout, storeSubDomain, storeDomain });
39
51
  }
40
52
 
53
+ /**
54
+ * The QA/test-tier-only demo-checkout fallback, or undefined when this
55
+ * environment hasn't declared itself eligible. Fails closed: only the literal
56
+ * value "test" enables it, so an unset var (today's only production-shaped
57
+ * state — there is no `[env.production]` block yet) never does.
58
+ */
59
+ async function demoCheckoutFallback() {
60
+ const tier = await readEnv("COMMERCE_DEMO_CHECKOUT_TIER");
61
+ return tier === "test" ? SHARED_DEMO_CHECKOUT : undefined;
62
+ }
63
+
41
64
  /**
42
65
  * The cart-validation secret for signed mode. Returns undefined in
43
66
  * `unsigned-demo` mode (never needed) or when unset. A signed-mode tenant with
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenoftrust/storefront-runner",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
6
6
  "packageManager": "pnpm@11.9.0",
@@ -59,6 +59,19 @@ export interface ManagedCheckoutConfig {
59
59
  cartDrawerCss?: string;
60
60
  }
61
61
 
62
+ /**
63
+ * The ONE shared ToT-owned demo checkout store (test mode, cart validation
64
+ * OFF, no secret). The local dev loop (`synthesizeDevTenant`) wires every
65
+ * local commerce checkout to this exact config; the hosted QA/test tier's
66
+ * demo-checkout fallback (`resolveTenantCommerce`) reuses this same constant
67
+ * rather than a second copy of the literal, so "the same as `tot dev`" stays
68
+ * true by construction instead of by two authors agreeing.
69
+ */
70
+ export const SHARED_DEMO_CHECKOUT: ManagedCheckoutConfig = {
71
+ storeSubDomain: "tot-preview",
72
+ mode: "unsigned-demo",
73
+ };
74
+
62
75
  /** Resolved, request-scoped commerce facts stashed on `Astro.locals`. */
63
76
  export interface ResolvedManagedCheckout extends ManagedCheckoutConfig {
64
77
  /** `https://<storeDomain>` — the loader + cart origin (for CSP + links). */