@cartbase/storefront 0.20.0 → 0.20.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.
- package/LICENSE +21 -21
- package/package.json +258 -258
- package/src/api/auth.ts +108 -108
- package/src/api/carts.ts +523 -523
- package/src/api/categories.ts +184 -184
- package/src/api/checkout.ts +526 -526
- package/src/api/collections.ts +130 -130
- package/src/api/consent.ts +75 -75
- package/src/api/content.ts +125 -125
- package/src/api/customers.ts +303 -303
- package/src/api/gift-cards.ts +112 -112
- package/src/api/http.ts +180 -180
- package/src/api/index.ts +30 -30
- package/src/api/menus.ts +77 -77
- package/src/api/metaobjects.ts +136 -136
- package/src/api/orders.ts +290 -290
- package/src/api/redirects.ts +37 -37
- package/src/api/regions.ts +200 -200
- package/src/api/search.ts +163 -163
- package/src/api/store.ts +35 -35
- package/src/api/types.ts +91 -91
- package/src/cart-drawer/context.tsx +778 -778
- package/src/cart-drawer/cross-sell-carousel.tsx +211 -211
- package/src/cart-drawer/cross-sell-sidebar.tsx +158 -158
- package/src/cart-drawer/gift-wrap.tsx +82 -82
- package/src/cart-drawer/item/index.tsx +162 -162
- package/src/cart-drawer/item/upsell.tsx +110 -110
- package/src/cart-drawer/labels.ts +123 -123
- package/src/cart-drawer/mutation-queue.ts +78 -78
- package/src/cart-drawer/notes.tsx +131 -131
- package/src/cart-drawer/sticky-footer.tsx +73 -73
- package/src/cart-drawer/summary-breakdown.tsx +197 -197
- package/src/checkout/address-error-copy.ts +117 -117
- package/src/checkout/boxnow-locker-selector.tsx +410 -410
- package/src/checkout/compare-addresses.ts +40 -40
- package/src/checkout/discount-section.tsx +218 -218
- package/src/checkout/error-copy-codes.ts +63 -63
- package/src/checkout/geocode.ts +154 -154
- package/src/checkout/gift-card-section.tsx +224 -224
- package/src/checkout/index.ts +72 -72
- package/src/checkout/labels.ts +495 -495
- package/src/checkout/payment-button.tsx +372 -372
- package/src/checkout/payment-error-copy.ts +154 -154
- package/src/checkout/promotion-error-copy.ts +91 -91
- package/src/common/country-flag.tsx +52 -52
- package/src/common/country-select.tsx +11 -11
- package/src/common/index.ts +20 -20
- package/src/common/market-select.tsx +57 -57
- package/src/index.ts +12 -12
- package/src/lib/country-name.ts +59 -59
- package/src/lib/get-product-price.ts +133 -133
- package/src/lib/media-image.tsx +39 -39
- package/src/lib/payment-constants.ts +53 -53
- package/src/lib/platform.ts +13 -13
- package/src/lib/price.tsx +39 -39
- package/src/lib/store-api-error.ts +36 -36
- package/src/lib/variant-caption.ts +32 -32
- package/src/locales/context.ts +37 -37
- package/src/locales/en.ts +26 -26
- package/src/locales/index.ts +19 -19
- package/src/locales/provider.tsx +59 -59
- package/src/locales/types.ts +77 -77
- package/src/order/index.ts +62 -62
- package/src/order/labels.ts +79 -79
- package/src/order/order-totals.tsx +250 -250
- package/src/primitives/select-field.tsx +93 -93
- package/src/products/image-gallery.tsx +43 -43
- package/src/products/option-select.tsx +67 -67
- package/src/products/product-info.tsx +5 -5
- package/src/products/product-price.tsx +69 -69
- package/src/products/product-promises.tsx +61 -61
- package/src/products/product-specs.tsx +65 -65
- package/src/products/product-tabs.tsx +123 -123
- package/src/products/purchase-options.tsx +130 -130
- package/src/products/sets.ts +110 -110
- package/src/products/variant-matching.ts +71 -71
- package/src/products/variant-url.ts +74 -74
- package/src/reviews-ui/lightbox-state.ts +46 -46
- package/src/reviews-ui/review-header.tsx +166 -166
- package/src/reviews-ui/review-lightbox.tsx +271 -271
- package/src/reviews-ui/review-list.tsx +193 -193
- package/src/reviews-ui/review-widget.tsx +219 -218
- package/src/reviews-ui/widget-options.ts +55 -55
- package/src/store/category-template.tsx +136 -136
- package/src/store/index.ts +40 -40
- package/src/tracking/chatgpt-pixel.tsx +99 -99
- package/src/tracking/consent-init.tsx +62 -62
- package/src/tracking/events.ts +348 -348
- package/src/tracking/ga4.tsx +93 -93
- package/src/tracking/google-ads.ts +84 -84
- package/src/tracking/gtm.tsx +60 -60
- package/src/tracking/inline-script.ts +49 -49
- package/src/tracking/oaiq.ts +206 -206
- package/src/tracking/tiktok-pixel.tsx +91 -91
- package/src/tracking/track-init.tsx +56 -56
- package/src/tracking/track-order-purchase.tsx +122 -122
- package/src/tracking/ttq.ts +180 -180
- package/src/tracking/use-tracking-config.ts +54 -54
- package/theme/index.css +25 -25
package/src/api/menus.ts
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @cartbase/storefront/api/menus — backend-owned navigation
|
|
3
|
-
* (content-navigation card).
|
|
4
|
-
*
|
|
5
|
-
* Ground truth: src/app/api/store/menus/[handle]/route.ts +
|
|
6
|
-
* src/lib/content/menus.ts.
|
|
7
|
-
*
|
|
8
|
-
* Shopify Storefront `Menu` shape verbatim. Item `url`s are COMPUTED AT
|
|
9
|
-
* READ TIME from live resource handles (src/lib/content/paths.ts) — a
|
|
10
|
-
* handle rename never breaks a menu. Items whose referenced resource is
|
|
11
|
-
* deleted or not storefront-visible (draft page/post/product, inactive or
|
|
12
|
-
* internal category) are SKIPPED, subtree included — the payload only ever
|
|
13
|
-
* contains renderable links. 3-level nesting max.
|
|
14
|
-
*
|
|
15
|
-
* ## ETag / caching semantics
|
|
16
|
-
* The route serves `ETag` (sha1 of the payload) +
|
|
17
|
-
* `Cache-Control: public, s-maxage=60, stale-while-revalidate=3600`, and
|
|
18
|
-
* answers `If-None-Match` with `304` (empty body). Browser `fetch` handles
|
|
19
|
-
* this transparently; server-side callers on Next.js should instead lean on
|
|
20
|
-
* the RSC cache (`next: { revalidate }`) via `RequestOptions`. Note the SDK
|
|
21
|
-
* itself does NOT replay ETags — a 304 only occurs when the caller's fetch
|
|
22
|
-
* layer sends `If-None-Match`, in which case the platform serves the cached
|
|
23
|
-
* body before the SDK sees it. The `menu.updated` event fires on every menu
|
|
24
|
-
* mutation for future revalidation hooks.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import type { StorefrontClient } from "./http"
|
|
28
|
-
|
|
29
|
-
/** One navigation node — recursive, ≤ 3 levels total. */
|
|
30
|
-
export interface MenuItem {
|
|
31
|
-
title: string
|
|
32
|
-
/** What the item points at. */
|
|
33
|
-
type:
|
|
34
|
-
| "frontpage"
|
|
35
|
-
| "collection"
|
|
36
|
-
| "product"
|
|
37
|
-
| "category"
|
|
38
|
-
| "page"
|
|
39
|
-
| "blog_post"
|
|
40
|
-
| "external"
|
|
41
|
-
/**
|
|
42
|
-
* Computed at read time: `/` for frontpage, the shared path convention
|
|
43
|
-
* (`/collections/<handle>`, `/products/<handle>`, `/categories/<handle>`,
|
|
44
|
-
* `/pages/<handle>`, `/blogs/<blog>/<post>`) for resources, and the
|
|
45
|
-
* stored URL verbatim for `external`.
|
|
46
|
-
*/
|
|
47
|
-
url: string
|
|
48
|
-
/** Referenced resource id (`pcol_…`, `prod_…`); null for frontpage/external. */
|
|
49
|
-
resourceId: string | null
|
|
50
|
-
items: MenuItem[]
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface Menu {
|
|
54
|
-
handle: string
|
|
55
|
-
title: string
|
|
56
|
-
items: MenuItem[]
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface MenuResponse {
|
|
60
|
-
menu: Menu
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* GET /api/store/menus/:handle — one menu, renderable links only.
|
|
65
|
-
*
|
|
66
|
-
* Auth: anon (x-client-id).
|
|
67
|
-
* Errors: 404 not_found (unknown/deleted handle — a store with zero menus
|
|
68
|
-
* 404s every handle; render no nav, never crash).
|
|
69
|
-
* Settings: menus are authored in admin → Content → Navigation; deleting a
|
|
70
|
-
* referenced resource silently drops its item (subtree included) here.
|
|
71
|
-
*/
|
|
72
|
-
export async function getMenu(
|
|
73
|
-
client: StorefrontClient,
|
|
74
|
-
handle: string
|
|
75
|
-
): Promise<MenuResponse> {
|
|
76
|
-
return client.get(`/api/store/menus/${encodeURIComponent(handle)}`)
|
|
77
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @cartbase/storefront/api/menus — backend-owned navigation
|
|
3
|
+
* (content-navigation card).
|
|
4
|
+
*
|
|
5
|
+
* Ground truth: src/app/api/store/menus/[handle]/route.ts +
|
|
6
|
+
* src/lib/content/menus.ts.
|
|
7
|
+
*
|
|
8
|
+
* Shopify Storefront `Menu` shape verbatim. Item `url`s are COMPUTED AT
|
|
9
|
+
* READ TIME from live resource handles (src/lib/content/paths.ts) — a
|
|
10
|
+
* handle rename never breaks a menu. Items whose referenced resource is
|
|
11
|
+
* deleted or not storefront-visible (draft page/post/product, inactive or
|
|
12
|
+
* internal category) are SKIPPED, subtree included — the payload only ever
|
|
13
|
+
* contains renderable links. 3-level nesting max.
|
|
14
|
+
*
|
|
15
|
+
* ## ETag / caching semantics
|
|
16
|
+
* The route serves `ETag` (sha1 of the payload) +
|
|
17
|
+
* `Cache-Control: public, s-maxage=60, stale-while-revalidate=3600`, and
|
|
18
|
+
* answers `If-None-Match` with `304` (empty body). Browser `fetch` handles
|
|
19
|
+
* this transparently; server-side callers on Next.js should instead lean on
|
|
20
|
+
* the RSC cache (`next: { revalidate }`) via `RequestOptions`. Note the SDK
|
|
21
|
+
* itself does NOT replay ETags — a 304 only occurs when the caller's fetch
|
|
22
|
+
* layer sends `If-None-Match`, in which case the platform serves the cached
|
|
23
|
+
* body before the SDK sees it. The `menu.updated` event fires on every menu
|
|
24
|
+
* mutation for future revalidation hooks.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import type { StorefrontClient } from "./http"
|
|
28
|
+
|
|
29
|
+
/** One navigation node — recursive, ≤ 3 levels total. */
|
|
30
|
+
export interface MenuItem {
|
|
31
|
+
title: string
|
|
32
|
+
/** What the item points at. */
|
|
33
|
+
type:
|
|
34
|
+
| "frontpage"
|
|
35
|
+
| "collection"
|
|
36
|
+
| "product"
|
|
37
|
+
| "category"
|
|
38
|
+
| "page"
|
|
39
|
+
| "blog_post"
|
|
40
|
+
| "external"
|
|
41
|
+
/**
|
|
42
|
+
* Computed at read time: `/` for frontpage, the shared path convention
|
|
43
|
+
* (`/collections/<handle>`, `/products/<handle>`, `/categories/<handle>`,
|
|
44
|
+
* `/pages/<handle>`, `/blogs/<blog>/<post>`) for resources, and the
|
|
45
|
+
* stored URL verbatim for `external`.
|
|
46
|
+
*/
|
|
47
|
+
url: string
|
|
48
|
+
/** Referenced resource id (`pcol_…`, `prod_…`); null for frontpage/external. */
|
|
49
|
+
resourceId: string | null
|
|
50
|
+
items: MenuItem[]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface Menu {
|
|
54
|
+
handle: string
|
|
55
|
+
title: string
|
|
56
|
+
items: MenuItem[]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface MenuResponse {
|
|
60
|
+
menu: Menu
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* GET /api/store/menus/:handle — one menu, renderable links only.
|
|
65
|
+
*
|
|
66
|
+
* Auth: anon (x-client-id).
|
|
67
|
+
* Errors: 404 not_found (unknown/deleted handle — a store with zero menus
|
|
68
|
+
* 404s every handle; render no nav, never crash).
|
|
69
|
+
* Settings: menus are authored in admin → Content → Navigation; deleting a
|
|
70
|
+
* referenced resource silently drops its item (subtree included) here.
|
|
71
|
+
*/
|
|
72
|
+
export async function getMenu(
|
|
73
|
+
client: StorefrontClient,
|
|
74
|
+
handle: string
|
|
75
|
+
): Promise<MenuResponse> {
|
|
76
|
+
return client.get(`/api/store/menus/${encodeURIComponent(handle)}`)
|
|
77
|
+
}
|
package/src/api/metaobjects.ts
CHANGED
|
@@ -1,136 +1,136 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @cartbase/storefront/api/metaobjects — merchant-defined content types
|
|
3
|
-
* (metaobjects card): size charts, brand profiles, FAQ blocks…
|
|
4
|
-
*
|
|
5
|
-
* Ground truth: src/app/api/store/metaobjects/** +
|
|
6
|
-
* src/lib/metaobjects/store.ts.
|
|
7
|
-
*
|
|
8
|
-
* ACTIVE entries only — drafts 404 (lib filter AND anon RLS). Capabilities
|
|
9
|
-
* per definition: `renderable` → `seo` present; `online_store` → `url`
|
|
10
|
-
* present (`/metaobjects/<type>/<handle>`; the storefront prepends its
|
|
11
|
-
* origin). References resolve at READ time: a target the storefront cannot
|
|
12
|
-
* see yields `reference: null` — never dropped, never a 500.
|
|
13
|
-
*
|
|
14
|
-
* `by-metafield` is a RESERVED type slug (the static route shadows /:type).
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import type { StorefrontClient } from "./http"
|
|
18
|
-
import type { IsoDateString, PaginationQuery } from "./types"
|
|
19
|
-
|
|
20
|
-
/** One field of a metaobject entry. */
|
|
21
|
-
export interface MetaobjectField {
|
|
22
|
-
key: string
|
|
23
|
-
/** Field kind from the definition (text, rich_text, reference kinds…). */
|
|
24
|
-
kind: string
|
|
25
|
-
/** Raw stored value (shape depends on `kind`). */
|
|
26
|
-
value: unknown
|
|
27
|
-
/**
|
|
28
|
-
* Reference kinds only (absent otherwise). Resolved target, or null when
|
|
29
|
-
* the target is deleted / not storefront-visible. NOT resolved on LIST
|
|
30
|
-
* payloads — only the by-handle read and by-metafield resolve references.
|
|
31
|
-
*/
|
|
32
|
-
reference?: { id: string; title: string; handle: string; type?: string } | null
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface Metaobject {
|
|
36
|
-
id: string
|
|
37
|
-
/** The definition's type slug. */
|
|
38
|
-
type: string
|
|
39
|
-
handle: string
|
|
40
|
-
displayName: string
|
|
41
|
-
fields: MetaobjectField[]
|
|
42
|
-
/** Present only when the definition has the `renderable` capability.
|
|
43
|
-
* title falls back to displayName; description to null. */
|
|
44
|
-
seo?: { title: string; description: string | null }
|
|
45
|
-
/** Present only with the `online_store` capability:
|
|
46
|
-
* `/metaobjects/<type>/<handle>`. */
|
|
47
|
-
url?: string
|
|
48
|
-
updatedAt: IsoDateString
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export type ListMetaobjectsQuery = PaginationQuery
|
|
52
|
-
|
|
53
|
-
export interface MetaobjectListResponse {
|
|
54
|
-
metaobjects: Metaobject[]
|
|
55
|
-
count: number
|
|
56
|
-
offset: number
|
|
57
|
-
limit: number
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* GET /api/store/metaobjects/:type — paginated ACTIVE entries of one type,
|
|
62
|
-
* newest-updated first. `limit` clamped to 1–100 (default 20; out-of-range
|
|
63
|
-
* values are clamped, not rejected). List payloads carry RAW field values —
|
|
64
|
-
* `reference` is NOT resolved here (use getMetaobject for the resolve path).
|
|
65
|
-
*
|
|
66
|
-
* Auth: anon (x-client-id).
|
|
67
|
-
* Errors: 404 not_found (unknown type).
|
|
68
|
-
*/
|
|
69
|
-
export async function listMetaobjects(
|
|
70
|
-
client: StorefrontClient,
|
|
71
|
-
type: string,
|
|
72
|
-
query?: ListMetaobjectsQuery
|
|
73
|
-
): Promise<MetaobjectListResponse> {
|
|
74
|
-
return client.get(`/api/store/metaobjects/${encodeURIComponent(type)}`, {
|
|
75
|
-
query: { ...query },
|
|
76
|
-
})
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export interface MetaobjectResponse {
|
|
80
|
-
metaobject: Metaobject
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* GET /api/store/metaobjects/:type/:handle — one ACTIVE entry, references
|
|
85
|
-
* RESOLVED (invisible targets → `reference: null`).
|
|
86
|
-
*
|
|
87
|
-
* Auth: anon (x-client-id).
|
|
88
|
-
* Errors: 404 not_found (unknown type, unknown handle, or draft entry).
|
|
89
|
-
*/
|
|
90
|
-
export async function getMetaobject(
|
|
91
|
-
client: StorefrontClient,
|
|
92
|
-
type: string,
|
|
93
|
-
handle: string
|
|
94
|
-
): Promise<MetaobjectResponse> {
|
|
95
|
-
return client.get(
|
|
96
|
-
`/api/store/metaobjects/${encodeURIComponent(type)}/${encodeURIComponent(handle)}`
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface ByMetafieldQuery {
|
|
101
|
-
/** Owning entity type, e.g. `product`. */
|
|
102
|
-
entity_type: string
|
|
103
|
-
/** Owning entity id, e.g. `prod_…`. */
|
|
104
|
-
entity_id: string
|
|
105
|
-
/** The metafield key — its definition MUST be `metaobject_reference`. */
|
|
106
|
-
key: string
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Response of the by-metafield chain. `metaobjects` is always present in
|
|
111
|
-
* stored order. `metaobject` (first entry or null) is present ONLY when the
|
|
112
|
-
* metafield definition is single-valued — LIST definitions return
|
|
113
|
-
* `{metaobjects}` alone.
|
|
114
|
-
*/
|
|
115
|
-
export interface ByMetafieldResponse {
|
|
116
|
-
metaobject?: Metaobject | null
|
|
117
|
-
metaobjects: Metaobject[]
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* GET /api/store/metaobjects/by-metafield — the product→size-chart fetch
|
|
122
|
-
* chain: resolve an entity's `metaobject_reference` METAFIELD into full
|
|
123
|
-
* metaobject payload(s), references resolved. Deliberate leak boundary:
|
|
124
|
-
* only `metaobject_reference` definitions resolve here (any other key →
|
|
125
|
-
* 404), and only ACTIVE entries return.
|
|
126
|
-
*
|
|
127
|
-
* Auth: anon (x-client-id).
|
|
128
|
-
* Errors: 400 invalid_data (missing entity_type/entity_id/key) ·
|
|
129
|
-
* 404 not_found (no such definition, wrong field_type, or no stored value).
|
|
130
|
-
*/
|
|
131
|
-
export async function getMetaobjectsByMetafield(
|
|
132
|
-
client: StorefrontClient,
|
|
133
|
-
query: ByMetafieldQuery
|
|
134
|
-
): Promise<ByMetafieldResponse> {
|
|
135
|
-
return client.get("/api/store/metaobjects/by-metafield", { query: { ...query } })
|
|
136
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @cartbase/storefront/api/metaobjects — merchant-defined content types
|
|
3
|
+
* (metaobjects card): size charts, brand profiles, FAQ blocks…
|
|
4
|
+
*
|
|
5
|
+
* Ground truth: src/app/api/store/metaobjects/** +
|
|
6
|
+
* src/lib/metaobjects/store.ts.
|
|
7
|
+
*
|
|
8
|
+
* ACTIVE entries only — drafts 404 (lib filter AND anon RLS). Capabilities
|
|
9
|
+
* per definition: `renderable` → `seo` present; `online_store` → `url`
|
|
10
|
+
* present (`/metaobjects/<type>/<handle>`; the storefront prepends its
|
|
11
|
+
* origin). References resolve at READ time: a target the storefront cannot
|
|
12
|
+
* see yields `reference: null` — never dropped, never a 500.
|
|
13
|
+
*
|
|
14
|
+
* `by-metafield` is a RESERVED type slug (the static route shadows /:type).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { StorefrontClient } from "./http"
|
|
18
|
+
import type { IsoDateString, PaginationQuery } from "./types"
|
|
19
|
+
|
|
20
|
+
/** One field of a metaobject entry. */
|
|
21
|
+
export interface MetaobjectField {
|
|
22
|
+
key: string
|
|
23
|
+
/** Field kind from the definition (text, rich_text, reference kinds…). */
|
|
24
|
+
kind: string
|
|
25
|
+
/** Raw stored value (shape depends on `kind`). */
|
|
26
|
+
value: unknown
|
|
27
|
+
/**
|
|
28
|
+
* Reference kinds only (absent otherwise). Resolved target, or null when
|
|
29
|
+
* the target is deleted / not storefront-visible. NOT resolved on LIST
|
|
30
|
+
* payloads — only the by-handle read and by-metafield resolve references.
|
|
31
|
+
*/
|
|
32
|
+
reference?: { id: string; title: string; handle: string; type?: string } | null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface Metaobject {
|
|
36
|
+
id: string
|
|
37
|
+
/** The definition's type slug. */
|
|
38
|
+
type: string
|
|
39
|
+
handle: string
|
|
40
|
+
displayName: string
|
|
41
|
+
fields: MetaobjectField[]
|
|
42
|
+
/** Present only when the definition has the `renderable` capability.
|
|
43
|
+
* title falls back to displayName; description to null. */
|
|
44
|
+
seo?: { title: string; description: string | null }
|
|
45
|
+
/** Present only with the `online_store` capability:
|
|
46
|
+
* `/metaobjects/<type>/<handle>`. */
|
|
47
|
+
url?: string
|
|
48
|
+
updatedAt: IsoDateString
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type ListMetaobjectsQuery = PaginationQuery
|
|
52
|
+
|
|
53
|
+
export interface MetaobjectListResponse {
|
|
54
|
+
metaobjects: Metaobject[]
|
|
55
|
+
count: number
|
|
56
|
+
offset: number
|
|
57
|
+
limit: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* GET /api/store/metaobjects/:type — paginated ACTIVE entries of one type,
|
|
62
|
+
* newest-updated first. `limit` clamped to 1–100 (default 20; out-of-range
|
|
63
|
+
* values are clamped, not rejected). List payloads carry RAW field values —
|
|
64
|
+
* `reference` is NOT resolved here (use getMetaobject for the resolve path).
|
|
65
|
+
*
|
|
66
|
+
* Auth: anon (x-client-id).
|
|
67
|
+
* Errors: 404 not_found (unknown type).
|
|
68
|
+
*/
|
|
69
|
+
export async function listMetaobjects(
|
|
70
|
+
client: StorefrontClient,
|
|
71
|
+
type: string,
|
|
72
|
+
query?: ListMetaobjectsQuery
|
|
73
|
+
): Promise<MetaobjectListResponse> {
|
|
74
|
+
return client.get(`/api/store/metaobjects/${encodeURIComponent(type)}`, {
|
|
75
|
+
query: { ...query },
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface MetaobjectResponse {
|
|
80
|
+
metaobject: Metaobject
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* GET /api/store/metaobjects/:type/:handle — one ACTIVE entry, references
|
|
85
|
+
* RESOLVED (invisible targets → `reference: null`).
|
|
86
|
+
*
|
|
87
|
+
* Auth: anon (x-client-id).
|
|
88
|
+
* Errors: 404 not_found (unknown type, unknown handle, or draft entry).
|
|
89
|
+
*/
|
|
90
|
+
export async function getMetaobject(
|
|
91
|
+
client: StorefrontClient,
|
|
92
|
+
type: string,
|
|
93
|
+
handle: string
|
|
94
|
+
): Promise<MetaobjectResponse> {
|
|
95
|
+
return client.get(
|
|
96
|
+
`/api/store/metaobjects/${encodeURIComponent(type)}/${encodeURIComponent(handle)}`
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface ByMetafieldQuery {
|
|
101
|
+
/** Owning entity type, e.g. `product`. */
|
|
102
|
+
entity_type: string
|
|
103
|
+
/** Owning entity id, e.g. `prod_…`. */
|
|
104
|
+
entity_id: string
|
|
105
|
+
/** The metafield key — its definition MUST be `metaobject_reference`. */
|
|
106
|
+
key: string
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Response of the by-metafield chain. `metaobjects` is always present in
|
|
111
|
+
* stored order. `metaobject` (first entry or null) is present ONLY when the
|
|
112
|
+
* metafield definition is single-valued — LIST definitions return
|
|
113
|
+
* `{metaobjects}` alone.
|
|
114
|
+
*/
|
|
115
|
+
export interface ByMetafieldResponse {
|
|
116
|
+
metaobject?: Metaobject | null
|
|
117
|
+
metaobjects: Metaobject[]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* GET /api/store/metaobjects/by-metafield — the product→size-chart fetch
|
|
122
|
+
* chain: resolve an entity's `metaobject_reference` METAFIELD into full
|
|
123
|
+
* metaobject payload(s), references resolved. Deliberate leak boundary:
|
|
124
|
+
* only `metaobject_reference` definitions resolve here (any other key →
|
|
125
|
+
* 404), and only ACTIVE entries return.
|
|
126
|
+
*
|
|
127
|
+
* Auth: anon (x-client-id).
|
|
128
|
+
* Errors: 400 invalid_data (missing entity_type/entity_id/key) ·
|
|
129
|
+
* 404 not_found (no such definition, wrong field_type, or no stored value).
|
|
130
|
+
*/
|
|
131
|
+
export async function getMetaobjectsByMetafield(
|
|
132
|
+
client: StorefrontClient,
|
|
133
|
+
query: ByMetafieldQuery
|
|
134
|
+
): Promise<ByMetafieldResponse> {
|
|
135
|
+
return client.get("/api/store/metaobjects/by-metafield", { query: { ...query } })
|
|
136
|
+
}
|