@cartbase/storefront 0.1.2 → 0.2.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 (101) hide show
  1. package/README.md +3 -3
  2. package/package.json +231 -226
  3. package/src/api/auth.ts +1 -1
  4. package/src/api/consent.ts +2 -2
  5. package/src/api/regions.ts +1 -1
  6. package/src/cart-drawer/context.tsx +4 -4
  7. package/src/cart-drawer/cross-sell-carousel.tsx +1 -1
  8. package/src/cart-drawer/cross-sell-sidebar.tsx +1 -1
  9. package/src/cart-drawer/header.tsx +1 -1
  10. package/src/cart-drawer/item/index.tsx +2 -2
  11. package/src/cart-drawer/item/quantity.tsx +2 -2
  12. package/src/cart-drawer/item/upsell.tsx +3 -3
  13. package/src/cart-drawer/item/variant.tsx +2 -2
  14. package/src/cart-drawer/labels-bg.ts +1 -1
  15. package/src/cart-drawer/labels.ts +2 -2
  16. package/src/cart-drawer/summary-breakdown.tsx +2 -2
  17. package/src/cart-drawer/template.tsx +2 -2
  18. package/src/cart-drawer/tiered-progress.tsx +1 -1
  19. package/src/checkout/address-error-copy.ts +3 -3
  20. package/src/checkout/address-form.tsx +2 -2
  21. package/src/checkout/address-select.tsx +1 -1
  22. package/src/checkout/boxnow-locker-selector.tsx +3 -3
  23. package/src/checkout/checkout-client.tsx +2 -2
  24. package/src/checkout/company-details.tsx +1 -1
  25. package/src/checkout/compare-addresses.ts +1 -1
  26. package/src/checkout/discount-section.tsx +5 -5
  27. package/src/checkout/econt-office-selector.tsx +2 -2
  28. package/src/checkout/gift-card-section.tsx +2 -2
  29. package/src/checkout/labels-bg.ts +1 -1
  30. package/src/checkout/labels.ts +4 -4
  31. package/src/checkout/line-item-card.tsx +2 -2
  32. package/src/checkout/order-summary.tsx +7 -7
  33. package/src/checkout/payment-button.tsx +4 -4
  34. package/src/checkout/payment-error-copy.ts +6 -6
  35. package/src/checkout/payment-method-list.tsx +2 -2
  36. package/src/checkout/payment-wrapper.tsx +8 -11
  37. package/src/checkout/promotion-error-copy.ts +2 -2
  38. package/src/checkout/shipping-method-list.tsx +2 -2
  39. package/src/checkout/stripe-wrapper.tsx +1 -1
  40. package/src/checkout/use-checkout-orchestration.ts +16 -16
  41. package/src/common/cart-button-client.tsx +1 -1
  42. package/src/common/cart-button.tsx +1 -1
  43. package/src/common/country-select.tsx +2 -2
  44. package/src/common/delete-button.tsx +1 -1
  45. package/src/common/index.ts +1 -1
  46. package/src/common/language-select.tsx +2 -2
  47. package/src/common/localized-link.tsx +1 -1
  48. package/src/lib/cart-helpers.ts +2 -2
  49. package/src/lib/cookie-names.ts +41 -0
  50. package/src/lib/get-product-price.ts +3 -3
  51. package/src/lib/payment-constants.ts +2 -2
  52. package/src/lib/store-api-error.ts +1 -1
  53. package/src/order/index.ts +1 -1
  54. package/src/order/labels.ts +3 -3
  55. package/src/order/order-address-card.tsx +1 -1
  56. package/src/order/order-completed-template.tsx +3 -3
  57. package/src/order/order-confirmation-header.tsx +1 -1
  58. package/src/order/order-delivery-card.tsx +3 -3
  59. package/src/order/order-item.tsx +2 -2
  60. package/src/order/order-items-list.tsx +3 -3
  61. package/src/order/order-payment-card.tsx +2 -2
  62. package/src/order/order-timeline.tsx +2 -2
  63. package/src/order/order-totals.tsx +5 -5
  64. package/src/platform/identity.ts +18 -0
  65. package/src/platform/index.ts +8 -0
  66. package/src/platform/metadata.ts +26 -0
  67. package/src/platform/platform-init.tsx +46 -0
  68. package/src/products/image-gallery.tsx +1 -1
  69. package/src/products/mobile-actions.tsx +1 -1
  70. package/src/products/option-select.tsx +1 -1
  71. package/src/products/preview-price.tsx +1 -1
  72. package/src/products/product-actions.tsx +6 -6
  73. package/src/products/product-info.tsx +1 -1
  74. package/src/products/product-preview.tsx +1 -1
  75. package/src/products/product-price.tsx +2 -2
  76. package/src/products/product-tabs.tsx +1 -1
  77. package/src/products/purchase-options.tsx +1 -1
  78. package/src/products/related-products.tsx +3 -3
  79. package/src/products/variant-matching.ts +4 -4
  80. package/src/reviews-ui/labels.ts +1 -1
  81. package/src/reviews-ui/photo-upload.tsx +1 -1
  82. package/src/reviews-ui/review-list.tsx +1 -1
  83. package/src/reviews-ui/review-widget.tsx +1 -1
  84. package/src/reviews-ui/review-wizard.tsx +1 -1
  85. package/src/reviews-ui/wizard-state.ts +1 -1
  86. package/src/store/category-template.tsx +2 -2
  87. package/src/store/collection-template.tsx +2 -2
  88. package/src/store/labels.ts +2 -2
  89. package/src/store/paginated-products.tsx +1 -1
  90. package/src/store/search-params.ts +1 -1
  91. package/src/store/search-template.tsx +1 -1
  92. package/src/tracking/consent-banner.tsx +1 -1
  93. package/src/tracking/consent-init.tsx +1 -1
  94. package/src/tracking/consent.ts +6 -6
  95. package/src/tracking/fbq.ts +2 -2
  96. package/src/tracking/get-tracking-attribution.ts +1 -1
  97. package/src/tracking/get-tracking-config.ts +2 -2
  98. package/src/tracking/index.ts +2 -2
  99. package/src/tracking/meta-pixel.tsx +1 -1
  100. package/src/tracking/rybbit.tsx +1 -1
  101. package/src/tracking/types.ts +6 -6
