@sixtyninecommerce/client 0.24.0 → 0.25.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 (293) hide show
  1. package/README.md +21 -0
  2. package/dist/admin/forms.js +19 -0
  3. package/dist/admin/forms.js.map +1 -1
  4. package/dist/admin/http.d.ts +9 -0
  5. package/dist/admin/http.d.ts.map +1 -1
  6. package/dist/admin/http.js +3 -0
  7. package/dist/admin/http.js.map +1 -1
  8. package/dist/admin/index.d.ts +63 -0
  9. package/dist/admin/index.d.ts.map +1 -1
  10. package/dist/admin/index.js +67 -0
  11. package/dist/admin/index.js.map +1 -1
  12. package/dist/admin/redirects.d.ts +6 -0
  13. package/dist/admin/redirects.d.ts.map +1 -1
  14. package/dist/admin/redirects.js +12 -0
  15. package/dist/admin/redirects.js.map +1 -1
  16. package/dist/admin/types.d.ts +63 -0
  17. package/dist/admin/types.d.ts.map +1 -1
  18. package/dist/cache-tags.d.ts +19 -0
  19. package/dist/cache-tags.d.ts.map +1 -1
  20. package/dist/cache-tags.js +19 -0
  21. package/dist/cache-tags.js.map +1 -1
  22. package/dist/client.d.ts +17 -0
  23. package/dist/client.d.ts.map +1 -1
  24. package/dist/client.js +17 -0
  25. package/dist/client.js.map +1 -1
  26. package/dist/commerce/age-verification.js +3 -3
  27. package/dist/commerce/age-verification.js.map +1 -1
  28. package/dist/commerce/branding.js +7 -0
  29. package/dist/commerce/branding.js.map +1 -1
  30. package/dist/commerce/cart.js +25 -0
  31. package/dist/commerce/cart.js.map +1 -1
  32. package/dist/commerce/checkout.d.ts +68 -0
  33. package/dist/commerce/checkout.d.ts.map +1 -1
  34. package/dist/commerce/checkout.js +83 -0
  35. package/dist/commerce/checkout.js.map +1 -1
  36. package/dist/commerce/customer.d.ts +58 -0
  37. package/dist/commerce/customer.d.ts.map +1 -1
  38. package/dist/commerce/customer.js +65 -0
  39. package/dist/commerce/customer.js.map +1 -1
  40. package/dist/commerce/pickup-location-parser.d.ts +18 -0
  41. package/dist/commerce/pickup-location-parser.d.ts.map +1 -1
  42. package/dist/commerce/pickup-location-parser.js +28 -0
  43. package/dist/commerce/pickup-location-parser.js.map +1 -1
  44. package/dist/commerce/placement-error.d.ts +52 -0
  45. package/dist/commerce/placement-error.d.ts.map +1 -1
  46. package/dist/commerce/placement-error.js +87 -0
  47. package/dist/commerce/placement-error.js.map +1 -1
  48. package/dist/commerce/products.d.ts +48 -0
  49. package/dist/commerce/products.d.ts.map +1 -1
  50. package/dist/commerce/products.js +92 -0
  51. package/dist/commerce/products.js.map +1 -1
  52. package/dist/commerce/queries.d.ts +113 -27
  53. package/dist/commerce/queries.d.ts.map +1 -1
  54. package/dist/commerce/queries.js +188 -2
  55. package/dist/commerce/queries.js.map +1 -1
  56. package/dist/commerce/quotes.js +33 -0
  57. package/dist/commerce/quotes.js.map +1 -1
  58. package/dist/commerce/saved-lists.d.ts +7 -7
  59. package/dist/commerce/saved-lists.d.ts.map +1 -1
  60. package/dist/commerce/saved-lists.js +1 -1
  61. package/dist/commerce/search.js +3 -0
  62. package/dist/commerce/search.js.map +1 -1
  63. package/dist/commerce/shipping.js +3 -3
  64. package/dist/commerce/shipping.js.map +1 -1
  65. package/dist/commerce/stock-notifications.d.ts +11 -0
  66. package/dist/commerce/stock-notifications.d.ts.map +1 -1
  67. package/dist/commerce/stock-notifications.js +11 -0
  68. package/dist/commerce/stock-notifications.js.map +1 -1
  69. package/dist/commerce/vat-validation.js +4 -4
  70. package/dist/commerce/vat-validation.js.map +1 -1
  71. package/dist/constants.d.ts +31 -0
  72. package/dist/constants.d.ts.map +1 -1
  73. package/dist/constants.js +32 -0
  74. package/dist/constants.js.map +1 -1
  75. package/dist/content/asset-urls.d.ts +50 -0
  76. package/dist/content/asset-urls.d.ts.map +1 -1
  77. package/dist/content/asset-urls.js +92 -0
  78. package/dist/content/asset-urls.js.map +1 -1
  79. package/dist/content/assets.d.ts +15 -0
  80. package/dist/content/assets.d.ts.map +1 -1
  81. package/dist/content/assets.js +15 -0
  82. package/dist/content/assets.js.map +1 -1
  83. package/dist/content/collection-pages.d.ts +5 -0
  84. package/dist/content/collection-pages.d.ts.map +1 -1
  85. package/dist/content/collection-pages.js +8 -0
  86. package/dist/content/collection-pages.js.map +1 -1
  87. package/dist/content/collections.d.ts +14 -0
  88. package/dist/content/collections.d.ts.map +1 -1
  89. package/dist/content/collections.js +16 -0
  90. package/dist/content/collections.js.map +1 -1
  91. package/dist/content/filtered-products.d.ts +18 -0
  92. package/dist/content/filtered-products.d.ts.map +1 -1
  93. package/dist/content/filtered-products.js +16 -0
  94. package/dist/content/filtered-products.js.map +1 -1
  95. package/dist/content/form-field-types.d.ts +6 -0
  96. package/dist/content/form-field-types.d.ts.map +1 -1
  97. package/dist/content/form-field-types.js +12 -0
  98. package/dist/content/form-field-types.js.map +1 -1
  99. package/dist/content/forms.d.ts +16 -0
  100. package/dist/content/forms.d.ts.map +1 -1
  101. package/dist/content/forms.js +23 -0
  102. package/dist/content/forms.js.map +1 -1
  103. package/dist/content/items.d.ts +26 -0
  104. package/dist/content/items.d.ts.map +1 -1
  105. package/dist/content/items.js +33 -0
  106. package/dist/content/items.js.map +1 -1
  107. package/dist/content/resolve.js +6 -0
  108. package/dist/content/resolve.js.map +1 -1
  109. package/dist/content/sitemap.d.ts +5 -0
  110. package/dist/content/sitemap.d.ts.map +1 -1
  111. package/dist/content/sitemap.js +5 -0
  112. package/dist/content/sitemap.js.map +1 -1
  113. package/dist/core/context.js +6 -0
  114. package/dist/core/context.js.map +1 -1
  115. package/dist/core/headers.js +2 -0
  116. package/dist/core/headers.js.map +1 -1
  117. package/dist/core/http.d.ts +8 -0
  118. package/dist/core/http.d.ts.map +1 -1
  119. package/dist/core/http.js +89 -1
  120. package/dist/core/http.js.map +1 -1
  121. package/dist/credit/credit-status.js +2 -2
  122. package/dist/credit/credit-status.js.map +1 -1
  123. package/dist/credit/payment-terms.js +2 -2
  124. package/dist/credit/payment-terms.js.map +1 -1
  125. package/dist/currency/exchange.d.ts +11 -0
  126. package/dist/currency/exchange.d.ts.map +1 -1
  127. package/dist/currency/exchange.js +11 -0
  128. package/dist/currency/exchange.js.map +1 -1
  129. package/dist/errors.d.ts +50 -2
  130. package/dist/errors.d.ts.map +1 -1
  131. package/dist/errors.js +48 -2
  132. package/dist/errors.js.map +1 -1
  133. package/dist/events/envelope.d.ts +36 -0
  134. package/dist/events/envelope.d.ts.map +1 -1
  135. package/dist/events/envelope.js +12 -0
  136. package/dist/events/envelope.js.map +1 -1
  137. package/dist/events/index.d.ts +13 -0
  138. package/dist/events/index.d.ts.map +1 -1
  139. package/dist/events/index.js +13 -0
  140. package/dist/events/index.js.map +1 -1
  141. package/dist/events/payloads.d.ts +19 -0
  142. package/dist/events/payloads.d.ts.map +1 -1
  143. package/dist/events/payloads.js +12 -0
  144. package/dist/events/payloads.js.map +1 -1
  145. package/dist/index.d.ts +7 -0
  146. package/dist/index.d.ts.map +1 -1
  147. package/dist/index.js +7 -0
  148. package/dist/index.js.map +1 -1
  149. package/dist/media/index.js +2 -0
  150. package/dist/media/index.js.map +1 -1
  151. package/dist/media/urls.d.ts +52 -0
  152. package/dist/media/urls.d.ts.map +1 -1
  153. package/dist/media/urls.js +38 -0
  154. package/dist/media/urls.js.map +1 -1
  155. package/dist/media/video.d.ts +16 -0
  156. package/dist/media/video.d.ts.map +1 -1
  157. package/dist/media/video.js +16 -0
  158. package/dist/media/video.js.map +1 -1
  159. package/dist/next/artifact-handler.d.ts +22 -0
  160. package/dist/next/artifact-handler.d.ts.map +1 -1
  161. package/dist/next/artifact-handler.js +22 -0
  162. package/dist/next/artifact-handler.js.map +1 -1
  163. package/dist/next/event-revalidate-handler.d.ts +67 -0
  164. package/dist/next/event-revalidate-handler.d.ts.map +1 -1
  165. package/dist/next/event-revalidate-handler.js +48 -0
  166. package/dist/next/event-revalidate-handler.js.map +1 -1
  167. package/dist/next/index.d.ts +6 -0
  168. package/dist/next/index.d.ts.map +1 -1
  169. package/dist/next/index.js +6 -0
  170. package/dist/next/index.js.map +1 -1
  171. package/dist/next/json-ld.d.ts +9 -0
  172. package/dist/next/json-ld.d.ts.map +1 -1
  173. package/dist/next/json-ld.js +9 -0
  174. package/dist/next/json-ld.js.map +1 -1
  175. package/dist/next/metadata.d.ts +18 -0
  176. package/dist/next/metadata.d.ts.map +1 -1
  177. package/dist/next/metadata.js +21 -0
  178. package/dist/next/metadata.js.map +1 -1
  179. package/dist/next/redirect-middleware.d.ts +39 -0
  180. package/dist/next/redirect-middleware.d.ts.map +1 -1
  181. package/dist/next/redirect-middleware.js +32 -0
  182. package/dist/next/redirect-middleware.js.map +1 -1
  183. package/dist/next/revalidate-handler.d.ts +30 -0
  184. package/dist/next/revalidate-handler.d.ts.map +1 -1
  185. package/dist/next/revalidate-handler.js +22 -0
  186. package/dist/next/revalidate-handler.js.map +1 -1
  187. package/dist/order-scope.d.ts +27 -0
  188. package/dist/order-scope.d.ts.map +1 -1
  189. package/dist/order-scope.js +29 -0
  190. package/dist/order-scope.js.map +1 -1
  191. package/dist/pricing/format.d.ts +17 -0
  192. package/dist/pricing/format.d.ts.map +1 -1
  193. package/dist/pricing/format.js +19 -0
  194. package/dist/pricing/format.js.map +1 -1
  195. package/dist/pricing/index.d.ts +8 -1
  196. package/dist/pricing/index.d.ts.map +1 -1
  197. package/dist/pricing/index.js +18 -2
  198. package/dist/pricing/index.js.map +1 -1
  199. package/dist/pricing/tax-display.d.ts +77 -0
  200. package/dist/pricing/tax-display.d.ts.map +1 -1
  201. package/dist/pricing/tax-display.js +85 -0
  202. package/dist/pricing/tax-display.js.map +1 -1
  203. package/dist/pricing/tiers.d.ts +9 -0
  204. package/dist/pricing/tiers.d.ts.map +1 -1
  205. package/dist/pricing/tiers.js +9 -0
  206. package/dist/pricing/tiers.js.map +1 -1
  207. package/dist/pricing/validation.d.ts +56 -1
  208. package/dist/pricing/validation.d.ts.map +1 -1
  209. package/dist/pricing/validation.js +61 -0
  210. package/dist/pricing/validation.js.map +1 -1
  211. package/dist/redirects/index.d.ts +1 -0
  212. package/dist/redirects/index.d.ts.map +1 -1
  213. package/dist/redirects/index.js +1 -0
  214. package/dist/redirects/index.js.map +1 -1
  215. package/dist/redirects/store.d.ts +20 -0
  216. package/dist/redirects/store.d.ts.map +1 -1
  217. package/dist/redirects/store.js +57 -0
  218. package/dist/redirects/store.js.map +1 -1
  219. package/dist/redirects/types.d.ts +24 -0
  220. package/dist/redirects/types.d.ts.map +1 -1
  221. package/dist/redirects/types.js +1 -0
  222. package/dist/redirects/types.js.map +1 -1
  223. package/dist/revalidation/event-plan.d.ts +48 -0
  224. package/dist/revalidation/event-plan.d.ts.map +1 -1
  225. package/dist/revalidation/event-plan.js +61 -0
  226. package/dist/revalidation/event-plan.js.map +1 -1
  227. package/dist/revalidation/event-verify.d.ts +25 -0
  228. package/dist/revalidation/event-verify.d.ts.map +1 -1
  229. package/dist/revalidation/event-verify.js +27 -0
  230. package/dist/revalidation/event-verify.js.map +1 -1
  231. package/dist/revalidation/types.d.ts +20 -0
  232. package/dist/revalidation/types.d.ts.map +1 -1
  233. package/dist/revalidation/types.js +10 -0
  234. package/dist/revalidation/types.js.map +1 -1
  235. package/dist/revalidation/url-context.d.ts +25 -0
  236. package/dist/revalidation/url-context.d.ts.map +1 -1
  237. package/dist/revalidation/url-context.js +17 -0
  238. package/dist/revalidation/url-context.js.map +1 -1
  239. package/dist/revalidation/verify.d.ts +8 -0
  240. package/dist/revalidation/verify.d.ts.map +1 -1
  241. package/dist/revalidation/verify.js +8 -0
  242. package/dist/revalidation/verify.js.map +1 -1
  243. package/dist/seo/ai.d.ts +17 -0
  244. package/dist/seo/ai.d.ts.map +1 -1
  245. package/dist/seo/ai.js +12 -0
  246. package/dist/seo/ai.js.map +1 -1
  247. package/dist/seo/alternates.js +13 -0
  248. package/dist/seo/alternates.js.map +1 -1
  249. package/dist/seo/artifacts.d.ts +13 -0
  250. package/dist/seo/artifacts.d.ts.map +1 -1
  251. package/dist/seo/artifacts.js +19 -0
  252. package/dist/seo/artifacts.js.map +1 -1
  253. package/dist/seo/canonical.d.ts +15 -0
  254. package/dist/seo/canonical.d.ts.map +1 -1
  255. package/dist/seo/canonical.js +24 -0
  256. package/dist/seo/canonical.js.map +1 -1
  257. package/dist/seo/index.js +6 -0
  258. package/dist/seo/index.js.map +1 -1
  259. package/dist/seo/json-ld.d.ts +13 -0
  260. package/dist/seo/json-ld.d.ts.map +1 -1
  261. package/dist/seo/json-ld.js +32 -0
  262. package/dist/seo/json-ld.js.map +1 -1
  263. package/dist/seo/locale-tag.d.ts +31 -0
  264. package/dist/seo/locale-tag.d.ts.map +1 -1
  265. package/dist/seo/locale-tag.js +31 -0
  266. package/dist/seo/locale-tag.js.map +1 -1
  267. package/dist/seo/meta-tags.d.ts +29 -0
  268. package/dist/seo/meta-tags.d.ts.map +1 -1
  269. package/dist/seo/meta-tags.js +28 -0
  270. package/dist/seo/meta-tags.js.map +1 -1
  271. package/dist/seo/metadata-parser.d.ts +24 -0
  272. package/dist/seo/metadata-parser.d.ts.map +1 -1
  273. package/dist/seo/metadata-parser.js +38 -0
  274. package/dist/seo/metadata-parser.js.map +1 -1
  275. package/dist/seo/metadata-types.d.ts +16 -0
  276. package/dist/seo/metadata-types.d.ts.map +1 -1
  277. package/dist/seo/product-path.d.ts +96 -0
  278. package/dist/seo/product-path.d.ts.map +1 -1
  279. package/dist/seo/product-path.js +96 -0
  280. package/dist/seo/product-path.js.map +1 -1
  281. package/dist/seo/robots.d.ts +17 -0
  282. package/dist/seo/robots.d.ts.map +1 -1
  283. package/dist/seo/robots.js +12 -0
  284. package/dist/seo/robots.js.map +1 -1
  285. package/dist/seo/types.d.ts +39 -0
  286. package/dist/seo/types.d.ts.map +1 -1
  287. package/dist/seo/url-builder.d.ts +31 -0
  288. package/dist/seo/url-builder.d.ts.map +1 -1
  289. package/dist/seo/url-builder.js +36 -0
  290. package/dist/seo/url-builder.js.map +1 -1
  291. package/dist/types.d.ts +1163 -0
  292. package/dist/types.d.ts.map +1 -1
  293. package/package.json +1 -1
package/dist/types.d.ts CHANGED
@@ -1,15 +1,44 @@
1
+ /** Retry configuration for transient GET failures. */
1
2
  export interface RetryConfig {
3
+ /** Maximum number of attempts including the first request. Default: 2. */
2
4
  attempts?: number;
5
+ /** Base delay in ms for exponential backoff. Default: 200. */
3
6
  baseDelayMs?: number;
4
7
  }
