@cartbase/storefront 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/src/api/customers.ts +6 -7
- package/src/api/http.ts +51 -1
- package/src/api/products.ts +330 -314
- package/src/cart-drawer/cross-sell-carousel.tsx +1 -1
- package/src/cart-drawer/cross-sell-sidebar.tsx +1 -1
- package/src/cart-drawer/free-gift.tsx +1 -1
- package/src/cart-drawer/item/index.tsx +1 -1
- package/src/cart-drawer/item/upsell.tsx +1 -1
- package/src/lib/media-image.tsx +39 -0
- package/src/locales/bg.ts +3 -0
- package/src/locales/es.ts +3 -0
- package/src/order/order-item.tsx +1 -1
- package/src/products/image-gallery.tsx +1 -1
- package/src/products/index.ts +14 -0
- package/src/products/labels.ts +7 -0
- package/src/products/product-actions-wrapper.tsx +62 -58
- package/src/products/product-actions.tsx +104 -177
- package/src/products/product-info.tsx +10 -5
- package/src/products/product-template.tsx +162 -149
- package/src/products/thumbnail.tsx +1 -1
- package/src/products/use-product-actions.ts +164 -0
- package/src/products/variant-url.ts +74 -0
- package/src/store/paginated-products.tsx +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cartbase/storefront",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Storefront SDK + UI component library for Cartbase stores: typed API client, checkout orchestration, cart drawer, product/catalog components, tracking. Source-shipped TypeScript — add it to transpilePackages.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"./lib/hooks/use-intersection": "./src/lib/hooks/use-intersection.ts",
|
|
57
57
|
"./lib/hooks/use-toggle-state": "./src/lib/hooks/use-toggle-state.ts",
|
|
58
58
|
"./lib/cookie-names": "./src/lib/cookie-names.ts",
|
|
59
|
+
"./lib/media-image": "./src/lib/media-image.tsx",
|
|
59
60
|
"./lib/platform": "./src/lib/platform.ts",
|
|
60
61
|
"./lib/visitor": "./src/lib/visitor.ts",
|
|
61
62
|
"./platform": "./src/platform/index.ts",
|
|
@@ -155,6 +156,8 @@
|
|
|
155
156
|
"./products/product-price": "./src/products/product-price.tsx",
|
|
156
157
|
"./products/option-select": "./src/products/option-select.tsx",
|
|
157
158
|
"./products/image-gallery": "./src/products/image-gallery.tsx",
|
|
159
|
+
"./products/variant-url": "./src/products/variant-url.ts",
|
|
160
|
+
"./products/use-product-actions": "./src/products/use-product-actions.ts",
|
|
158
161
|
"./products/product-actions": "./src/products/product-actions.tsx",
|
|
159
162
|
"./products/mobile-actions": "./src/products/mobile-actions.tsx",
|
|
160
163
|
"./products/product-tabs": "./src/products/product-tabs.tsx",
|
package/src/api/customers.ts
CHANGED
|
@@ -43,10 +43,11 @@ export interface CustomerAddress {
|
|
|
43
43
|
/**
|
|
44
44
|
* The customer payload: the customer's own row as the store serves it, plus
|
|
45
45
|
* addresses. Named columns since 2026-09-14: no tenant id, no soft-delete
|
|
46
|
-
* stamp, no staff identity, no provider account id
|
|
46
|
+
* stamp, no staff identity, no provider account id, and no merchant tags
|
|
47
|
+
* (the labels a merchant puts on a customer are staff knowledge and never
|
|
48
|
+
* reach the shopper).
|
|
47
49
|
* `account_status` (`pending` | `approved`) gates B2B storefront content
|
|
48
|
-
* when the store's approval policy is on (b2b-v1).
|
|
49
|
-
* labels — readable here, never writable from the store surface.
|
|
50
|
+
* when the store's approval policy is on (b2b-v1).
|
|
50
51
|
*/
|
|
51
52
|
export interface StoreCustomer {
|
|
52
53
|
id: string
|
|
@@ -61,7 +62,6 @@ export interface StoreCustomer {
|
|
|
61
62
|
has_account: boolean
|
|
62
63
|
/** `pending` | `approved` — store approval policy (customer-accounts card). */
|
|
63
64
|
account_status: string
|
|
64
|
-
tags: string[]
|
|
65
65
|
metadata: Record<string, unknown> | null
|
|
66
66
|
created_at: IsoDateString
|
|
67
67
|
updated_at: IsoDateString
|
|
@@ -120,12 +120,11 @@ export interface UpdateCustomerInput {
|
|
|
120
120
|
company_eik?: string | null
|
|
121
121
|
vat_number?: string | null
|
|
122
122
|
metadata?: Record<string, unknown>
|
|
123
|
-
// NOTE: `tags` deliberately absent — admin-only; the server strips them.
|
|
124
123
|
}
|
|
125
124
|
|
|
126
125
|
/**
|
|
127
|
-
* POST /api/store/customers/me — update own profile. Unknown keys
|
|
128
|
-
*
|
|
126
|
+
* POST /api/store/customers/me — update own profile. Unknown keys are
|
|
127
|
+
* stripped server-side; returns the refreshed customer.
|
|
129
128
|
*
|
|
130
129
|
* Auth: Bearer JWT (+ x-client-id).
|
|
131
130
|
* Errors: 401 unauthenticated · 400 validation_failed.
|
package/src/api/http.ts
CHANGED
|
@@ -42,6 +42,42 @@ export interface StorefrontClientConfig {
|
|
|
42
42
|
export type QueryValue = string | number | boolean | null | undefined
|
|
43
43
|
export type Query = Record<string, QueryValue | QueryValue[]>
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* The reads the platform's CDN holds for anonymous shoppers (store-api.md
|
|
47
|
+
* § Caching). Such a request carries the store's publishable key in its
|
|
48
|
+
* address as `pk`, so the edge can tell one store's answers from another's,
|
|
49
|
+
* and the shopper's locale as `locale`. A request with a customer token
|
|
50
|
+
* carries neither: its prices are the shopper's own, and an address without
|
|
51
|
+
* the key is never held and never served from the hold. Carts, checkout,
|
|
52
|
+
* consent, customers and every write are never on this list.
|
|
53
|
+
*/
|
|
54
|
+
const CACHEABLE_READ_PREFIXES = [
|
|
55
|
+
"/api/store/store",
|
|
56
|
+
"/api/store/menus",
|
|
57
|
+
"/api/store/regions",
|
|
58
|
+
"/api/store/collections",
|
|
59
|
+
"/api/store/products",
|
|
60
|
+
"/api/store/product-variants",
|
|
61
|
+
"/api/store/product-categories",
|
|
62
|
+
"/api/store/product-types",
|
|
63
|
+
"/api/store/product-tags",
|
|
64
|
+
"/api/store/reviews",
|
|
65
|
+
"/api/store/currencies",
|
|
66
|
+
"/api/store/countries",
|
|
67
|
+
"/api/store/locales",
|
|
68
|
+
"/api/store/pages",
|
|
69
|
+
"/api/store/blogs",
|
|
70
|
+
"/api/store/metaobjects",
|
|
71
|
+
"/api/store/url-redirects",
|
|
72
|
+
"/api/store/return-reasons",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
export function isCacheableStoreRead(pathname: string): boolean {
|
|
76
|
+
return CACHEABLE_READ_PREFIXES.some(
|
|
77
|
+
(prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`)
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
45
81
|
export interface RequestOptions {
|
|
46
82
|
method?: "GET" | "POST" | "DELETE"
|
|
47
83
|
query?: Query
|
|
@@ -92,9 +128,23 @@ export class StorefrontClient {
|
|
|
92
128
|
const locale = this.config.getLocale ? await this.config.getLocale() : null
|
|
93
129
|
if (locale && !headers["x-locale"]) headers["x-locale"] = locale
|
|
94
130
|
|
|
131
|
+
// An anonymous catalogue read carries its key (and locale) in the
|
|
132
|
+
// address, so the platform's CDN may hold the answer for this store.
|
|
133
|
+
const method = opts.method ?? "GET"
|
|
134
|
+
const anonymous = !headers.authorization
|
|
135
|
+
if (
|
|
136
|
+
method === "GET" &&
|
|
137
|
+
anonymous &&
|
|
138
|
+
this.config.publishableKey &&
|
|
139
|
+
isCacheableStoreRead(url.pathname)
|
|
140
|
+
) {
|
|
141
|
+
url.searchParams.set("pk", this.config.publishableKey)
|
|
142
|
+
if (locale) url.searchParams.set("locale", locale)
|
|
143
|
+
}
|
|
144
|
+
|
|
95
145
|
const doFetch = this.config.fetch ?? fetch
|
|
96
146
|
const res = await doFetch(url.toString(), {
|
|
97
|
-
method
|
|
147
|
+
method,
|
|
98
148
|
headers,
|
|
99
149
|
body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,
|
|
100
150
|
cache: opts.cache,
|