@@ -54,7 +54,7 @@ import type { BoxNowLocker } from "../api/integrations"
54
54
  * persistence, custom summary).
55
55
  *
56
56
  * Ported from `@1click/ui/src/checkout/use-checkout-orchestration.ts`
57
- * (v2.3.1, the deferred-intent architecture) with the barter data seam:
57
+ * (v2.3.1, the deferred-intent architecture) with the Cartbase data seam:
58
58
  *
59
59
  * - Server actions → `@cartbase/storefront/api` calls on a caller-supplied
60
60
  * `StorefrontClient` (`updateCart`, `prepareCheckout`,
@@ -63,14 +63,14 @@ import type { BoxNowLocker } from "../api/integrations"
63
63
  * - `placeOrder` (server action with baked-in redirect) →
64
64
  * `completeCart()` + template navigation (`orderConfirmedPath` with
65
65
  * `{id}`/`{country}` substitution) or the `onOrderPlaced` callback.
66
- * - **Zero-remainder gift path** (barter gift-card tender,
66
+ * - **Zero-remainder gift path** (Cartbase gift-card tender,
67
67
  * docs/storefront/checkout.md): when applied gift cards cover the whole
68
68
  * total, `prepareCheckout` returns `client_secret: null` +
69
69
  * `provider_id: null` and the card path SKIPS `stripe.confirmPayment`
70
70
  * entirely — the cart completes on the gift session alone. The @1click
71
- * original threw on a missing client_secret; barter treats
71
+ * original threw on a missing client_secret; Cartbase treats
72
72
  * null-secret + null-provider as the documented gift path.
73
- * - COD fee: barter's fee is CART-LEVEL decoration (`cod_fee_total` /
73
+ * - COD fee: Cartbase's fee is CART-LEVEL decoration (`cod_fee_total` /
74
74
  * `cod_fee_label`, folded into `cart.total` while a live pp_cod session
75
75
  * exists) — not a metadata-flagged line item. The optimistic-fee math
76
76
  * reads `cart.cod_fee_total`; the prediction comes from the
@@ -78,9 +78,9 @@ import type { BoxNowLocker } from "../api/integrations"
78
78
  * - Provider ids: `pp_stripe` / `pp_cod` / `pp_manual` exactly
79
79
  * (lib/payment-constants + the pp_cod resolution below).
80
80
  * - `logCheckoutError`/`logEvent` (Supabase-side sinks in @1click) have no
81
- * barter store endpoint — the hook takes an optional `logError` callback
81
+ * Cartbase store endpoint — the hook takes an optional `logError` callback
82
82
  * so stores wire their own sink; all production log points are kept.
83
- * - Barter regions carry NO embedded countries array (api/regions.ts
83
+ * - Cartbase regions carry NO embedded countries array (api/regions.ts
84
84
  * divergence note) — the country list is a `countries` option with a
85
85
  * `countryCode` single-entry fallback.
86
86
  *
@@ -115,7 +115,7 @@ export type UseCheckoutOrchestrationOptions = {
115
115
  /** Default country code when the cart has no shipping address yet. */
116
116
  countryCode?: string
117
117
  /**
118
- * Countries offered in the address form. Barter regions do NOT embed a
118
+ * Countries offered in the address form. Cartbase regions do NOT embed a
119
119
  * countries array (store-API divergence), so the host app supplies the
120
120
  * list; omitted → a single entry derived from `countryCode`.
121
121
  */
@@ -159,7 +159,7 @@ export type UseCheckoutOrchestrationOptions = {
159
159
  resolveTrackingMetadata?: () => Record<string, unknown> | undefined
160
160
  /**
161
161
  * Operational-visibility sink (successor of @1click's logCheckoutError /
162
- * logEvent Supabase writers — barter has no store-side log endpoint).
162
+ * logEvent Supabase writers — Cartbase has no store-side log endpoint).
163
163
  * Called with (errorType, message, context). Optional; defaults to no-op.
164
164
  */
165
165
  logError?: CheckoutLogError
@@ -171,7 +171,7 @@ export type UseCheckoutOrchestrationOptions = {
171
171
  *
172
172
  * `shipping_address.phone` is required — Bulgarian carriers (Econt,
173
173
  * BoxNow) need it to contact the customer; it's the courier's primary
174
- * recovery channel when the address is ambiguous. (Barter's
174
+ * recovery channel when the address is ambiguous. (Cartbase's
175
175
  * prepare-checkout schema requires it too — docs/storefront/checkout.md.)
176
176
  */
177
177
  const REQUIRED_ADDRESS_FIELDS = [
@@ -194,7 +194,7 @@ const REQUIRED_ADDRESS_FIELDS = [
194
194
  */
195
195
  const ADDRESS_AUTO_SAVE_DEBOUNCE_MS = 600
196
196
 
197
- /** Barter COD provider resolution: `pp_cod` exactly, with the Medusa-era
197
+ /** Cartbase COD provider resolution: `pp_cod` exactly, with the Medusa-era
198
198
  * `pp_system_default*` prefix kept as fallback (lib/payment-constants),
199
199
  * and `pp_manual` accepted as the offline tab when no true COD provider
200
200
  * is enabled. Fee prediction only ever applies via `codConfig` (pp_cod). */
@@ -322,7 +322,7 @@ export function useCheckoutOrchestration({
322
322
  : true
323
323
  )
324
324
 
325
- // Barter regions have no embedded countries — the caller-supplied list
325
+ // Cartbase regions have no embedded countries — the caller-supplied list
326
326
  // (or the countryCode fallback) is the authority for both the select
327
327
  // options and the saved-address region filter.
328
328
  const regionCountries = useMemo(
@@ -500,7 +500,7 @@ export function useCheckoutOrchestration({
500
500
  lastSavedSnapshotRef.current = snapshot
501
501
 
502
502
  if (customer) {
503
- // Sync the profile best-effort. Barter has first-class company
503
+ // Sync the profile best-effort. Cartbase has first-class company
504
504
  // fields on the customer (company_name / company_eik —
505
505
  // api/customers.ts), so the invoice data also lands on the
506
506
  // profile — an upgrade over the @1click cart-metadata-only
@@ -702,7 +702,7 @@ export function useCheckoutOrchestration({
702
702
  [paymentMethodFilter, availablePaymentMethods, selectedShippingOption]
703
703
  )
704
704
 
705
- // Calculated-rate price resolution. Barter serves flat prices today
705
+ // Calculated-rate price resolution. Cartbase serves flat prices today
706
706
  // (`price_type: "flat"` always — api/checkout.ts), so this effect
707
707
  // normally resolves immediately; the calculated branch is kept for
708
708
  // forward-compat with calculated-rate carriers (the /calculate route
@@ -818,7 +818,7 @@ export function useCheckoutOrchestration({
818
818
 
819
819
  // Optimistic COD-fee state. Painted instantly on tab toggle so the
820
820
  // totals row shows the predicted fee BEFORE the server applies the
821
- // native fee (barter: at prepare, when the pp_cod session is minted).
821
+ // native fee (Cartbase: at prepare, when the pp_cod session is minted).
822
822
  // Three values:
823
823
  // - null → no prediction; render whatever the cart says
824
824
  // - 0 → predict no fee (toggling away from COD)
@@ -1089,7 +1089,7 @@ export function useCheckoutOrchestration({
1089
1089
  // shipping/fee)
1090
1090
  // if optimisticShippingCost set: replace cart.shipping_total with it
1091
1091
  // if optimisticCodFee set: replace cart.cod_fee_total with it
1092
- // (barter: the COD fee is CART-LEVEL decoration folded into total,
1092
+ // (Cartbase: the COD fee is CART-LEVEL decoration folded into total,
1093
1093
  // not a fee line item)
1094
1094
  // When nothing is optimistic, this collapses to cart.total.
1095
1095
  const optimisticTotal = useMemo(() => {
@@ -1287,7 +1287,7 @@ export function useCheckoutOrchestration({
1287
1287
  provider_id: prep.provider_id,
1288
1288
  })
1289
1289
 
1290
- // ── Zero-remainder gift path (barter gift-card tender) ──────────
1290
+ // ── Zero-remainder gift path (Cartbase gift-card tender) ──────────
1291
1291
  // When applied gift cards cover the whole total, prepare skips the
1292
1292
  // provider session: client_secret AND provider_id come back null
1293
1293
  // and the cart completes on the internal pp_giftcard session alone
@@ -9,7 +9,7 @@ import { useCartDrawer } from "../cart-drawer/context"
9
9
  * Header cart button (badge + opens the cart drawer). Ported from
10
10
  * `@1click/ui/src/common/cart-button-client.tsx` (v2.3.1); seams:
11
11
  *
12
- * - `cart` is the barter decorated cart (`api/carts` `Cart`).
12
+ * - `cart` is the Cartbase decorated cart (`api/carts` `Cart`).
13
13
  * - Badge count uses `productItemCount` (fee-line-aware) instead of the
14
14
  * source's raw `reduce` — keeps the badge consistent with the cart
15
15
  * drawer's own count, which already excludes backend-injected fee
@@ -5,7 +5,7 @@ import { CartButtonClient } from "./cart-button-client"
5
5
  /**
6
6
  * Server wrapper for the header cart button. Ported from
7
7
  * `@1click/ui/src/common/cart-button.tsx` (v2.3.1); data seam: the source
8
- * called the cookie-reading `retrieveCart()` server action — barter takes
8
+ * called the cookie-reading `retrieveCart()` server action — Cartbase takes
9
9
  * the `StorefrontClient` + the app-persisted cart id explicitly (the app
10
10
  * owns the cart-id cookie, see docs/storefront/carts.md) and calls
11
11
  * `api/carts.retrieveCart`. Any fetch failure (stale id, 404) degrades to
@@ -9,12 +9,12 @@ import type { StoreRegion } from "../api/regions"
9
9
  * change forced by the SDK (SDK wins over the source):
10
10
  *
11
11
  * - Medusa regions embedded a `countries[]` array and the select listed
12
- * countries; barter regions carry NO countries on the store surface
12
+ * countries; Cartbase regions carry NO countries on the store surface
13
13
  * (divergence documented in `api/regions` — tax scoping is by
14
14
  * `tax_regions` server-side). The select therefore lists the REGIONS
15
15
  * themselves (`regions.listRegions`), valued by region id.
16
16
  * - The source called the `updateRegion(countryCode, path)` server
17
- * action bound to URL `[countryCode]` routing; barter region
17
+ * action bound to URL `[countryCode]` routing; Cartbase region
18
18
  * persistence is app-owned (usually `carts.updateCart(client, cartId,
19
19
  * {region_id})` + a cookie) — so the change surfaces via `onChange`.
20
20
  */
@@ -10,7 +10,7 @@ import { cn } from "../lib/utils"
10
10
  * Cart-line delete button with spinner. Ported from
11
11
  * `@1click/ui/src/common/delete-button.tsx` (v2.3.1); data seam: the
12
12
  * source called the cookie-scoped `deleteLineItem(id)` server action —
13
- * barter calls `api/carts.deleteLineItem(client, cartId, lineItemId)`
13
+ * Cartbase calls `api/carts.deleteLineItem(client, cartId, lineItemId)`
14
14
  * (idempotent server-side) and hands the refreshed cart to `onDeleted`
15
15
  * so the app can update its state / `router.refresh()`. The spinner
16
16
  * resets on failure exactly like the source's `.catch`.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @cartbase/storefront/common — shared storefront chrome. Ported from
3
3
  * `@1click/ui/src/common` (v2.3.1) + `LocalizedLink` (from the
4
- * mindpages-storefront production component); barter data seams per
4
+ * mindpages-storefront production component); Cartbase data seams per
5
5
  * module JSDoc.
6
6
  */
7
7
  export { LocalizedLink, type LocalizedLinkProps } from "./localized-link"
@@ -7,13 +7,13 @@ import { useTransition } from "react"
7
7
  * `@1click/ui/src/common/language-select.tsx` (v2.3.1); data seam:
8
8
  *
9
9
  * - The locale list feeds from `api/regions.listLocales(client)` — an
10
- * array of bare codes, store default first (barter has no `{code,
10
+ * array of bare codes, store default first (Cartbase has no `{code,
11
11
  * name}` locale objects on the store surface; SDK wins). Display
12
12
  * names resolve via `localeDisplayName()` below (native-language
13
13
  * autonym through `Intl.DisplayNames`), overridable per store with
14
14
  * the `labels` map.
15
15
  * - The source awaited an `updateLocale(code)` server action then
16
- * `router.refresh()`; barter locale persistence is app-owned (the
16
+ * `router.refresh()`; Cartbase locale persistence is app-owned (the
17
17
  * cookie read by `StorefrontClient.getLocale`) — the async `onChange`
18
18
  * callback carries it, and the `useTransition` pending-disable UX is
19
19
  * preserved around it.
@@ -10,7 +10,7 @@ import type { ReactNode } from "react"
10
10
  * `LocalizedClientLink` (src/modules/common/components/localized-client-link)
11
11
  * — the component `@1click/ui` consumers used for the same job.
12
12
  *
13
- * barter seam: barter storefronts default to COOKIE-based locale
13
+ * Cartbase seam: Cartbase storefronts default to COOKIE-based locale
14
14
  * (`StorefrontClient.getLocale`, see docs/storefront/BUILD-A-STOREFRONT.md)
15
15
  * with no mandatory URL segment — so the prefix is applied ONLY when the
16
16
  * route actually has a `[countryCode]` (or custom `paramName`) dynamic
@@ -4,7 +4,7 @@
4
4
  * Ported from `@1click/ui/src/lib/cart-helpers.ts` (v2.3.1) with its
5
5
  * production reasoning intact; the `@medusajs/types` generic constraint is
6
6
  * replaced by the structural `LineLike` shape so this module stays decoupled
7
- * from any SDK layer (barter cart/order line items are structurally
7
+ * from any SDK layer (Cartbase cart/order line items are structurally
8
8
  * compatible: they carry `metadata`, `total`, `quantity`).
9
9
  *
10
10
  * Why this exists. There is no native "fee" / "surcharge" primitive in the
@@ -29,7 +29,7 @@
29
29
  * `findFeeLine`. Customer SHOULD see the fee in checkout / on the
30
30
  * order; they should NOT see it in the cart drawer pre-checkout.
31
31
  *
32
- * Money note (barter): amounts are decimal EUR major units everywhere in
32
+ * Money note (Cartbase): amounts are decimal EUR major units everywhere in
33
33
  * the store API — the arithmetic below is unit-agnostic and unchanged.
34
34
  */
35
35
 
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Cookie names the store API + @cartbase/storefront agree on
3
+ * (platform-fingerprints card, fingerprint #4 — cookie names are a
4
+ * primary Wappalyzer/BuiltWith detection signal).
5
+ *
6
+ * The app still OWNS *setting* the cart cookie — carts.md is explicit that
7
+ * "the SDK never persists the cart" — this module is the single source of
8
+ * the NAME so every consumer emits the same wire fingerprint instead of
9
+ * inventing its own prefix (the reference app previously hardcoded
10
+ * `_barter_cart_id` locally in `examples/storefront/src/lib/config.ts`).
11
+ *
12
+ * Renamed from the `_barter_*` prefix (2026-08-04, docs/features/
13
+ * cartbase-rename.md). `readCartCookie` accepts the legacy name for the
14
+ * transition window; every write uses the new name only.
15
+ */
16
+
17
+ /** Current cart-id cookie name. */
18
+ export const CART_COOKIE = "_cartbase_cart"
19
+
20
+ /** @deprecated Legacy name — read-only compat, never written. */
21
+ export const LEGACY_CART_COOKIE = "_barter_cart_id"
22
+
23
+ /**
24
+ * Reserved for a future cookie-backed customer session. Auth today is pure
25
+ * Bearer-JWT, persisted by the consuming app (auth.md — "the Cartbase API
26
+ * does not proxy token refresh"); nothing sets this cookie yet. Defined now
27
+ * so a future cookie-based session launches with the fingerprint-correct
28
+ * name from day one rather than inventing a new prefix later.
29
+ */
30
+ export const SESSION_COOKIE = "_cartbase_session"
31
+
32
+ /**
33
+ * Read a cart id given a cookie-name → value lookup, preferring the
34
+ * current name and falling back to the legacy `_barter_cart_id` name so an
35
+ * existing visitor's cart survives the rename.
36
+ */
37
+ export function readCartCookie(
38
+ get: (name: string) => string | undefined
39
+ ): string | undefined {
40
+ return get(CART_COOKIE) ?? get(LEGACY_CART_COOKIE)
41
+ }
@@ -6,11 +6,11 @@ import { convertToLocale } from "./money"
6
6
  * `@1click/ui/src/lib/get-product-price.ts` (v2.3.1). The
7
7
  * `@medusajs/types` `HttpTypes.StoreProduct` parameter is replaced by the
8
8
  * structural shapes below so this module stays decoupled from the SDK
9
- * domain modules (barter's `variant.calculated_price` is the b2b-v1
9
+ * domain modules (Cartbase's `variant.calculated_price` is the b2b-v1
10
10
  * pricing context documented in `@cartbase/storefront/api/types`
11
11
  * `CalculatedPrice`, decimal EUR major units).
12
12
  *
13
- * Wire-shape note (code truth, `src/lib/products/pricing.ts`): barter serves
13
+ * Wire-shape note (code truth, `src/lib/products/pricing.ts`): Cartbase serves
14
14
  * `calculated_price.price_list_type` FLAT on the calculated_price object.
15
15
  * The Medusa wire shape ALSO nests a `calculated_price.calculated_price`
16
16
  * detail object carrying `price_list_type` — the original library read the
@@ -71,7 +71,7 @@ export const getPricesForVariant = (
71
71
  currency_code: cp.currency_code,
72
72
  }),
73
73
  currency_code: cp.currency_code,
74
- // Flat key (barter wire shape) first — an explicit null stays null;
74
+ // Flat key (Cartbase wire shape) first — an explicit null stays null;
75
75
  // the nested Medusa detail is the fallback only when the flat key is
76
76
  // absent entirely (the original @1click read path).
77
77
  price_type:
@@ -2,7 +2,7 @@
2
2
  * Payment provider helpers — identifier sniffing for store payment sessions.
3
3
  *
4
4
  * Ported from `@1click/ui/src/lib/payment-constants.ts` (v2.3.1) and
5
- * translated to the barter provider-id seam (code truth:
5
+ * translated to the Cartbase provider-id seam (code truth:
6
6
  * `src/lib/stripe/providers.ts isStripeProviderId` matches exactly
7
7
  * `"pp_stripe" | "stripe"`; the accepted checkout ids are
8
8
  * `pp_stripe | pp_cod | pp_manual` — docs/contracts/store-api.md).
@@ -18,7 +18,7 @@
18
18
 
19
19
  /**
20
20
  * True if the provider id is a Stripe-backed card payment provider.
21
- * Barter's canonical ids first (`pp_stripe` / `stripe`), then the
21
+ * Cartbase's canonical ids first (`pp_stripe` / `stripe`), then the
22
22
  * Medusa-era prefixes (`pp_stripe_*`, `pp_medusa-*`).
23
23
  */
24
24
  export const isStripeLike = (providerId?: string): boolean => {
@@ -6,7 +6,7 @@ import { StoreApiError } from "../api/types"
6
6
  * Normalizes any error thrown by the `@cartbase/storefront` SDK layer into a
7
7
  * clean, user-presentable `Error` whose message starts with a capital and
8
8
  * ends with a period — the same normalization contract the Medusa-era
9
- * helper enforced, adapted to the barter error contract (`StoreApiError`
9
+ * helper enforced, adapted to the Cartbase error contract (`StoreApiError`
10
10
  * with `status` + `code` + raw `body`, see `../api/types`).
11
11
  *
12
12
  * Always throws — never returns. Use in `.catch()` chains:
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @cartbase/storefront/order — order confirmation + account order views.
3
- * Ported from `@1click/ui/src/order` (v2.3.1) with barter data seams; see
3
+ * Ported from `@1click/ui/src/order` (v2.3.1) with Cartbase data seams; see
4
4
  * per-module JSDoc and docs/storefront/components.md for the contracts.
5
5
  */
6
6
  export { OrderLabelsProvider, useOrderLabels } from "./context"
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Order family label pack. Ported from `@1click/ui/src/order/labels.ts`
3
- * (v2.3.1) unchanged, plus `tracking` — new in the barter port because the
4
- * barter order surface exposes fulfillment tracking labels
3
+ * (v2.3.1) unchanged, plus `tracking` — new in the Cartbase port because the
4
+ * Cartbase order surface exposes fulfillment tracking labels
5
5
  * (`StoreOrderDetail.fulfillments[].fulfillment.labels`) that
6
6
  * `OrderDeliveryCard` now renders.
7
7
  */
@@ -40,7 +40,7 @@ export type OrderLabels = {
40
40
  free: string
41
41
  continueShopping: string
42
42
  qty: string
43
- /** Heading for the fulfillment tracking-numbers block (barter addition). */
43
+ /** Heading for the fulfillment tracking-numbers block (Cartbase addition). */
44
44
  tracking: string
45
45
  }
46
46
 
@@ -3,7 +3,7 @@ import { defaultOrderLabels, type OrderLabels } from "./labels"
3
3
  /**
4
4
  * Contact-info card (name, phone, email). Ported from
5
5
  * `@1click/ui/src/order/order-address-card.tsx` (v2.3.1); data seam:
6
- * structural pick — barter's `StoreOrderDetail` (with its embedded
6
+ * structural pick — Cartbase's `StoreOrderDetail` (with its embedded
7
7
  * `order_addresses` row) satisfies it directly.
8
8
  */
9
9
  export interface OrderContactData {
@@ -25,11 +25,11 @@ import { OrderHelpSection } from "./order-help-section"
25
25
  /**
26
26
  * Full order-confirmation page. Ported from
27
27
  * `@1click/ui/src/order/order-completed-template.tsx` (v2.3.1) with the
28
- * barter data seam: Medusa's `StoreOrder` was one object carrying items
29
- * with totals, order totals, shipping methods and payments — barter splits
28
+ * Cartbase data seam: Medusa's `StoreOrder` was one object carrying items
29
+ * with totals, order totals, shipping methods and payments — Cartbase splits
30
30
  * those across surfaces, so the template takes them as separate props:
31
31
  *
32
- * - `order` — barter `StoreOrderDetail` (or any structural equivalent:
32
+ * - `order` — Cartbase `StoreOrderDetail` (or any structural equivalent:
33
33
  * id/display_id/email/created_at/currency_code/metadata/addresses/
34
34
  * fulfillments). The fulfillment timeline is derived from
35
35
  * `order.fulfillments` internally.
@@ -4,7 +4,7 @@ import { defaultOrderLabels, type OrderLabels } from "./labels"
4
4
  /**
5
5
  * Confirmation hero (check mark + order number + date). Ported from
6
6
  * `@1click/ui/src/order/order-confirmation-header.tsx` (v2.3.1); data
7
- * seam: structural pick instead of Medusa's `StoreOrder` — both barter's
7
+ * seam: structural pick instead of Medusa's `StoreOrder` — both Cartbase's
8
8
  * `StoreOrderDetail` and `completeCart()`'s `CompletedOrder` satisfy it.
9
9
  */
10
10
  export interface OrderHeaderData {
@@ -5,17 +5,17 @@ import { defaultOrderLabels, type OrderLabels } from "./labels"
5
5
 
6
6
  /**
7
7
  * Delivery card: pickup point / address, shipping method row, and — new in
8
- * the barter port — the fulfillment tracking labels. Ported from
8
+ * the Cartbase port — the fulfillment tracking labels. Ported from
9
9
  * `@1click/ui/src/order/order-delivery-card.tsx` (v2.3.1) with these seam
10
10
  * translations:
11
11
  *
12
- * - Medusa's `order.shipping_methods[0]` embed does not exist on barter's
12
+ * - Medusa's `order.shipping_methods[0]` embed does not exist on Cartbase's
13
13
  * `StoreOrderDetail`; the method comes via the `shippingMethod` prop
14
14
  * (structural — `api/carts` `CartShippingMethod` from the decorated
15
15
  * cart on the confirmation page satisfies it; `data` still carries the
16
16
  * fulfillment-option id used for the pickup detection below).
17
17
  * - `order.fulfillments[].fulfillment.labels` (tracking_number /
18
- * tracking_url) ARE on the barter surface (docs/storefront/orders.md);
18
+ * tracking_url) ARE on the Cartbase surface (docs/storefront/orders.md);
19
19
  * `pickTrackingLabels()` selects the renderable ones and the card shows
20
20
  * them under a `labels.tracking` heading.
21
21
  * - Pickup detection preserved verbatim: `metadata.econt_office_code` (the
@@ -6,10 +6,10 @@ import { defaultOrderLabels, type OrderLabels } from "./labels"
6
6
 
7
7
  /**
8
8
  * Order line row. Ported from `@1click/ui/src/order/order-item.tsx`
9
- * (v2.3.1) with the data seam translated to barter:
9
+ * (v2.3.1) with the data seam translated to Cartbase:
10
10
  *
11
11
  * Medusa's `StoreOrderLineItem` carried per-line computed totals
12
- * (`total` / `original_total`). Barter's store order surface does NOT —
12
+ * (`total` / `original_total`). Cartbase's store order surface does NOT —
13
13
  * `StoreOrderDetail.items` are version-pivot rows (`{quantity, line_item}`)
14
14
  * whose embedded `order_line_items` row carries only `unit_price` (see
15
15
  * docs/storefront/orders.md). The component therefore renders a normalized
@@ -5,7 +5,7 @@ import { defaultOrderLabels, type OrderLabels } from "./labels"
5
5
  /**
6
6
  * Order items list. Ported from `@1click/ui/src/order/order-items-list.tsx`
7
7
  * (v2.3.1); data seam: takes normalized `OrderDisplayItem[]` (see
8
- * `order-item.tsx` converters) + the currency, since barter's
8
+ * `order-item.tsx` converters) + the currency, since Cartbase's
9
9
  * `StoreOrderDetail` carries no order-level computed fields beyond
10
10
  * `currency_code`.
11
11
  */
@@ -23,9 +23,9 @@ export function OrderItemsList({
23
23
  const l = { ...defaultOrderLabels, ...labels }
24
24
  // Render product lines only — backend-injected fee lines (legacy COD-fee
25
25
  // line items tagged `metadata.is_cod_fee`) are hidden here and surfaced
26
- // as a dedicated row in OrderTotals instead. barter's NATIVE COD fee is
26
+ // as a dedicated row in OrderTotals instead. Cartbase's NATIVE COD fee is
27
27
  // never a line item (order_summaries.totals.cod_fee_total), so on pure
28
- // barter data this filter is a no-op safety net.
28
+ // Cartbase data this filter is a no-op safety net.
29
29
  const visible = (items || []).filter((i) => isProductLine(i))
30
30
 
31
31
  return (
@@ -11,7 +11,7 @@ import { defaultOrderLabels, type OrderLabels } from "./labels"
11
11
  * Payment-method card. Ported from
12
12
  * `@1click/ui/src/order/order-payment-card.tsx` (v2.3.1); data seam:
13
13
  * Medusa's `order.payment_collections[0].payments[0]` embed does not exist
14
- * on barter's `StoreOrderDetail` (payment internals never cross the store
14
+ * on Cartbase's `StoreOrderDetail` (payment internals never cross the store
15
15
  * surface) — the provider id arrives via props instead: from
16
16
  * `prepareCheckout().payment_provider`, the decorated cart's
17
17
  * `payment_collection` sessions, or the app's checkout state.
@@ -33,7 +33,7 @@ import { defaultOrderLabels, type OrderLabels } from "./labels"
33
33
  *
34
34
  * The bucket is determined by the same `isStripeLike` / `isManual` /
35
35
  * `isPaypal` predicates used everywhere else in the library (translated to
36
- * barter ids in `lib/payment-constants`), so a single change to those
36
+ * Cartbase ids in `lib/payment-constants`), so a single change to those
37
37
  * propagates here automatically.
38
38
  */
39
39
  export function resolvePaymentTitle(
@@ -6,14 +6,14 @@ import { defaultOrderLabels, type OrderLabels } from "./labels"
6
6
  /**
7
7
  * Fulfillment progress timeline. Ported from
8
8
  * `@1click/ui/src/order/order-timeline.tsx` (v2.3.1) — the step state
9
- * machine and rendering are unchanged. Barter seam: there is no
9
+ * machine and rendering are unchanged. Cartbase seam: there is no
10
10
  * `order.fulfillment_status` column on the store surface; derive the
11
11
  * status from the fulfillments' lifecycle timestamps with
12
12
  * `deriveFulfillmentStatus(order.fulfillments)` and pass it in.
13
13
  */
14
14
 
15
15
  /**
16
- * Derive a Medusa-style fulfillment status from barter's fulfillment
16
+ * Derive a Medusa-style fulfillment status from Cartbase's fulfillment
17
17
  * lifecycle timestamps (packed_at → fulfilled, shipped_at → shipped,
18
18
  * delivered_at → delivered; canceled fulfillments are ignored). Returns
19
19
  * `undefined` for "not fulfilled yet" (timeline shows "Placed"). Partial
@@ -4,9 +4,9 @@ import { defaultOrderLabels, type OrderLabels } from "./labels"
4
4
 
5
5
  /**
6
6
  * Order totals breakdown. Ported from `@1click/ui/src/order/order-totals.tsx`
7
- * (v2.3.1) with the barter money seam:
7
+ * (v2.3.1) with the Cartbase money seam:
8
8
  *
9
- * Totals are SERVER truth and the barter store order read
9
+ * Totals are SERVER truth and the Cartbase store order read
10
10
  * (`StoreOrderDetail`) carries NONE of them — they live where the server
11
11
  * computed them: the decorated cart the app holds on the confirmation page
12
12
  * (`api/carts` `Cart`: `item_subtotal`, `shipping_subtotal`,
@@ -18,7 +18,7 @@ import { defaultOrderLabels, type OrderLabels } from "./labels"
18
18
  * computes money beyond the two production subtractions documented below.
19
19
  *
20
20
  * COD fee display, in preference order (production fix preserved):
21
- * 1. barter-native fee: `cod_fee_total` > 0 (never a line item;
21
+ * 1. Cartbase-native fee: `cod_fee_total` > 0 (never a line item;
22
22
  * already folded into `total` server-side), labeled by the
23
23
  * admin-editable `cod_fee_label`.
24
24
  * 2. legacy Medusa-era fee LINE ITEM (`metadata.is_cod_fee`) found in
@@ -42,7 +42,7 @@ export interface OrderTotalsSource {
42
42
  discount_total?: number | null
43
43
  tax_total?: number | null
44
44
  total?: number | null
45
- /** barter-native COD fee (already folded into `total`). */
45
+ /** Cartbase-native COD fee (already folded into `total`). */
46
46
  cod_fee_total?: number | null
47
47
  /** Admin-editable COD fee label from the server. */
48
48
  cod_fee_label?: string | null
@@ -98,7 +98,7 @@ export function selectOrderTotalsRows(
98
98
  const l = { ...defaultOrderLabels, ...opts.labels }
99
99
  const rows: OrderTotalsRow[] = []
100
100
 
101
- // Legacy fee LINE (Medusa-era injection) — barter-native carts never
101
+ // Legacy fee LINE (Medusa-era injection) — Cartbase-native carts never
102
102
  // have one, but ported data / hybrid stores might.
103
103
  const codFeeItem = findFeeLine(opts.items || [])
104
104
  const nativeFee = Number(source.cod_fee_total ?? 0)
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Platform identity — MIRROR of `src/lib/platform/identity.ts` in the main
3
+ * app (docs/cards/platform-fingerprints.md). This library publishes to npm
4
+ * independently, so it cannot import the app's root `package.json` across
5
+ * the package boundary — it reads its OWN `package.json` instead.
6
+ *
7
+ * Sync obligation: if `PLATFORM_NAME` ever changes, update BOTH copies in
8
+ * the same commit. There is no automated link between them.
9
+ *
10
+ * Emitters that consume this: `./metadata.ts` (generator meta tag),
11
+ * `./platform-init.tsx` (window.Cartbase).
12
+ */
13
+ import pkg from "../../package.json"
14
+
15
+ export const PLATFORM_NAME = "Cartbase"
16
+
17
+ /** This package's own published version. */
18
+ export const PLATFORM_VERSION: string = pkg.version
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @cartbase/storefront/platform — platform-fingerprint emitters
3
+ * (docs/cards/platform-fingerprints.md). Same barrel discipline as every
4
+ * other feature folder (tracking, checkout, cart-drawer, ...).
5
+ */
6
+ export { PLATFORM_NAME, PLATFORM_VERSION } from "./identity"
7
+ export { createStorefrontMetadata } from "./metadata"
8
+ export { PlatformInit, type PlatformInitProps, type CartbaseWindowGlobal } from "./platform-init"
@@ -0,0 +1,26 @@
1
+ import type { Metadata } from "next"
2
+ import { PLATFORM_NAME } from "./identity"
3
+
4
+ /**
5
+ * createStorefrontMetadata — root-layout metadata helper
6
+ * (platform-fingerprints card, fingerprint #1). Every storefront built on
7
+ * `@cartbase/storefront` calls this instead of hand-writing
8
+ * `export const metadata`, so `<meta name="generator" content="Cartbase" />`
9
+ * ships by construction on every storefront-rendered page.
10
+ *
11
+ * Usage:
12
+ *
13
+ * export const metadata: Metadata = createStorefrontMetadata({
14
+ * title: "My Store",
15
+ * description: "...",
16
+ * })
17
+ *
18
+ * `generator` always resolves to the platform name — it is not
19
+ * overridable from `overrides` (a stray key there is simply shadowed).
20
+ */
21
+ export function createStorefrontMetadata(overrides: Metadata = {}): Metadata {
22
+ return {
23
+ ...overrides,
24
+ generator: PLATFORM_NAME,
25
+ }
26
+ }
@@ -0,0 +1,46 @@
1
+ import { PLATFORM_VERSION } from "./identity"
2
+
3
+ /**
4
+ * The shape of `window.Cartbase` — the strongest platform-detection signal
5
+ * (same mechanism as `window.Shopify`). No PII: store id + platform
6
+ * version only.
7
+ */
8
+ export interface CartbaseWindowGlobal {
9
+ version: string
10
+ storeId: string
11
+ }
12
+
13
+ declare global {
14
+ interface Window {
15
+ Cartbase?: CartbaseWindowGlobal
16
+ }
17
+ }
18
+
19
+ export interface PlatformInitProps {
20
+ /** The store's client id — the ONLY identifying value exposed. */
21
+ storeId: string
22
+ }
23
+
24
+ /**
25
+ * PlatformInit — mounts `window.Cartbase = { version, storeId }`
26
+ * (platform-fingerprints card, fingerprint #3). Same shape as
27
+ * `<ConsentInit />` (`../tracking/consent-init.tsx`): a server component
28
+ * rendering one synchronous inline `<script>`, mounted once near the top
29
+ * of `<body>` — no hydration wait, no client bundle cost.
30
+ *
31
+ * Storefront-surface only. Never mount this in an admin bundle — admin is
32
+ * not a storefront (category discipline: Cartbase exists ONLY as
33
+ * Ecommerce, and `window.Cartbase` must only ever appear where commerce
34
+ * actually happens).
35
+ */
36
+ export function PlatformInit({ storeId }: PlatformInitProps) {
37
+ const payload: CartbaseWindowGlobal = { version: PLATFORM_VERSION, storeId }
38
+ return (
39
+ <script
40
+ id="cartbase-platform-init"
41
+ dangerouslySetInnerHTML={{
42
+ __html: `window.Cartbase=${JSON.stringify(payload)};`,
43
+ }}
44
+ />
45
+ )
46
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * PDP image gallery — ported from
3
3
  * `@1click/ui/src/products/image-gallery.tsx` (v2.3.1). Data seam:
4
- * `HttpTypes.StoreProductImage[]` → barter `StoreProductImage[]`
4
+ * `HttpTypes.StoreProductImage[]` → Cartbase `StoreProductImage[]`
5
5
  * (`@cartbase/storefront/api/products`; images arrive rank-ordered from the
6
6
  * API). Server-safe.
7
7
  */