8
+ /**
9
+ * Per-call request controls. Pass to read methods (catalog, content,
10
+ * navigation) to cancel in-flight requests — useful for SSR and
11
+ * search-as-you-type.
12
+ */
5
13
  export interface RequestOptions {
6
14
  signal?: AbortSignal;
15
+ /**
16
+ * Extra cache tags for this request, added to the SDK's own — e.g.
17
+ * `getProduct(slug, { cacheTags: [productCacheTag(route.id)] })` when the id
18
+ * is already known from the route manifest. Applied to commerce (Vendure)
19
+ * requests only; see {@link StorefrontClientConfig.cacheTags}.
20
+ */
7
21
  cacheTags?: readonly string[];
8
22
  }
23
+ /**
24
+ * Decides the cache tags a commerce request carries. Receives the SDK's
25
+ * defaults (plus any per-request `cacheTags`) and the SDK method name
26
+ * (`getProduct`, `getProductById`, `searchProducts`, …); returns what to send.
27
+ */
9
28
  export type CacheTagResolver = (tags: readonly string[], request: {
10
29
  readonly operation: string;
11
30
  }) => readonly string[];
31
+ /**
32
+ * Which storefront a cart/order belongs to.
33
+ *
34
+ * A tenant can run a consumer shop and a trade (B2B/dealer) shop off ONE
35
+ * channel. Without a scope both storefronts share a single active order per
36
+ * customer, because Vendure's fallback lookup is "the one active order for this
37
+ * customer in this channel" — separate cookies do not change that. Setting a
38
+ * scope keeps the two carts apart.
39
+ */
12
40
  export type OrderScope = 'CONSUMER' | 'TRADE';
41
+ /** Configuration for creating a storefront client. */
13
42
  export interface StorefrontClientConfig {
14
43
  storeCode: string;
15
44
  cdnUrl: string;
@@ -18,18 +47,96 @@ export interface StorefrontClientConfig {
18
47
  pluginsUrl?: string;
19
48
  defaultLanguageCode?: string;
20
49
  fetch?: typeof globalThis.fetch;
50
+ /** Called when an auth token is received from Vendure (e.g. after login). Use to persist the token. */
21
51
  onAuthToken?: (token: string) => void;
52
+ /**
53
+ * Called when the SDK detects the stored session is genuinely dead. Fires on
54
+ * an UNAUTHORIZED error, and on a FORBIDDEN error only when a follow-up
55
+ * `activeCustomer` probe confirms there is no active session — Vendure's Shop
56
+ * API returns FORBIDDEN for both an expired session and a real authorization
57
+ * denial, so the probe is what tells them apart. Use to prompt re-login or
58
+ * clear local user state. A FORBIDDEN with a still-valid session is an
59
+ * authorization denial, NOT an expiry: `onAuthExpired` does not fire and the
60
+ * caller receives a StorefrontError with `errorCode: 'FORBIDDEN'` /
61
+ * `statusCode: 403` to handle.
62
+ */
22
63
  onAuthExpired?: () => void;
64
+ /**
65
+ * Called after `logout()` clears the stored auth token — the inverse of
66
+ * `onAuthToken`. Use to drop the persisted token from storage/cookies. NOT
67
+ * fired on session expiry (that is `onAuthExpired`).
68
+ */
23
69
  onAuthCleared?: () => void;
70
+ /**
71
+ * Retry config for transient GET failures (network errors and 502/503/504).
72
+ * Defaults to `{ attempts: 2, baseDelayMs: 200 }`. Set `attempts: 1` to
73
+ * disable retries entirely. Mutations are never retried.
74
+ */
24
75
  retry?: RetryConfig;
76
+ /**
77
+ * Which storefront this client speaks for — `'CONSUMER'` or `'TRADE'`. Sent
78
+ * as the `x-order-scope` header on every Vendure Shop API request, which is
79
+ * what keeps a dealer's consumer basket and trade order separate on a single
80
+ * channel.
81
+ *
82
+ * Leave it unset for a single-storefront tenant: the engine then behaves
83
+ * exactly as stock Vendure does. Unset is NOT the same as `'CONSUMER'` — a
84
+ * client that omits the header never has an existing trade cart reclassified.
85
+ *
86
+ * A `'TRADE'` cart requires a logged-in customer; the engine rejects an
87
+ * anonymous trade order with `error.trade-order-requires-authentication`.
88
+ *
89
+ * Per client, not per request — run two clients (or call `setOrderScope`) if
90
+ * one process serves both storefronts.
91
+ */
25
92
  orderScope?: OrderScope;
93
+ /**
94
+ * Cache tags on product and collection reads, for Next.js `revalidateTag` —
95
+ * the tags `createEventRevalidateHandler` purges. The SDK adds
96
+ * `next: { tags }` to the fetch init (Next reads it; other fetch
97
+ * implementations ignore unknown init keys) and sets no cache policy:
98
+ * whether a request is cached stays your app's decision.
99
+ *
100
+ * - `true` (default): tags derived from each call's inputs — `product:<id>`
101
+ * for `getProductById` and `getProductProperties`, `collection:<id>` for
102
+ * `getCollectionById`, `getProductsInCollectionById` and `searchProducts`
103
+ * with `collectionId`/`collectionIds`.
104
+ * - `false`: no `next` key on any request.
105
+ * - a {@link CacheTagResolver}: decides per request.
106
+ *
107
+ * Load pages by the id `findRoute` resolves and they are tagged. Raw slug
108
+ * reads (`getProduct(slug)`, `getCollection(slug)`,
109
+ * `getProductsInCollection(slug)`) stay untagged — the id is not known until
110
+ * the response arrives; pass `route.cacheTags` per request to tag one.
111
+ */
26
112
  cacheTags?: boolean | CacheTagResolver;
27
113
  }
114
+ /**
115
+ * Storefront-visible Channel custom fields. Enumerates fields the SDK or its
116
+ * consumers read directly. Unknown fields are still accessible via the index
117
+ * signature, so adding a new field on the backend doesn't require an SDK
118
+ * release for storefronts to consume it.
119
+ */
28
120
  export interface ChannelCustomFields {
121
+ /** SDK consumes this to gate the entire client into read-only mode. */
29
122
  maintenanceMode?: boolean;
123
+ /** Custom CDN domain for asset URLs (set per-channel via cdn-domain plugin). */
30
124
  cdnDomain?: string | null;
125
+ /**
126
+ * Absolute URL of the storefront for this channel (e.g. `https://store.example.com`).
127
+ * Required by the SEO module to emit canonical URLs and hreflang tags.
128
+ */
31
129
  storefrontUrl?: string;
130
+ /**
131
+ * URL strategy the storefront uses to encode the active language. Drives
132
+ * canonical/alternate URL generation in the SEO module.
133
+ */
32
134
  urlLocaleStrategy?: 'path-prefix' | 'subdomain' | 'none';
135
+ /**
136
+ * When `true`, the URL still includes a locale prefix even for the channel's
137
+ * default language. When `false` (default), the default language URL has no
138
+ * prefix.
139
+ */
33
140
  urlLocalePrefixDefault?: boolean;
34
141
  businessName?: string | null;
35
142
  businessDescription?: string | null;
@@ -50,19 +157,50 @@ export interface ChannelCustomFields {
50
157
  postalCode?: string | null;
51
158
  province?: string | null;
52
159
  country?: string | null;
160
+ /** JSON-encoded social URLs map. Keys: facebook, instagram, twitter, linkedin, youtube, tiktok. */
53
161
  socialLinks?: string | null;
54
162
  commercePathPrefix?: string | null;
163
+ /** JSON-encoded `{ [languageCode]: pathPrefix }` per-locale overrides. */
55
164
  commercePathPrefixTranslations?: string | null;
165
+ /** Segment canonical product URLs sit under. Unset/empty means `products`. */
56
166
  productPathSegment?: string | null;
167
+ /** Channel default Twitter / X handle (without @). Used by `metaTagsFor()` for `twitter:site`. */
57
168
  twitterHandle?: string | null;
169
+ /** Vendure Asset ID used as the fallback OpenGraph image when a product does not provide one. */
58
170
  defaultOgImageId?: string | null;
171
+ /** When true, the storefront serves `/llms.txt` advertising AI-friendly endpoints. */
59
172
  llmsTxtEnabled?: boolean;
173
+ /**
174
+ * When true, B2B customers can submit quote requests on this channel.
175
+ * Storefronts should gate quote UI (request-quote buttons, "My quotes"
176
+ * account section) on this flag instead of probing `createQuoteRequest`.
177
+ */
60
178
  quotesEnabled?: boolean;
179
+ /**
180
+ * When true, customers can request order returns on this channel.
181
+ * Storefronts should gate return UI ("Request return" buttons, "My
182
+ * returns" account section) on this flag instead of probing
183
+ * `requestReturn`.
184
+ */
61
185
  returnsEnabled?: boolean;
186
+ /** Days after delivery/shipment during which a return may be requested. */
62
187
  returnWindowDays?: number;
188
+ /**
189
+ * Channel-wide display default: `channel` (follow `pricesIncludeTax`),
190
+ * `gross` or `net`. Raw storage value — read it with `parseTaxDisplayPolicy`
191
+ * and render from `pricing.getTaxDisplayMode()`, which resolves the whole
192
+ * policy server-side for the actual shopper.
193
+ */
63
194
  taxDisplayDefault?: string | null;
195
+ /** B2B override: `inherit`, `gross` or `net`. See {@link taxDisplayDefault}. */
64
196
  taxDisplayB2b?: string | null;
197
+ /**
198
+ * JSON array of ISO-3166 alpha-2 codes, e.g. `["US"]`. A shopper whose
199
+ * country is listed always sees prices excl. tax AND is taxed by their own
200
+ * country's tax zone. Empty/unset = the rule is off.
201
+ */
65
202
  taxExclusiveCountries?: string | null;
203
+ /** Forward-compat: any additional storefront-visible custom fields. */
66
204
  [key: string]: unknown;
67
205
  }
68
206
  export interface BrandingAssetRef {
@@ -77,6 +215,7 @@ export interface BrandingFontResource {
77
215
  kind: 'google' | 'self_hosted';
78
216
  family: string;
79
217
  weights: number[];
218
+ /** Resolved Asset references for self-hosted fonts. Empty for Google Fonts. */
80
219
  files: BrandingAssetRef[];
81
220
  }
82
221
  export interface BrandingSocialLinks {
@@ -120,6 +259,11 @@ export interface BrandingLegal {
120
259
  }
121
260
  export interface BrandingStorefrontConfig {
122
261
  url: string | null;
262
+ /**
263
+ * Resolved CDN base URL. When the channel sets `cdnDomain`, this is
264
+ * `https://{cdnDomain}`; otherwise it falls back to the global CDN URL the
265
+ * client was constructed with.
266
+ */
123
267
  cdnUrl: string;
124
268
  urlLocaleStrategy: 'path-prefix' | 'subdomain' | 'none';
125
269
  urlLocalePrefixDefault: boolean;
@@ -139,15 +283,23 @@ export interface BrandingInfo {
139
283
  social: BrandingSocialLinks;
140
284
  storefront: BrandingStorefrontConfig;
141
285
  }
286
+ /** Channel info resolved from CMS at initialization. */
142
287
  export interface ChannelInfo {
143
288
  id: string;
144
289
  code: string;
145
290
  token: string;
146
291
  defaultLanguageCode: string;
147
292
  defaultCurrencyCode: string;
293
+ /**
294
+ * The channel's tax-display storage mode. When `true`, `price`/`*Price`
295
+ * fields already include tax; when `false`, they are net and the gross
296
+ * figure lives in the matching `priceWithTax`/`*PriceWithTax` field. Drives
297
+ * net-vs-gross display decisions (e.g. a B2B/B2C BTW toggle).
298
+ */
148
299
  pricesIncludeTax: boolean;
149
300
  customFields: ChannelCustomFields;
150
301
  }
302
+ /** Shared context used by all modules. */
151
303
  export interface StoreContext {
152
304
  channel: ChannelInfo;
153
305
  cdnUrl: string;
@@ -157,9 +309,21 @@ export interface StoreContext {
157
309
  pluginsUrl: string;
158
310
  languageCode: string;
159
311
  currencyCode: string;
312
+ /** Channel tax-display storage mode — see {@link ChannelInfo.pricesIncludeTax}. */
160
313
  pricesIncludeTax: boolean;
161
314
  authToken: string | null;
315
+ /**
316
+ * Active order scope, emitted as the `x-order-scope` header. `null`/absent
317
+ * means "send no header" — legacy, unscoped behaviour. See
318
+ * {@link StorefrontClientConfig.orderScope}.
319
+ */
162
320
  orderScope?: OrderScope | null;
321
+ /**
322
+ * Last resolved tax display mode, cached against the identity it was resolved
323
+ * for (see `identityStamp`). Owned by `pricing.getTaxDisplayMode()`; cleared
324
+ * by `setShippingAddress` because moving the order's country can flip the
325
+ * mode without changing the identity. Treat as internal.
326
+ */
163
327
  taxDisplay?: ResolvedTaxDisplay | null;
164
328
  fetch: typeof globalThis.fetch;
165
329
  onAuthToken?: (token: string) => void;
@@ -169,6 +333,7 @@ export interface StoreContext {
169
333
  attempts: number;
170
334
  baseDelayMs: number;
171
335
  };
336
+ /** See {@link StorefrontClientConfig.cacheTags}. Absent means `true`. */
172
337
  cacheTags?: boolean | CacheTagResolver;
173
338
  }
174
339
  export interface GraphQLResponse<T = unknown> {
@@ -202,7 +367,9 @@ export interface AssetPresets {
202
367
  export interface Asset {
203
368
  source: string;
204
369
  name?: string;
370
+ /** Intrinsic pixel width of the source image. Absent when not selected. */
205
371
  width?: number | null;
372
+ /** Intrinsic pixel height of the source image. Absent when not selected. */
206
373
  height?: number | null;
207
374
  customFields?: {
208
375
  altText?: string;
@@ -214,6 +381,7 @@ export interface CmsAssetTranslation {
214
381
  language_code: string;
215
382
  alt_text: string | null;
216
383
  }
384
+ /** Public-safe CMS asset returned by /assets/lookup, /public-assets/:id. */
217
385
  export interface CmsAsset {
218
386
  id: string;
219
387
  filename: string;
@@ -265,15 +433,52 @@ export interface ProductVariant {
265
433
  priceWithTax: number;
266
434
  currencyCode: string;
267
435
  stockLevel: string;
436
+ /**
437
+ * Physical on-hand stock across the channel's locations. `null` when the
438
+ * channel does not expose operational stock numbers (the default) — fall
439
+ * back to the `stockLevel` string.
440
+ */
268
441
  stockOnHand: number | null;
442
+ /** Stock reserved by open orders. `null` when the channel does not expose it. */
269
443
  stockAllocated: number | null;
444
+ /**
445
+ * Units a customer can actually order right now (available-to-promise).
446
+ * `null` when the channel does not expose operational stock numbers.
447
+ */
270
448
  saleable: number | null;
449
+ /**
450
+ * Units already on order from suppliers (e.g. open Exact purchase orders).
451
+ * `null` unless the channel exposes stock AND the signed-in customer's group
452
+ * may see incoming stock — anonymous visitors always get `null`.
453
+ */
271
454
  incomingStock: number | null;
455
+ /** Forward-looking `max(0, saleable) + incomingStock`. Same gate as `incomingStock`. */
272
456
  projectedSaleable: number | null;
457
+ /**
458
+ * Earliest FUTURE expected warehouse arrival, ISO 8601. Never a past date.
459
+ * `null` under the same gate as `incomingStock`, and ALSO when no open line
460
+ * has a future date — so `incomingStock > 0` with `nextExpectedArrival: null`
461
+ * is normal (on order, but every date is overdue or missing). Show a dateless
462
+ * "restock on order" hint then. This is a warehouse-arrival estimate, never a
463
+ * delivery promise.
464
+ */
273
465
  nextExpectedArrival: string | null;
466
+ /**
467
+ * Units BEYOND `saleable` the signed-in customer may order on backorder right
468
+ * now. The quantity ceiling is `max(0, saleable) + backorderAllowance` (see
469
+ * `maxOrderableQuantity` in `@sixtyninecommerce/client/pricing`). `null` when
470
+ * the question does not apply — anonymous, group may not backorder, or the
471
+ * channel hides stock — treat exactly like today; `0` = denied; a large
472
+ * value (2,000,000,000) is the "unlimited" sentinel. A snapshot: the server
473
+ * re-checks on add-to-cart and at placement and refuses with the usual
474
+ * `InsufficientStockError` / `INSUFFICIENT_STOCK`, whose `quantityAvailable`
475
+ * then already includes the allowance.
476
+ */
477
+ backorderAllowance: number | null;
274
478
  priceListName: string | null;
275
479
  retailPrice: number | null;
276
480
  retailPriceWithTax: number | null;
481
+ /** Tax rate applied to this price in the active channel/zone, e.g. `{ value: 21 }` for 21% VAT. */
277
482
  taxRateApplied: {
278
483
  value: number;
279
484
  } | null;
@@ -303,6 +508,14 @@ export interface CollectionRef {
303
508
  name: string;
304
509
  slug: string;
305
510
  position?: number;
511
+ /**
512
+ * The parent's `slug` is load-bearing, not decoration: a top-level collection
513
+ * is parented to the `__root_collection__` SENTINEL (Vendure resolves `parent`
514
+ * to null only when the real parent is PRIVATE), so the slug is what
515
+ * distinguishes "this is a root" from "this is nested". The SDK's own product
516
+ * queries select it. A caller writing its own query and omitting it gets the
517
+ * flat product path for every canonical — see `isUserFacingRoot`.
518
+ */
306
519
  parent?: {
307
520
  id: string;
308
521
  slug?: string;
@@ -342,6 +555,7 @@ export interface PublicProductDocument {
342
555
  fileMimeType: string;
343
556
  fileSize: number;
344
557
  fileName: string;
558
+ /** When true, the URL is presigned and short-lived. Don't cache it. */
345
559
  requiresAuth: boolean;
346
560
  }
347
561
  export interface Product {
@@ -357,6 +571,11 @@ export interface Product {
357
571
  collections: CollectionRef[];
358
572
  translations?: ProductTranslation[];
359
573
  documents?: PublicProductDocument[];
574
+ /**
575
+ * Per-product SEO/social/AI metadata. Resolved server-side for the active
576
+ * language and validated client-side at the SDK boundary. `null` when no
577
+ * metadata has been authored for this product on the current channel.
578
+ */
360
579
  metadata?: import('./seo/metadata-types.js').ProductMetadata | null;
361
580
  }
362
581
  export interface RecommendedProductGroup {
@@ -369,6 +588,7 @@ export interface ProductSummary {
369
588
  name: string;
370
589
  slug: string;
371
590
  description?: string;
591
+ /** Whether the product is enabled on the channel. Selected by `LIST_PRODUCTS`. */
372
592
  enabled?: boolean;
373
593
  featuredAsset: Asset | null;
374
594
  variants: Array<{
@@ -379,12 +599,21 @@ export interface ProductSummary {
379
599
  priceWithTax: number;
380
600
  currencyCode: string;
381
601
  stockLevel: string;
602
+ /** ATP numbers — `null` when the channel does not expose operational stock. */
382
603
  stockOnHand?: number | null;
383
604
  stockAllocated?: number | null;
384
605
  saleable?: number | null;
606
+ /**
607
+ * Incoming-stock numbers — additionally `null` unless the signed-in customer's
608
+ * group may see incoming stock. `nextExpectedArrival` is the earliest FUTURE
609
+ * arrival (ISO 8601, never past) and is `null` when every open line is overdue,
610
+ * even while `incomingStock > 0`.
611
+ */
385
612
  incomingStock?: number | null;
386
613
  projectedSaleable?: number | null;
387
614
  nextExpectedArrival?: string | null;
615
+ /** Units beyond `saleable` this buyer may backorder; `null` = not applicable. */
616
+ backorderAllowance?: number | null;
388
617
  availabilityByLocation?: VariantLocationAvailability[];
389
618
  priceListName?: string | null;
390
619
  retailPrice?: number | null;
@@ -417,6 +646,7 @@ export interface Breadcrumb {
417
646
  name: string;
418
647
  slug: string;
419
648
  }
649
+ /** Per-language translation of a collection, including SEO custom fields. */
420
650
  export interface CollectionTranslation {
421
651
  languageCode: string;
422
652
  name?: string;
@@ -430,6 +660,7 @@ export interface CollectionTranslation {
430
660
  socialImageAlt?: string | null;
431
661
  } | null;
432
662
  }
663
+ /** Collection-scoped custom fields: routing directives + SEO scalars. */
433
664
  export interface CollectionCustomFields {
434
665
  isRoutable?: boolean | null;
435
666
  isCanonical?: boolean | null;
@@ -462,12 +693,21 @@ export interface CollectionDetail extends Collection {
462
693
  priceWithTax: number;
463
694
  currencyCode: string;
464
695
  stockLevel: string;
696
+ /** ATP numbers — `null` when the channel does not expose operational stock. */
465
697
  stockOnHand: number | null;
466
698
  stockAllocated: number | null;
467
699
  saleable: number | null;
700
+ /**
701
+ * Incoming-stock numbers — additionally `null` unless the signed-in customer's
702
+ * group may see incoming stock. `nextExpectedArrival` is the earliest FUTURE
703
+ * arrival (ISO 8601, never past) and is `null` when every open line is overdue,
704
+ * even while `incomingStock > 0`.
705
+ */
468
706
  incomingStock: number | null;
469
707
  projectedSaleable: number | null;
470
708
  nextExpectedArrival: string | null;
709
+ /** Units beyond `saleable` this buyer may backorder; `null` = not applicable. */
710
+ backorderAllowance: number | null;
471
711
  priceListName: string | null;
472
712
  retailPrice: number | null;
473
713
  retailPriceWithTax: number | null;
@@ -485,29 +725,75 @@ export interface CollectionDetail extends Collection {
485
725
  totalItems: number;
486
726
  };
487
727
  }
728
+ /**
729
+ * Stable, append-only vocabulary for why an order could not be placed — or why
730
+ * a payment was refused before it was taken.
731
+ *
732
+ * Branch on this instead of keyword-matching `transitionError` /
733
+ * `paymentErrorMessage`: that prose is operator English, is re-worded per
734
+ * merchant, and is translated. This list is a deliberate copy of the
735
+ * platform's (`@sixtynine-digital/commerce-shared/placement-rejection`) so the
736
+ * published client stays zero-dependency; a spec asserts the two match.
737
+ *
738
+ * Treat an unrecognised value defensively — always give your `switch` a
739
+ * `default:` branch and fall back to `MutationError.message`. Codes are added
740
+ * over time, and the SDK deliberately passes a code it does not know through
741
+ * unchanged rather than rewriting it to `UNKNOWN`.
742
+ */
488
743
  export type PlacementRejectionCode = 'ORDER_EMPTY' | 'CUSTOMER_REQUIRED' | 'SHIPPING_METHOD_REQUIRED' | 'INSUFFICIENT_STOCK' | 'ORDER_MINIMUM_AMOUNT_NOT_MET' | 'ORDER_MINIMUM_QUANTITY_NOT_MET' | 'FULFILLMENT_MINIMUM_NOT_MET' | 'LINE_MINIMUM_QUANTITY_NOT_MET' | 'LINE_SALES_UNIT_NOT_MET' | 'SHIPPING_ADDRESS_INCOMPLETE' | 'SHIPPING_COUNTRY_NOT_SERVED' | 'AGE_VERIFICATION_REQUIRED' | 'AGE_REQUIREMENT_NOT_MET' | 'DELIVERY_TERMS_UNAVAILABLE' | 'PAYMENT_TERMS_UNAVAILABLE' | 'PAYMENT_INTENT_MISMATCH' | 'PLACEMENT_BLOCKED' | 'UNKNOWN';
744
+ /**
745
+ * An order line implicated in a rejection — the line below its minimum
746
+ * quantity, the line that ran short of stock.
747
+ *
748
+ * The engine caps a rejection at 20 lines (`PlacementRejection.linesTruncated`
749
+ * says when it did). Every field except the variant id is nullable, so render
750
+ * defensively; `productName`/`productVariantName` are already translated.
751
+ */
489
752
  export interface PlacementRejectionLine {
490
753
  orderLineId?: string | null;
491
754
  productVariantId: string;
492
755
  sku?: string | null;
493
756
  productVariantName?: string | null;
494
757
  productName?: string | null;
758
+ /** What was asked for, before any correction the engine applied. */
495
759
  quantityRequested?: number | null;
496
760
  quantityAvailable?: number | null;
497
761
  }
762
+ /**
763
+ * Field-level detail, e.g. which part of the shipping address is unusable.
764
+ *
765
+ * Deliberately NOT `FieldError` (the CMS form-validation shape): `field` is
766
+ * nullable here, because a detail may be about the order as a whole.
767
+ */
498
768
  export interface PlacementRejectionDetail {
499
769
  field?: string | null;
500
770
  code?: string | null;
501
771
  message: string;
502
772
  }
773
+ /**
774
+ * The structured, customer-safe half of a placement rejection.
775
+ *
776
+ * `customerMessage` is plain shopper English and safe to render as-is; the
777
+ * operator prose stays on the error's own reason field for merchant-facing
778
+ * surfaces. The metadata fields are populated per code (e.g. `requiredAmount` +
779
+ * `amountBasis` for a minimum-amount rejection) and are null otherwise.
780
+ */
503
781
  export interface PlacementRejection {
782
+ /**
783
+ * Widened past the union on purpose: the SDK passes a code it does not know
784
+ * through unchanged, so an exhaustive `switch` must still have a `default:`.
785
+ */
504
786
  code: PlacementRejectionCode | (string & {});
787
+ /** Shopper-safe sentence. Null when the veto site supplied none. */
505
788
  customerMessage?: string | null;
506
789
  lines?: PlacementRejectionLine[] | null;
507
790
  details?: PlacementRejectionDetail[] | null;
791
+ /** True when `lines` was capped and does not list every affected line. */
508
792
  linesTruncated: boolean;
793
+ /** Minor units, in `currencyCode`. */
509
794
  requiredAmount?: number | null;
510
795
  currencyCode?: string | null;
796
+ /** `net` or `gross` — which basis `requiredAmount` is expressed in. */
511
797
  amountBasis?: string | null;
512
798
  requiredQuantity?: number | null;
513
799
  priceListName?: string | null;
@@ -516,16 +802,21 @@ export interface PlacementRejection {
516
802
  }
517
803
  export type AdjustmentType = 'PROMOTION' | 'DISTRIBUTED_ORDER_PROMOTION' | 'OTHER';
518
804
  export interface Discount {
805
+ /** Identifier of the source (e.g. promotion code or shipping method id). */
519
806
  adjustmentSource: string;
520
807
  type: AdjustmentType | string;
521
808
  description: string;
809
+ /** Pre-tax discount amount in minor units. Negative values reduce the price. */
522
810
  amount: number;
523
811
  amountWithTax: number;
524
812
  }
525
813
  export interface OrderTaxSummary {
526
814
  description: string;
815
+ /** Tax rate as a percentage (e.g. 21 for 21%). */
527
816
  taxRate: number;
817
+ /** Net total to which this tax rate applies, in minor units. */
528
818
  taxBase: number;
819
+ /** Tax total at this rate, in minor units. */
529
820
  taxTotal: number;
530
821
  }
531
822
  export interface OrderPromotion {
@@ -537,18 +828,41 @@ export interface OrderPromotion {
537
828
  export interface OrderLine {
538
829
  id: string;
539
830
  quantity: number;
831
+ /**
832
+ * Units of this line physical stock did NOT cover when the order was placed
833
+ * (the part the merchant ships later). Stamped at placement, never
834
+ * decremented as the line ships — the fulfilments record what arrived.
835
+ *
836
+ * Selected by the PLACED-order reads alone (`getOrderByCode`,
837
+ * `getCustomerOrders`), so it is `undefined` from the cart reads and
838
+ * mutations: a cart line has no stamp to carry, and selecting it in the
839
+ * shared fragment would couple every cart call to an engine that has the
840
+ * field.
841
+ */
842
+ backorderedQuantity?: number;
540
843
  unitPrice: number;
541
844
  unitPriceWithTax: number;
845
+ /** Tax rate applied to this line as a percentage (e.g. 21 for 21%). */
542
846
  taxRate: number;
543
847
  linePrice: number;
544
848
  linePriceWithTax: number;
849
+ /** Line price after item-level discounts, excluding tax. */
545
850
  discountedLinePrice: number;
546
851
  discountedLinePriceWithTax: number;
852
+ /** Discounts applied to this line (item-level promotions). */
547
853
  discounts: Discount[];
548
854
  productVariant: {
549
855
  id: string;
550
856
  name: string;
551
857
  sku: string;
858
+ /**
859
+ * Units the channel will sell right now, `null` when it hides stock. Here
860
+ * so a cart can show how much of a line is on backorder BEFORE placement,
861
+ * when `backorderedQuantity` is still 0 — through
862
+ * `pricing.backorderedQuantityForCart(variant, quantity)`, which yields no
863
+ * hint at all when this is `null` (never read `null` as 0).
864
+ */
865
+ saleable: number | null;
552
866
  product: {
553
867
  id: string;
554
868
  name: string;
@@ -579,22 +893,42 @@ export interface FulfillmentLine {
579
893
  orderLineId: string;
580
894
  quantity: number;
581
895
  }
896
+ /**
897
+ * A shipment created for (part of) an order. `trackingCode` is the carrier
898
+ * barcode — feed it to `commerce.trackShipment(trackingCode, postalCode)`
899
+ * for live tracking history.
900
+ */
582
901
  export interface Fulfillment {
583
902
  id: string;
903
+ /** Fulfillment FSM state, e.g. Pending, Shipped, Delivered, Cancelled. */
584
904
  state: string;
905
+ /** Human-readable fulfillment/shipping method description. */
585
906
  method: string;
586
907
  trackingCode: string | null;
587
908
  createdAt: string;
588
909
  updatedAt: string;
589
910
  lines: FulfillmentLine[];
590
911
  }
912
+ /**
913
+ * A payment recorded against an order. `method` is the payment-method *code*
914
+ * (e.g. `manual-payment`, `mollie-payment`) — drives storefront invoice-vs-PSP
915
+ * routing. `transactionId` is the PSP receipt; null for manual/offline methods.
916
+ */
591
917
  export interface OrderPayment {
592
918
  id: string;
919
+ /** Payment-method code, e.g. `mollie-payment` or `manual-payment`. */
593
920
  method: string;
921
+ /** Amount captured by this payment, in minor units. */
594
922
  amount: number;
923
+ /** Payment FSM state, e.g. Authorized, Settled, Declined, Cancelled. */
595
924
  state: string;
925
+ /** PSP transaction reference; null for manual/offline payments. */
596
926
  transactionId: string | null;
597
927
  }
928
+ /**
929
+ * A shipping charge applied to an order. The selected method's name/code feeds
930
+ * order-detail rendering; `priceWithTax` is the charged amount in minor units.
931
+ */
598
932
  export interface ShippingLine {
599
933
  shippingMethod: {
600
934
  id: string;
@@ -608,7 +942,9 @@ export interface Order {
608
942
  code: string;
609
943
  state: string;
610
944
  active: boolean;
945
+ /** When the order (cart) was created — ISO-8601 instant. */
611
946
  createdAt: string;
947
+ /** When the order left the cart state (was placed) — ISO-8601 instant; null while still an active cart. */
612
948
  orderPlacedAt: string | null;
613
949
  totalQuantity: number;
614
950
  subTotal: number;
@@ -619,10 +955,15 @@ export interface Order {
619
955
  totalWithTax: number;
620
956
  currencyCode: string;
621
957
  lines: OrderLine[];
958
+ /** Order-level discounts (e.g. order-total promotions, free shipping). */
622
959
  discounts: Discount[];
960
+ /** Tax breakdown grouped by tax rate. */
623
961
  taxSummary: OrderTaxSummary[];
962
+ /** Promotions applied to this order. */
624
963
  promotions: OrderPromotion[];
964
+ /** Shipping charges on the order (selected method + charged price). */
625
965
  shippingLines: ShippingLine[];
966
+ /** Payments recorded against the order (method code, state, PSP receipt). */
626
967
  payments: OrderPayment[];
627
968
  shippingAddress?: OrderAddress;
628
969
  billingAddress?: OrderAddress;
@@ -633,30 +974,102 @@ export interface Order {
633
974
  emailAddress: string;
634
975
  };
635
976
  couponCodes: string[];
977
+ /**
978
+ * Shipments for this order. Only selected on placed-order reads
979
+ * (`getOrderByCode`, customer order history) — absent on cart operations.
980
+ */
636
981
  fulfillments?: Fulfillment[] | null;
982
+ /**
983
+ * Tracking pushed by an external fulfilment system, oldest delivery first.
984
+ * Prefer this over `fulfillments[].trackingCode` for display: one fulfilment can
985
+ * cover several parcels, which a single tracking code cannot express.
986
+ */
637
987
  externalShipments?: ExternalShipment[] | null;
988
+ /** Immutable source-aware payment condition captured when this order was accepted. */
638
989
  paymentTerms?: OrderPaymentTermsSnapshot | null;
990
+ /** Immutable Exact-aware delivery terms captured when this order was accepted. */
639
991
  deliveryTerms?: OrderDeliveryTermsSnapshot | null;
992
+ /**
993
+ * Order-level custom fields.
994
+ *
995
+ * Only populated on the order returned by
996
+ * {@link CommerceModule.setPaymentIntent | commerce.setPaymentIntent} —
997
+ * ordinary cart and order reads do not select it, so that a client release
998
+ * cannot break every cart operation against an engine that predates a field.
999
+ * Keep the buyer's chosen intent in your own state; that call's response is
1000
+ * where to read it back.
1001
+ */
640
1002
  customFields?: OrderCustomFields | null;
641
1003
  }
1004
+ /**
1005
+ * How the buyer said they would settle this order.
1006
+ *
1007
+ * `pay_now` = paid immediately (iDEAL, card, …), which is what a pay-now
1008
+ * discount promotion looks for; `on_account` = pay later on the net terms the
1009
+ * account carries. Written only by
1010
+ * {@link CommerceModule.setPaymentIntent | commerce.setPaymentIntent}, which
1011
+ * re-prices the order in the same call.
1012
+ */
642
1013
  export type OrderPaymentIntentValue = 'pay_now' | 'on_account';
1014
+ /** The Shop API enum accepted by `commerce.setPaymentIntent`. */
643
1015
  export type OrderPaymentIntent = 'PAY_NOW' | 'PAY_ON_ACCOUNT';
644
1016
  export interface OrderCustomFields {
1017
+ /**
1018
+ * The buyer's stated payment intent, or `null` when they never stated one.
1019
+ * Read-only: the only write path is `commerce.setPaymentIntent`.
1020
+ */
645
1021
  paymentIntent?: OrderPaymentIntentValue | null;
646
1022
  }
1023
+ /**
1024
+ * One parcel, pallet or pickup instruction pushed by the external fulfilment
1025
+ * system.
1026
+ *
1027
+ * `reference` is overloaded by design, because the sending systems overload it:
1028
+ * a parcel carrier sends a tracking URL, a pallet carrier sends a URL *or* a
1029
+ * plain reference, and ex-works sends free-text pickup instructions. Branch on
1030
+ * {@link ExternalShipment.isLink} — derived server-side — to decide between an
1031
+ * anchor and a text block. Never put a non-link reference in an `href`.
1032
+ */
647
1033
  export interface ExternalShipment {
1034
+ /** Carrier name as the sender reports it, e.g. `PostNL`, `Pallet`, `Ex works`. */
648
1035
  carrier: string;
1036
+ /** A tracking URL, a carrier reference, or pickup instructions. */
649
1037
  reference: string;
1038
+ /** True when `reference` is an http(s) URL safe to render as a link. */
650
1039
  isLink: boolean;
1040
+ /** ISO-8601 dispatch timestamp, or null if the sender omitted it. */
651
1041
  shippedAt: string | null;
1042
+ /** Which delivery of the order this parcel belongs to. */
652
1043
  deliveryNumber: string;
653
1044
  }
1045
+ /**
1046
+ * Order minimums in effect on the active channel (inline order-constraints
1047
+ * plugin). Display/pre-validation only — checkout enforces server-side.
1048
+ */
654
1049
  export interface ActiveChannelOrderConstraints {
1050
+ /**
1051
+ * Minimum vs the GROSS order total, minor units. Null when unset. This is the
1052
+ * channel-wide minimum raised by any price-list minimum applying to the
1053
+ * signed-in customer, so it varies per visitor.
1054
+ */
655
1055
  minOrderAmountGross: number | null;
1056
+ /**
1057
+ * Minimum vs the NET (tax-exclusive) total, minor units, when a price list
1058
+ * applying to this customer states its minimum ex tax. Independent of
1059
+ * `minOrderAmountGross` — both bind, and neither can be derived from the
1060
+ * other without a tax rate. Null when no net-basis minimum applies.
1061
+ */
656
1062
  minOrderAmountNet: number | null;
1063
+ /** Minimum total item count, from an applicable price list. Null when unset. */
657
1064
  minOrderQuantity: number | null;
1065
+ /** Default fulfillment profile minimum vs the NET subtotal, minor units. Null when unset. */
658
1066
  fulfillmentMinOrderNet: number | null;
659
1067
  currencyCode: string;
1068
+ /**
1069
+ * True when the signed-in customer's group is exempt from the CHANNEL-wide
1070
+ * minimum. A price-list minimum still applies, so `minOrderAmountGross` may
1071
+ * be non-null while this is true.
1072
+ */
660
1073
  customerIsExempt: boolean;
661
1074
  }
662
1075
  export interface ShippingMethod {
@@ -666,7 +1079,9 @@ export interface ShippingMethod {
666
1079
  price: number;
667
1080
  priceWithTax: number;
668
1081
  metadata?: Record<string, unknown>;
1082
+ /** True when this is the signed-in customer's eligible Exact default. */
669
1083
  isPreferred: boolean;
1084
+ /** False when the current externally governed customer cannot select this mapping. */
670
1085
  isDeliveryTermsEligible: boolean;
671
1086
  }
672
1087
  export interface PaymentMethod {
@@ -688,13 +1103,33 @@ export interface Customer {
688
1103
  items: OrderSummary[];
689
1104
  totalItems: number;
690
1105
  };
1106
+ /**
1107
+ * Customer groups the customer belongs to in the active channel. Drives
1108
+ * B2B-only UI (navigation, VAT-mode default, order gating) — pricing is
1109
+ * already applied server-side, so groups are for presentation only.
1110
+ */
691
1111
  groups?: CustomerGroup[];
1112
+ /**
1113
+ * Whether this customer is a trade (B2B) account — i.e. belongs to one of the
1114
+ * channel's configured B2B customer groups. The authoritative signal to gate
1115
+ * B2B UI on, so a storefront never hard-codes a group name. Optional because
1116
+ * a Vendure predating the field simply omits it.
1117
+ *
1118
+ * Presentation only: pricing, the tax display mode and access to quotes /
1119
+ * credit / contract pricing are all resolved server-side regardless.
1120
+ */
692
1121
  isB2B?: boolean;
693
1122
  }
1123
+ /** A customer group, as exposed to the storefront (identity only). */
694
1124
  export interface CustomerGroup {
695
1125
  id: string;
696
1126
  name: string;
697
1127
  }
1128
+ /**
1129
+ * A price list applying to the active customer. Identity only — prices are
1130
+ * applied server-side; storefronts use this to label which lists (contract /
1131
+ * tier) the signed-in customer is on.
1132
+ */
698
1133
  export interface CustomerPriceList {
699
1134
  id: string;
700
1135
  name: string;
@@ -719,6 +1154,7 @@ export interface OrderSummary {
719
1154
  id: string;
720
1155
  code: string;
721
1156
  state: string;
1157
+ /** Net (excl. tax) order total, in minor units. */
722
1158
  total: number;
723
1159
  totalWithTax: number;
724
1160
  currencyCode: string;
@@ -726,6 +1162,12 @@ export interface OrderSummary {
726
1162
  lines: Array<{
727
1163
  id: string;
728
1164
  quantity: number;
1165
+ /**
1166
+ * Units stock did not cover at placement (backorder); 0 otherwise.
1167
+ * Selected by `getCustomerOrders`; `undefined` from `getCurrentCustomer`.
1168
+ */
1169
+ backorderedQuantity?: number;
1170
+ /** Line total incl. tax, in minor units. */
729
1171
  linePriceWithTax: number;
730
1172
  productVariant: {
731
1173
  id: string;
@@ -745,24 +1187,32 @@ export interface OrderSummary {
745
1187
  };
746
1188
  }>;
747
1189
  fulfillments?: Fulfillment[] | null;
1190
+ /** Tracking pushed by an external fulfilment system. See {@link ExternalShipment}. */
748
1191
  externalShipments?: ExternalShipment[] | null;
1192
+ /** Immutable source-aware payment condition captured when this order was accepted. */
749
1193
  paymentTerms?: OrderPaymentTermsSnapshot | null;
1194
+ /** Immutable delivery terms captured when this order was accepted. */
750
1195
  deliveryTerms?: OrderDeliveryTermsSnapshot | null;
751
1196
  }
1197
+ /** An invoice issued for one of the signed-in customer's orders. */
752
1198
  export interface CustomerInvoice {
753
1199
  id: string;
754
1200
  invoiceNumber: string;
1201
+ /** Issue date (ISO-8601 date). */
755
1202
  invoicedOn: string;
1203
+ /** Minor units. */
756
1204
  totalWithTax: number;
757
1205
  currencyCode: string;
758
1206
  languageCode: string;
759
1207
  createdAt: string;
760
1208
  }
1209
+ /** Base64-encoded invoice PDF download. */
761
1210
  export interface CustomerInvoicePdf {
762
1211
  base64: string;
763
1212
  filename: string;
764
1213
  invoiceNumber: string;
765
1214
  }
1215
+ /** A line that could not be re-added during a `reorder()` call. */
766
1216
  export interface ReorderSkipped {
767
1217
  variantId: string;
768
1218
  quantity: number;
@@ -774,6 +1224,20 @@ export interface ReorderResult {
774
1224
  addedLines: number;
775
1225
  skipped: ReorderSkipped[];
776
1226
  }
1227
+ /**
1228
+ * Outcome of {@link CommerceModule.login}. A discriminated union so the
1229
+ * storefront can distinguish a genuine bad password from a migrated/imported
1230
+ * account that needs to set a new password.
1231
+ *
1232
+ * - `success`: signed in; `id`/`identifier` are the current user.
1233
+ * - `password_reset_required`: an imported account with no migrated password.
1234
+ * The platform has already emailed a reset link — prompt the user to check
1235
+ * their inbox, do NOT report invalid credentials.
1236
+ * - `account_not_verified`: the account exists but has not been verified yet.
1237
+ *
1238
+ * Genuine invalid credentials still throw a `MutationError` and never produce a
1239
+ * result here.
1240
+ */
777
1241
  export type LoginResult = {
778
1242
  status: 'success';
779
1243
  id: string;
@@ -825,13 +1289,30 @@ export interface MolliePaymentMethod {
825
1289
  size2x: string;
826
1290
  svg: string;
827
1291
  };
1292
+ /**
1293
+ * Mollie's availability status for this method on the order (e.g.
1294
+ * `"activated"`, `"pending-boarding"`). `null` when Mollie omits it.
1295
+ */
828
1296
  status: string | null;
829
1297
  }
1298
+ /**
1299
+ * A storefront-visible Mollie payment method, ordered per the channel's saved
1300
+ * configuration with hidden methods removed. Returned by
1301
+ * `commerce.getOrderedMolliePaymentMethods`. Decoupled from
1302
+ * {@link MolliePaymentMethod}: this is the curated, channel-ordered shape from
1303
+ * the platform's `payment-config` plugin, not the raw community plugin type.
1304
+ */
830
1305
  export interface OrderedMollieMethod {
831
1306
  id: string;
1307
+ /** Mollie method id (e.g. `"ideal"`); pass as `molliePaymentMethodCode`. */
832
1308
  code: string;
833
1309
  description: string | null;
1310
+ /** Mollie's icon URL (SVG preferred, 2x PNG fallback); null when omitted. */
834
1311
  imageUrl: string | null;
1312
+ /**
1313
+ * Mollie's availability status for this method (e.g. `"activated"`). `null`
1314
+ * when Mollie omits it.
1315
+ */
835
1316
  status: string | null;
836
1317
  }
837
1318
  export interface CreateMolliePaymentIntentInput {
@@ -840,11 +1321,21 @@ export interface CreateMolliePaymentIntentInput {
840
1321
  molliePaymentMethodCode?: string;
841
1322
  locale?: string;
842
1323
  immediateCapture?: boolean;
1324
+ /**
1325
+ * Create the intent for a specific order rather than the session's active
1326
+ * order — required when topping up an order in `ArrangingAdditionalPayment`,
1327
+ * or when driving checkout for a non-active order.
1328
+ */
843
1329
  orderId?: string;
844
1330
  }
845
1331
  export interface MolliePaymentIntentResult {
846
1332
  url: string;
847
1333
  }
1334
+ /**
1335
+ * Minimal order shape returned by `syncMolliePaymentStatus`. Use the `state`
1336
+ * to confirm the order settled (e.g. `PaymentSettled`) after a delayed/missing
1337
+ * Mollie webhook. `null` when no order matches the code.
1338
+ */
848
1339
  export interface MollieOrderStatusResult {
849
1340
  id: string;
850
1341
  code: string;
@@ -899,7 +1390,14 @@ export interface SearchInput {
899
1390
  term: string;
900
1391
  collectionSlug?: string;
901
1392
  collectionId?: string;
1393
+ /**
1394
+ * Filter to products belonging to ALL of these collections (AND). Combine with
1395
+ * `collectionSlugs` to intersect categories across collection groups. A slug
1396
+ * that doesn't resolve in the active channel yields an empty result rather than
1397
+ * widening the search.
1398
+ */
902
1399
  collectionSlugs?: string[];
1400
+ /** Filter to products belonging to ALL of these collection ids (AND). */
903
1401
  collectionIds?: string[];
904
1402
  facetValueIds?: string[];
905
1403
  facetValueFilters?: FacetValueFilterInput[];
@@ -912,6 +1410,11 @@ export interface SearchInput {
912
1410
  }
913
1411
  export interface SearchResultItem {
914
1412
  productId: string;
1413
+ /**
1414
+ * Orderable variant id for this search row — pass THIS (never `productId`) to
1415
+ * `addToCart`. Under `groupByProduct` it is a representative variant; for the
1416
+ * exact variant on multi-variant products, load `getProduct(slug)`.
1417
+ */
915
1418
  productVariantId: string;
916
1419
  productName: string;
917
1420
  slug: string;
@@ -935,6 +1438,7 @@ export interface SearchResultItem {
935
1438
  };
936
1439
  } | null;
937
1440
  collectionIds: string[];
1441
+ /** Aggregate availability across all stock locations (Meilisearch plugin). */
938
1442
  inStock: boolean;
939
1443
  }
940
1444
  export interface SearchFacetValue {
@@ -955,9 +1459,16 @@ export interface SearchResult {
955
1459
  totalItems: number;
956
1460
  facetValues: SearchFacetValue[];
957
1461
  }
1462
+ /** `eq` boolean operator mirroring Vendure's `BooleanOperators` input. */
958
1463
  export interface BooleanOperators {
959
1464
  eq?: boolean;
960
1465
  }
1466
+ /**
1467
+ * Subset of Vendure's `ProductFilterParameter` the SDK types explicitly.
1468
+ * `enabled` is the field `getProducts` defaults on; the index signature keeps
1469
+ * the parameter open to the other server-side filter fields without the SDK
1470
+ * having to enumerate them all.
1471
+ */
961
1472
  export interface ProductFilterParameter {
962
1473
  enabled?: BooleanOperators;
963
1474
  [field: string]: unknown;
@@ -965,32 +1476,108 @@ export interface ProductFilterParameter {
965
1476
  export interface ProductListOptions {
966
1477
  take?: number;
967
1478
  skip?: number;
1479
+ /**
1480
+ * How much of each product to fetch. Defaults to `'full'` — the existing
1481
+ * selection, unchanged for every current caller.
1482
+ *
1483
+ * `'card'` asks only for what a grid tile renders. It drops the per-VARIANT
1484
+ * stock reads a tile never shows — `availabilityByLocation`, `stockOnHand`,
1485
+ * `stockAllocated`, `incomingStock`, `projectedSaleable`,
1486
+ * `nextExpectedArrival` — and the product `description`, including the
1487
+ * per-language copy inside `translations`. The variant fields are resolved by
1488
+ * per-variant field resolvers server-side (`availabilityByLocation` issues one
1489
+ * stock query PER VARIANT), so the saving is backend work and SQL statements,
1490
+ * not just bytes.
1491
+ *
1492
+ * **The collection tree and the translated slugs are kept**, so card rows can
1493
+ * still feed `seo.canonicalFor`/`alternatesFor`: `collections` keeps
1494
+ * `parent`, `position`, `translations` and `customFields { isRoutable
1495
+ * isCanonical }`, and the product keeps `translations { languageCode name
1496
+ * slug }`. Also kept: `enabled` and `saleable` (storefronts gate orderability
1497
+ * on `saleable == null || saleable > 0`), `sku`, `stockLevel`,
1498
+ * `priceListName`, `retailPrice`/`retailPriceWithTax`, `priceTiers`, variant
1499
+ * `customFields` (purchase constraints) and `facetValues`. These cost bytes,
1500
+ * not queries.
1501
+ *
1502
+ * Ignored on the deprecated `{ collectionSlug }` path, which reroutes to the
1503
+ * search backend and returns its own already-flat row shape regardless.
1504
+ *
1505
+ * Both shapes are typed `ProductSummary`; the omitted members are optional on
1506
+ * that type, so a card row is a valid — just sparser — `ProductSummary`. Read
1507
+ * a dropped field and you get `undefined`, not a stale value.
1508
+ */
968
1509
  detail?: 'card' | 'full';
1510
+ /**
1511
+ * @deprecated Use `getProductsInCollection(slug, options)` instead. This
1512
+ * option silently reroutes the call through the search backend, whose rows
1513
+ * are flatter than the products list (single synthesised variant, no `sku`,
1514
+ * `facetValues`, or `collections`) — the named method makes that shape
1515
+ * explicit. The option keeps working for now.
1516
+ */
969
1517
  collectionSlug?: string;
1518
+ /**
1519
+ * Vendure's `products` query cannot sort by price — `ProductSortParameter`
1520
+ * has no such field (price lives on variants). For price-sorted listings use
1521
+ * `getProductsInCollection` or `searchProducts`, both of which sort by price
1522
+ * server-side.
1523
+ */
970
1524
  sort?: {
971
1525
  name?: 'ASC' | 'DESC';
972
1526
  createdAt?: 'ASC' | 'DESC';
973
1527
  };
1528
+ /**
1529
+ * Vendure `ProductFilterParameter`. When omitted, `getProducts` defaults to
1530
+ * `{ enabled: { eq: true } }` so disabled products never leak into an
1531
+ * unfiltered listing. An explicit `filter` REPLACES the default — but note
1532
+ * the Shop API additionally forces `enabled: { eq: true }` server-side, so
1533
+ * no filter can surface disabled products.
1534
+ */
974
1535
  filter?: ProductFilterParameter;
1536
+ /**
1537
+ * @deprecated The Shop API forces `enabled: { eq: true }` server-side, so
1538
+ * `enabled: false` cannot surface disabled products; the shorthand is
1539
+ * meaningless. Disabled products are only reachable through the Admin API.
1540
+ */
975
1541
  enabled?: boolean;
976
1542
  }
1543
+ /** Options for `getProductsInCollection` — the search-backed collection listing. */
977
1544
  export interface CollectionProductListOptions {
978
1545
  take?: number;
979
1546
  skip?: number;
1547
+ /** The search backend sorts by `name` or `price` (unlike the products list, which cannot sort by price). */
980
1548
  sort?: {
981
1549
  name?: 'ASC' | 'DESC';
982
1550
  price?: 'ASC' | 'DESC';
983
1551
  };
984
1552
  }
1553
+ /**
1554
+ * A product card row from the search backend, as returned by
1555
+ * `getProductsInCollection`. Honest projection of a search hit: exactly one
1556
+ * synthesised variant, and none of the fields the search index does not carry
1557
+ * (`sku`, `facetValues`, `collections`). Structurally a subset of
1558
+ * `ProductSummary`, so card components consuming `{ featuredAsset,
1559
+ * variants[0] }` work with either. Load `getProduct(slug)` for the full
1560
+ * variant/asset tree.
1561
+ */
985
1562
  export interface CollectionProductSummary {
986
1563
  id: string;
987
1564
  name: string;
988
1565
  slug: string;
989
1566
  description: string;
1567
+ /**
1568
+ * Synthesised from the search row's single preview URL — every preset
1569
+ * points at the same image and `source` is empty.
1570
+ */
990
1571
  featuredAsset: Asset | null;
1572
+ /** Exactly one synthesised variant per row (search groups by product). */
991
1573
  variants: [CollectionProductVariant];
992
1574
  }
1575
+ /** The single synthesised variant on a `CollectionProductSummary`. */
993
1576
  export interface CollectionProductVariant {
1577
+ /**
1578
+ * Orderable variant id — pass THIS (never the product id) to `addToCart`.
1579
+ * A representative variant for multi-variant products.
1580
+ */
994
1581
  id: string;
995
1582
  name: string;
996
1583
  price: number;
@@ -1014,15 +1601,35 @@ export interface FavoriteVariant {
1014
1601
  priceWithTax: number;
1015
1602
  currencyCode: string;
1016
1603
  stockLevel: string;
1604
+ /** ATP numbers — `null` when the channel does not expose operational stock. */
1017
1605
  stockOnHand: number | null;
1018
1606
  stockAllocated: number | null;
1019
1607
  saleable: number | null;
1608
+ /**
1609
+ * Incoming-stock numbers — additionally `null` unless the signed-in customer's
1610
+ * group may see incoming stock. `nextExpectedArrival` is the earliest FUTURE
1611
+ * arrival (ISO 8601, never past) and is `null` when every open line is overdue,
1612
+ * even while `incomingStock > 0`.
1613
+ */
1020
1614
  incomingStock: number | null;
1021
1615
  projectedSaleable: number | null;
1022
1616
  nextExpectedArrival: string | null;
1617
+ /**
1618
+ * Units BEYOND `saleable` the signed-in customer may order on backorder right
1619
+ * now. The quantity ceiling is `max(0, saleable) + backorderAllowance` (see
1620
+ * `maxOrderableQuantity` in `@sixtyninecommerce/client/pricing`). `null` when
1621
+ * the question does not apply — anonymous, group may not backorder, or the
1622
+ * channel hides stock — treat exactly like today; `0` = denied; a large
1623
+ * value (2,000,000,000) is the "unlimited" sentinel. A snapshot: the server
1624
+ * re-checks on add-to-cart and at placement and refuses with the usual
1625
+ * `InsufficientStockError` / `INSUFFICIENT_STOCK`, whose `quantityAvailable`
1626
+ * then already includes the allowance.
1627
+ */
1628
+ backorderAllowance: number | null;
1023
1629
  priceListName: string | null;
1024
1630
  retailPrice: number | null;
1025
1631
  retailPriceWithTax: number | null;
1632
+ /** Tax rate applied to this price in the active channel/zone, e.g. `{ value: 21 }` for 21% VAT. */
1026
1633
  taxRateApplied: {
1027
1634
  value: number;
1028
1635
  } | null;
@@ -1081,6 +1688,7 @@ export interface PaginatedList<T> {
1081
1688
  export interface ResolvedContent {
1082
1689
  data?: Record<string, unknown>;
1083
1690
  item?: Record<string, unknown>;
1691
+ /** Resolved field values keyed by field slug (locale-filtered). */
1084
1692
  values?: Record<string, unknown>;
1085
1693
  collection?: {
1086
1694
  id: string;
@@ -1096,6 +1704,10 @@ export interface ResolvedContent {
1096
1704
  path: string;
1097
1705
  }>;
1098
1706
  slug_translations?: Record<string, string>;
1707
+ /**
1708
+ * Derived SEO metadata block (from the standard SEO field group). `null` when
1709
+ * the item/page carries no SEO fields. Feed to `parseCmsItemMetadata`.
1710
+ */
1099
1711
  metadata?: Record<string, unknown> | null;
1100
1712
  }
1101
1713
  export interface SitemapEntry {
@@ -1104,7 +1716,9 @@ export interface SitemapEntry {
1104
1716
  title: string | null;
1105
1717
  collection_slug: string | null;
1106
1718
  updated_at: string;
1719
+ /** Present only for collection landing pages (basePath routes). */
1107
1720
  type?: 'collection_page';
1721
+ /** Present only when the request specified a language_code. */
1108
1722
  language_code?: string;
1109
1723
  }
1110
1724
  export interface ContentItemSummary {
@@ -1116,6 +1730,11 @@ export interface ContentItemSummary {
1116
1730
  collection_title_field_slug: string | null;
1117
1731
  title: string | null;
1118
1732
  }
1733
+ /**
1734
+ * Channel-wide CMS search query. All fields optional — supplying only `q`
1735
+ * searches across every collection in the store. Use `collectionId` or
1736
+ * `collectionSlug` to scope results.
1737
+ */
1119
1738
  export interface ContentSearchQuery {
1120
1739
  q?: string;
1121
1740
  collectionId?: string;
@@ -1123,9 +1742,15 @@ export interface ContentSearchQuery {
1123
1742
  parentId?: string;
1124
1743
  limit?: number;
1125
1744
  offset?: number;
1745
+ /** Meilisearch sort spec, e.g. `'updated_at:desc'`. */
1126
1746
  sort?: string;
1127
1747
  languageCode?: string;
1128
1748
  }
1749
+ /**
1750
+ * A single CMS content item search hit. Field values are flattened on the
1751
+ * document with locale-suffixed keys (`title_en`, `title_nl`, ...) — index
1752
+ * with `[fieldSlug]` or `[fieldSlug + '_' + languageCode]` as needed.
1753
+ */
1129
1754
  export interface ContentSearchHit {
1130
1755
  id: string;
1131
1756
  channel_id: string;
@@ -1167,6 +1792,7 @@ export interface CollectionPageValues {
1167
1792
  fields: CollectionFieldDefinition[];
1168
1793
  values: Record<string, unknown>;
1169
1794
  }
1795
+ /** A CMS collection (content type) as returned by `GET /collections`. */
1170
1796
  export interface CmsCollection {
1171
1797
  id: string;
1172
1798
  name: string;
@@ -1182,6 +1808,11 @@ export interface CmsCollection {
1182
1808
  export interface CmsCollectionDetail extends CmsCollection {
1183
1809
  fields: CollectionFieldDefinition[];
1184
1810
  }
1811
+ /**
1812
+ * A collection item from the direct CMS item endpoints. `values` holds the
1813
+ * item's field values keyed by field slug, locale-merged when a
1814
+ * `languageCode` was requested. Public callers only ever see published items.
1815
+ */
1185
1816
  export interface CmsCollectionItem {
1186
1817
  id: string;
1187
1818
  collectionId: string;
@@ -1192,7 +1823,9 @@ export interface CmsCollectionItem {
1192
1823
  createdAt: string;
1193
1824
  updatedAt: string;
1194
1825
  values: Record<string, unknown>;
1826
+ /** Per-language slug overrides. Present on single-item reads. */
1195
1827
  slug_translations?: Record<string, string>;
1828
+ /** Forward-compat: additional entity fields the CMS may add. */
1196
1829
  [key: string]: unknown;
1197
1830
  }
1198
1831
  export interface CmsCollectionItemList {
@@ -1200,8 +1833,10 @@ export interface CmsCollectionItemList {
1200
1833
  total: number;
1201
1834
  }
1202
1835
  export interface CollectionItemsQuery {
1836
+ /** Filter by parent item; pass `'root'` for top-level items. */
1203
1837
  parentId?: string;
1204
1838
  slug?: string;
1839
+ /** Full-text search within the collection (Meilisearch-assisted). */
1205
1840
  search?: string;
1206
1841
  sort?: string;
1207
1842
  languageCode?: string;
@@ -1222,10 +1857,19 @@ export interface FormField {
1222
1857
  label: string;
1223
1858
  type: string;
1224
1859
  required: boolean;
1860
+ /** Presentational config (e.g. select option labels). */
1225
1861
  config: Record<string, unknown>;
1862
+ /**
1863
+ * Effective per-field validation constraints the server enforces on submit
1864
+ * (min/max length, numeric range, options, pattern), resolved from the
1865
+ * field's `validation` first and `config` as a fallback. Contains only
1866
+ * recognized constraint keys. Mirror it to validate client-side. See
1867
+ * {@link FormFieldTypeDescriptor} / `content.getFormFieldTypes()`.
1868
+ */
1226
1869
  validation: Record<string, unknown>;
1227
1870
  position: number;
1228
1871
  }
1872
+ /** A form-level translation as emitted by the public projection. */
1229
1873
  export interface FormTranslation {
1230
1874
  languageCode: string;
1231
1875
  title: string;
@@ -1237,8 +1881,11 @@ export interface FormDefinition {
1237
1881
  id: string;
1238
1882
  name: string;
1239
1883
  slug: string;
1884
+ /** Where the storefront should send the visitor after a successful submit. */
1240
1885
  redirectUrlOnSuccess: string | null;
1886
+ /** True when the form has internal-notification recipients configured (addresses are never exposed). */
1241
1887
  hasNotifications: boolean;
1888
+ /** True when a visitor confirmation email will be sent on submit. */
1242
1889
  sendsConfirmation: boolean;
1243
1890
  fields: FormField[];
1244
1891
  translations: FormTranslation[];
@@ -1246,6 +1893,12 @@ export interface FormDefinition {
1246
1893
  submitMethod: string;
1247
1894
  submitHeaders: Record<string, string>;
1248
1895
  }
1896
+ /**
1897
+ * A form as returned by `content.listForms()`. Mirrors the public projection.
1898
+ * NOTE: list responses populate id/name/slug/redirect + the email booleans;
1899
+ * `fields` and `translations` arrive EMPTY in list context — fetch a single
1900
+ * form via `getForm`/`getFormBySlug` to load them.
1901
+ */
1249
1902
  export interface FormSummary {
1250
1903
  id: string;
1251
1904
  name: string;
@@ -1259,8 +1912,11 @@ export interface FormSummary {
1259
1912
  export interface FormListOptions {
1260
1913
  limit?: number;
1261
1914
  offset?: number;
1915
+ /** Case-insensitive match against the form name. */
1262
1916
  search?: string;
1917
+ /** Sort field; prefix with `-` for descending (name, created_at, updated_at). */
1263
1918
  sort?: string;
1919
+ /** Locale for the projected field labels. Defaults to the client language. */
1264
1920
  locale?: string;
1265
1921
  }
1266
1922
  export interface FormListResult {
@@ -1269,40 +1925,66 @@ export interface FormListResult {
1269
1925
  total: number;
1270
1926
  };
1271
1927
  }
1928
+ /** One constraint key a field type honors (see {@link FormFieldTypeDescriptor}). */
1272
1929
  export interface FormFieldTypeConstraint {
1273
1930
  key: string;
1274
1931
  valueType: 'integer' | 'number' | 'string' | 'string[]';
1275
1932
  description: string;
1276
1933
  }
1934
+ /**
1935
+ * Describes a form field type and the config/validation constraints it honors.
1936
+ * The SDK ships a static mirror as {@link FORM_FIELD_TYPES}; the same data is
1937
+ * served live by `content.getFormFieldTypes()` (GET /forms/field-types).
1938
+ */
1277
1939
  export interface FormFieldTypeDescriptor {
1278
1940
  type: string;
1279
1941
  label: string;
1280
1942
  description: string;
1943
+ /** Shape of the value a submission sends for this field. */
1281
1944
  valueType: string;
1945
+ /** Constraint keys honored on submit; resolved from `validation` first, then `config`. */
1282
1946
  constraints: FormFieldTypeConstraint[];
1283
1947
  notes?: string;
1284
1948
  }
1949
+ /** The slug shape one authoring surface enforces (form slug or field slug). */
1285
1950
  export interface FormSlugRule {
1951
+ /** Source of the regex the CMS validates against. */
1286
1952
  pattern: string;
1287
1953
  maxLength: number;
1288
1954
  description: string;
1289
1955
  validExamples: string[];
1290
1956
  invalidExamples: string[];
1291
1957
  }
1958
+ /**
1959
+ * Slug rules for form authoring: form slugs are HYPHEN-separated, field slugs
1960
+ * are UNDERSCORE-separated. Shipped statically as {@link FORM_SLUG_RULES} and
1961
+ * served live in the field-types registry response.
1962
+ */
1292
1963
  export interface FormSlugRules {
1293
1964
  form: FormSlugRule;
1294
1965
  field: FormSlugRule;
1295
1966
  }
1967
+ /** Everything GET /forms/field-types carries: the field types plus the slug rules. */
1296
1968
  export interface FormFieldTypeRegistry {
1297
1969
  fieldTypes: FormFieldTypeDescriptor[];
1298
1970
  slugRules: FormSlugRules;
1299
1971
  }
1972
+ /**
1973
+ * Result of `submitForm` — discriminate on `success`. Field-validation
1974
+ * failures RESOLVE with `success: false` + per-field errors (render them
1975
+ * inline next to the fields); rate limits (429, carries
1976
+ * `retryAfterSeconds`), transport failures, and server errors still throw
1977
+ * `StorefrontError`.
1978
+ */
1300
1979
  export type FormSubmissionResult = {
1301
1980
  success: true;
1981
+ /** Stored submission id. */
1302
1982
  id: string;
1983
+ /** ISO-8601 creation timestamp. */
1303
1984
  createdAt: string;
1304
1985
  } | {
1305
1986
  success: false;
1987
+ /** Per-field validation errors, in the CMS's field order. */
1306
1988
  errors: Array<{
1307
1989
  field: string;
1308
1990
  code?: string;
@@ -1343,8 +2025,21 @@ export interface RouteEntry {
1343
2025
  slug?: string;
1344
2026
  updated_at?: string;
1345
2027
  source?: string;
2028
+ /**
2029
+ * Only set on `product` routes. A product listed under multiple collections
2030
+ * emits one route per collection; exactly one — the canonical URL home — is
2031
+ * `true`, the rest `false`. Filter to `canonical !== false` to get the
2032
+ * deduplicated (one-per-product) URL set. `undefined` on `cms`/`collection`
2033
+ * routes, which are already one-per-entity.
2034
+ */
1346
2035
  canonical?: boolean;
1347
2036
  }
2037
+ /**
2038
+ * A manifest entry as `findRoute` returns it, plus the cache tags the page's
2039
+ * reads should carry — `product:<id>` / `collection:<id>`, none for CMS pages.
2040
+ * Load the page by `id` (`getProductById`, `getCollectionById`,
2041
+ * `getProductsInCollectionById`) and those tags are already on its reads.
2042
+ */
1348
2043
  export interface ResolvedRoute extends RouteEntry {
1349
2044
  readonly cacheTags: readonly string[];
1350
2045
  }
@@ -1372,6 +2067,7 @@ export interface ConvertedAmount {
1372
2067
  rate: string;
1373
2068
  rateDate: string;
1374
2069
  }
2070
+ /** One entry of a `convertToMultiple()` result. */
1375
2071
  export interface BulkConversionResult {
1376
2072
  currency: string;
1377
2073
  amount: string;
@@ -1384,6 +2080,7 @@ export interface PriceDisplay {
1384
2080
  retailPrice: number | null;
1385
2081
  retailPriceWithTax: number | null;
1386
2082
  priceListName: string | null;
2083
+ /** Tax rate percentage applied to this price (e.g. `21`), or null if unknown. */
1387
2084
  taxRate: number | null;
1388
2085
  hasDiscount: boolean;
1389
2086
  discountPercentage: number | null;
@@ -1393,33 +2090,68 @@ export interface TierTableEntry {
1393
2090
  minQuantity: number;
1394
2091
  price: number;
1395
2092
  priceWithTax: number;
2093
+ /** Tax rate percentage applied to this tier's price (e.g. `21`), or null if unknown. */
1396
2094
  taxRate: number | null;
1397
2095
  discountLabel: string | null;
1398
2096
  savingsPercentage: number | null;
1399
2097
  }
2098
+ /**
2099
+ * Which tax figure to display. `gross` = tax-inclusive (BTW "incl."),
2100
+ * `net` = tax-exclusive (BTW "excl."). The platform always returns both the
2101
+ * net (`price`) and gross (`priceWithTax`) figures, so switching modes never
2102
+ * recomputes tax — it just picks the server-authoritative field.
2103
+ */
1400
2104
  export type TaxDisplayMode = 'gross' | 'net';
2105
+ /**
2106
+ * Channel-wide display default (`Channel.customFields.taxDisplayDefault`).
2107
+ * `channel` means "follow `pricesIncludeTax`", which is what every storefront
2108
+ * did before the policy existed.
2109
+ */
1401
2110
  export type TaxDisplayDefault = 'channel' | 'gross' | 'net';
2111
+ /**
2112
+ * B2B override (`Channel.customFields.taxDisplayB2b`). `inherit` leaves trade
2113
+ * accounts on the channel default.
2114
+ */
1402
2115
  export type TaxDisplayB2bMode = 'inherit' | 'gross' | 'net';
2116
+ /**
2117
+ * The channel's price-display policy, as parsed from `activeChannel.customFields`
2118
+ * by `parseTaxDisplayPolicy`. Feed it to `resolveTaxDisplayMode` to preview a
2119
+ * mode offline; the authority is `getTaxDisplayMode()`.
2120
+ */
1403
2121
  export interface TaxDisplayPolicy {
1404
2122
  default: TaxDisplayDefault;
1405
2123
  b2b: TaxDisplayB2bMode;
2124
+ /** Upper-case ISO-3166 alpha-2 codes. Empty = the country rule is off. */
1406
2125
  countries: readonly string[];
1407
2126
  }
2127
+ /** The per-shopper facts `resolveTaxDisplayMode` judges. */
1408
2128
  export interface TaxDisplayInputs {
2129
+ /** Member of one of the channel's configured B2B customer groups (`Customer.isB2B`). */
1409
2130
  isB2B: boolean;
2131
+ /** The request carries `x-order-scope: trade` — the dealer storefront. */
1410
2132
  isTrade: boolean;
2133
+ /** The shopper's country: active order shipping address, else their default one. */
1411
2134
  countryCode: string | null;
2135
+ /** `Channel.pricesIncludeTax` — the STORAGE mode, not a display decision. */
1412
2136
  pricesIncludeTax: boolean;
1413
2137
  }
2138
+ /**
2139
+ * A resolved mode cached against the identity it was resolved for. Stored on
2140
+ * {@link StoreContext.taxDisplay}; `stamp` is `identityStamp(ctx)`.
2141
+ */
1414
2142
  export interface ResolvedTaxDisplay {
1415
2143
  stamp: string;
1416
2144
  mode: TaxDisplayMode;
1417
2145
  }
1418
2146
  export interface DisplayPrice {
2147
+ /** The amount to show, in minor units, for the requested mode. */
1419
2148
  amount: number;
2149
+ /** The strikethrough/retail amount for the requested mode, or null. */
1420
2150
  retailAmount: number | null;
1421
2151
  currencyCode: string;
2152
+ /** True when `amount` includes tax (i.e. mode was `gross`). */
1422
2153
  isGross: boolean;
2154
+ /** True when a higher retail amount exists for the same mode. */
1423
2155
  hasDiscount: boolean;
1424
2156
  }
1425
2157
  export interface VariantPriceData {
@@ -1470,6 +2202,11 @@ export interface PropertyConfig {
1470
2202
  maxLength?: number;
1471
2203
  allowedCollectionIds?: string[];
1472
2204
  filterableFieldSlugs?: string[];
2205
+ /**
2206
+ * For `product` field type: strict filter applied in the admin UI to
2207
+ * narrow the picker. Storefront callers can ignore this — the selected
2208
+ * product IDs are already stored in `PropertyValue.value` (as `string[]`).
2209
+ */
1473
2210
  productFilter?: {
1474
2211
  filters?: Array<{
1475
2212
  property_slug: string;
@@ -1506,6 +2243,18 @@ export interface ProductPropertyGroupValues {
1506
2243
  group: PropertyGroup;
1507
2244
  values: PropertyValue[];
1508
2245
  }
2246
+ /**
2247
+ * A product's property values flattened to a `slug → value` record (the shape
2248
+ * a product-detail view actually renders). Produced by
2249
+ * `commerce.mapProductProperties(...)`.
2250
+ *
2251
+ * Values keep their stored JSON type: `string` (string/text/enum fields),
2252
+ * `boolean`, `number`, or `string[]` (multi_enum / product-reference fields).
2253
+ *
2254
+ * CAVEAT — `content_item` fields (e.g. `producer_winehouse`) store a **CMS
2255
+ * content-item id string**, NOT a human-readable name. To display the producer,
2256
+ * resolve that id against the CMS content API; do not render it verbatim.
2257
+ */
1509
2258
  export type ProductPropertyRecord = Record<string, unknown>;
1510
2259
  export type PresetName = 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl';
1511
2260
  export interface ResponsiveImageData {
@@ -1632,6 +2381,13 @@ export interface SubscriptionUpcomingPayment {
1632
2381
  dueAt: string | null;
1633
2382
  amount: number;
1634
2383
  currencyCode: string;
2384
+ /**
2385
+ * The outstanding cycle's payment state (`ready`, `processing`, `pending`,
2386
+ * `action_required`, `unknown`, `failed`, or `charged_back` — a paid cycle the
2387
+ * bank reversed), else a live checkout's state, else `scheduled`, `paused` or
2388
+ * `none`. `failed` and `charged_back` are recovered with
2389
+ * `recoverMySubscriptionPayment`.
2390
+ */
1635
2391
  state: string;
1636
2392
  nextRetryAt: string | null;
1637
2393
  checkoutUrl: string | null;
@@ -1639,9 +2395,19 @@ export interface SubscriptionUpcomingPayment {
1639
2395
  export interface SubscriptionPurchasePreview {
1640
2396
  planId: string;
1641
2397
  planName: string;
2398
+ /**
2399
+ * What the customer is charged per cycle, in minor units: products, shipping and
2400
+ * the tax of their zone included. Pass it back as `expectedAmount` when starting.
2401
+ */
1642
2402
  amount: number;
2403
+ /**
2404
+ * Whether plan prices on this channel include tax. When false the plan price is
2405
+ * net and `amount` adds the customer's VAT (none under reverse charge).
2406
+ */
1643
2407
  pricesIncludeTax: boolean;
2408
+ /** `amount` without tax. */
1644
2409
  netAmount: number;
2410
+ /** The tax in `amount` for the customer's tax zone. */
1645
2411
  taxAmount: number;
1646
2412
  currencyCode: string;
1647
2413
  firstPaymentAt: string;
@@ -1662,7 +2428,12 @@ export interface SubscriptionPurchaseInput {
1662
2428
  provider?: 'mollie' | 'stripe';
1663
2429
  mandateId?: string;
1664
2430
  returnUrl: string;
2431
+ /** Persist this key for the purchase; reuse it when retrying the same request. */
1665
2432
  requestKey: string;
2433
+ /**
2434
+ * The previewed `amount`. When given, the purchase is rejected — before any
2435
+ * payment starts — if the price changed since the preview; preview again.
2436
+ */
1666
2437
  expectedAmount?: number;
1667
2438
  }
1668
2439
  export interface SubscriptionPaymentActionInput {
@@ -1727,6 +2498,7 @@ export interface CustomerSubscription {
1727
2498
  cancelAtPeriodEnd: boolean;
1728
2499
  createdAt: string;
1729
2500
  }
2501
+ /** Customer-safe subscription plan for the storefront catalogue. */
1730
2502
  export interface SubscriptionPlanPublic {
1731
2503
  firstChargeTiming: SubscriptionFirstChargeTiming;
1732
2504
  customerChangeCutoffHours: number;
@@ -1734,6 +2506,11 @@ export interface SubscriptionPlanPublic {
1734
2506
  name: string;
1735
2507
  description: string | null;
1736
2508
  currencyCode: string;
2509
+ /**
2510
+ * Price per cycle in minor units, shipping included, on the channel's price
2511
+ * basis: gross when the channel's prices include tax, otherwise net. Use
2512
+ * `previewSubscriptionPurchase` for the amount a customer is charged.
2513
+ */
1737
2514
  price: number;
1738
2515
  billingInterval: string;
1739
2516
  billingIntervalCount: number;
@@ -1741,17 +2518,21 @@ export interface SubscriptionPlanPublic {
1741
2518
  minCycles: number | null;
1742
2519
  maxCycles: number | null;
1743
2520
  }
2521
+ /** Customer-safe view of a stored payment mandate. */
1744
2522
  export interface MyPaymentMandate {
1745
2523
  id: string;
1746
2524
  provider: string;
1747
2525
  mandateMethod: string | null;
2526
+ /** 'pending' | 'valid' | 'invalid' | 'revoked' */
1748
2527
  mandateStatus: string;
1749
2528
  isDefault: boolean;
1750
2529
  createdAt: string;
1751
2530
  }
1752
2531
  export interface SetupPaymentMandateResult {
1753
2532
  mandate: MyPaymentMandate;
2533
+ /** Mollie checkout URL to redirect the customer to (null for Stripe). */
1754
2534
  checkoutUrl: string | null;
2535
+ /** Stripe SetupIntent client secret (null for Mollie). */
1755
2536
  clientSecret: string | null;
1756
2537
  }
1757
2538
  export type QuoteStatus = 'draft' | 'requested' | 'in_review' | 'approved' | 'declined' | 'expired' | 'converted_to_order' | 'cancelled';
@@ -1759,16 +2540,62 @@ export interface QuoteLine {
1759
2540
  id: string;
1760
2541
  productVariantId: string;
1761
2542
  quantity: number;
2543
+ /** Minor units in the quote currency. Null until a sales rep prices the line. */
1762
2544
  unitPrice: number | null;
2545
+ /**
2546
+ * Line-level discount the rep applied. `percentage` is basis points
2547
+ * (10000 = 100%); `fixed` is whole-line minor units. Null when no discount.
2548
+ */
1763
2549
  discountType: 'percentage' | 'fixed' | null;
2550
+ /** Discount magnitude (basis points for `percentage`, minor units for `fixed`). */
1764
2551
  discountValue: number;
1765
2552
  discountLabel: string | null;
1766
2553
  position: number;
2554
+ /**
2555
+ * Variant display name at read time, in the request's language. `null` when
2556
+ * the variant has been deleted or left the channel — render a placeholder
2557
+ * rather than scanning the catalogue for it.
2558
+ *
2559
+ * Optional, like the five fields below: they are `undefined` against a
2560
+ * Vendure that predates them, which the client detects once and then stops
2561
+ * asking for (see `createQuotesMethods`).
2562
+ */
1767
2563
  productName?: string | null;
2564
+ /** Variant SKU at read time. `null` under the same conditions as `productName`. */
1768
2565
  sku?: string | null;
2566
+ /**
2567
+ * Effective tax rate for this line as a PERCENT — 21 for 21%, and fractional
2568
+ * where the statutory rate is (13.5 in IE, 8.1 in CH). It is the variant's
2569
+ * own applied TaxRate, the rate the converted order is charged at; never
2570
+ * assume a national rate. `null` when the variant is unavailable.
2571
+ */
1769
2572
  taxRate?: number | null;
2573
+ /**
2574
+ * Per-unit GROSS (incl. tax) price in minor units, with the whole-line
2575
+ * discount already amortised across the units. `null` when the variant is
2576
+ * unavailable, and while the line is still unpriced (`unitPrice` is `null`,
2577
+ * i.e. a draft or requested quote) — render a placeholder, never `0`.
2578
+ *
2579
+ * Derived from `lineTotalWithTax / quantity`, so it is the quote's own
2580
+ * agreed per-unit figure: `unitPriceWithTax × quantity` reconciles with the
2581
+ * line total exactly, and may differ from the variant's catalogue gross
2582
+ * unit price by a rounding unit.
2583
+ */
1770
2584
  unitPriceWithTax?: number | null;
2585
+ /**
2586
+ * NET (excl. tax) line total in minor units, after discount. `null` when the
2587
+ * variant is unavailable or the line is still unpriced.
2588
+ */
1771
2589
  lineTotal?: number | null;
2590
+ /**
2591
+ * GROSS (incl. tax) line total in minor units, after discount — what this
2592
+ * line adds to the payable total. `null` when the variant is unavailable or
2593
+ * the line is still unpriced.
2594
+ *
2595
+ * This is the quote's OWN line maths. The order `acceptQuote` creates
2596
+ * re-prices per unit, so an order total can differ from the sum of these by
2597
+ * a minor unit per line when the discount does not divide evenly.
2598
+ */
1772
2599
  lineTotalWithTax?: number | null;
1773
2600
  createdAt: string;
1774
2601
  updatedAt: string;
@@ -1783,6 +2610,7 @@ export interface Quote {
1783
2610
  expiresAt: string | null;
1784
2611
  salesRepUserId: string | null;
1785
2612
  customerNotes: string | null;
2613
+ /** Set once the quote has been accepted and converted to an Order. */
1786
2614
  convertedOrderId: string | null;
1787
2615
  lines: QuoteLine[];
1788
2616
  createdAt: string;
@@ -1804,6 +2632,11 @@ export interface CreateQuoteRequestInput {
1804
2632
  }>;
1805
2633
  customerNotes?: string;
1806
2634
  }
2635
+ /**
2636
+ * Lifecycle state of a return, derived from its status log. Customers can
2637
+ * only cancel while still `requested`; everything after that is merchant- or
2638
+ * system-driven.
2639
+ */
1807
2640
  export type CustomerReturnState = 'requested' | 'approved' | 'rejected' | 'cancelled' | 'items_received' | 'settlement_pending' | 'settlement_failed' | 'settled';
1808
2641
  export type CustomerReturnSettlementMethod = 'refund' | 'store_credit';
1809
2642
  export type CustomerReturnReasonCode = 'damaged' | 'defective' | 'wrong_item' | 'not_as_described' | 'arrived_late' | 'no_longer_needed' | 'order_error' | 'other';
@@ -1814,26 +2647,40 @@ export interface CustomerReturnLine {
1814
2647
  productVariantName: string;
1815
2648
  productVariantSku: string;
1816
2649
  requestedQty: number;
2650
+ /** Null until the merchant approves; 0 means the line was declined. */
1817
2651
  approvedQty: number | null;
2652
+ /** Cumulative units received back by the merchant across all receipts. */
1818
2653
  receivedQty: number;
1819
2654
  restockQty: number;
1820
2655
  writeOffQty: number;
1821
2656
  reasonCode: CustomerReturnReasonCode;
1822
2657
  reasonNote: string | null;
2658
+ /** Snapshot of the order line's prorated unit price incl. tax (minor units). */
1823
2659
  unitPriceWithTax: number;
2660
+ /**
2661
+ * The same snapshot before per-unit rounding; null for returns requested
2662
+ * before the field existed. Multiply by a quantity and round ONCE to get
2663
+ * that quantity's share, exactly as the order line totals itself.
2664
+ */
1824
2665
  unitPriceWithTaxUnrounded: number | null;
2666
+ /** Refund amount for this line (minor units); null until approved. */
1825
2667
  refundAmount: number | null;
1826
2668
  }
2669
+ /** A customer-facing return (RMA). All money fields are Int minor units. */
1827
2670
  export interface CustomerReturn {
1828
2671
  id: string;
2672
+ /** Human-facing RMA code, e.g. RMA-000042. */
1829
2673
  code: string;
1830
2674
  state: CustomerReturnState;
1831
2675
  orderId: string;
1832
2676
  orderCode: string;
1833
2677
  currencyCode: string;
1834
2678
  preferredSettlementMethod: CustomerReturnSettlementMethod | null;
2679
+ /** Settlement method actually used; null until settled. */
1835
2680
  settlementMethod: CustomerReturnSettlementMethod | null;
2681
+ /** Shipping refunded on top of line refunds (minor units). */
1836
2682
  shippingRefundAmount: number;
2683
+ /** Total actually settled (minor units); null until settled. */
1837
2684
  settledAmount: number | null;
1838
2685
  customerNote: string | null;
1839
2686
  requestedAt: string;
@@ -1861,39 +2708,74 @@ export interface RequestReturnInput {
1861
2708
  customerNote?: string;
1862
2709
  preferredSettlementMethod?: CustomerReturnSettlementMethod;
1863
2710
  }
2711
+ /** Per-order-line returnable quantities for the return-request flow. */
1864
2712
  export interface ReturnableOrderLine {
1865
2713
  orderLineId: string;
1866
2714
  productVariantId: string;
1867
2715
  productVariantName: string;
1868
2716
  productVariantSku: string;
2717
+ /** Units shipped or delivered for this order line. */
1869
2718
  fulfilledQty: number;
2719
+ /** fulfilledQty minus quantities tied up in active returns. */
1870
2720
  returnableQty: number;
2721
+ /** The order line's prorated unit price incl. tax (minor units). */
1871
2722
  unitPriceWithTax: number;
2723
+ /**
2724
+ * The same price before per-unit rounding. Multiply by a quantity and round
2725
+ * ONCE to preview that quantity's refund, exactly as the order line totals
2726
+ * itself.
2727
+ */
1872
2728
  unitPriceWithTaxUnrounded: number;
1873
2729
  }
1874
2730
  export interface CustomerReturnEligibility {
1875
2731
  orderId: string;
1876
2732
  eligible: boolean;
2733
+ /** Why the order is not eligible; null when eligible. */
1877
2734
  reason: string | null;
1878
2735
  returnWindowEndsAt: string | null;
2736
+ /** Only lines with fulfilled quantity appear here. */
1879
2737
  lines: ReturnableOrderLine[];
1880
2738
  }
2739
+ /**
2740
+ * The authenticated customer's B2B accounts-receivable credit status in the
2741
+ * current channel. All money fields are in minor units of `currencyCode`.
2742
+ * Returned by `client.credit.getCreditStatus()`; `null` when the customer is
2743
+ * not signed in, has no credit account, or the channel has B2B credit disabled.
2744
+ */
1881
2745
  export interface B2bCreditStatus {
1882
2746
  customerId: string;
1883
2747
  currencyCode: string;
2748
+ /** Outstanding invoiced-but-unpaid ledger balance. */
1884
2749
  balance: number;
2750
+ /** Total value of placed B2B orders not yet invoiced. */
1885
2751
  uninvoicedOrdersTotal: number;
2752
+ /** Total credit exposure (`balance + uninvoicedOrdersTotal`). */
1886
2753
  exposure: number;
2754
+ /** Configured credit limit; `null` when no limit is set. */
1887
2755
  creditLimit: number | null;
2756
+ /** Remaining headroom (`creditLimit - exposure`); `null` when no limit is set. */
1888
2757
  available: number | null;
1889
2758
  overdueInvoiceCount: number;
1890
2759
  overLimit: boolean;
1891
2760
  hasOverdue: boolean;
2761
+ /**
2762
+ * Where `balance` was sourced from. `LOCAL_LEDGER` = computed from the local
2763
+ * AR subledger; `ERP_LIVE` = read live from the ERP; `ERP_UNLINKED` = the
2764
+ * channel is ERP-driven but this customer isn't linked yet (treat the balance
2765
+ * as unavailable rather than zero, and surface a "not linked" notice).
2766
+ */
1892
2767
  balanceSource: CreditBalanceSource;
1893
2768
  }
2769
+ /** Where a {@link B2bCreditStatus.balanceSource} balance was sourced from. */
1894
2770
  export type CreditBalanceSource = 'LOCAL_LEDGER' | 'ERP_LIVE' | 'ERP_UNLINKED';
2771
+ /** How reliably the source payment condition could be interpreted. */
1895
2772
  export type PaymentTermsClassification = 'SINGLE_DUE_DATE' | 'COMPLEX' | 'UNRESOLVED' | 'UNASSIGNED' | 'CONFLICT';
2773
+ /** Assignment and freshness state for externally managed customer payment terms. */
1896
2774
  export type PaymentTermsStatus = 'ASSIGNED' | 'UNASSIGNED' | 'UNRESOLVED' | 'STALE' | 'CONFLICT';
2775
+ /**
2776
+ * Source-aware payment terms for the authenticated customer. Exact-backed terms preserve the
2777
+ * original condition code and complex-rule fields rather than reducing every condition to days.
2778
+ */
1897
2779
  export interface CustomerPaymentTerms {
1898
2780
  customerId: string | null;
1899
2781
  source: string;
@@ -1914,15 +2796,25 @@ export interface CustomerPaymentTerms {
1914
2796
  syncedAt: string | null;
1915
2797
  error: string | null;
1916
2798
  }
2799
+ /** Payment terms frozen on an order at acceptance, including later remote confirmation metadata. */
1917
2800
  export interface OrderPaymentTermsSnapshot extends Omit<CustomerPaymentTerms, 'customerId'> {
1918
2801
  resolvedAt: string;
1919
2802
  remoteConditionCode: string | null;
1920
2803
  remoteConfirmedAt: string | null;
2804
+ /** True after the ERP confirms a different condition than the accepted snapshot. */
1921
2805
  remoteMismatch: boolean;
1922
2806
  }
2807
+ /** Assignment and freshness state for Exact-managed customer delivery terms. */
1923
2808
  export type DeliveryTermsStatus = 'ASSIGNED' | 'UNASSIGNED' | 'UNRESOLVED' | 'STALE' | 'CONFLICT';
2809
+ /** Exact's account-level partial-delivery policy, exposed as operational guidance. */
1924
2810
  export type DeliveryAdvice = 'PARTIAL_ALLOWED' | 'COMPLETE_ORDER' | 'PARTIAL_WITHOUT_BACKORDER' | 'UNKNOWN';
2811
+ /** Why the placed order uses its selected shipping method. */
1925
2812
  export type DeliverySelectionSource = 'CUSTOMER_DEFAULT' | 'EXPLICIT_OVERRIDE' | 'IMPORTED' | 'UNKNOWN';
2813
+ /**
2814
+ * Exact-aware delivery terms for the authenticated customer in the current channel.
2815
+ * The preferred method is a default, not an eligibility restriction; checkout pricing
2816
+ * still comes from the platform's shipping calculator.
2817
+ */
1926
2818
  export interface CustomerDeliveryTerms {
1927
2819
  customerId: string | null;
1928
2820
  source: string;
@@ -1935,18 +2827,22 @@ export interface CustomerDeliveryTerms {
1935
2827
  preferredShippingMethodCode: string | null;
1936
2828
  preferredShippingMethodName: string | null;
1937
2829
  preferredShippingMethodAvailable: boolean;
2830
+ /** Active platform mappings that may be selected as deliberate overrides. */
1938
2831
  eligibleShippingMethodIds: string[];
1939
2832
  incotermStatus: DeliveryTermsStatus;
1940
2833
  incotermCode: string | null;
1941
2834
  incotermVersion: number | null;
1942
2835
  incotermAddress: string | null;
1943
2836
  incotermDescription: string | null;
2837
+ /** Exact dispatch lead time in days; this is not a promised arrival date. */
1944
2838
  shippingLeadDays: number | null;
1945
2839
  deliveryAdvice: DeliveryAdvice | null;
1946
2840
  stale: boolean;
1947
2841
  syncedAt: string | null;
2842
+ /** Customer-safe warning; raw synchronization errors remain Admin-only. */
1948
2843
  warning: string | null;
1949
2844
  }
2845
+ /** Delivery terms frozen on an order at acceptance, plus later Exact readback metadata. */
1950
2846
  export interface OrderDeliveryTermsSnapshot {
1951
2847
  source: string;
1952
2848
  managedExternally: boolean;
@@ -1961,7 +2857,9 @@ export interface OrderDeliveryTermsSnapshot {
1961
2857
  platformShippingMethodCode: string | null;
1962
2858
  platformShippingMethodName: string | null;
1963
2859
  platformShippingMethodDescription: string | null;
2860
+ /** Accepted platform shipping quote in order-currency minor units. */
1964
2861
  platformShippingPrice: number | null;
2862
+ /** Accepted platform shipping quote including tax, in order-currency minor units. */
1965
2863
  platformShippingPriceWithTax: number | null;
1966
2864
  preferredShippingMethodId: string | null;
1967
2865
  incotermStatus: DeliveryTermsStatus;
@@ -1982,6 +2880,7 @@ export interface OrderDeliveryTermsSnapshot {
1982
2880
  remoteIncotermAddress: string | null;
1983
2881
  remoteDeliveryDate: string | null;
1984
2882
  remoteConfirmedAt: string | null;
2883
+ /** True after Exact confirms delivery fields that differ from the accepted snapshot. */
1985
2884
  remoteMismatch: boolean;
1986
2885
  }
1987
2886
  export interface VatValidationResult {
@@ -2014,6 +2913,7 @@ export interface DropOffPoint {
2014
2913
  availableDays: number[] | null;
2015
2914
  cutOffTime: string | null;
2016
2915
  carrierId: number | null;
2916
+ /** Distance from the postal code, in metres. */
2017
2917
  distance: number | null;
2018
2918
  }
2019
2919
  export interface DeliveryOptionsInput {
@@ -2030,10 +2930,12 @@ export interface DeliveryTimeFrame {
2030
2930
  start: string;
2031
2931
  end: string;
2032
2932
  priceComment: string | null;
2933
+ /** Base rate for this window in minor units (cents); null when the carrier omits it. Surcharges finalize after shipment creation. */
2033
2934
  price: {
2034
2935
  amount: number;
2035
2936
  currency: string;
2036
2937
  } | null;
2938
+ /** Carrier delivery type of this window (MyParcel: 1 morning, 2 evening, 3 standard, 4 pickup). */
2037
2939
  deliveryType: number | null;
2038
2940
  }
2039
2941
  export interface DeliveryOption {
@@ -2045,14 +2947,21 @@ export interface PickupLocationAddress {
2045
2947
  number: string;
2046
2948
  postalCode: string;
2047
2949
  city: string;
2950
+ /** ISO 3166-1 alpha-2 country code. */
2048
2951
  countryCode: string;
2049
2952
  region?: string;
2050
2953
  }
2051
2954
  export interface PickupLocationOpeningHours {
2955
+ /** 0 = Sunday ... 6 = Saturday. */
2052
2956
  weekday: number;
2957
+ /** `HH:MM` (24-hour). */
2053
2958
  open: string;
2054
2959
  close: string;
2055
2960
  }
2961
+ /**
2962
+ * Carrier-agnostic pickup location. Currently MyParcel-backed; future
2963
+ * providers (Sendcloud, Hendriks) implement the same shape.
2964
+ */
2056
2965
  export interface PickupLocation {
2057
2966
  provider: string;
2058
2967
  carrier: number;
@@ -2060,9 +2969,11 @@ export interface PickupLocation {
2060
2969
  name: string;
2061
2970
  address: PickupLocationAddress;
2062
2971
  openingHours?: PickupLocationOpeningHours[];
2972
+ /** Carrier-specific extras. */
2063
2973
  details?: Record<string, unknown>;
2064
2974
  }
2065
2975
  export interface PickupLocationSearchInput {
2976
+ /** ISO 3166-1 alpha-2 country code. */
2066
2977
  countryCode: string;
2067
2978
  postalCode: string;
2068
2979
  carrierId: number;
@@ -2071,6 +2982,7 @@ export interface PickupLocationSearchInput {
2071
2982
  number?: string;
2072
2983
  latitude?: number;
2073
2984
  longitude?: number;
2985
+ /** Search radius in metres. */
2074
2986
  distance?: number;
2075
2987
  }
2076
2988
  export interface ShipmentTrackingHistoryEntry {
@@ -2092,17 +3004,24 @@ export interface CommerceModule {
2092
3004
  getProductById(id: string, options?: RequestOptions): Promise<Product>;
2093
3005
  getProducts(listOptions?: ProductListOptions, options?: RequestOptions): Promise<PaginatedList<ProductSummary>>;
2094
3006
  getProductsInCollection(collectionSlug: string, listOptions?: CollectionProductListOptions, options?: RequestOptions): Promise<PaginatedList<CollectionProductSummary>>;
3007
+ /**
3008
+ * `getProductsInCollection` by collection id — typically `route.id` from the
3009
+ * routes manifest. Tagged `collection:<id>`, which the slug variant cannot be,
3010
+ * so `collection.membership_changed` purges the listing.
3011
+ */
2095
3012
  getProductsInCollectionById(collectionId: string, listOptions?: CollectionProductListOptions, options?: RequestOptions): Promise<PaginatedList<CollectionProductSummary>>;
2096
3013
  getFacets(options?: RequestOptions): Promise<Facet[]>;
2097
3014
  searchProducts(input: SearchInput, options?: RequestOptions): Promise<SearchResult>;
2098
3015
  getActiveOrder(): Promise<Order | null>;
2099
3016
  addToCart(variantId: string, quantity: number): Promise<Order>;
3017
+ /** Add several variants in one call (e.g. favourite-box bundles). */
2100
3018
  addItemsToCart(items: Array<{
2101
3019
  productVariantId: string;
2102
3020
  quantity: number;
2103
3021
  }>): Promise<Order>;
2104
3022
  updateCartLine(lineId: string, quantity: number): Promise<Order>;
2105
3023
  removeFromCart(lineId: string): Promise<Order>;
3024
+ /** Remove every line from the active order, leaving an empty cart. */
2106
3025
  clearCart(): Promise<Order>;
2107
3026
  applyCouponCode(code: string): Promise<Order>;
2108
3027
  removeCouponCode(code: string): Promise<Order>;
@@ -2110,18 +3029,42 @@ export interface CommerceModule {
2110
3029
  setShippingAddress(input: AddressInput): Promise<Order>;
2111
3030
  setBillingAddress(input: AddressInput): Promise<Order>;
2112
3031
  getEligibleShippingMethods(): Promise<ShippingMethod[]>;
3032
+ /** Exact-aware delivery defaults for the signed-in customer, or null when unavailable. */
2113
3033
  getDeliveryTerms(options?: RequestOptions): Promise<CustomerDeliveryTerms | null>;
2114
3034
  setShippingMethod(ids: string[]): Promise<Order>;
3035
+ /** Apply the signed-in customer's currently eligible Exact default shipping method. */
2115
3036
  applyPreferredShippingMethod(): Promise<Order>;
2116
3037
  getEligiblePaymentMethods(): Promise<PaymentMethod[]>;
3038
+ /** Order minimums on the active channel — display/pre-validation; server enforces. */
2117
3039
  getOrderConstraints(): Promise<ActiveChannelOrderConstraints>;
3040
+ /**
3041
+ * Record how the buyer intends to settle this order and return the
3042
+ * **re-priced** order — a pay-now discount promotion only applies once the
3043
+ * engine knows the intent, and a payment method is not chosen until
3044
+ * {@link CommerceModule.addPayment}, long after the totals the buyer is
3045
+ * looking at were computed. Call it whenever the buyer picks or changes a
3046
+ * payment method, before {@link CommerceModule.transitionToArrangingPayment}.
3047
+ */
2118
3048
  setPaymentIntent(intent: OrderPaymentIntent): Promise<Order>;
2119
3049
  transitionToArrangingPayment(): Promise<Order>;
2120
3050
  addPayment(input: PaymentInput): Promise<Order>;
2121
3051
  createStripePaymentIntent(options?: RequestOptions): Promise<StripePaymentIntentResult>;
2122
3052
  getMolliePaymentMethods(input: MolliePaymentMethodsInput, options?: RequestOptions): Promise<MolliePaymentMethod[]>;
3053
+ /**
3054
+ * Mollie payment methods for the given PaymentMethod, ordered per the
3055
+ * channel's saved configuration and with hidden methods removed. Use this
3056
+ * (rather than `getMolliePaymentMethods`) when the storefront should respect
3057
+ * the merchant's curated order + visibility. Returns `[]` when no Mollie API
3058
+ * key is configured for the channel or Mollie is unreachable.
3059
+ */
2123
3060
  getOrderedMolliePaymentMethods(paymentMethodCode: string, options?: RequestOptions): Promise<OrderedMollieMethod[]>;
2124
3061
  createMolliePaymentIntent(input: CreateMolliePaymentIntentInput, options?: RequestOptions): Promise<MolliePaymentIntentResult>;
3062
+ /**
3063
+ * Force-fetch the Mollie payment status and reconcile the order state.
3064
+ * Use as a fallback when the Mollie webhook is delayed or did not arrive
3065
+ * (e.g. local/staging without a public tunnel). Returns `null` when no
3066
+ * order matches `orderCode`.
3067
+ */
2125
3068
  syncMolliePaymentStatus(orderCode: string, options?: RequestOptions): Promise<MollieOrderStatusResult | null>;
2126
3069
  login(email: string, password: string): Promise<LoginResult>;
2127
3070
  register(input: RegisterInput): Promise<{
@@ -2129,11 +3072,25 @@ export interface CommerceModule {
2129
3072
  }>;
2130
3073
  logout(): Promise<void>;
2131
3074
  getCurrentCustomer(): Promise<Customer | null>;
3075
+ /**
3076
+ * Price lists currently applying to the signed-in customer (identity only,
3077
+ * sorted by resolution priority). Empty for anonymous visitors with no
3078
+ * channel-wide lists.
3079
+ */
2132
3080
  getActiveCustomerPriceLists(options?: RequestOptions): Promise<CustomerPriceList[]>;
2133
3081
  getCustomerOrders(options?: OrderListOptions): Promise<PaginatedList<OrderSummary>>;
3082
+ /**
3083
+ * Add every line of a previous order to the active cart. Returns the new
3084
+ * active order plus a list of lines that could not be added (e.g. variant
3085
+ * removed, out of stock).
3086
+ */
2134
3087
  reorder(orderCode: string): Promise<ReorderResult>;
2135
3088
  getCollections(listOptions?: CollectionListOptions, options?: RequestOptions): Promise<Collection[]>;
2136
3089
  getCollection(slug: string, options?: RequestOptions): Promise<CollectionDetail>;
3090
+ /**
3091
+ * A collection by id — typically `route.id` from the routes manifest. Tagged
3092
+ * `collection:<id>`; throws a `NOT_FOUND` StorefrontError (404) when absent.
3093
+ */
2137
3094
  getCollectionById(id: string, options?: RequestOptions): Promise<CollectionDetail>;
2138
3095
  updateCustomer(input: UpdateCustomerInput): Promise<Customer>;
2139
3096
  updatePassword(currentPassword: string, newPassword: string): Promise<void>;
@@ -2163,11 +3120,18 @@ export interface CommerceModule {
2163
3120
  deleteAddress(id: string): Promise<void>;
2164
3121
  getAvailableCountries(): Promise<Country[]>;
2165
3122
  getOrderByCode(code: string): Promise<Order>;
3123
+ /** Invoices for one of the signed-in customer's own orders. */
2166
3124
  getMyOrderInvoices(orderCode: string): Promise<CustomerInvoice[]>;
3125
+ /** Download one of the signed-in customer's own invoices as a base64 PDF. */
2167
3126
  getMyInvoicePdf(invoiceId: string): Promise<CustomerInvoicePdf>;
2168
3127
  getActiveChannel(): Promise<ActiveChannel>;
2169
3128
  getPropertyGroups(options?: RequestOptions): Promise<PropertyGroup[]>;
2170
3129
  getProductProperties(productId: string, options?: RequestOptions): Promise<ProductPropertyGroupValues[]>;
3130
+ /**
3131
+ * Flatten `getProductProperties(...)` output into a `slug → value` record for
3132
+ * the product-detail view. Pure helper — see `ProductPropertyRecord` for the
3133
+ * `content_item` (producer) caveat.
3134
+ */
2171
3135
  mapProductProperties(groups: ProductPropertyGroupValues[]): ProductPropertyRecord;
2172
3136
  getMySavedLists(): Promise<SavedList[]>;
2173
3137
  getMySavedList(id: string): Promise<SavedList | null>;
@@ -2222,30 +3186,91 @@ export interface CommerceModule {
2222
3186
  replaceMySubscriptionMandate(id: string, input: SubscriptionPaymentActionInput & {
2223
3187
  provider: 'mollie' | 'stripe';
2224
3188
  }): Promise<SubscriptionPurchaseResult>;
3189
+ /**
3190
+ * A hosted link that pays the outstanding failed or charged-back cycle again,
3191
+ * without another delivery. Reuse `upcomingPayment.checkoutUrl` while it is live.
3192
+ */
2225
3193
  recoverMySubscriptionPayment(id: string, input: SubscriptionPaymentActionInput): Promise<SubscriptionPurchaseResult>;
2226
3194
  getMySubscriptions(): Promise<CustomerSubscription[]>;
3195
+ /**
3196
+ * Plans available to subscribe to in the current channel. Public —
3197
+ * works for anonymous visitors. Only enabled plans are returned.
3198
+ */
2227
3199
  getSubscriptionPlans(): Promise<SubscriptionPlanPublic[]>;
3200
+ /**
3201
+ * The active customer's valid or still-pending payment mandates. Poll this
3202
+ * after `setupPaymentMandate` until the mandate flips to `valid`.
3203
+ */
2228
3204
  getMyPaymentMandates(): Promise<MyPaymentMandate[]>;
3205
+ /**
3206
+ * Begin establishing a payment mandate. Returns a `checkoutUrl` (Mollie) or
3207
+ * `clientSecret` (Stripe) for the frontend to complete the setup.
3208
+ */
2229
3209
  setupPaymentMandate(input: {
2230
3210
  provider: string;
2231
3211
  redirectUrl: string;
2232
3212
  }): Promise<SetupPaymentMandateResult>;
3213
+ /**
3214
+ * Create a subscription for the active customer against an enabled plan
3215
+ * using one of their valid mandates.
3216
+ */
2233
3217
  createSubscription(planId: string, mandateId: string, requestKey?: string): Promise<CustomerSubscription>;
3218
+ /** Pause an active or trial subscription owned by the active customer. */
2234
3219
  pauseMySubscription(id: string, reason?: string): Promise<CustomerSubscription>;
3220
+ /** Resume a paused subscription owned by the active customer. */
2235
3221
  resumeMySubscription(id: string): Promise<CustomerSubscription>;
3222
+ /**
3223
+ * Cancel a subscription owned by the active customer. Defaults to
3224
+ * the earliest eligible cancellation date; minimum paid-cycle commitments still apply.
3225
+ */
2236
3226
  cancelMySubscription(id: string, options?: {
2237
3227
  reason?: string;
2238
3228
  immediate?: boolean;
2239
3229
  }): Promise<CustomerSubscription>;
3230
+ /** Returns the active customer's quotes in the current channel. */
2240
3231
  getMyQuotes(options?: QuoteListOptions): Promise<QuoteList>;
3232
+ /** Returns one of the active customer's quotes by id. */
2241
3233
  getMyQuote(id: string): Promise<Quote | null>;
3234
+ /**
3235
+ * Submits a new quote request. Lines are unpriced — a sales rep
3236
+ * prices them later. Requires the customer to belong to a configured
3237
+ * B2B customer group.
3238
+ */
2242
3239
  createQuoteRequest(input: CreateQuoteRequestInput): Promise<Quote>;
3240
+ /**
3241
+ * Accepts a priced+approved quote, producing a real `Order` in
3242
+ * `ArrangingPayment` with the quoted unit prices applied.
3243
+ */
2243
3244
  acceptQuote(id: string): Promise<Order>;
3245
+ /** Cancels a quote owned by the active customer. */
2244
3246
  cancelMyQuote(id: string, reason?: string): Promise<Quote>;
3247
+ /**
3248
+ * Returns the active customer's returns (RMAs) in the current channel,
3249
+ * newest first. Requires an authenticated customer session.
3250
+ */
2245
3251
  getMyReturns(options?: CustomerReturnListOptions): Promise<CustomerReturnList>;
3252
+ /**
3253
+ * Returns one of the active customer's returns by id, or `null` when it
3254
+ * does not exist or belongs to another customer.
3255
+ */
2246
3256
  getMyReturn(id: string): Promise<CustomerReturn | null>;
3257
+ /**
3258
+ * Requests a return (RMA) for fulfilled lines of one of the active
3259
+ * customer's orders. Only allowed when the channel has returns enabled and
3260
+ * the order is inside the return window; quantities are capped at each
3261
+ * line's returnable quantity (see `getReturnableLinesForOrder`).
3262
+ */
2247
3263
  requestReturn(input: RequestReturnInput): Promise<CustomerReturn>;
3264
+ /**
3265
+ * Cancels a return owned by the active customer. Only possible while the
3266
+ * return is still in the `requested` state.
3267
+ */
2248
3268
  cancelMyReturn(id: string): Promise<CustomerReturn>;
3269
+ /**
3270
+ * Per-line returnable quantities and the return window for one of the
3271
+ * active customer's orders — drives the return-request UI. Lines only
3272
+ * appear once they have shipped/delivered quantity.
3273
+ */
2249
3274
  getReturnableLinesForOrder(orderId: string): Promise<CustomerReturnEligibility>;
2250
3275
  getMyVatValidationStatus(): Promise<VatValidationResult | null>;
2251
3276
  setMyVatNumber(vatNumber: string): Promise<VatValidationResult>;
@@ -2253,22 +3278,52 @@ export interface CommerceModule {
2253
3278
  getDropOffPoints(input: DropOffPointInput): Promise<DropOffPoint[]>;
2254
3279
  getDeliveryOptions(input: DeliveryOptionsInput): Promise<DeliveryOption[]>;
2255
3280
  trackShipment(barcode: string, postalCode: string): Promise<ShipmentTrackingInfo | null>;
3281
+ /**
3282
+ * Carrier-agnostic pickup-location search. Currently MyParcel-backed;
3283
+ * future providers (Sendcloud, Hendriks) implement the same shape.
3284
+ */
2256
3285
  findPickupLocations(input: PickupLocationSearchInput): Promise<PickupLocation[]>;
3286
+ /** Persist the customer's chosen pickup location on the active order. */
2257
3287
  selectPickupLocation(location: PickupLocation): Promise<Order>;
3288
+ /** Read the pickup location stored on the active order, or `null`. */
2258
3289
  getActivePickupLocation(): Promise<PickupLocation | null>;
3290
+ /**
3291
+ * Returns the channel's public branding info: identity (logos, name),
3292
+ * theme (primary color), fonts (Google + self-hosted), contact, legal,
3293
+ * social links, and storefront routing config. Asset URLs are resolved
3294
+ * against the channel's CDN domain (or global cdnUrl fallback).
3295
+ *
3296
+ * Used by the `@sixtyninecommerce/create-storefront` CLI for fail-fast scaffolding
3297
+ * validation and at storefront runtime for footer/header/SEO rendering.
3298
+ */
2259
3299
  getBranding(options?: RequestOptions): Promise<BrandingInfo>;
2260
3300
  }
2261
3301
  export interface ContentModule {
2262
3302
  resolvePath(path: string, locale?: string, options?: RequestOptions): Promise<ResolvedContent>;
2263
3303
  getContent(queryOptions: ContentQueryOptions, options?: RequestOptions): Promise<Record<string, unknown>>;
3304
+ /**
3305
+ * Typed channel-wide CMS content search. Pass `collectionId`/`collectionSlug`
3306
+ * to scope, or omit both to search across every collection.
3307
+ */
2264
3308
  searchContent(query: ContentSearchQuery, options?: RequestOptions): Promise<ContentSearchResult>;
2265
3309
  getAsset(id: string, options?: RequestOptions): Promise<CmsAsset>;
2266
3310
  lookupAssets(ids: string[], options?: RequestOptions): Promise<CmsAsset[]>;
2267
3311
  lookupVendureAssetDescriptions(vendureAssetIds: string[], options?: RequestOptions): Promise<Record<string, VendureAssetDescriptionTranslation[]>>;
3312
+ /** Discover the channel's forms (public projection). See {@link FormSummary}. */
2268
3313
  listForms(options?: FormListOptions & RequestOptions): Promise<FormListResult>;
2269
3314
  getForm(id: string, options?: RequestOptions): Promise<FormDefinition>;
2270
3315
  getFormBySlug(slug: string, options?: RequestOptions): Promise<FormDefinition>;
3316
+ /**
3317
+ * The field-type registry (GET /forms/field-types) — every legal field type
3318
+ * and its config/validation schema. Prefer the static {@link FORM_FIELD_TYPES}
3319
+ * constant when a round-trip isn't warranted.
3320
+ */
2271
3321
  getFormFieldTypes(options?: RequestOptions): Promise<FormFieldTypeDescriptor[]>;
3322
+ /**
3323
+ * The same request as {@link ContentModule.getFormFieldTypes}, but keeping the
3324
+ * slug rules the response carries alongside the field types — use it when
3325
+ * authoring forms, so the hyphen/underscore split is known before the write.
3326
+ */
2272
3327
  getFormFieldTypeRegistry(options?: RequestOptions): Promise<FormFieldTypeRegistry>;
2273
3328
  submitForm(id: string, values: Record<string, unknown>, options?: RequestOptions): Promise<FormSubmissionResult>;
2274
3329
  getContentStrings(format?: 'list' | 'export', options?: RequestOptions): Promise<ContentStrings>;
@@ -2289,48 +3344,149 @@ export interface NavigationModule {
2289
3344
  getRoutesByType(type: 'cms' | 'collection' | 'product', languageCode?: string, options?: RequestOptions): Promise<RouteEntry[]>;
2290
3345
  }
2291
3346
  export interface PricingModule {
3347
+ /**
3348
+ * The channel's tax-display STORAGE mode (mirrors
3349
+ * {@link ChannelInfo.pricesIncludeTax}) — which of `price`/`priceWithTax` the
3350
+ * merchant typed in. It is NOT the display decision: use
3351
+ * {@link PricingModule.getTaxDisplayMode} for that. This stays the last-resort
3352
+ * fallback when the mode cannot be resolved.
3353
+ */
2292
3354
  readonly pricesIncludeTax: boolean;
2293
3355
  formatPrice(amount: number, currencyCode?: string, locale?: string): string;
2294
3356
  formatPriceRange(min: number, max: number, currencyCode?: string, locale?: string): string;
2295
3357
  getTierForQuantity(tiers: PriceTier[], quantity: number): PriceTier | null;
2296
3358
  computeTierTable(variant: VariantPriceData): TierTableEntry[];
2297
3359
  getPriceDisplay(variant: VariantPriceData): PriceDisplay;
3360
+ /**
3361
+ * Pick the net-or-gross figure to display for a variant. Never recomputes
3362
+ * tax — selects the server-authoritative `price`/`priceWithTax` (and the
3363
+ * matching retail field) for the requested mode.
3364
+ *
3365
+ * Omit `mode` to use {@link PricingModule.currentTaxDisplayMode}, i.e. the
3366
+ * mode `getTaxDisplayMode()` last resolved for this shopper. Pass one only to
3367
+ * override — a side-by-side incl./excl. table, or a toggle the shopper drove.
3368
+ */
2298
3369
  selectDisplayPrice(variant: VariantPriceData, mode?: TaxDisplayMode): DisplayPrice;
3370
+ /**
3371
+ * The mode this shopper should see prices in, resolved by the server from the
3372
+ * channel's policy (country list → B2B/trade → channel default →
3373
+ * `pricesIncludeTax`). Call it once per request/session and let
3374
+ * `selectDisplayPrice(variant)` default to it.
3375
+ *
3376
+ * Never throws and never blocks a render: an unreachable or older engine
3377
+ * falls back to the channel storage mode (`pricesIncludeTax ? 'gross' :
3378
+ * 'net'`), which is exactly the pre-policy behaviour. Only a real answer is
3379
+ * cached, so a transient failure does not pin the mode for the session.
3380
+ *
3381
+ * The result is cached per identity (auth token + order scope) and is
3382
+ * re-resolved automatically after a sign-in/out, a `setOrderScope`, or a
3383
+ * `setShippingAddress` — moving the order's country can flip the mode. Pass
3384
+ * `{ refresh: true }` to force a round-trip.
3385
+ */
2299
3386
  getTaxDisplayMode(options?: {
2300
3387
  refresh?: boolean;
2301
3388
  }): Promise<TaxDisplayMode>;
3389
+ /**
3390
+ * The last mode {@link PricingModule.getTaxDisplayMode} resolved for the
3391
+ * current identity, without a round-trip — the channel storage mode when
3392
+ * nothing has been resolved yet. Synchronous, for render paths.
3393
+ */
2302
3394
  currentTaxDisplayMode(): TaxDisplayMode;
3395
+ /**
3396
+ * Preview the mode for a hypothetical shopper, offline. Mirrors the engine's
3397
+ * precedence rule for a "who sees what" table or an SSR guess before the
3398
+ * first round-trip — `getTaxDisplayMode()` remains the authority, because
3399
+ * only the server knows the shopper's resolved country.
3400
+ */
2303
3401
  resolveTaxDisplayMode(policy: TaxDisplayPolicy, inputs: TaxDisplayInputs): TaxDisplayMode;
3402
+ /**
3403
+ * Read the channel's display policy off `activeChannel.customFields`.
3404
+ * Lenient — an unreadable value degrades to the pre-policy default.
3405
+ */
2304
3406
  parseTaxDisplayPolicy(fields: unknown): TaxDisplayPolicy;
3407
+ /**
3408
+ * Pre-validate the cart against the channel's order minimums. Pass the object
3409
+ * from `getOrderConstraints()` straight through. The server enforces at the
3410
+ * `ArrangingPayment` transition regardless.
3411
+ */
2305
3412
  validateOrderMinimums(order: {
2306
3413
  totalWithTax: number;
2307
3414
  currencyCode: string;
2308
3415
  totalQuantity?: number;
3416
+ /**
3417
+ * Net (tax-exclusive) total, minor units — required for the
3418
+ * `minOrderAmountNet` check. `subTotal` is preferred over `total` because
3419
+ * the server compares line totals, which exclude shipping. Without one of
3420
+ * them the net check is skipped.
3421
+ */
2309
3422
  subTotal?: number;
2310
3423
  total?: number;
2311
3424
  }, constraints: {
2312
3425
  minOrderAmountGross?: number | null;
2313
3426
  minOrderAmountNet?: number | null;
2314
3427
  minOrderQuantity?: number | null;
3428
+ /** @deprecated Use `minOrderAmountGross`. */
2315
3429
  minOrderAmount?: number | null;
2316
3430
  }): OrderValidationResult;
3431
+ /**
3432
+ * The quantity ceiling for a variant: `max(0, saleable) + backorderAllowance`.
3433
+ * `null` when the channel hides stock — no ceiling to show, let the server
3434
+ * decide, exactly as before backorders. Clamp quantity steppers to it.
3435
+ */
3436
+ maxOrderableQuantity(variant: OrderableStockInput): number | null;
3437
+ /**
3438
+ * Whether a variant is orderable only on backorder: nothing saleable, but an
3439
+ * allowance. The signal to label "Backorder" instead of "Out of stock".
3440
+ */
3441
+ isBackorderOnly(variant: OrderableStockInput): boolean;
3442
+ /**
3443
+ * Units of a cart line stock will not cover — the "N on backorder" hint
3444
+ * before placement, as the server will stamp it. `null` when the channel
3445
+ * hides stock or stock covers the line: show nothing.
3446
+ */
3447
+ backorderedQuantityForCart(variant: Pick<OrderableStockInput, 'saleable'>, quantity: number): number | null;
3448
+ }
3449
+ /** The two fields the quantity ceiling reads; satisfied by every SDK variant shape. */
3450
+ export interface OrderableStockInput {
3451
+ saleable?: number | null;
3452
+ backorderAllowance?: number | null;
2317
3453
  }
2318
3454
  export interface MediaModule {
2319
3455
  assetUrl(path: string): string;
3456
+ /**
3457
+ * Absolute full-resolution URL for an asset's original `source`. Use for the
3458
+ * gallery main/lightbox image — `Asset.source` arrives as a CDN-relative
3459
+ * storage key and must never be rendered directly. Returns `''` for an asset
3460
+ * with an empty `source`.
3461
+ */
2320
3462
  getFullUrl(asset: Asset): string;
2321
3463
  getPresetUrl(asset: Asset, preset: PresetName, format?: 'original' | 'webp'): string;
2322
3464
  getResponsiveImageData(asset: Asset, presets?: PresetName[]): ResponsiveImageData;
2323
3465
  }
2324
3466
  export interface CurrencyModule {
2325
3467
  getExchangeRates(): Promise<ExchangeRate[]>;
3468
+ /** Current rate for a single base→target pair, or `null` when unknown. */
2326
3469
  getExchangeRate(targetCurrency: string): Promise<ExchangeRate | null>;
2327
3470
  convertCurrency(amount: string, fromCurrency: string, toCurrency: string): Promise<ConvertedAmount>;
3471
+ /** Convert from the base currency (EUR) to a target currency. */
2328
3472
  convertFromBase(amount: string, targetCurrency: string): Promise<ConvertedAmount>;
3473
+ /** Convert from a source currency to the base currency (EUR). */
2329
3474
  convertToBase(amount: string, sourceCurrency: string): Promise<ConvertedAmount>;
3475
+ /** Convert one amount into several currencies in a single roundtrip. */
2330
3476
  convertToMultiple(amount: string, fromCurrency: string, toCurrencies: string[]): Promise<BulkConversionResult[]>;
2331
3477
  }
2332
3478
  export interface CreditModule {
3479
+ /**
3480
+ * Returns the signed-in customer's B2B credit status in the current
3481
+ * channel, or `null` when not signed in, no credit account exists, or the
3482
+ * channel has B2B credit disabled. Soft-enforcement only — display the
3483
+ * `overLimit` / `hasOverdue` flags as warnings; the SDK never blocks checkout.
3484
+ */
2333
3485
  getCreditStatus(options?: RequestOptions): Promise<B2bCreditStatus | null>;
3486
+ /**
3487
+ * Returns the signed-in customer's source-aware payment terms (including local B2B terms), or
3488
+ * `null` when the customer is not signed in or has no payment-terms account in this channel.
3489
+ */
2334
3490
  getPaymentTerms(options?: RequestOptions): Promise<CustomerPaymentTerms | null>;
2335
3491
  }
2336
3492
  export interface StorefrontClient {
@@ -2343,13 +3499,20 @@ export interface StorefrontClient {
2343
3499
  readonly currency: CurrencyModule;
2344
3500
  readonly credit: CreditModule;
2345
3501
  readonly seo: import('./seo/types.js').SeoModule;
3502
+ /** Platform-managed URL redirects for this channel. */
2346
3503
  readonly redirects: import('./redirects/types.js').RedirectStore;
2347
3504
  readonly maintenanceMode: boolean;
2348
3505
  setLanguage(code: string): void;
2349
3506
  getLanguage(): string;
2350
3507
  setAuthToken(token: string): void;
2351
3508
  clearAuthToken(): void;
3509
+ /**
3510
+ * Change which storefront this client speaks for. Takes effect on the next
3511
+ * request. Pass `null` to stop sending the header entirely (legacy,
3512
+ * unscoped behaviour) — which is not the same as `'CONSUMER'`.
3513
+ */
2352
3514
  setOrderScope(scope: OrderScope | null): void;
3515
+ /** The scope currently sent as `x-order-scope`, or `null` when none is set. */
2353
3516
  getOrderScope(): OrderScope | null;
2354
3517
  graphql<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T>;
2355
3518
  }