@sixtyninecommerce/client 0.29.0 → 0.31.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 (358) hide show
  1. package/README.md +556 -16
  2. package/dist/admin/http.d.ts.map +1 -1
  3. package/dist/admin/http.js.map +1 -1
  4. package/dist/admin/types.d.ts.map +1 -1
  5. package/dist/build-client.d.ts +9 -0
  6. package/dist/build-client.d.ts.map +1 -0
  7. package/dist/build-client.js +58 -0
  8. package/dist/build-client.js.map +1 -0
  9. package/dist/cache-tags.d.ts +35 -1
  10. package/dist/cache-tags.d.ts.map +1 -1
  11. package/dist/cache-tags.js +39 -1
  12. package/dist/cache-tags.js.map +1 -1
  13. package/dist/client.d.ts +25 -0
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/client.js +9 -62
  16. package/dist/client.js.map +1 -1
  17. package/dist/commerce/age-verification.d.ts +7 -4
  18. package/dist/commerce/age-verification.d.ts.map +1 -1
  19. package/dist/commerce/age-verification.js +6 -4
  20. package/dist/commerce/age-verification.js.map +1 -1
  21. package/dist/commerce/arguments.d.ts +13 -0
  22. package/dist/commerce/arguments.d.ts.map +1 -0
  23. package/dist/commerce/arguments.js +19 -0
  24. package/dist/commerce/arguments.js.map +1 -0
  25. package/dist/commerce/branding.d.ts.map +1 -1
  26. package/dist/commerce/branding.js.map +1 -1
  27. package/dist/commerce/capabilities.d.ts +40 -0
  28. package/dist/commerce/capabilities.d.ts.map +1 -0
  29. package/dist/commerce/capabilities.js +41 -0
  30. package/dist/commerce/capabilities.js.map +1 -0
  31. package/dist/commerce/cart.d.ts +9 -12
  32. package/dist/commerce/cart.d.ts.map +1 -1
  33. package/dist/commerce/cart.js +6 -1
  34. package/dist/commerce/cart.js.map +1 -1
  35. package/dist/commerce/checkout.d.ts +95 -15
  36. package/dist/commerce/checkout.d.ts.map +1 -1
  37. package/dist/commerce/checkout.js +230 -10
  38. package/dist/commerce/checkout.js.map +1 -1
  39. package/dist/commerce/customer.d.ts +82 -38
  40. package/dist/commerce/customer.d.ts.map +1 -1
  41. package/dist/commerce/customer.js +146 -10
  42. package/dist/commerce/customer.js.map +1 -1
  43. package/dist/commerce/favorites.d.ts +2 -5
  44. package/dist/commerce/favorites.d.ts.map +1 -1
  45. package/dist/commerce/favorites.js.map +1 -1
  46. package/dist/commerce/index.d.ts +189 -133
  47. package/dist/commerce/index.d.ts.map +1 -1
  48. package/dist/commerce/index.js +9 -0
  49. package/dist/commerce/index.js.map +1 -1
  50. package/dist/commerce/order-states.d.ts +18 -0
  51. package/dist/commerce/order-states.d.ts.map +1 -0
  52. package/dist/commerce/order-states.js +30 -0
  53. package/dist/commerce/order-states.js.map +1 -0
  54. package/dist/commerce/parcel-pricing.d.ts +48 -0
  55. package/dist/commerce/parcel-pricing.d.ts.map +1 -0
  56. package/dist/commerce/parcel-pricing.js +39 -0
  57. package/dist/commerce/parcel-pricing.js.map +1 -0
  58. package/dist/commerce/parked-orders.d.ts +22 -0
  59. package/dist/commerce/parked-orders.d.ts.map +1 -0
  60. package/dist/commerce/parked-orders.js +47 -0
  61. package/dist/commerce/parked-orders.js.map +1 -0
  62. package/dist/commerce/payments.d.ts +12 -5
  63. package/dist/commerce/payments.d.ts.map +1 -1
  64. package/dist/commerce/payments.js +10 -1
  65. package/dist/commerce/payments.js.map +1 -1
  66. package/dist/commerce/placement-error.d.ts +17 -0
  67. package/dist/commerce/placement-error.d.ts.map +1 -1
  68. package/dist/commerce/placement-error.js.map +1 -1
  69. package/dist/commerce/products.d.ts +92 -38
  70. package/dist/commerce/products.d.ts.map +1 -1
  71. package/dist/commerce/products.js +162 -123
  72. package/dist/commerce/products.js.map +1 -1
  73. package/dist/commerce/queries.d.ts +204 -49
  74. package/dist/commerce/queries.d.ts.map +1 -1
  75. package/dist/commerce/queries.js +1296 -737
  76. package/dist/commerce/queries.js.map +1 -1
  77. package/dist/commerce/quotes.d.ts +5 -4
  78. package/dist/commerce/quotes.d.ts.map +1 -1
  79. package/dist/commerce/quotes.js +1 -36
  80. package/dist/commerce/quotes.js.map +1 -1
  81. package/dist/commerce/recommendations.d.ts +3 -3
  82. package/dist/commerce/recommendations.d.ts.map +1 -1
  83. package/dist/commerce/recommendations.js +3 -1
  84. package/dist/commerce/recommendations.js.map +1 -1
  85. package/dist/commerce/returns.d.ts +7 -6
  86. package/dist/commerce/returns.d.ts.map +1 -1
  87. package/dist/commerce/returns.js.map +1 -1
  88. package/dist/commerce/reviews.d.ts +24 -15
  89. package/dist/commerce/reviews.d.ts.map +1 -1
  90. package/dist/commerce/reviews.js +67 -50
  91. package/dist/commerce/reviews.js.map +1 -1
  92. package/dist/commerce/saved-lists.d.ts +15 -15
  93. package/dist/commerce/saved-lists.d.ts.map +1 -1
  94. package/dist/commerce/saved-lists.js +67 -55
  95. package/dist/commerce/saved-lists.js.map +1 -1
  96. package/dist/commerce/search.d.ts +3 -2
  97. package/dist/commerce/search.d.ts.map +1 -1
  98. package/dist/commerce/search.js +10 -2
  99. package/dist/commerce/search.js.map +1 -1
  100. package/dist/commerce/shipping.d.ts +11 -4
  101. package/dist/commerce/shipping.d.ts.map +1 -1
  102. package/dist/commerce/shipping.js +17 -2
  103. package/dist/commerce/shipping.js.map +1 -1
  104. package/dist/commerce/stock-notifications.d.ts +2 -0
  105. package/dist/commerce/stock-notifications.d.ts.map +1 -1
  106. package/dist/commerce/stock-notifications.js +2 -2
  107. package/dist/commerce/stock-notifications.js.map +1 -1
  108. package/dist/commerce/subscriptions.d.ts +35 -37
  109. package/dist/commerce/subscriptions.d.ts.map +1 -1
  110. package/dist/commerce/subscriptions.js +159 -120
  111. package/dist/commerce/subscriptions.js.map +1 -1
  112. package/dist/commerce/vat-validation.d.ts +6 -3
  113. package/dist/commerce/vat-validation.d.ts.map +1 -1
  114. package/dist/commerce/vat-validation.js +24 -19
  115. package/dist/commerce/vat-validation.js.map +1 -1
  116. package/dist/constants.d.ts.map +1 -1
  117. package/dist/constants.js.map +1 -1
  118. package/dist/content/assets.d.ts +5 -4
  119. package/dist/content/assets.d.ts.map +1 -1
  120. package/dist/content/assets.js.map +1 -1
  121. package/dist/content/collection-pages.d.ts +3 -2
  122. package/dist/content/collection-pages.d.ts.map +1 -1
  123. package/dist/content/collection-pages.js.map +1 -1
  124. package/dist/content/collections.d.ts +5 -4
  125. package/dist/content/collections.d.ts.map +1 -1
  126. package/dist/content/collections.js.map +1 -1
  127. package/dist/content/filtered-products.d.ts.map +1 -1
  128. package/dist/content/filtered-products.js.map +1 -1
  129. package/dist/content/form-field-types.d.ts +3 -3
  130. package/dist/content/form-field-types.d.ts.map +1 -1
  131. package/dist/content/form-field-types.js.map +1 -1
  132. package/dist/content/forms.d.ts +4 -3
  133. package/dist/content/forms.d.ts.map +1 -1
  134. package/dist/content/forms.js +3 -0
  135. package/dist/content/forms.js.map +1 -1
  136. package/dist/content/index.d.ts +18 -17
  137. package/dist/content/index.d.ts.map +1 -1
  138. package/dist/content/items.d.ts +5 -4
  139. package/dist/content/items.d.ts.map +1 -1
  140. package/dist/content/items.js +2 -0
  141. package/dist/content/items.js.map +1 -1
  142. package/dist/content/menus.d.ts +3 -2
  143. package/dist/content/menus.d.ts.map +1 -1
  144. package/dist/content/menus.js +7 -1
  145. package/dist/content/menus.js.map +1 -1
  146. package/dist/content/resolve.d.ts +3 -2
  147. package/dist/content/resolve.d.ts.map +1 -1
  148. package/dist/content/resolve.js +1 -1
  149. package/dist/content/resolve.js.map +1 -1
  150. package/dist/content/sitemap.d.ts +3 -2
  151. package/dist/content/sitemap.d.ts.map +1 -1
  152. package/dist/content/sitemap.js.map +1 -1
  153. package/dist/content/strings.d.ts +16 -2
  154. package/dist/content/strings.d.ts.map +1 -1
  155. package/dist/content/strings.js +32 -4
  156. package/dist/content/strings.js.map +1 -1
  157. package/dist/core/context.d.ts +127 -1
  158. package/dist/core/context.d.ts.map +1 -1
  159. package/dist/core/context.js +436 -45
  160. package/dist/core/context.js.map +1 -1
  161. package/dist/core/currency.d.ts +14 -0
  162. package/dist/core/currency.d.ts.map +1 -0
  163. package/dist/core/currency.js +52 -0
  164. package/dist/core/currency.js.map +1 -0
  165. package/dist/core/deprecation.d.ts +23 -0
  166. package/dist/core/deprecation.d.ts.map +1 -0
  167. package/dist/core/deprecation.js +81 -0
  168. package/dist/core/deprecation.js.map +1 -0
  169. package/dist/core/http.d.ts +15 -1
  170. package/dist/core/http.d.ts.map +1 -1
  171. package/dist/core/http.js +55 -3
  172. package/dist/core/http.js.map +1 -1
  173. package/dist/core/public-artifact.d.ts +72 -0
  174. package/dist/core/public-artifact.d.ts.map +1 -0
  175. package/dist/core/public-artifact.js +122 -0
  176. package/dist/core/public-artifact.js.map +1 -0
  177. package/dist/core/unknown-field-rejection.d.ts +18 -0
  178. package/dist/core/unknown-field-rejection.d.ts.map +1 -0
  179. package/dist/core/unknown-field-rejection.js +37 -0
  180. package/dist/core/unknown-field-rejection.js.map +1 -0
  181. package/dist/credit/credit-status.d.ts +2 -0
  182. package/dist/credit/credit-status.d.ts.map +1 -1
  183. package/dist/credit/credit-status.js +71 -19
  184. package/dist/credit/credit-status.js.map +1 -1
  185. package/dist/credit/index.d.ts +1 -1
  186. package/dist/credit/payment-terms.d.ts +3 -3
  187. package/dist/credit/payment-terms.d.ts.map +1 -1
  188. package/dist/credit/payment-terms.js +28 -24
  189. package/dist/credit/payment-terms.js.map +1 -1
  190. package/dist/currency/exchange.d.ts +7 -7
  191. package/dist/currency/exchange.d.ts.map +1 -1
  192. package/dist/currency/exchange.js +5 -1
  193. package/dist/currency/exchange.js.map +1 -1
  194. package/dist/errors.d.ts +17 -0
  195. package/dist/errors.d.ts.map +1 -1
  196. package/dist/errors.js +13 -0
  197. package/dist/errors.js.map +1 -1
  198. package/dist/events/index.d.ts +20 -7
  199. package/dist/events/index.d.ts.map +1 -1
  200. package/dist/events/index.js +17 -5
  201. package/dist/events/index.js.map +1 -1
  202. package/dist/events/payloads.d.ts +7 -4
  203. package/dist/events/payloads.d.ts.map +1 -1
  204. package/dist/events/payloads.js +6 -3
  205. package/dist/events/payloads.js.map +1 -1
  206. package/dist/feeds/index.d.ts +5 -0
  207. package/dist/feeds/index.d.ts.map +1 -0
  208. package/dist/feeds/index.js +12 -0
  209. package/dist/feeds/index.js.map +1 -0
  210. package/dist/feeds/types.d.ts +18 -0
  211. package/dist/feeds/types.d.ts.map +1 -0
  212. package/dist/feeds/types.js +8 -0
  213. package/dist/feeds/types.js.map +1 -0
  214. package/dist/generated/cms.d.ts +2136 -0
  215. package/dist/generated/cms.d.ts.map +1 -0
  216. package/dist/generated/cms.js +4 -0
  217. package/dist/generated/cms.js.map +1 -0
  218. package/dist/generated/plugins.d.ts +550 -0
  219. package/dist/generated/plugins.d.ts.map +1 -0
  220. package/dist/generated/plugins.js +4 -0
  221. package/dist/generated/plugins.js.map +1 -0
  222. package/dist/generated/shop.d.ts +5539 -0
  223. package/dist/generated/shop.d.ts.map +1 -0
  224. package/dist/generated/shop.js +5 -0
  225. package/dist/generated/shop.js.map +1 -0
  226. package/dist/graphql-document.d.ts +29 -0
  227. package/dist/graphql-document.d.ts.map +1 -0
  228. package/dist/graphql-document.js +21 -0
  229. package/dist/graphql-document.js.map +1 -0
  230. package/dist/index.d.ts +9 -4
  231. package/dist/index.d.ts.map +1 -1
  232. package/dist/index.js +4 -2
  233. package/dist/index.js.map +1 -1
  234. package/dist/media/urls.d.ts.map +1 -1
  235. package/dist/media/urls.js +12 -1
  236. package/dist/media/urls.js.map +1 -1
  237. package/dist/media/video.d.ts.map +1 -1
  238. package/dist/media/video.js.map +1 -1
  239. package/dist/multi-store.d.ts +200 -0
  240. package/dist/multi-store.d.ts.map +1 -0
  241. package/dist/multi-store.js +558 -0
  242. package/dist/multi-store.js.map +1 -0
  243. package/dist/navigation/routes.d.ts +4 -3
  244. package/dist/navigation/routes.d.ts.map +1 -1
  245. package/dist/navigation/routes.js.map +1 -1
  246. package/dist/next/artifact-handler.d.ts +21 -13
  247. package/dist/next/artifact-handler.d.ts.map +1 -1
  248. package/dist/next/artifact-handler.js +28 -66
  249. package/dist/next/artifact-handler.js.map +1 -1
  250. package/dist/next/event-revalidate-handler.d.ts +26 -6
  251. package/dist/next/event-revalidate-handler.d.ts.map +1 -1
  252. package/dist/next/event-revalidate-handler.js +126 -19
  253. package/dist/next/event-revalidate-handler.js.map +1 -1
  254. package/dist/next/feed-handler.d.ts +50 -0
  255. package/dist/next/feed-handler.d.ts.map +1 -0
  256. package/dist/next/feed-handler.js +61 -0
  257. package/dist/next/feed-handler.js.map +1 -0
  258. package/dist/next/index.d.ts +3 -1
  259. package/dist/next/index.d.ts.map +1 -1
  260. package/dist/next/index.js +1 -0
  261. package/dist/next/index.js.map +1 -1
  262. package/dist/next/metadata.d.ts.map +1 -1
  263. package/dist/next/metadata.js.map +1 -1
  264. package/dist/next/redirect-middleware.d.ts +5 -31
  265. package/dist/next/redirect-middleware.d.ts.map +1 -1
  266. package/dist/next/redirect-middleware.js +4 -46
  267. package/dist/next/redirect-middleware.js.map +1 -1
  268. package/dist/next/revalidate-handler.d.ts.map +1 -1
  269. package/dist/next/revalidate-handler.js.map +1 -1
  270. package/dist/pricing/index.d.ts +1 -1
  271. package/dist/pricing/index.d.ts.map +1 -1
  272. package/dist/pricing/index.js +5 -2
  273. package/dist/pricing/index.js.map +1 -1
  274. package/dist/pricing/tax-display.js +1 -1
  275. package/dist/pricing/tax-display.js.map +1 -1
  276. package/dist/pricing/tiers.d.ts +3 -2
  277. package/dist/pricing/tiers.d.ts.map +1 -1
  278. package/dist/pricing/tiers.js.map +1 -1
  279. package/dist/pricing/validation.d.ts +152 -13
  280. package/dist/pricing/validation.d.ts.map +1 -1
  281. package/dist/pricing/validation.js +167 -13
  282. package/dist/pricing/validation.js.map +1 -1
  283. package/dist/redirects/index.d.ts.map +1 -1
  284. package/dist/redirects/index.js +2 -1
  285. package/dist/redirects/index.js.map +1 -1
  286. package/dist/redirects/store.d.ts.map +1 -1
  287. package/dist/redirects/store.js +6 -2
  288. package/dist/redirects/store.js.map +1 -1
  289. package/dist/redirects/types.d.ts +5 -2
  290. package/dist/redirects/types.d.ts.map +1 -1
  291. package/dist/revalidation/event-plan.d.ts +55 -4
  292. package/dist/revalidation/event-plan.d.ts.map +1 -1
  293. package/dist/revalidation/event-plan.js +115 -8
  294. package/dist/revalidation/event-plan.js.map +1 -1
  295. package/dist/revalidation/event-verify.d.ts +8 -37
  296. package/dist/revalidation/event-verify.d.ts.map +1 -1
  297. package/dist/revalidation/event-verify.js +7 -97
  298. package/dist/revalidation/event-verify.js.map +1 -1
  299. package/dist/revalidation/types.d.ts.map +1 -1
  300. package/dist/revalidation/url-context.d.ts +17 -0
  301. package/dist/revalidation/url-context.d.ts.map +1 -1
  302. package/dist/revalidation/url-context.js +35 -2
  303. package/dist/revalidation/url-context.js.map +1 -1
  304. package/dist/seo/ai.d.ts.map +1 -1
  305. package/dist/seo/ai.js.map +1 -1
  306. package/dist/seo/artifacts.d.ts +86 -4
  307. package/dist/seo/artifacts.d.ts.map +1 -1
  308. package/dist/seo/artifacts.js +115 -16
  309. package/dist/seo/artifacts.js.map +1 -1
  310. package/dist/seo/availability.d.ts +95 -0
  311. package/dist/seo/availability.d.ts.map +1 -0
  312. package/dist/seo/availability.js +89 -0
  313. package/dist/seo/availability.js.map +1 -0
  314. package/dist/seo/index.d.ts +4 -0
  315. package/dist/seo/index.d.ts.map +1 -1
  316. package/dist/seo/index.js +6 -1
  317. package/dist/seo/index.js.map +1 -1
  318. package/dist/seo/json-ld.d.ts.map +1 -1
  319. package/dist/seo/json-ld.js +34 -1
  320. package/dist/seo/json-ld.js.map +1 -1
  321. package/dist/seo/meta-tags.d.ts +40 -1
  322. package/dist/seo/meta-tags.d.ts.map +1 -1
  323. package/dist/seo/meta-tags.js +8 -1
  324. package/dist/seo/meta-tags.js.map +1 -1
  325. package/dist/seo/metadata-parser.d.ts.map +1 -1
  326. package/dist/seo/metadata-parser.js.map +1 -1
  327. package/dist/seo/metadata-types.d.ts.map +1 -1
  328. package/dist/seo/robots.d.ts.map +1 -1
  329. package/dist/seo/robots.js.map +1 -1
  330. package/dist/seo/types.d.ts +20 -2
  331. package/dist/seo/types.d.ts.map +1 -1
  332. package/dist/seo/url-builder.d.ts +5 -3
  333. package/dist/seo/url-builder.d.ts.map +1 -1
  334. package/dist/seo/url-builder.js +3 -1
  335. package/dist/seo/url-builder.js.map +1 -1
  336. package/dist/types.d.ts +1306 -2429
  337. package/dist/types.d.ts.map +1 -1
  338. package/dist/web/artifact-responder.d.ts +69 -0
  339. package/dist/web/artifact-responder.d.ts.map +1 -0
  340. package/dist/web/artifact-responder.js +90 -0
  341. package/dist/web/artifact-responder.js.map +1 -0
  342. package/dist/web/feed-responder.d.ts +72 -0
  343. package/dist/web/feed-responder.d.ts.map +1 -0
  344. package/dist/web/feed-responder.js +81 -0
  345. package/dist/web/feed-responder.js.map +1 -0
  346. package/dist/web/index.d.ts +23 -0
  347. package/dist/web/index.d.ts.map +1 -0
  348. package/dist/web/index.js +19 -0
  349. package/dist/web/index.js.map +1 -0
  350. package/dist/web/redirect-middleware.d.ts +76 -0
  351. package/dist/web/redirect-middleware.d.ts.map +1 -0
  352. package/dist/web/redirect-middleware.js +94 -0
  353. package/dist/web/redirect-middleware.js.map +1 -0
  354. package/dist/web/respond.d.ts +20 -0
  355. package/dist/web/respond.d.ts.map +1 -0
  356. package/dist/web/respond.js +52 -0
  357. package/dist/web/respond.js.map +1 -0
  358. package/package.json +19 -3
package/dist/types.d.ts CHANGED
@@ -1,4 +1,8 @@
1
- import type { ChannelResolver } from '@sixtyninecommerce/core';
1
+ import type { ChannelResolver, ConditionalReadsOption, DeprecationNotice } from '@sixtyninecommerce/core';
2
+ import type * as Cms from './generated/cms.js';
3
+ import type * as Plugins from './generated/plugins.js';
4
+ import type * as Shop from './generated/shop.js';
5
+ import type { ProductMetadata } from './seo/metadata-types.js';
2
6
  /** Retry configuration for transient GET failures. */
3
7
  export interface RetryConfig {
4
8
  /** Maximum number of attempts including the first request. Default: 2. */
@@ -20,6 +24,12 @@ export interface RequestOptions {
20
24
  * requests only; see {@link StorefrontClientConfig.cacheTags}.
21
25
  */
22
26
  cacheTags?: readonly string[];
27
+ /**
28
+ * The shopper THIS call is for, overriding
29
+ * {@link StorefrontClientConfig.buyerIp}. Only sent by a client built with a
30
+ * `privateToken`; ignored otherwise.
31
+ */
32
+ buyerIp?: string;
23
33
  }
24
34
  /**
25
35
  * Decides the cache tags a commerce request carries. Receives the SDK's
@@ -37,8 +47,41 @@ export type CacheTagResolver = (tags: readonly string[], request: {
37
47
  * customer, because Vendure's fallback lookup is "the one active order for this
38
48
  * customer in this channel" — separate cookies do not change that. Setting a
39
49
  * scope keeps the two carts apart.
50
+ *
51
+ * The Shop API's own `OrderScope` enum: the values the engine stores on an
52
+ * order and reads from the `x-order-scope` header.
53
+ */
54
+ export type OrderScope = Shop.OrderScope;
55
+ /**
56
+ * A head KEY (Dashboard → Settings → Heads), sent as `x-head`. The platform
57
+ * composes every link it emails for the request — sign-in, magic link,
58
+ * invite, password reset — on that head's origin, so a trade portal's
59
+ * shoppers land back on the trade portal.
60
+ *
61
+ * Any key the store registered, in the server's own form (lowercase letters,
62
+ * digits and single hyphens, at most 64 characters); the three suggested are
63
+ * the conventional keys. The platform honours a key only when it names a head
64
+ * of kind `web`, `trade` or `native`, and ignores any other — including a key
65
+ * that names no head — by falling back to the store's default head.
66
+ */
67
+ export type HeadKey = 'web' | 'trade' | 'native' | (string & {});
68
+ /**
69
+ * Which storefront a magic-link email lands on: `'CONSUMER'` links to
70
+ * `/sign-in/magic`, `'B2B'` to `/b2b/login/magic`. Pass the entry point the
71
+ * shopper started from. It is not an authorization signal — B2B portal access
72
+ * is still checked when the link or code is consumed. The Shop API's own
73
+ * `MagicLinkPortal` enum.
40
74
  */
41
- export type OrderScope = 'CONSUMER' | 'TRADE';
75
+ export type MagicLinkPortal = Shop.MagicLinkPortal;
76
+ /** Options for {@link CommerceModule.requestMagicLink}. */
77
+ export interface RequestMagicLinkOptions {
78
+ /**
79
+ * The storefront the emailed link should open. Omitted, the engine derives
80
+ * it from the account (a B2B customer gets the B2B path), which is what
81
+ * every release before this option did.
82
+ */
83
+ portal?: MagicLinkPortal;
84
+ }
42
85
  /** Configuration for creating a storefront client. */
43
86
  export interface StorefrontClientConfig {
44
87
  storeCode: string;
@@ -47,7 +90,36 @@ export interface StorefrontClientConfig {
47
90
  cmsUrl?: string;
48
91
  pluginsUrl?: string;
49
92
  defaultLanguageCode?: string;
93
+ /**
94
+ * The currency the shopper chose, restored — e.g. from a cookie on a
95
+ * server-rendered request. Every Shop API request then names it
96
+ * (`?currencyCode=`), so catalogue prices, the cart and checkout are all in
97
+ * it, and `pricing.format*` default to it. Unset: the channel's default
98
+ * currency, and nothing is sent.
99
+ *
100
+ * A shopper chooses with `commerce.setOrderCurrency(code)`, which switches the
101
+ * client the same way; persist that code and pass it here on the next request.
102
+ *
103
+ * Three upper-case letters, or construction throws 400 `INVALID_ARGUMENT`. A
104
+ * currency the store does not offer (anymore) cannot be checked here — the
105
+ * client does not hold the channel's currency list — so the first Shop API
106
+ * request refuses it with `CURRENCY_NOT_AVAILABLE`, and the client goes back
107
+ * to the channel's default currency: drop the stored code. The engine-side
108
+ * limits of a non-default currency are listed on `commerce.setOrderCurrency`.
109
+ */
110
+ currencyCode?: string;
50
111
  fetch?: typeof globalThis.fetch;
112
+ /**
113
+ * Start the client SIGNED IN as a customer: the bearer is sent on every Vendure
114
+ * Shop API call, exactly as a token from `login` or `setAuthToken` would be.
115
+ * Never sent to the CMS or the plugins service.
116
+ *
117
+ * This is how a trusted-agent session is used: `admin.customers.actAs(customerId,
118
+ * { reason })` on `@sixtyninecommerce/admin` answers `{ token }`, and a server-side
119
+ * client built with `customerToken: token` acts inside that customer's cart and
120
+ * checkout for 15 minutes. Anything else is refused with `AGENT_SESSION_SCOPE`.
121
+ */
122
+ customerToken?: string;
51
123
  /** Called when an auth token is received from Vendure (e.g. after login). Use to persist the token. */
52
124
  onAuthToken?: (token: string) => void;
53
125
  /**
@@ -68,6 +140,38 @@ export interface StorefrontClientConfig {
68
140
  * fired on session expiry (that is `onAuthExpired`).
69
141
  */
70
142
  onAuthCleared?: () => void;
143
+ /**
144
+ * Called when the store this client serves turns out to have been renamed: the platform
145
+ * answered `storeCode` (or the code this client had switched to) under the store's NEW code.
146
+ * The client switches to the new code by itself — requests, feed and sitemap URLs, asset
147
+ * paths and cache tags all follow — but the old code stops answering at `previousCodeUntil`,
148
+ * so a process started after that on the old configuration finds no store. Update the
149
+ * configuration within that time.
150
+ *
151
+ * Unset: one `console.warn` per process naming the new code to configure. Called at most once
152
+ * per client for each rename; an error it throws (or a promise it returns that rejects) is
153
+ * logged, never thrown into a request. If the new code stops answering while the old one
154
+ * answers again as the same store (the rename was undone), the client switches back and this
155
+ * is called again with the codes the other way round.
156
+ *
157
+ * On a store router (`resolveStore`): called once per router for each rename. A router does
158
+ * NOT switch — it keeps resolving the code `resolveStore` names, and serves the store under it
159
+ * only until `previousCodeUntil`; update `resolveStore` (and any `stores` / `privateToken`
160
+ * entries) before then.
161
+ */
162
+ onStoreRenamed?: (rename: StoreRename) => void | Promise<void>;
163
+ /**
164
+ * Where this client's deprecation notices go: a deprecated method of this SDK
165
+ * (`kind: 'method'` — `client.graphql()`), or a platform route that answered with a
166
+ * `Deprecation` header (`kind: 'endpoint'`). Route them to your logger, or pass
167
+ * `() => {}` to silence them.
168
+ *
169
+ * Unset: printed with `console.warn` — a deprecated method ONCE PER PROCESS however many
170
+ * clients use it, a deprecated route once per client. Set: called once per client for each
171
+ * (once per router on `resolveStore`); an error it throws, or a promise it returns that
172
+ * rejects, is logged and never thrown into the call it observed.
173
+ */
174
+ onDeprecation?: (notice: StorefrontDeprecationNotice) => void;
71
175
  /**
72
176
  * Retry config for transient GET failures (network errors and 502/503/504).
73
177
  * Defaults to `{ attempts: 2, baseDelayMs: 200 }`. Set `attempts: 1` to
@@ -92,117 +196,97 @@ export interface StorefrontClientConfig {
92
196
  */
93
197
  orderScope?: OrderScope;
94
198
  /**
95
- * Cache tags on product and collection reads, for Next.js `revalidateTag` —
96
- * the tags `createEventRevalidateHandler` purges. The SDK adds
97
- * `next: { tags }` to the fetch init (Next reads it; other fetch
98
- * implementations ignore unknown init keys) and sets no cache policy:
99
- * whether a request is cached stays your app's decision.
199
+ * Which of the store's heads this client speaks for, sent as `x-head` on every
200
+ * request — see {@link HeadKey}. Unset: the store's default head, which is
201
+ * exactly what every release before this option did.
202
+ *
203
+ * It moves where emailed links point, NOT canonical URLs: `seo.canonicalFor`
204
+ * and the hreflang alternates are always built on the store's main shop
205
+ * address (`storefrontUrl`), whatever head the request names.
206
+ */
207
+ head?: HeadKey;
208
+ /**
209
+ * Cache tags on catalogue and menu reads, for Next.js `revalidateTag` — the
210
+ * tags `createEventRevalidateHandler` purges. The SDK adds `next: { tags }`
211
+ * to the fetch init (Next reads it; other fetch implementations ignore
212
+ * unknown init keys) and sets no cache policy: whether a request is cached
213
+ * stays your app's decision.
100
214
  *
101
- * - `true` (default): tags derived from each call's inputs — `product:<id>`
102
- * for `getProductById` and `getProductProperties`, `collection:<id>` for
103
- * `getCollectionById`, `getProductsInCollectionById` and `searchProducts`
104
- * with `collectionId`/`collectionIds`.
215
+ * - `true` (default): `catalog` on EVERY catalogue read (products,
216
+ * collections, search, facets, property groups and properties,
217
+ * recommendations), first in the list; plus tags derived from each call's
218
+ * inputs — `product:<id>` for `getProductById` and `getProductProperties`,
219
+ * `collection:<id>` for `getCollectionById`, `getProductsInCollectionById`
220
+ * and `searchProducts` with `collectionId`/`collectionIds`, and
221
+ * `menu:<id>` for `getMenu(id)`.
105
222
  * - `false`: no `next` key on any request.
106
- * - a {@link CacheTagResolver}: decides per request.
223
+ * - a {@link CacheTagResolver}: decides per request; it sees `catalog` too.
107
224
  *
108
- * Load pages by the id `findRoute` resolves and they are tagged. Raw slug
109
- * reads (`getProduct(slug)`, `getCollection(slug)`,
110
- * `getProductsInCollection(slug)`) stay untagged — the id is not known until
111
- * the response arrives; pass `route.cacheTags` per request to tag one.
225
+ * Load pages by the id `findRoute` resolves and they carry their id tag.
226
+ * Raw slug reads (`getProduct(slug)`, `getCollection(slug)`,
227
+ * `getProductsInCollection(slug)`, `getMenu(slug)`) carry no id tag — the id
228
+ * is not known until the response arrives; pass `route.cacheTags` per
229
+ * request to tag one. The catalogue ones still carry `catalog`.
112
230
  */
113
231
  cacheTags?: boolean | CacheTagResolver;
114
- }
115
- /**
116
- * Storefront-visible Channel custom fields. Enumerates fields the SDK or its
117
- * consumers read directly. Unknown fields are still accessible via the index
118
- * signature, so adding a new field on the backend doesn't require an SDK
119
- * release for storefronts to consume it.
120
- */
121
- export interface ChannelCustomFields {
122
- /** SDK consumes this to gate the entire client into read-only mode. */
123
- maintenanceMode?: boolean;
124
- /** Custom CDN domain for asset URLs (set per-channel via cdn-domain plugin). */
125
- cdnDomain?: string | null;
126
- /**
127
- * Absolute URL of the storefront for this channel (e.g. `https://store.example.com`).
128
- * Required by the SEO module to emit canonical URLs and hreflang tags.
129
- */
130
- storefrontUrl?: string;
131
- /**
132
- * URL strategy the storefront uses to encode the active language. Drives
133
- * canonical/alternate URL generation in the SEO module.
134
- */
135
- urlLocaleStrategy?: 'path-prefix' | 'subdomain' | 'none';
136
- /**
137
- * When `true`, the URL still includes a locale prefix even for the channel's
138
- * default language. When `false` (default), the default language URL has no
139
- * prefix.
140
- */
141
- urlLocalePrefixDefault?: boolean;
142
- businessName?: string | null;
143
- businessDescription?: string | null;
144
- logoAssetId?: string | null;
145
- darkLogoAssetId?: string | null;
146
- coverAssetId?: string | null;
147
- faviconAssetId?: string | null;
148
- websiteUrl?: string | null;
149
- primaryColor?: string | null;
150
- contactEmail?: string | null;
151
- contactPhone?: string | null;
152
- legalName?: string | null;
153
- vatNumber?: string | null;
154
- registrationNumber?: string | null;
155
- addressLine1?: string | null;
156
- addressLine2?: string | null;
157
- city?: string | null;
158
- postalCode?: string | null;
159
- province?: string | null;
160
- country?: string | null;
161
- /** JSON-encoded social URLs map. Keys: facebook, instagram, twitter, linkedin, youtube, tiktok. */
162
- socialLinks?: string | null;
163
- commercePathPrefix?: string | null;
164
- /** JSON-encoded `{ [languageCode]: pathPrefix }` per-locale overrides. */
165
- commercePathPrefixTranslations?: string | null;
166
- /** Segment canonical product URLs sit under. Unset/empty means `products`. */
167
- productPathSegment?: string | null;
168
- /** Channel default Twitter / X handle (without @). Used by `metaTagsFor()` for `twitter:site`. */
169
- twitterHandle?: string | null;
170
- /** Vendure Asset ID used as the fallback OpenGraph image when a product does not provide one. */
171
- defaultOgImageId?: string | null;
172
- /** When true, the storefront serves `/llms.txt` advertising AI-friendly endpoints. */
173
- llmsTxtEnabled?: boolean;
174
- /**
175
- * When true, B2B customers can submit quote requests on this channel.
176
- * Storefronts should gate quote UI (request-quote buttons, "My quotes"
177
- * account section) on this flag instead of probing `createQuoteRequest`.
178
- */
179
- quotesEnabled?: boolean;
180
- /**
181
- * When true, customers can request order returns on this channel.
182
- * Storefronts should gate return UI ("Request return" buttons, "My
183
- * returns" account section) on this flag instead of probing
184
- * `requestReturn`.
185
- */
186
- returnsEnabled?: boolean;
187
- /** Days after delivery/shipment during which a return may be requested. */
188
- returnWindowDays?: number;
189
- /**
190
- * Channel-wide display default: `channel` (follow `pricesIncludeTax`),
191
- * `gross` or `net`. Raw storage value — read it with `parseTaxDisplayPolicy`
192
- * and render from `pricing.getTaxDisplayMode()`, which resolves the whole
193
- * policy server-side for the actual shopper.
194
- */
195
- taxDisplayDefault?: string | null;
196
- /** B2B override: `inherit`, `gross` or `net`. See {@link taxDisplayDefault}. */
197
- taxDisplayB2b?: string | null;
198
- /**
199
- * JSON array of ISO-3166 alpha-2 codes, e.g. `["US"]`. A shopper whose
200
- * country is listed always sees prices excl. tax AND is taxed by their own
201
- * country's tax zone. Empty/unset = the rule is off.
202
- */
203
- taxExclusiveCountries?: string | null;
204
- /** Forward-compat: any additional storefront-visible custom fields. */
205
- [key: string]: unknown;
232
+ /**
233
+ * A PRIVATE STOREFRONT TOKEN (`s69p_…`) for a SERVER-SIDE storefront — one per
234
+ * head, issued with `admin.heads.privateTokens.issue` from
235
+ * `@sixtyninecommerce/admin`. Sent as `x-storefront-token` on every Vendure,
236
+ * CMS and plugins call, beside the public channel token.
237
+ *
238
+ * It grants no permission. It gives the server its own rate-limit budget
239
+ * instead of the anonymous one, and makes the platform key per-shopper budgets
240
+ * (and the CMS form limiter) on the address in {@link buyerIp} — without it,
241
+ * every shopper of a server-rendered storefront shares the server's address.
242
+ *
243
+ * NEVER in a browser: `createStorefrontClient` throws `CREDENTIAL_IN_BROWSER`
244
+ * there, because a token a page holds is a token every visitor holds.
245
+ */
246
+ privateToken?: string;
247
+ /**
248
+ * The shopper every call is for — the address YOUR server saw the shopper
249
+ * connect from (e.g. the first untrusted `X-Forwarded-For` hop), one IPv4 or
250
+ * IPv6 address. Requires {@link privateToken}. Override it per call with
251
+ * `{ buyerIp }` in the request options, which is what a server rendering for
252
+ * many shoppers at once should do. The platform refuses a value that is not
253
+ * an address with `INVALID_BUYER_IP`.
254
+ */
255
+ buyerIp?: string;
256
+ /**
257
+ * Remember public CMS and plugins reads — menus, content strings, collections,
258
+ * the routes and capability manifests — and ask the server "has this changed?" (`If-None-Match`)
259
+ * instead of downloading them again. **On by default, except on Next.js's
260
+ * patched `fetch`** (below). The server is asked on every read, so nothing is
261
+ * ever served stale: an unchanged read comes back as a bodyless 304 and is
262
+ * answered from memory, parsed afresh for each caller. Identical reads in
263
+ * flight at the same moment share one request.
264
+ *
265
+ * - `true` (the default off Next): one cache per process, shared by every
266
+ * client built on the same `fetch` — at most 500 reads and 5 MB, least
267
+ * recently used first out. A storefront that builds a client per request
268
+ * still benefits.
269
+ * - `{ maxEntries?, maxBytes? }`: a cache of this client's own, with these bounds.
270
+ * - `false` (the default on Next's `fetch`): every read downloads, as before.
271
+ *
272
+ * Never for anything signed in: Shop API calls (the cart, checkout, the
273
+ * customer's account, every price) are never cached, and the CMS and plugins
274
+ * reads never carry the shopper's session — they are the same request for a
275
+ * signed-in shopper as for a guest, so sharing them shares nothing personal.
276
+ * The cache key is everything the request sends (store, language, the private
277
+ * token, the query), so one store's or language's answer is never another's.
278
+ *
279
+ * **Next.js: off unless you ask.** When the `fetch` this client runs on (yours,
280
+ * or the global one) is Next's patched `fetch` — it carries `__nextPatched` —
281
+ * the default is `false`. This cache sits ABOVE that `fetch`, and Next's data
282
+ * cache lives inside it: Next keys a cached fetch on its request headers and
283
+ * stores only a 200, so the `If-None-Match` this cache adds would miss Next's
284
+ * entry and turn every render's zero-request hit into a 304 round trip. An app
285
+ * that does NOT cache its fetches with Next (no `cache: 'force-cache'`, segment
286
+ * `revalidate` or `fetchCache`) may pass `true` and gain from it. A wrapper
287
+ * around Next's `fetch` hides the marker: pass `false` yourself then.
288
+ */
289
+ conditionalReads?: ConditionalReadsOption;
206
290
  }
207
291
  export interface BrandingAssetRef {
208
292
  id: string;
@@ -284,6 +368,40 @@ export interface BrandingInfo {
284
368
  social: BrandingSocialLinks;
285
369
  storefront: BrandingStorefrontConfig;
286
370
  }
371
+ /** A store's code moved (headless W8-16b): the code this client knew, and the one it uses now. */
372
+ export interface StoreRename {
373
+ /** The code the client was configured with, or had followed to before. */
374
+ previousCode: string;
375
+ /** The store's current code: configure this one. */
376
+ code: string;
377
+ /** When the old code stops answering (ISO-8601), when the platform said. */
378
+ previousCodeUntil?: string;
379
+ /**
380
+ * `previousCode` had already stopped answering: the rename this client followed was undone
381
+ * (or the code it moved to was ended early), and it found the store again under `code`.
382
+ * Configure `code` now.
383
+ */
384
+ previousCodeGone?: boolean;
385
+ }
386
+ /** A method of this SDK that is going away (headless spec §11): `client.graphql()`. */
387
+ export interface MethodDeprecationNotice {
388
+ readonly kind: 'method';
389
+ /** The method as a consumer calls it: `'client.graphql'`. */
390
+ readonly name: string;
391
+ /** What to call instead. */
392
+ readonly replacement: string;
393
+ /** The one line the client prints for it when no `onDeprecation` is configured. */
394
+ readonly message: string;
395
+ }
396
+ /**
397
+ * A platform route this client called answered with a `Deprecation` header — the route, the
398
+ * deprecation date, and the `Sunset` and replacement link when the platform sent them.
399
+ */
400
+ export interface EndpointDeprecationNotice extends DeprecationNotice {
401
+ readonly kind: 'endpoint';
402
+ }
403
+ /** Something this client uses is going away: one of its methods, or a platform route. */
404
+ export type StorefrontDeprecationNotice = MethodDeprecationNotice | EndpointDeprecationNotice;
287
405
  /** Channel info resolved from CMS at initialization. */
288
406
  export interface ChannelInfo {
289
407
  id: string;
@@ -298,11 +416,30 @@ export interface ChannelInfo {
298
416
  * net-vs-gross display decisions (e.g. a B2B/B2C BTW toggle).
299
417
  */
300
418
  pricesIncludeTax: boolean;
301
- customFields: ChannelCustomFields;
419
+ /**
420
+ * The channel's public custom fields exactly as the CMS sends them: the keys
421
+ * it selects from the Shop API's `activeChannel`, each optional and nullable,
422
+ * and an empty bag while Vendure is unreachable. A key the CMS does not select
423
+ * is absent — read the Shop API's `commerce.getActiveChannel()` for those.
424
+ */
425
+ customFields: Cms.PublicChannelDto['custom_fields'];
426
+ /**
427
+ * Set when the channel was resolved through a renamed store's OLD code: that old code, which
428
+ * stops answering at {@link previousCodeUntil}. `code` is the current one.
429
+ */
430
+ previousCode?: string;
431
+ /** With {@link previousCode}: when the store was renamed away from it (ISO-8601). */
432
+ renamedAt?: string;
433
+ /** With {@link previousCode}: when the old code stops answering (ISO-8601). */
434
+ previousCodeUntil?: string;
302
435
  }
303
436
  /** Shared context used by all modules. */
304
437
  export interface StoreContext {
305
- channel: ChannelInfo;
438
+ /**
439
+ * The store's channel. On a client, a getter over its CURRENT code: it moves when the store is
440
+ * renamed (`onStoreRenamed`), and is never assigned.
441
+ */
442
+ readonly channel: ChannelInfo;
306
443
  /**
307
444
  * The channel resolver the transport re-resolves through. `createStoreContext`
308
445
  * always sets it; a context assembled BY HAND (a test double) may leave it
@@ -316,7 +453,15 @@ export interface StoreContext {
316
453
  cmsUrl: string;
317
454
  pluginsUrl: string;
318
455
  languageCode: string;
456
+ /** The currency prices are formatted in: the session currency, else the channel default. */
319
457
  currencyCode: string;
458
+ /**
459
+ * The shopper's chosen currency, sent as `?currencyCode=` on every Shop API
460
+ * request; `null`/absent sends nothing (the channel default). Set from
461
+ * {@link StorefrontClientConfig.currencyCode} and by
462
+ * `commerce.setOrderCurrency`; reset when the engine refuses it.
463
+ */
464
+ sessionCurrencyCode?: string | null;
320
465
  /** Channel tax-display storage mode — see {@link ChannelInfo.pricesIncludeTax}. */
321
466
  pricesIncludeTax: boolean;
322
467
  authToken: string | null;
@@ -326,6 +471,30 @@ export interface StoreContext {
326
471
  * {@link StorefrontClientConfig.orderScope}.
327
472
  */
328
473
  orderScope?: OrderScope | null;
474
+ /**
475
+ * The head key sent as `x-head`, or `null`/absent for none (the store's
476
+ * default head). See {@link StorefrontClientConfig.head}.
477
+ */
478
+ head?: string | null;
479
+ /**
480
+ * Set by a multi-store client (`createStorefrontClient({ resolveStore })`):
481
+ * every cache tag a read carries is also sent scoped to the store,
482
+ * `store:<code>:<tag>`, beside the bare tag. Treat as internal.
483
+ */
484
+ storeScopedCacheTags?: boolean;
485
+ /**
486
+ * Set by a multi-store client: one deprecation reporter for every request's
487
+ * transports, so a deprecated route is announced once per router rather than
488
+ * once per request. Absent: each transport's own reporter. Treat as internal.
489
+ */
490
+ onDeprecation?: (notice: DeprecationNotice) => void;
491
+ /**
492
+ * Who hears that a deprecated method of this SDK was used (`client.graphql()`): the
493
+ * configured `onDeprecation`, once per client — shared by a multi-store client's
494
+ * per-request clients, so once per router. Absent: the process-wide default line. Treat as
495
+ * internal.
496
+ */
497
+ reportDeprecatedMethod?: (notice: MethodDeprecationNotice) => void;
329
498
  /**
330
499
  * Last resolved tax display mode, cached against the identity it was resolved
331
500
  * for (see `identityStamp`). Owned by `pricing.getTaxDisplayMode()`; cleared
@@ -343,6 +512,16 @@ export interface StoreContext {
343
512
  };
344
513
  /** See {@link StorefrontClientConfig.cacheTags}. Absent means `true`. */
345
514
  cacheTags?: boolean | CacheTagResolver;
515
+ /** See {@link StorefrontClientConfig.privateToken}. Null for a public client. */
516
+ privateToken?: string | null;
517
+ /** See {@link StorefrontClientConfig.buyerIp}. */
518
+ buyerIp?: string | null;
519
+ /**
520
+ * See {@link StorefrontClientConfig.conditionalReads}: `createStoreContext`
521
+ * resolves the default (off on Next's patched `fetch`, else on). Absent — a
522
+ * context built by hand — means `true`. CMS and plugins transport only.
523
+ */
524
+ conditionalReads?: ConditionalReadsOption;
346
525
  }
347
526
  export interface GraphQLResponse<T = unknown> {
348
527
  data: T;
@@ -354,12 +533,6 @@ export interface GraphQLResponse<T = unknown> {
354
533
  };
355
534
  }>;
356
535
  }
357
- export interface AgeVerificationStatus {
358
- required: boolean;
359
- minimumAge: number | null;
360
- verified: boolean;
361
- dateOfBirth: string | null;
362
- }
363
536
  export interface AssetPresetSize {
364
537
  url: string;
365
538
  webpUrl: string;
@@ -380,381 +553,88 @@ export interface Asset {
380
553
  /** Intrinsic pixel height of the source image. Absent when not selected. */
381
554
  height?: number | null;
382
555
  customFields?: {
383
- altText?: string;
384
- contentHash?: string;
385
- };
386
- presets?: AssetPresets;
387
- }
388
- export interface CmsAssetTranslation {
389
- language_code: string;
390
- alt_text: string | null;
391
- }
392
- /** Public-safe CMS asset returned by /assets/lookup, /public-assets/:id. */
393
- export interface CmsAsset {
394
- id: string;
395
- filename: string;
396
- mime_type: string;
397
- file_size: number;
398
- storage_key: string;
399
- content_hash: string | null;
400
- width: number | null;
401
- height: number | null;
402
- alt_text: string | null;
403
- presets: Record<PresetName, {
404
- url: string;
405
- webp_url: string;
406
- width: number;
407
- height: number;
408
- }> | null;
409
- translations: CmsAssetTranslation[];
410
- }
411
- export interface VendureAssetDescriptionTranslation {
412
- language_code: string;
413
- description: string;
414
- }
415
- export interface PriceTier {
416
- minQuantity: number;
417
- price: number;
418
- priceWithTax: number;
419
- discountLabel: string | null;
420
- }
421
- export interface VariantLocationAvailability {
422
- locationId: string;
423
- locationName: string;
424
- inStock: boolean;
425
- }
426
- export interface ProductOption {
427
- id: string;
428
- code: string;
429
- name: string;
430
- group: {
431
- id: string;
432
- name: string;
433
- code: string;
434
- };
435
- }
436
- export interface ProductVariant {
437
- id: string;
438
- name: string;
439
- sku: string;
440
- price: number;
441
- priceWithTax: number;
442
- currencyCode: string;
443
- stockLevel: string;
444
- /**
445
- * Physical on-hand stock across the channel's locations. `null` when the
446
- * channel does not expose operational stock numbers (the default) — fall
447
- * back to the `stockLevel` string.
448
- */
449
- stockOnHand: number | null;
450
- /** Stock reserved by open orders. `null` when the channel does not expose it. */
451
- stockAllocated: number | null;
452
- /**
453
- * Units a customer can actually order right now (available-to-promise).
454
- * `null` when the channel does not expose operational stock numbers.
455
- */
456
- saleable: number | null;
457
- /**
458
- * Units already on order from suppliers (e.g. open Exact purchase orders).
459
- * `null` unless the channel exposes stock AND the signed-in customer's group
460
- * may see incoming stock — anonymous visitors always get `null`.
461
- */
462
- incomingStock: number | null;
463
- /** Forward-looking `max(0, saleable) + incomingStock`. Same gate as `incomingStock`. */
464
- projectedSaleable: number | null;
465
- /**
466
- * Earliest FUTURE expected warehouse arrival, ISO 8601. Never a past date.
467
- * `null` under the same gate as `incomingStock`, and ALSO when no open line
468
- * has a future date — so `incomingStock > 0` with `nextExpectedArrival: null`
469
- * is normal (on order, but every date is overdue or missing). Show a dateless
470
- * "restock on order" hint then. This is a warehouse-arrival estimate, never a
471
- * delivery promise.
472
- */
473
- nextExpectedArrival: string | null;
474
- /**
475
- * Units BEYOND `saleable` the signed-in customer may order on backorder right
476
- * now. The quantity ceiling is `max(0, saleable) + backorderAllowance` (see
477
- * `maxOrderableQuantity` in `@sixtyninecommerce/client/pricing`). `null` when
478
- * the question does not apply — anonymous, group may not backorder, or the
479
- * channel hides stock — treat exactly like today; `0` = denied; a large
480
- * value (2,000,000,000) is the "unlimited" sentinel. A snapshot: the server
481
- * re-checks on add-to-cart and at placement and refuses with the usual
482
- * `InsufficientStockError` / `INSUFFICIENT_STOCK`, whose `quantityAvailable`
483
- * then already includes the allowance.
484
- */
485
- backorderAllowance: number | null;
486
- priceListName: string | null;
487
- retailPrice: number | null;
488
- retailPriceWithTax: number | null;
489
- /** Tax rate applied to this price in the active channel/zone, e.g. `{ value: 21 }` for 21% VAT. */
490
- taxRateApplied: {
491
- value: number;
492
- } | null;
493
- priceTiers: PriceTier[] | null;
494
- availabilityByLocation: VariantLocationAvailability[];
495
- options: ProductOption[];
496
- featuredAsset: Asset | null;
497
- assets: Asset[];
498
- customFields: {
499
- minOrderQuantity: number | null;
500
- salesUnit: number | null;
501
- position: number | null;
502
- };
503
- }
504
- export interface FacetValue {
505
- id: string;
506
- name: string;
507
- code: string;
508
- facet: {
509
- id: string;
510
- name: string;
511
- code: string;
512
- };
513
- }
514
- export interface CollectionRef {
515
- id: string;
516
- name: string;
517
- slug: string;
518
- position?: number;
519
- /**
520
- * The parent's `slug` is load-bearing, not decoration: a top-level collection
521
- * is parented to the `__root_collection__` SENTINEL (Vendure resolves `parent`
522
- * to null only when the real parent is PRIVATE), so the slug is what
523
- * distinguishes "this is a root" from "this is nested". The SDK's own product
524
- * queries select it. A caller writing its own query and omitting it gets the
525
- * flat product path for every canonical — see `isUserFacingRoot`.
526
- */
527
- parent?: {
528
- id: string;
529
- slug?: string;
530
- } | null;
531
- translations?: Array<{
532
- languageCode: string;
533
- name: string;
534
- slug: string;
535
- }>;
536
- customFields?: {
537
- isRoutable?: boolean | null;
538
- isCanonical?: boolean | null;
539
- } | null;
540
- }
541
- export interface ProductTranslation {
542
- languageCode: string;
543
- name: string;
544
- slug: string;
545
- description?: string;
546
- }
547
- export interface OptionGroup {
548
- id: string;
549
- name: string;
550
- code: string;
551
- options: Array<{
552
- id: string;
553
- name: string;
554
- code: string;
555
- }>;
556
- }
557
- export interface PublicProductDocument {
558
- id: string;
559
- position: number;
560
- title: string;
561
- description: string | null;
562
- fileUrl: string;
563
- fileMimeType: string;
564
- fileSize: number;
565
- fileName: string;
566
- /** When true, the URL is presigned and short-lived. Don't cache it. */
567
- requiresAuth: boolean;
568
- }
569
- export interface Product {
570
- id: string;
571
- name: string;
572
- slug: string;
573
- description: string;
574
- featuredAsset: Asset | null;
575
- assets: Asset[];
576
- variants: ProductVariant[];
577
- optionGroups: OptionGroup[];
578
- facetValues: FacetValue[];
579
- collections: CollectionRef[];
580
- translations?: ProductTranslation[];
581
- documents?: PublicProductDocument[];
582
- /**
583
- * Per-product SEO/social/AI metadata. Resolved server-side for the active
584
- * language and validated client-side at the SDK boundary. `null` when no
585
- * metadata has been authored for this product on the current channel.
586
- */
587
- metadata?: import('./seo/metadata-types.js').ProductMetadata | null;
588
- }
589
- export interface RecommendedProductGroup {
590
- groupName: string;
591
- groupSlug: string;
592
- products: ProductSummary[];
593
- }
594
- export interface ProductSummary {
595
- id: string;
596
- name: string;
597
- slug: string;
598
- description?: string;
599
- /** Whether the product is enabled on the channel. Selected by `LIST_PRODUCTS`. */
600
- enabled?: boolean;
601
- featuredAsset: Asset | null;
602
- variants: Array<{
603
- id: string;
604
- name?: string;
605
- sku?: string;
606
- price: number;
607
- priceWithTax: number;
608
- currencyCode: string;
609
- stockLevel: string;
610
- /** ATP numbers — `null` when the channel does not expose operational stock. */
611
- stockOnHand?: number | null;
612
- stockAllocated?: number | null;
613
- saleable?: number | null;
614
- /**
615
- * Incoming-stock numbers — additionally `null` unless the signed-in customer's
616
- * group may see incoming stock. `nextExpectedArrival` is the earliest FUTURE
617
- * arrival (ISO 8601, never past) and is `null` when every open line is overdue,
618
- * even while `incomingStock > 0`.
619
- */
620
- incomingStock?: number | null;
621
- projectedSaleable?: number | null;
622
- nextExpectedArrival?: string | null;
623
- /** Units beyond `saleable` this buyer may backorder; `null` = not applicable. */
624
- backorderAllowance?: number | null;
625
- availabilityByLocation?: VariantLocationAvailability[];
626
- priceListName?: string | null;
627
- retailPrice?: number | null;
628
- retailPriceWithTax?: number | null;
629
- taxRateApplied?: {
630
- value: number;
631
- } | null;
632
- priceTiers?: PriceTier[] | null;
633
- customFields?: {
634
- minOrderQuantity: number | null;
635
- salesUnit: number | null;
636
- position: number | null;
637
- };
638
- }>;
639
- facetValues?: FacetValue[];
640
- collections?: CollectionRef[];
641
- }
642
- export interface Facet {
643
- id: string;
644
- name: string;
645
- code: string;
646
- values: Array<{
647
- id: string;
648
- name: string;
649
- code: string;
650
- }>;
651
- }
652
- export interface Breadcrumb {
653
- id: string;
654
- name: string;
655
- slug: string;
656
- }
657
- /** Per-language translation of a collection, including SEO custom fields. */
658
- export interface CollectionTranslation {
659
- languageCode: string;
660
- name?: string;
661
- slug: string;
662
- customFields?: {
663
- seoTitle?: string | null;
664
- seoDescription?: string | null;
665
- canonicalUrl?: string | null;
666
- socialTitle?: string | null;
667
- socialDescription?: string | null;
668
- socialImageAlt?: string | null;
556
+ altText?: string | null;
557
+ contentHash?: string | null;
669
558
  } | null;
559
+ presets?: AssetPresets | null;
670
560
  }
671
- /** Collection-scoped custom fields: routing directives + SEO scalars. */
672
- export interface CollectionCustomFields {
673
- isRoutable?: boolean | null;
674
- isCanonical?: boolean | null;
675
- noindex?: boolean | null;
676
- nofollow?: boolean | null;
677
- metaRobotsMaxImagePreview?: string | null;
678
- socialImageId?: string | null;
679
- socialOgType?: string | null;
680
- twitterCardType?: string | null;
681
- }
682
- export interface Collection {
683
- id: string;
684
- name: string;
685
- slug: string;
686
- description?: string;
687
- position?: number;
688
- featuredAsset?: Asset | null;
689
- breadcrumbs?: Breadcrumb[];
690
- parent?: CollectionRef | null;
691
- children?: CollectionRef[];
692
- customFields?: CollectionCustomFields | null;
693
- translations?: CollectionTranslation[];
694
- }
695
- export interface CollectionDetail extends Collection {
696
- productVariants?: {
697
- items: Array<{
698
- id: string;
699
- product: ProductSummary;
700
- price: number;
701
- priceWithTax: number;
702
- currencyCode: string;
703
- stockLevel: string;
704
- /** ATP numbers — `null` when the channel does not expose operational stock. */
705
- stockOnHand: number | null;
706
- stockAllocated: number | null;
707
- saleable: number | null;
708
- /**
709
- * Incoming-stock numbers — additionally `null` unless the signed-in customer's
710
- * group may see incoming stock. `nextExpectedArrival` is the earliest FUTURE
711
- * arrival (ISO 8601, never past) and is `null` when every open line is overdue,
712
- * even while `incomingStock > 0`.
713
- */
714
- incomingStock: number | null;
715
- projectedSaleable: number | null;
716
- nextExpectedArrival: string | null;
717
- /** Units beyond `saleable` this buyer may backorder; `null` = not applicable. */
718
- backorderAllowance: number | null;
719
- priceListName: string | null;
720
- retailPrice: number | null;
721
- retailPriceWithTax: number | null;
722
- taxRateApplied: {
723
- value: number;
724
- } | null;
725
- priceTiers: PriceTier[] | null;
726
- availabilityByLocation: VariantLocationAvailability[];
727
- customFields: {
728
- minOrderQuantity: number | null;
729
- salesUnit: number | null;
730
- position: number | null;
731
- };
732
- }>;
733
- totalItems: number;
734
- };
735
- }
561
+ /**
562
+ * A merchant's publication state for a product that is launched but not simply
563
+ * in stock. NOT a stock figure: stock arriving does not end it — only its
564
+ * `availableFrom` date, or the merchant, does.
565
+ *
566
+ * - `'none'` — nothing in force; the ordinary stock (and backorder) rules apply.
567
+ * - `'comingSoon'` — shown, but nobody can order it, not even from stock on hand.
568
+ * - `'preorder'` — buyers the merchant allows to backorder may order beyond
569
+ * stock; everyone else can still buy whatever is in stock.
570
+ *
571
+ * A widened literal union on purpose: **never `switch` exhaustively on it**. The
572
+ * engine can gain a state before your storefront is redeployed, and a `switch`
573
+ * without a default would hand that shopper `undefined`. Compare the states you
574
+ * handle and treat everything else as `'none'` — every helper in
575
+ * `@sixtyninecommerce/client/pricing` does exactly that.
576
+ */
577
+ export type ProductAvailabilityState = Shop.ProductAvailabilityState;
578
+ export type { AddItemInput, AdjustmentType, AuthenticationInput, BreadcrumbFragment, ChannelCustomFieldsFragment, CollectionDetailFragment, CollectionFragment, CollectionRefFragment, ConvertedAmountFragment, CreateAddressInput, CreateCustomerInput, CreateProductReviewInput, CreateQuoteRequestInput, CreditBalanceSource, CurrencyCode, CurrentUserFragment, CustomerPaymentTermsFragment, CustomerReturnFragment, CustomerSubscriptionFragment, DeliveryAdvice, DeliverySelectionSource, DeliveryTermsStatus, DepositPaymentIntentInput, FacetFragment, FacetValueFragment, FavoriteListOptions, LanguageCode, MolliePaymentIntentInput, MolliePaymentMethodsInput, MyPaymentMandateFragment, MyparcelDeliveryOptionsInput, MyparcelDropOffPointInput, NativeAuthInput, OrderDeliveryTermsFragment, OrderFragment, OrderFulfillmentParcelsFragment, OrderFulfillmentsFragment, OrderPaymentIntent, OrderPaymentTermsFragment, OrderReturnReasonCode, OrderReturnSettlementMethod, OrderReturnState, OrderSummaryFragment, OrderWritableCustomFieldsFragment, ParkedOrderFragment, ParkedOrderPaymentIntentInput, PayDepositInput, PaymentInput, PaymentTermsClassification, PaymentTermsStatus, PayParkedOrderInput, PickupLocationSearchInput, PlacementRejectionFragment, PriceTierFragment, ProductAvailabilityFragment, ProductCardFragment, ProductFragment, ProductMetadataFragment, ProductPropertyGroupValuesFragment, ProductReviewFragment, ProductReviewListOptions, ProductSummaryFragment, ProductVariantFragment, PropertyGroupFragment, PublicPaymentMethodFragment, PublicShippingMethodFragment, QuoteFragment, QuoteLegacyFragment, QuoteLineDiscountType, QuoteLineRequestInput, QuoteListOptions, QuoteStatus, RecentReviewsOptions, RecommendedProductGroupFragment, RegisterCustomerInput, RequestReturnInput, ReturnRequestLineInput, ReviewSortKey, ReviewStatus, SavedListFragment, SearchResultFragment, SearchResultItemFragment, SetupPaymentMandateInput, SubscriptionFirstChargeTiming, SubscriptionPlanPublicFragment, SubscriptionPurchaseResultFragment, UpdateAddressInput, UpdateCustomerInput, UpdateOrderCustomFieldsInput, UpdateProductReviewInput, VariantLocationAvailabilityFragment, VatValidationResultFragment, } from './generated/shop.js';
579
+ /** A strategy `commerce.authenticate` can sign in through: a member of the engine's `AuthenticationInput` (`native` today). */
580
+ export type AuthenticationStrategy = keyof Shop.AuthenticationInput;
581
+ /** What a strategy takes — `{ username, password }` for `native`. */
582
+ export type AuthenticationStrategyInput<S extends AuthenticationStrategy> = NonNullable<Shop.AuthenticationInput[S]>;
583
+ /**
584
+ * A product as `getProduct` / `getProductById` return it: the generated
585
+ * {@link ProductFragment} with `metadata` parsed and validated at the SDK
586
+ * boundary (its JSON-scalar members arrive as `unknown` on the wire).
587
+ * `null` when no metadata has been authored for the product on this channel.
588
+ *
589
+ * `availability` is the PRODUCT's own publication state, ignoring any variant
590
+ * override — the banner for a detail page. What applies to the variant about to
591
+ * be added is `variant.availability`, which is what the buy button reads.
592
+ */
593
+ export type Product = Omit<Shop.ProductFragment, 'metadata'> & {
594
+ metadata: ProductMetadata | null;
595
+ };
736
596
  /**
737
597
  * Stable, append-only vocabulary for why an order could not be placed — or why
738
- * a payment was refused before it was taken.
598
+ * a payment was refused before it was taken: the Shop API's own enum, which a
599
+ * spec keeps equal to the platform's
600
+ * (`@sixtynine-digital/commerce-shared/placement-rejection`).
739
601
  *
740
602
  * Branch on this instead of keyword-matching `transitionError` /
741
603
  * `paymentErrorMessage`: that prose is operator English, is re-worded per
742
- * merchant, and is translated. This list is a deliberate copy of the
743
- * platform's (`@sixtynine-digital/commerce-shared/placement-rejection`) so the
744
- * published client stays zero-dependency; a spec asserts the two match.
604
+ * merchant, and is translated.
745
605
  *
746
606
  * Treat an unrecognised value defensively — always give your `switch` a
747
607
  * `default:` branch and fall back to `MutationError.message`. Codes are added
748
608
  * over time, and the SDK deliberately passes a code it does not know through
749
609
  * unchanged rather than rewriting it to `UNKNOWN`.
610
+ *
611
+ * - `HOOK_REJECTED` — an app the store installed refused the order (its
612
+ * `order.validate` hook). `customerMessage` is the app's own sentence for the
613
+ * buyer.
614
+ * - `HOOK_UNAVAILABLE` — an app the store installed could not confirm the order
615
+ * right now; the order is refused until it can. Ask the buyer to try again
616
+ * later.
617
+ * - `TAX_CHANGED` — the store's tax provider now calculates different tax for
618
+ * this order, and the order already CARRIES it: re-read the order, show the
619
+ * buyer the new total, and place it again — that attempt goes through. Not an
620
+ * outage.
621
+ * - `VARIANT_NOT_FOR_SALE_IN_CURRENCY` — the cart holds products the store does
622
+ * not sell in the order's currency (`currencyCode`; `lines` names them). The
623
+ * buyer removes them or checks out in another currency. A product's
624
+ * `forSaleInCurrency` says so before it reaches the cart, and adding one is
625
+ * refused with the same code.
626
+ * - `PRODUCT_EXCLUDED_FROM_STORE` — the cart holds products the store no longer
627
+ * sells (`lines` names them; the store stopped offering a product its
628
+ * organization shares). The buyer removes them. Adding one is refused with the
629
+ * same code.
750
630
  */
751
- 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';
631
+ export type PlacementRejectionCode = Shop.PlacementRejectionCode;
752
632
  /**
753
633
  * An order line implicated in a rejection — the line below its minimum
754
634
  * quantity, the line that ran short of stock.
755
635
  *
756
636
  * The engine caps a rejection at 20 lines (`PlacementRejection.linesTruncated`
757
- * says when it did). Every field except the variant id is nullable, so render
637
+ * says when it did). Every field except the variant id is optional, so render
758
638
  * defensively; `productName`/`productVariantName` are already translated.
759
639
  */
760
640
  export interface PlacementRejectionLine {
@@ -768,458 +648,42 @@ export interface PlacementRejectionLine {
768
648
  quantityAvailable?: number | null;
769
649
  }
770
650
  /**
771
- * Field-level detail, e.g. which part of the shipping address is unusable.
651
+ * The structured, customer-safe half of a placement rejection: the generated
652
+ * {@link PlacementRejectionFragment} as `readPlacement` hands it on — `code`
653
+ * widened past the enum (a code this build predates passes through unchanged)
654
+ * and `lines` rebuilt as {@link PlacementRejectionLine}s (an entry naming no
655
+ * variant is dropped). A field-level detail (`details[number]`) says, e.g.,
656
+ * which part of the shipping address is unusable; its `field` is null when the
657
+ * detail is about the order as a whole.
772
658
  *
773
- * Deliberately NOT `FieldError` (the CMS form-validation shape): `field` is
774
- * nullable here, because a detail may be about the order as a whole.
659
+ * `customerMessage` is plain shopper English and safe to render as-is (null when
660
+ * the veto site supplied none); the operator prose stays on the error's own
661
+ * reason field for merchant-facing surfaces. The metadata fields are populated
662
+ * per code (e.g. `requiredAmount` + `amountBasis` — `net` or `gross` — for a
663
+ * minimum-amount rejection, in minor units of `currencyCode`) and are null
664
+ * otherwise. `linesTruncated` is true when `lines` was capped.
775
665
  */
776
- export interface PlacementRejectionDetail {
777
- field?: string | null;
778
- code?: string | null;
779
- message: string;
780
- }
781
- /**
782
- * The structured, customer-safe half of a placement rejection.
783
- *
784
- * `customerMessage` is plain shopper English and safe to render as-is; the
785
- * operator prose stays on the error's own reason field for merchant-facing
786
- * surfaces. The metadata fields are populated per code (e.g. `requiredAmount` +
787
- * `amountBasis` for a minimum-amount rejection) and are null otherwise.
788
- */
789
- export interface PlacementRejection {
666
+ export type PlacementRejection = Omit<Shop.PlacementRejectionFragment, 'code' | 'lines'> & {
790
667
  /**
791
- * Widened past the union on purpose: the SDK passes a code it does not know
668
+ * Widened past the enum on purpose: the SDK passes a code it does not know
792
669
  * through unchanged, so an exhaustive `switch` must still have a `default:`.
793
670
  */
794
671
  code: PlacementRejectionCode | (string & {});
795
- /** Shopper-safe sentence. Null when the veto site supplied none. */
796
- customerMessage?: string | null;
797
- lines?: PlacementRejectionLine[] | null;
798
- details?: PlacementRejectionDetail[] | null;
799
- /** True when `lines` was capped and does not list every affected line. */
800
- linesTruncated: boolean;
801
- /** Minor units, in `currencyCode`. */
802
- requiredAmount?: number | null;
803
- currencyCode?: string | null;
804
- /** `net` or `gross` — which basis `requiredAmount` is expressed in. */
805
- amountBasis?: string | null;
806
- requiredQuantity?: number | null;
807
- priceListName?: string | null;
808
- salesUnit?: number | null;
809
- minimumAge?: number | null;
810
- }
811
- export type AdjustmentType = 'PROMOTION' | 'DISTRIBUTED_ORDER_PROMOTION' | 'OTHER';
812
- export interface Discount {
813
- /** Identifier of the source (e.g. promotion code or shipping method id). */
814
- adjustmentSource: string;
815
- type: AdjustmentType | string;
816
- description: string;
817
- /** Pre-tax discount amount in minor units. Negative values reduce the price. */
818
- amount: number;
819
- amountWithTax: number;
820
- }
821
- export interface OrderTaxSummary {
822
- description: string;
823
- /** Tax rate as a percentage (e.g. 21 for 21%). */
824
- taxRate: number;
825
- /** Net total to which this tax rate applies, in minor units. */
826
- taxBase: number;
827
- /** Tax total at this rate, in minor units. */
828
- taxTotal: number;
829
- }
830
- export interface OrderPromotion {
831
- id: string;
832
- name: string;
833
- description: string;
834
- couponCode: string | null;
835
- }
836
- export interface OrderLine {
837
- id: string;
838
- quantity: number;
839
- /**
840
- * Units of this line physical stock did NOT cover when the order was placed
841
- * (the part the merchant ships later). Stamped at placement, never
842
- * decremented as the line ships — the fulfilments record what arrived.
843
- *
844
- * Selected by the PLACED-order reads alone (`getOrderByCode`,
845
- * `getCustomerOrders`), so it is `undefined` from the cart reads and
846
- * mutations: a cart line has no stamp to carry, and selecting it in the
847
- * shared fragment would couple every cart call to an engine that has the
848
- * field.
849
- */
850
- backorderedQuantity?: number;
851
- unitPrice: number;
852
- unitPriceWithTax: number;
853
- /** Tax rate applied to this line as a percentage (e.g. 21 for 21%). */
854
- taxRate: number;
855
- linePrice: number;
856
- linePriceWithTax: number;
857
- /** Line price after item-level discounts, excluding tax. */
858
- discountedLinePrice: number;
859
- discountedLinePriceWithTax: number;
860
- /** Discounts applied to this line (item-level promotions). */
861
- discounts: Discount[];
862
- productVariant: {
863
- id: string;
864
- name: string;
865
- sku: string;
866
- /**
867
- * Units the channel will sell right now, `null` when it hides stock. Here
868
- * so a cart can show how much of a line is on backorder BEFORE placement,
869
- * when `backorderedQuantity` is still 0 — through
870
- * `pricing.backorderedQuantityForCart(variant, quantity)`, which yields no
871
- * hint at all when this is `null` (never read `null` as 0).
872
- */
873
- saleable: number | null;
874
- product: {
875
- id: string;
876
- name: string;
877
- slug: string;
878
- };
879
- options: Array<{
880
- id: string;
881
- name: string;
882
- group: {
883
- name: string;
884
- };
885
- }>;
886
- };
887
- featuredAsset: Asset | null;
888
- }
889
- export interface OrderAddress {
890
- fullName: string;
891
- company?: string;
892
- streetLine1: string;
893
- streetLine2?: string;
894
- city: string;
895
- province?: string;
896
- postalCode: string;
897
- countryCode: string;
898
- phoneNumber?: string;
899
- }
900
- export interface FulfillmentLine {
901
- orderLineId: string;
902
- quantity: number;
903
- }
904
- /**
905
- * A shipment created for (part of) an order. `trackingCode` is the carrier
906
- * barcode — feed it to `commerce.trackShipment(trackingCode, postalCode)`
907
- * for live tracking history.
908
- */
909
- export interface Fulfillment {
910
- id: string;
911
- /** Fulfillment FSM state, e.g. Pending, Shipped, Delivered, Cancelled. */
912
- state: string;
913
- /** Human-readable fulfillment/shipping method description. */
914
- method: string;
915
- trackingCode: string | null;
916
- createdAt: string;
917
- updatedAt: string;
918
- lines: FulfillmentLine[];
919
- }
920
- /**
921
- * A payment recorded against an order. `method` is the payment-method *code*
922
- * (e.g. `manual-payment`, `mollie-payment`) — drives storefront invoice-vs-PSP
923
- * routing. `transactionId` is the PSP receipt; null for manual/offline methods.
924
- */
925
- export interface OrderPayment {
926
- id: string;
927
- /** Payment-method code, e.g. `mollie-payment` or `manual-payment`. */
928
- method: string;
929
- /** Amount captured by this payment, in minor units. */
930
- amount: number;
931
- /** Payment FSM state, e.g. Authorized, Settled, Declined, Cancelled. */
932
- state: string;
933
- /** PSP transaction reference; null for manual/offline payments. */
934
- transactionId: string | null;
935
- }
936
- /**
937
- * A shipping charge applied to an order. The selected method's name/code feeds
938
- * order-detail rendering; `priceWithTax` is the charged amount in minor units.
939
- */
940
- export interface ShippingLine {
941
- shippingMethod: {
942
- id: string;
943
- name: string;
944
- code: string;
945
- };
946
- priceWithTax: number;
947
- }
948
- export interface Order {
949
- id: string;
950
- code: string;
951
- state: string;
952
- active: boolean;
953
- /** When the order (cart) was created — ISO-8601 instant. */
954
- createdAt: string;
955
- /** When the order left the cart state (was placed) — ISO-8601 instant; null while still an active cart. */
956
- orderPlacedAt: string | null;
957
- totalQuantity: number;
958
- subTotal: number;
959
- subTotalWithTax: number;
960
- shipping: number;
961
- shippingWithTax: number;
962
- total: number;
963
- totalWithTax: number;
964
- currencyCode: string;
965
- lines: OrderLine[];
966
- /** Order-level discounts (e.g. order-total promotions, free shipping). */
967
- discounts: Discount[];
968
- /** Tax breakdown grouped by tax rate. */
969
- taxSummary: OrderTaxSummary[];
970
- /** Promotions applied to this order. */
971
- promotions: OrderPromotion[];
972
- /** Shipping charges on the order (selected method + charged price). */
973
- shippingLines: ShippingLine[];
974
- /** Payments recorded against the order (method code, state, PSP receipt). */
975
- payments: OrderPayment[];
976
- shippingAddress?: OrderAddress;
977
- billingAddress?: OrderAddress;
978
- customer?: {
979
- id: string;
980
- firstName: string;
981
- lastName: string;
982
- emailAddress: string;
983
- };
984
- couponCodes: string[];
985
- /**
986
- * Shipments for this order. Only selected on placed-order reads
987
- * (`getOrderByCode`, customer order history) — absent on cart operations.
988
- */
989
- fulfillments?: Fulfillment[] | null;
990
- /**
991
- * Tracking pushed by an external fulfilment system, oldest delivery first.
992
- * Prefer this over `fulfillments[].trackingCode` for display: one fulfilment can
993
- * cover several parcels, which a single tracking code cannot express.
994
- */
995
- externalShipments?: ExternalShipment[] | null;
996
- /** Immutable source-aware payment condition captured when this order was accepted. */
997
- paymentTerms?: OrderPaymentTermsSnapshot | null;
998
- /** Immutable Exact-aware delivery terms captured when this order was accepted. */
999
- deliveryTerms?: OrderDeliveryTermsSnapshot | null;
1000
- /**
1001
- * Order-level custom fields.
1002
- *
1003
- * Only populated on the order returned by
1004
- * {@link CommerceModule.setPaymentIntent | commerce.setPaymentIntent} —
1005
- * ordinary cart and order reads do not select it, so that a client release
1006
- * cannot break every cart operation against an engine that predates a field.
1007
- * Keep the buyer's chosen intent in your own state; that call's response is
1008
- * where to read it back.
1009
- */
1010
- customFields?: OrderCustomFields | null;
1011
- }
1012
- /**
1013
- * How the buyer said they would settle this order.
1014
- *
1015
- * `pay_now` = paid immediately (iDEAL, card, …), which is what a pay-now
1016
- * discount promotion looks for; `on_account` = pay later on the net terms the
1017
- * account carries. Written only by
1018
- * {@link CommerceModule.setPaymentIntent | commerce.setPaymentIntent}, which
1019
- * re-prices the order in the same call.
1020
- */
1021
- export type OrderPaymentIntentValue = 'pay_now' | 'on_account';
1022
- /** The Shop API enum accepted by `commerce.setPaymentIntent`. */
1023
- export type OrderPaymentIntent = 'PAY_NOW' | 'PAY_ON_ACCOUNT';
1024
- export interface OrderCustomFields {
1025
- /**
1026
- * The buyer's stated payment intent, or `null` when they never stated one.
1027
- * Read-only: the only write path is `commerce.setPaymentIntent`.
1028
- */
1029
- paymentIntent?: OrderPaymentIntentValue | null;
1030
- }
1031
- /**
1032
- * One parcel, pallet or pickup instruction pushed by the external fulfilment
1033
- * system.
1034
- *
1035
- * `reference` is overloaded by design, because the sending systems overload it:
1036
- * a parcel carrier sends a tracking URL, a pallet carrier sends a URL *or* a
1037
- * plain reference, and ex-works sends free-text pickup instructions. Branch on
1038
- * {@link ExternalShipment.isLink} — derived server-side — to decide between an
1039
- * anchor and a text block. Never put a non-link reference in an `href`.
1040
- */
1041
- export interface ExternalShipment {
1042
- /** Carrier name as the sender reports it, e.g. `PostNL`, `Pallet`, `Ex works`. */
1043
- carrier: string;
1044
- /** A tracking URL, a carrier reference, or pickup instructions. */
1045
- reference: string;
1046
- /** True when `reference` is an http(s) URL safe to render as a link. */
1047
- isLink: boolean;
1048
- /** ISO-8601 dispatch timestamp, or null if the sender omitted it. */
1049
- shippedAt: string | null;
1050
- /** Which delivery of the order this parcel belongs to. */
1051
- deliveryNumber: string;
1052
- }
1053
- /**
1054
- * Order minimums in effect on the active channel (inline order-constraints
1055
- * plugin). Display/pre-validation only — checkout enforces server-side.
1056
- */
1057
- export interface ActiveChannelOrderConstraints {
1058
- /**
1059
- * Minimum vs the GROSS order total, minor units. Null when unset. This is the
1060
- * channel-wide minimum raised by any price-list minimum applying to the
1061
- * signed-in customer, so it varies per visitor.
1062
- */
1063
- minOrderAmountGross: number | null;
1064
- /**
1065
- * Minimum vs the NET (tax-exclusive) total, minor units, when a price list
1066
- * applying to this customer states its minimum ex tax. Independent of
1067
- * `minOrderAmountGross` — both bind, and neither can be derived from the
1068
- * other without a tax rate. Null when no net-basis minimum applies.
1069
- */
1070
- minOrderAmountNet: number | null;
1071
- /** Minimum total item count, from an applicable price list. Null when unset. */
1072
- minOrderQuantity: number | null;
1073
- /** Default fulfillment profile minimum vs the NET subtotal, minor units. Null when unset. */
1074
- fulfillmentMinOrderNet: number | null;
1075
- currencyCode: string;
1076
- /**
1077
- * True when the signed-in customer's group is exempt from the CHANNEL-wide
1078
- * minimum. A price-list minimum still applies, so `minOrderAmountGross` may
1079
- * be non-null while this is true.
1080
- */
1081
- customerIsExempt: boolean;
1082
- }
1083
- export interface ShippingMethod {
1084
- id: string;
1085
- name: string;
1086
- description: string;
1087
- price: number;
1088
- priceWithTax: number;
1089
- metadata?: Record<string, unknown>;
1090
- /** True when this is the signed-in customer's eligible Exact default. */
1091
- isPreferred: boolean;
1092
- /** False when the current externally governed customer cannot select this mapping. */
1093
- isDeliveryTermsEligible: boolean;
1094
- }
1095
- export interface PaymentMethod {
1096
- id: string;
1097
- name: string;
1098
- code: string;
1099
- description: string;
1100
- isEligible: boolean;
1101
- eligibilityMessage: string | null;
1102
- }
1103
- export interface Customer {
1104
- id: string;
1105
- firstName: string;
1106
- lastName: string;
1107
- emailAddress: string;
1108
- phoneNumber?: string;
1109
- addresses: CustomerAddress[];
1110
- orders?: {
1111
- items: OrderSummary[];
1112
- totalItems: number;
1113
- };
1114
- /**
1115
- * Customer groups the customer belongs to in the active channel. Drives
1116
- * B2B-only UI (navigation, VAT-mode default, order gating) — pricing is
1117
- * already applied server-side, so groups are for presentation only.
1118
- */
1119
- groups?: CustomerGroup[];
1120
- /**
1121
- * Whether this customer is a trade (B2B) account — i.e. belongs to one of the
1122
- * channel's configured B2B customer groups. The authoritative signal to gate
1123
- * B2B UI on, so a storefront never hard-codes a group name. Optional because
1124
- * a Vendure predating the field simply omits it.
1125
- *
1126
- * Presentation only: pricing, the tax display mode and access to quotes /
1127
- * credit / contract pricing are all resolved server-side regardless.
1128
- */
1129
- isB2B?: boolean;
1130
- }
1131
- /** A customer group, as exposed to the storefront (identity only). */
1132
- export interface CustomerGroup {
1133
- id: string;
1134
- name: string;
1135
- }
672
+ lines: PlacementRejectionLine[] | null;
673
+ };
1136
674
  /**
1137
- * A price list applying to the active customer. Identity only — prices are
1138
- * applied server-side; storefronts use this to label which lists (contract /
1139
- * tier) the signed-in customer is on.
675
+ * A generated result with every list two selections merge typed as ONE list of
676
+ * the merged element. When a document selects a list twice — a fragment's
677
+ * `lines` and its own `lines { backorderedQuantity }`, or the `fulfillments` of
678
+ * two fragments — codegen prints it as `A[] & B[]`, and TypeScript types the
679
+ * callbacks of `.map`, `.filter` and `.find` on such a list with `A` alone, so
680
+ * the fields only `B` selected cannot be read there. GraphQL sends one list of
681
+ * merged elements; this says so. `getOrderByCode` and `getCustomerOrders`
682
+ * resolve to it.
1140
683
  */
1141
- export interface CustomerPriceList {
1142
- id: string;
1143
- name: string;
1144
- isContract: boolean;
1145
- }
1146
- export interface CustomerAddress {
1147
- id: string;
1148
- fullName: string;
1149
- streetLine1: string;
1150
- streetLine2?: string;
1151
- city: string;
1152
- province?: string;
1153
- postalCode: string;
1154
- country: {
1155
- code: string;
1156
- name: string;
1157
- };
1158
- defaultShippingAddress: boolean;
1159
- defaultBillingAddress: boolean;
1160
- }
1161
- export interface OrderSummary {
1162
- id: string;
1163
- code: string;
1164
- state: string;
1165
- /** Net (excl. tax) order total, in minor units. */
1166
- total: number;
1167
- totalWithTax: number;
1168
- currencyCode: string;
1169
- createdAt: string;
1170
- lines: Array<{
1171
- id: string;
1172
- quantity: number;
1173
- /**
1174
- * Units stock did not cover at placement (backorder); 0 otherwise.
1175
- * Selected by `getCustomerOrders`; `undefined` from `getCurrentCustomer`.
1176
- */
1177
- backorderedQuantity?: number;
1178
- /** Line total incl. tax, in minor units. */
1179
- linePriceWithTax: number;
1180
- productVariant: {
1181
- id: string;
1182
- name: string;
1183
- sku: string;
1184
- product: {
1185
- slug: string;
1186
- featuredAsset: {
1187
- preview: string;
1188
- presets?: {
1189
- xs?: {
1190
- webpUrl: string;
1191
- };
1192
- };
1193
- } | null;
1194
- };
1195
- };
1196
- }>;
1197
- fulfillments?: Fulfillment[] | null;
1198
- /** Tracking pushed by an external fulfilment system. See {@link ExternalShipment}. */
1199
- externalShipments?: ExternalShipment[] | null;
1200
- /** Immutable source-aware payment condition captured when this order was accepted. */
1201
- paymentTerms?: OrderPaymentTermsSnapshot | null;
1202
- /** Immutable delivery terms captured when this order was accepted. */
1203
- deliveryTerms?: OrderDeliveryTermsSnapshot | null;
1204
- }
1205
- /** An invoice issued for one of the signed-in customer's orders. */
1206
- export interface CustomerInvoice {
1207
- id: string;
1208
- invoiceNumber: string;
1209
- /** Issue date (ISO-8601 date). */
1210
- invoicedOn: string;
1211
- /** Minor units. */
1212
- totalWithTax: number;
1213
- currencyCode: string;
1214
- languageCode: string;
1215
- createdAt: string;
1216
- }
1217
- /** Base64-encoded invoice PDF download. */
1218
- export interface CustomerInvoicePdf {
1219
- base64: string;
1220
- filename: string;
1221
- invoiceNumber: string;
1222
- }
684
+ export type MergedSelection<T> = [T] extends [string | number | boolean | bigint | null | undefined] ? T : T extends ReadonlyArray<unknown> ? MergedSelection<T[number]>[] : T extends object ? {
685
+ [K in keyof T]: MergedSelection<T[K]>;
686
+ } : T;
1223
687
  /** A line that could not be re-added during a `reorder()` call. */
1224
688
  export interface ReorderSkipped {
1225
689
  variantId: string;
@@ -1227,8 +691,9 @@ export interface ReorderSkipped {
1227
691
  errorCode: string;
1228
692
  message: string;
1229
693
  }
694
+ /** What `reorder()` resolves to: the cart after the last line that could be added. */
1230
695
  export interface ReorderResult {
1231
- order: Order;
696
+ order: Shop.OrderFragment;
1232
697
  addedLines: number;
1233
698
  skipped: ReorderSkipped[];
1234
699
  }
@@ -1255,145 +720,15 @@ export type LoginResult = {
1255
720
  } | {
1256
721
  status: 'account_not_verified';
1257
722
  };
1258
- export interface CustomerInput {
1259
- firstName: string;
1260
- lastName: string;
1261
- emailAddress: string;
1262
- phoneNumber?: string;
1263
- }
1264
- export interface AddressInput {
1265
- fullName: string;
1266
- streetLine1: string;
1267
- streetLine2?: string;
1268
- city: string;
1269
- province?: string;
1270
- postalCode: string;
1271
- countryCode: string;
1272
- phoneNumber?: string;
1273
- company?: string;
1274
- }
1275
- export interface PaymentInput {
1276
- method: string;
1277
- metadata?: Record<string, unknown>;
1278
- }
723
+ /** A Stripe PaymentIntent for the active order: hand `clientSecret` to Stripe.js. */
1279
724
  export interface StripePaymentIntentResult {
1280
725
  clientSecret: string;
1281
726
  }
1282
- export interface MolliePaymentMethodsInput {
1283
- paymentMethodCode: string;
1284
- }
1285
- export interface MolliePaymentMethodAmount {
1286
- value: number;
1287
- currency: string;
1288
- }
1289
- export interface MolliePaymentMethod {
1290
- id: string;
1291
- code: string;
1292
- description: string;
1293
- minimumAmount: MolliePaymentMethodAmount;
1294
- maximumAmount: MolliePaymentMethodAmount | null;
1295
- image: {
1296
- size1x: string;
1297
- size2x: string;
1298
- svg: string;
1299
- };
1300
- /**
1301
- * Mollie's availability status for this method on the order (e.g.
1302
- * `"activated"`, `"pending-boarding"`). `null` when Mollie omits it.
1303
- */
1304
- status: string | null;
1305
- }
1306
- /**
1307
- * A storefront-visible Mollie payment method, ordered per the channel's saved
1308
- * configuration with hidden methods removed. Returned by
1309
- * `commerce.getOrderedMolliePaymentMethods`. Decoupled from
1310
- * {@link MolliePaymentMethod}: this is the curated, channel-ordered shape from
1311
- * the platform's `payment-config` plugin, not the raw community plugin type.
1312
- */
1313
- export interface OrderedMollieMethod {
1314
- id: string;
1315
- /** Mollie method id (e.g. `"ideal"`); pass as `molliePaymentMethodCode`. */
1316
- code: string;
1317
- description: string | null;
1318
- /** Mollie's icon URL (SVG preferred, 2x PNG fallback); null when omitted. */
1319
- imageUrl: string | null;
1320
- /**
1321
- * Mollie's availability status for this method (e.g. `"activated"`). `null`
1322
- * when Mollie omits it.
1323
- */
1324
- status: string | null;
1325
- }
1326
- export interface CreateMolliePaymentIntentInput {
1327
- paymentMethodCode: string;
1328
- redirectUrl?: string;
1329
- molliePaymentMethodCode?: string;
1330
- locale?: string;
1331
- immediateCapture?: boolean;
1332
- /**
1333
- * Create the intent for a specific order rather than the session's active
1334
- * order — required when topping up an order in `ArrangingAdditionalPayment`,
1335
- * or when driving checkout for a non-active order.
1336
- */
1337
- orderId?: string;
1338
- }
727
+ /** A Mollie hosted checkout for the order: redirect the shopper to `url`. */
1339
728
  export interface MolliePaymentIntentResult {
1340
729
  url: string;
1341
730
  }
1342
- /**
1343
- * Minimal order shape returned by `syncMolliePaymentStatus`. Use the `state`
1344
- * to confirm the order settled (e.g. `PaymentSettled`) after a delayed/missing
1345
- * Mollie webhook. `null` when no order matches the code.
1346
- */
1347
- export interface MollieOrderStatusResult {
1348
- id: string;
1349
- code: string;
1350
- state: string;
1351
- }
1352
- export interface RegisterInput {
1353
- firstName: string;
1354
- lastName: string;
1355
- emailAddress: string;
1356
- password: string;
1357
- phoneNumber?: string;
1358
- }
1359
- export interface UpdateCustomerInput {
1360
- title?: string;
1361
- firstName: string;
1362
- lastName: string;
1363
- phoneNumber?: string;
1364
- }
1365
- export interface UpdateAddressInput {
1366
- id: string;
1367
- fullName?: string;
1368
- streetLine1?: string;
1369
- streetLine2?: string;
1370
- city?: string;
1371
- province?: string;
1372
- postalCode?: string;
1373
- countryCode?: string;
1374
- phoneNumber?: string;
1375
- company?: string;
1376
- defaultShippingAddress?: boolean;
1377
- defaultBillingAddress?: boolean;
1378
- }
1379
- export interface Country {
1380
- id: string;
1381
- code: string;
1382
- name: string;
1383
- }
1384
- export interface ActiveChannel {
1385
- id: string;
1386
- code: string;
1387
- defaultLanguageCode: string;
1388
- availableLanguageCodes: string[];
1389
- defaultCurrencyCode: string;
1390
- availableCurrencyCodes: string[];
1391
- customFields: ChannelCustomFields;
1392
- }
1393
- export interface FacetValueFilterInput {
1394
- and?: string;
1395
- or?: string[];
1396
- }
731
+ export type { FacetValueFilterInput } from './generated/shop.js';
1397
732
  export interface SearchInput {
1398
733
  term: string;
1399
734
  collectionSlug?: string;
@@ -1408,79 +743,32 @@ export interface SearchInput {
1408
743
  /** Filter to products belonging to ALL of these collection ids (AND). */
1409
744
  collectionIds?: string[];
1410
745
  facetValueIds?: string[];
1411
- facetValueFilters?: FacetValueFilterInput[];
746
+ facetValueFilters?: Shop.FacetValueFilterInput[];
1412
747
  take?: number;
1413
748
  skip?: number;
1414
749
  sort?: {
1415
750
  name?: 'ASC' | 'DESC';
1416
751
  price?: 'ASC' | 'DESC';
1417
752
  };
1418
- }
1419
- export interface SearchResultItem {
1420
- productId: string;
1421
753
  /**
1422
- * Orderable variant id for this search row — pass THIS (never `productId`) to
1423
- * `addToCart`. Under `groupByProduct` it is a representative variant; for the
1424
- * exact variant on multi-variant products, load `getProduct(slug)`.
754
+ * Return only results whose availability is one of these states, judged
755
+ * server-side at the moment of the request. Several states are OR-ed, so
756
+ * `['none', 'preorder']` is "everything except coming soon".
757
+ *
758
+ * Date-aware on purpose: the index stores the state the merchant SET, so a
759
+ * pre-order whose launch date has passed is excluded from `['preorder']` —
760
+ * and included in `['none']` — without waiting for the sweep that tidies the
761
+ * stored row.
762
+ *
763
+ * **Until the channel has had a full reindex**, documents written before this
764
+ * attribute existed carry no state at all: they match `['none']` and nothing
765
+ * else, and their `SearchResultItemFragment.availability` reads `null`. So a
766
+ * "coming soon" or "pre-order" filter can legitimately come back empty on a
767
+ * channel that has the products but not the index.
1425
768
  */
1426
- productVariantId: string;
1427
- productName: string;
1428
- slug: string;
1429
- description: string;
1430
- price: {
1431
- value?: number;
1432
- min?: number;
1433
- max?: number;
1434
- };
1435
- priceWithTax: {
1436
- value?: number;
1437
- min?: number;
1438
- max?: number;
1439
- };
1440
- currencyCode: string;
1441
- productAsset: {
1442
- preview: string;
1443
- focalPoint?: {
1444
- x: number;
1445
- y: number;
1446
- };
1447
- } | null;
1448
- collectionIds: string[];
1449
- /** Aggregate availability across all stock locations (Meilisearch plugin). */
1450
- inStock: boolean;
1451
- }
1452
- export interface SearchFacetValue {
1453
- facetValue: {
1454
- id: string;
1455
- name: string;
1456
- code?: string;
1457
- facet: {
1458
- id: string;
1459
- name: string;
1460
- code?: string;
1461
- };
1462
- };
1463
- count: number;
1464
- }
1465
- export interface SearchResult {
1466
- items: SearchResultItem[];
1467
- totalItems: number;
1468
- facetValues: SearchFacetValue[];
1469
- }
1470
- /** `eq` boolean operator mirroring Vendure's `BooleanOperators` input. */
1471
- export interface BooleanOperators {
1472
- eq?: boolean;
1473
- }
1474
- /**
1475
- * Subset of Vendure's `ProductFilterParameter` the SDK types explicitly.
1476
- * `enabled` is the field `getProducts` defaults on; the index signature keeps
1477
- * the parameter open to the other server-side filter fields without the SDK
1478
- * having to enumerate them all.
1479
- */
1480
- export interface ProductFilterParameter {
1481
- enabled?: BooleanOperators;
1482
- [field: string]: unknown;
769
+ availability?: ProductAvailabilityState[];
1483
770
  }
771
+ export type { BooleanOperators, ProductFilterParameter } from './generated/shop.js';
1484
772
  export interface ProductListOptions {
1485
773
  take?: number;
1486
774
  skip?: number;
@@ -1510,9 +798,9 @@ export interface ProductListOptions {
1510
798
  * Ignored on the deprecated `{ collectionSlug }` path, which reroutes to the
1511
799
  * search backend and returns its own already-flat row shape regardless.
1512
800
  *
1513
- * Both shapes are typed `ProductSummary`; the omitted members are optional on
1514
- * that type, so a card row is a valid — just sparser — `ProductSummary`. Read
1515
- * a dropped field and you get `undefined`, not a stale value.
801
+ * A `'card'` row is typed {@link ProductCardFragment}, the full row
802
+ * {@link ProductSummaryFragment}; `getProducts` picks the type from this
803
+ * option when it is a literal.
1516
804
  */
1517
805
  detail?: 'card' | 'full';
1518
806
  /**
@@ -1520,7 +808,9 @@ export interface ProductListOptions {
1520
808
  * option silently reroutes the call through the search backend, whose rows
1521
809
  * are flatter than the products list (single synthesised variant, no `sku`,
1522
810
  * `facetValues`, or `collections`) — the named method makes that shape
1523
- * explicit. The option keeps working for now.
811
+ * explicit. The option keeps working for now; a non-empty slug returns
812
+ * {@link CollectionProductSummary} rows, so the call types as
813
+ * {@link ProductListPage}.
1524
814
  */
1525
815
  collectionSlug?: string;
1526
816
  /**
@@ -1540,7 +830,7 @@ export interface ProductListOptions {
1540
830
  * the Shop API additionally forces `enabled: { eq: true }` server-side, so
1541
831
  * no filter can surface disabled products.
1542
832
  */
1543
- filter?: ProductFilterParameter;
833
+ filter?: Shop.ProductFilterParameter;
1544
834
  /**
1545
835
  * @deprecated The Shop API forces `enabled: { eq: true }` server-side, so
1546
836
  * `enabled: false` cannot surface disabled products; the shorthand is
@@ -1562,10 +852,9 @@ export interface CollectionProductListOptions {
1562
852
  * A product card row from the search backend, as returned by
1563
853
  * `getProductsInCollection`. Honest projection of a search hit: exactly one
1564
854
  * synthesised variant, and none of the fields the search index does not carry
1565
- * (`sku`, `facetValues`, `collections`). Structurally a subset of
1566
- * `ProductSummary`, so card components consuming `{ featuredAsset,
1567
- * variants[0] }` work with either. Load `getProduct(slug)` for the full
1568
- * variant/asset tree.
855
+ * (`sku`, `facetValues`, `collections`). Card components consuming
856
+ * `{ featuredAsset, variants[0] }` work with this and the list rows alike.
857
+ * Load `getProduct(slug)` for the full variant/asset tree.
1569
858
  */
1570
859
  export interface CollectionProductSummary {
1571
860
  id: string;
@@ -1592,6 +881,14 @@ export interface CollectionProductVariant {
1592
881
  priceWithTax: number;
1593
882
  currencyCode: string;
1594
883
  stockLevel: 'IN_STOCK' | 'OUT_OF_STOCK';
884
+ /**
885
+ * The merchant's publication state for this row, carried through from the
886
+ * search hit — so it is `null` on the same terms `SearchResultItemFragment`
887
+ * describes: a document written before the attribute existed does not know,
888
+ * and only a full reindex fixes that. Not `'none'`; render `null` exactly as
889
+ * you would have before pre-orders existed.
890
+ */
891
+ availability: Shop.ProductAvailabilityFragment | null;
1595
892
  }
1596
893
  export interface CollectionListOptions {
1597
894
  take?: number;
@@ -1601,172 +898,21 @@ export interface OrderListOptions {
1601
898
  take?: number;
1602
899
  skip?: number;
1603
900
  }
1604
- export interface FavoriteVariant {
1605
- id: string;
1606
- name: string;
1607
- sku: string;
1608
- price: number;
1609
- priceWithTax: number;
1610
- currencyCode: string;
1611
- stockLevel: string;
1612
- /** ATP numbers — `null` when the channel does not expose operational stock. */
1613
- stockOnHand: number | null;
1614
- stockAllocated: number | null;
1615
- saleable: number | null;
1616
- /**
1617
- * Incoming-stock numbers — additionally `null` unless the signed-in customer's
1618
- * group may see incoming stock. `nextExpectedArrival` is the earliest FUTURE
1619
- * arrival (ISO 8601, never past) and is `null` when every open line is overdue,
1620
- * even while `incomingStock > 0`.
1621
- */
1622
- incomingStock: number | null;
1623
- projectedSaleable: number | null;
1624
- nextExpectedArrival: string | null;
1625
- /**
1626
- * Units BEYOND `saleable` the signed-in customer may order on backorder right
1627
- * now. The quantity ceiling is `max(0, saleable) + backorderAllowance` (see
1628
- * `maxOrderableQuantity` in `@sixtyninecommerce/client/pricing`). `null` when
1629
- * the question does not apply — anonymous, group may not backorder, or the
1630
- * channel hides stock — treat exactly like today; `0` = denied; a large
1631
- * value (2,000,000,000) is the "unlimited" sentinel. A snapshot: the server
1632
- * re-checks on add-to-cart and at placement and refuses with the usual
1633
- * `InsufficientStockError` / `INSUFFICIENT_STOCK`, whose `quantityAvailable`
1634
- * then already includes the allowance.
1635
- */
1636
- backorderAllowance: number | null;
1637
- priceListName: string | null;
1638
- retailPrice: number | null;
1639
- retailPriceWithTax: number | null;
1640
- /** Tax rate applied to this price in the active channel/zone, e.g. `{ value: 21 }` for 21% VAT. */
1641
- taxRateApplied: {
1642
- value: number;
1643
- } | null;
1644
- priceTiers: PriceTier[] | null;
1645
- availabilityByLocation: VariantLocationAvailability[];
1646
- product: {
1647
- id: string;
1648
- name: string;
1649
- slug: string;
1650
- featuredAsset: Asset | null;
1651
- };
1652
- options: Array<{
1653
- id: string;
1654
- name: string;
1655
- group: {
1656
- name: string;
1657
- };
1658
- }>;
1659
- customFields: {
1660
- minOrderQuantity: number | null;
1661
- salesUnit: number | null;
1662
- position: number | null;
1663
- };
1664
- }
1665
- export interface FavoriteItem {
1666
- id: string;
1667
- productVariantId: string;
1668
- createdAt: string;
1669
- productVariant: FavoriteVariant | null;
1670
- }
1671
- export interface SavedListItem {
1672
- id: string;
1673
- productVariantId: string;
1674
- quantity: number;
1675
- position: number;
1676
- createdAt: string;
1677
- productVariant: ProductVariant | null;
1678
- }
1679
- export interface SavedList {
1680
- id: string;
1681
- name: string;
1682
- items: SavedListItem[];
1683
- createdAt: string;
1684
- updatedAt: string;
1685
- }
901
+ /** A "back in stock" subscription, as `subscribeToStockNotification` returns it. */
1686
902
  export interface StockNotificationSubscriptionResult {
1687
903
  id: string;
1688
904
  productVariantId: string;
1689
905
  emailAddress: string;
1690
906
  createdAt: string;
1691
907
  }
908
+ /** One page of `getProducts`, whichever of its three row shapes the options chose. */
909
+ export type ProductListPage = PaginatedList<Shop.ProductSummaryFragment> | PaginatedList<Shop.ProductCardFragment> | PaginatedList<CollectionProductSummary>;
1692
910
  export interface PaginatedList<T> {
1693
911
  items: T[];
1694
912
  totalItems: number;
1695
913
  }
1696
- /**
1697
- * One locale's slug override for a CMS collection item, as the CMS emits it.
1698
- *
1699
- * NOT a bare string: both `GET /resolve` and the single-item endpoints build
1700
- * this map from `CollectionItemsService.getSlugTranslations`, which returns
1701
- * `{ slug, path }` per language. It was declared here as `Record<string, string>`,
1702
- * so `slug_translations[locale].replace(...)` — what the SEO chain did — threw
1703
- * `translated.replace is not a function` on every translated CMS page.
1704
- */
1705
- export interface SlugTranslation {
1706
- /** The locale's slug SEGMENT — `over-ons`, never a full path. */
1707
- slug: string;
1708
- /**
1709
- * Channel-relative, locale-UNPREFIXED path for this locale (`/over-ons`), or
1710
- * `null` when the item has no addressable path at all (its collection has no
1711
- * `basePath`). The column is nullable, so a consumer must handle `null`; the
1712
- * locale prefix is applied downstream from channel config, never stored here.
1713
- */
1714
- path: string | null;
1715
- }
1716
- export interface ResolvedContent {
1717
- item?: Record<string, unknown>;
1718
- /** Resolved field values keyed by field slug (locale-filtered). */
1719
- values?: Record<string, unknown>;
1720
- collection?: {
1721
- id: string;
1722
- name: string;
1723
- slug: string;
1724
- basePath?: string | null;
1725
- isSingleton?: boolean;
1726
- titleFieldSlug?: string | null;
1727
- [key: string]: unknown;
1728
- };
1729
- /**
1730
- * Ancestor chain, root first, seeded with the item itself — so a path that
1731
- * resolves always carries at least one entry. Carries no `title`: the CMS's
1732
- * recursive ancestor walk selects `id`, `slug` and `path` only
1733
- * (`ResolveService.getBreadcrumbs`). This was declared
1734
- * `Array<{ title: string; path: string }>`, which named a field the platform
1735
- * has never emitted.
1736
- */
1737
- breadcrumbs?: Array<{
1738
- id: string;
1739
- slug: string;
1740
- path: string | null;
1741
- }>;
1742
- /** Per-locale slug overrides, keyed by language code. See {@link SlugTranslation}. */
1743
- slug_translations?: Record<string, SlugTranslation>;
1744
- /**
1745
- * Derived SEO metadata block (from the standard SEO field group). `null` when
1746
- * the item/page carries no SEO fields. Feed to `parseCmsItemMetadata`.
1747
- */
1748
- metadata?: Record<string, unknown> | null;
1749
- }
1750
- export interface SitemapEntry {
1751
- id: string;
1752
- path: string;
1753
- title: string | null;
1754
- collection_slug: string | null;
1755
- updated_at: string;
1756
- /** Present only for collection landing pages (basePath routes). */
1757
- type?: 'collection_page';
1758
- /** Present only when the request specified a language_code. */
1759
- language_code?: string;
1760
- }
1761
- export interface ContentItemSummary {
1762
- id: string;
1763
- slug: string | null;
1764
- status: string;
1765
- collection_id: string;
1766
- collection_name: string;
1767
- collection_title_field_slug: string | null;
1768
- title: string | null;
1769
- }
914
+ export type { PublicAssetDto, PublicAssetPresetsDto, PublicAssetPresetUrlsDto, PublicAssetTranslationDto, PublicBreadcrumbDto, PublicChannelDto, PublicCollectionDetailDto, PublicCollectionDto, PublicCollectionFieldDto, PublicCollectionItemDetailDto, PublicCollectionItemDto, PublicCollectionItemSearchResultDto, PublicCollectionPageValuesDto, PublicContentStringDto, PublicContentStringListResponseDto, PublicContentStringValueDto, PublicFormDto, PublicFormFieldConstraintDto, PublicFormFieldDto, PublicFormFieldTypeDto, PublicFormListResponseDto, PublicFormSlugRuleDto, PublicFormSlugRulesDto, PublicFormTranslationDto, PublicItemSummaryDto, PublicItemWithFieldsDto, PublicMenuDetailDto, PublicMenuSummaryDto, PublicPaginationTotalDto, PublicResolvedCollectionDto, PublicResolvedContentDto, PublicResolvedFieldDto, PublicResolvedItemDto, PublicResolvedSubFieldDto, PublicSeoMetadataDto, PublicSitemapEntryDto, PublicSitemapSeoDto, PublicVendureAssetDescriptionDto, } from './generated/cms.js';
915
+ export type { PublicCapabilitiesDto, PublicCapabilityManifestDto, PublicCapabilityReadinessDto, PublicRouteEntryDto, PublicRoutesMetadataDto, PublicRoutesResponseDto, } from './generated/plugins.js';
1770
916
  /**
1771
917
  * Channel-wide CMS search query. All fields optional — supplying only `q`
1772
918
  * searches across every collection in the store. Use `collectionId` or
@@ -1784,94 +930,13 @@ export interface ContentSearchQuery {
1784
930
  languageCode?: string;
1785
931
  }
1786
932
  /**
1787
- * A single CMS content item search hit. Field values are flattened on the
1788
- * document with locale-suffixed keys (`title_en`, `title_nl`, ...) — index
1789
- * with `[fieldSlug]` or `[fieldSlug + '_' + languageCode]` as needed.
933
+ * One page of `content.getCollectionItems`: the items (field values
934
+ * locale-merged when a `languageCode` was requested, asset references
935
+ * resolved) and the total across every page.
1790
936
  */
1791
- export interface ContentSearchHit {
1792
- id: string;
1793
- channel_id: string;
1794
- collection_id: string;
1795
- collection_slug: string;
1796
- slug: string | null;
1797
- path: string | null;
1798
- parent_id: string | null;
1799
- position: number;
1800
- status: string;
1801
- created_at: number;
1802
- updated_at: number;
1803
- published_at: number | null;
1804
- [fieldSlug: string]: unknown;
1805
- }
1806
- export interface ContentSearchResult {
1807
- hits: ContentSearchHit[];
1808
- total: number;
1809
- limit: number;
1810
- offset: number;
1811
- processing_time_ms: number;
1812
- }
1813
- export interface ContentItemWithFields {
1814
- id: string;
1815
- title: string | null;
1816
- fieldValues: Record<string, unknown>;
1817
- }
1818
- export interface CollectionFieldDefinition {
1819
- id: string;
1820
- slug: string;
1821
- label: string;
1822
- fieldType: string;
1823
- position: number;
1824
- isRequired: boolean;
1825
- isLocalizable: boolean;
1826
- config: Record<string, unknown> | null;
1827
- }
1828
- export interface CollectionPageValues {
1829
- fields: CollectionFieldDefinition[];
1830
- values: Record<string, unknown>;
1831
- }
1832
- /** A CMS collection (content type) as returned by `GET /collections`. */
1833
- export interface CmsCollection {
1834
- id: string;
1835
- name: string;
1836
- slug: string;
1837
- description: string | null;
1838
- isSingleton: boolean;
1839
- basePath: string | null;
1840
- isHierarchical: boolean;
1841
- titleFieldSlug: string | null;
1842
- createdAt: string;
1843
- updatedAt: string;
1844
- }
1845
- export interface CmsCollectionDetail extends CmsCollection {
1846
- fields: CollectionFieldDefinition[];
1847
- }
1848
- /**
1849
- * A collection item from the direct CMS item endpoints. `values` holds the
1850
- * item's field values keyed by field slug, locale-merged when a
1851
- * `languageCode` was requested. Public callers only ever see published items.
1852
- */
1853
- export interface CmsCollectionItem {
1854
- id: string;
1855
- collectionId: string;
1856
- slug: string | null;
1857
- status: 'draft' | 'published' | 'archived';
1858
- parentId: string | null;
1859
- publishedAt: string | null;
1860
- createdAt: string;
1861
- updatedAt: string;
1862
- values: Record<string, unknown>;
1863
- /**
1864
- * Per-language slug overrides, keyed by language code. Present on single-item
1865
- * reads, filled from the same `getSlugTranslations` helper `GET /resolve`
1866
- * uses — hence the same object-per-locale shape. See {@link SlugTranslation}.
1867
- */
1868
- slug_translations?: Record<string, SlugTranslation>;
1869
- /** Forward-compat: additional entity fields the CMS may add. */
1870
- [key: string]: unknown;
1871
- }
1872
937
  export interface CmsCollectionItemList {
1873
- items: CmsCollectionItem[];
1874
- total: number;
938
+ items: Cms.PublicCollectionItemDto[];
939
+ total: Cms.PublicPaginationTotalDto['total'];
1875
940
  }
1876
941
  export interface CollectionItemsQuery {
1877
942
  /** Filter by parent item; pass `'root'` for top-level items. */
@@ -1893,63 +958,15 @@ export interface ContentQueryOptions {
1893
958
  sort?: string;
1894
959
  languageCode?: string;
1895
960
  }
1896
- export interface FormField {
1897
- slug: string;
1898
- label: string;
1899
- type: string;
1900
- required: boolean;
1901
- /** Presentational config (e.g. select option labels). */
1902
- config: Record<string, unknown>;
1903
- /**
1904
- * Effective per-field validation constraints the server enforces on submit
1905
- * (min/max length, numeric range, options, pattern), resolved from the
1906
- * field's `validation` first and `config` as a fallback. Contains only
1907
- * recognized constraint keys. Mirror it to validate client-side. See
1908
- * {@link FormFieldTypeDescriptor} / `content.getFormFieldTypes()`.
1909
- */
1910
- validation: Record<string, unknown>;
1911
- position: number;
1912
- }
1913
- /** A form-level translation as emitted by the public projection. */
1914
- export interface FormTranslation {
1915
- languageCode: string;
1916
- title: string;
1917
- description: string | null;
1918
- submitButtonText: string | null;
1919
- successMessage: string | null;
1920
- }
1921
- export interface FormDefinition {
1922
- id: string;
1923
- name: string;
1924
- slug: string;
1925
- /** Where the storefront should send the visitor after a successful submit. */
1926
- redirectUrlOnSuccess: string | null;
1927
- /** True when the form has internal-notification recipients configured (addresses are never exposed). */
1928
- hasNotifications: boolean;
1929
- /** True when a visitor confirmation email will be sent on submit. */
1930
- sendsConfirmation: boolean;
1931
- fields: FormField[];
1932
- translations: FormTranslation[];
961
+ /**
962
+ * `content.getForm` / `getFormBySlug`: the public form, plus where and how to
963
+ * submit it (the SDK adds `submitUrl`, `submitMethod` and `submitHeaders`).
964
+ */
965
+ export type FormDefinition = Cms.PublicFormDto & {
1933
966
  submitUrl: string;
1934
967
  submitMethod: string;
1935
968
  submitHeaders: Record<string, string>;
1936
- }
1937
- /**
1938
- * A form as returned by `content.listForms()`. Mirrors the public projection.
1939
- * NOTE: list responses populate id/name/slug/redirect + the email booleans;
1940
- * `fields` and `translations` arrive EMPTY in list context — fetch a single
1941
- * form via `getForm`/`getFormBySlug` to load them.
1942
- */
1943
- export interface FormSummary {
1944
- id: string;
1945
- name: string;
1946
- slug: string;
1947
- redirectUrlOnSuccess: string | null;
1948
- hasNotifications: boolean;
1949
- sendsConfirmation: boolean;
1950
- fields: FormField[];
1951
- translations: FormTranslation[];
1952
- }
969
+ };
1953
970
  export interface FormListOptions {
1954
971
  limit?: number;
1955
972
  offset?: number;
@@ -1960,55 +977,10 @@ export interface FormListOptions {
1960
977
  /** Locale for the projected field labels. Defaults to the client language. */
1961
978
  locale?: string;
1962
979
  }
1963
- export interface FormListResult {
1964
- data: FormSummary[];
1965
- pagination: {
1966
- total: number;
1967
- };
1968
- }
1969
- /** One constraint key a field type honors (see {@link FormFieldTypeDescriptor}). */
1970
- export interface FormFieldTypeConstraint {
1971
- key: string;
1972
- valueType: 'integer' | 'number' | 'string' | 'string[]';
1973
- description: string;
1974
- }
1975
- /**
1976
- * Describes a form field type and the config/validation constraints it honors.
1977
- * The SDK ships a static mirror as {@link FORM_FIELD_TYPES}; the same data is
1978
- * served live by `content.getFormFieldTypes()` (GET /forms/field-types).
1979
- */
1980
- export interface FormFieldTypeDescriptor {
1981
- type: string;
1982
- label: string;
1983
- description: string;
1984
- /** Shape of the value a submission sends for this field. */
1985
- valueType: string;
1986
- /** Constraint keys honored on submit; resolved from `validation` first, then `config`. */
1987
- constraints: FormFieldTypeConstraint[];
1988
- notes?: string;
1989
- }
1990
- /** The slug shape one authoring surface enforces (form slug or field slug). */
1991
- export interface FormSlugRule {
1992
- /** Source of the regex the CMS validates against. */
1993
- pattern: string;
1994
- maxLength: number;
1995
- description: string;
1996
- validExamples: string[];
1997
- invalidExamples: string[];
1998
- }
1999
- /**
2000
- * Slug rules for form authoring: form slugs are HYPHEN-separated, field slugs
2001
- * are UNDERSCORE-separated. Shipped statically as {@link FORM_SLUG_RULES} and
2002
- * served live in the field-types registry response.
2003
- */
2004
- export interface FormSlugRules {
2005
- form: FormSlugRule;
2006
- field: FormSlugRule;
2007
- }
2008
980
  /** Everything GET /forms/field-types carries: the field types plus the slug rules. */
2009
981
  export interface FormFieldTypeRegistry {
2010
- fieldTypes: FormFieldTypeDescriptor[];
2011
- slugRules: FormSlugRules;
982
+ fieldTypes: Cms.PublicFormFieldTypeDto[];
983
+ slugRules: Cms.PublicFormSlugRulesDto;
2012
984
  }
2013
985
  /**
2014
986
  * Result of `submitForm` — discriminate on `success`. Field-validation
@@ -2032,88 +1004,36 @@ export type FormSubmissionResult = {
2032
1004
  message: string;
2033
1005
  }>;
2034
1006
  };
2035
- export interface ContentStrings {
2036
- [key: string]: Record<string, string>;
2037
- }
2038
- export interface MenuItem {
2039
- id: string;
2040
- parentId: string | null;
2041
- itemType: string;
2042
- url: string | null;
2043
- targetId: string | null;
2044
- position: number;
2045
- openInNewTab: boolean;
2046
- metadata: Record<string, unknown> | null;
2047
- translations: Array<{
2048
- languageCode: string;
2049
- label: string;
2050
- title: string | null;
2051
- }>;
2052
- resolvedPath?: string;
1007
+ /**
1008
+ * `content.getContentStrings('export')`: every content string of the channel,
1009
+ * `key → language code → value`.
1010
+ */
1011
+ export type ContentStrings = Cms.paths['/content-strings/export']['get']['responses'][200]['content']['application/json'];
1012
+ /**
1013
+ * One node of the tree `content.getMenu` builds from the menu's flat items:
1014
+ * the item's own members (camelCase or legacy snake_case on the wire, read
1015
+ * either way), its translations, and its children ordered by `position`.
1016
+ */
1017
+ export type MenuItem = Pick<Cms.PublicMenuItemDto, 'id' | 'parentId' | 'itemType' | 'url' | 'targetId' | 'position' | 'openInNewTab' | 'metadata' | 'resolvedPath'> & {
1018
+ translations: Array<Pick<Cms.PublicMenuItemTranslationDto, 'languageCode' | 'label' | 'title'>>;
2053
1019
  children: MenuItem[];
2054
- }
2055
- export interface Menu {
2056
- id: string;
2057
- name: string;
2058
- slug: string;
2059
- items?: MenuItem[];
2060
- }
2061
- export interface RouteEntry {
2062
- path: string;
2063
- type: 'cms' | 'collection' | 'product';
2064
- id: string;
2065
- title: string;
2066
- slug?: string;
2067
- updated_at?: string;
2068
- source?: string;
2069
- /**
2070
- * Only set on `product` routes. A product listed under multiple collections
2071
- * emits one route per collection; exactly one — the canonical URL home — is
2072
- * `true`, the rest `false`. Filter to `canonical !== false` to get the
2073
- * deduplicated (one-per-product) URL set. `undefined` on `cms`/`collection`
2074
- * routes, which are already one-per-entity.
2075
- */
2076
- canonical?: boolean;
2077
- }
1020
+ };
1021
+ /**
1022
+ * `content.getMenu`: the menu, its flat `items` replaced by the tree of
1023
+ * {@link MenuItem}s. `content.getMenus` returns {@link PublicMenuSummaryDto}s.
1024
+ */
1025
+ export type Menu = Omit<Cms.PublicMenuDetailDto, 'items'> & {
1026
+ items: MenuItem[];
1027
+ };
2078
1028
  /**
2079
1029
  * A manifest entry as `findRoute` returns it, plus the cache tags the page's
2080
1030
  * reads should carry — `product:<id>` / `collection:<id>`, none for CMS pages.
2081
1031
  * Load the page by `id` (`getProductById`, `getCollectionById`,
2082
1032
  * `getProductsInCollectionById`) and those tags are already on its reads.
2083
1033
  */
2084
- export interface ResolvedRoute extends RouteEntry {
1034
+ export type ResolvedRoute = Plugins.PublicRouteEntryDto & {
2085
1035
  readonly cacheTags: readonly string[];
2086
- }
2087
- export interface RoutesMetadata {
2088
- default_language: string;
2089
- available_languages: string[];
2090
- generated_at: string;
2091
- }
2092
- export interface RoutesResponse {
2093
- data: Record<string, RouteEntry[]>;
2094
- metadata: RoutesMetadata;
2095
- }
2096
- export interface ExchangeRate {
2097
- baseCurrency: string;
2098
- targetCurrency: string;
2099
- rate: string;
2100
- inverseRate: string;
2101
- rateDate: string;
2102
- }
2103
- export interface ConvertedAmount {
2104
- originalAmount: string;
2105
- originalCurrency: string;
2106
- convertedAmount: string;
2107
- targetCurrency: string;
2108
- rate: string;
2109
- rateDate: string;
2110
- }
2111
- /** One entry of a `convertToMultiple()` result. */
2112
- export interface BulkConversionResult {
2113
- currency: string;
2114
- amount: string;
2115
- rate: string;
2116
- }
1036
+ };
2117
1037
  export interface PriceDisplay {
2118
1038
  price: number;
2119
1039
  priceWithTax: number;
@@ -2125,7 +1045,7 @@ export interface PriceDisplay {
2125
1045
  taxRate: number | null;
2126
1046
  hasDiscount: boolean;
2127
1047
  discountPercentage: number | null;
2128
- activeTier: PriceTier | null;
1048
+ activeTier: Shop.PriceTierFragment | null;
2129
1049
  }
2130
1050
  export interface TierTableEntry {
2131
1051
  minQuantity: number;
@@ -2205,7 +1125,7 @@ export interface VariantPriceData {
2205
1125
  taxRateApplied?: {
2206
1126
  value: number;
2207
1127
  } | null;
2208
- priceTiers?: PriceTier[] | null;
1128
+ priceTiers?: Shop.PriceTierFragment[] | null;
2209
1129
  }
2210
1130
  export interface OrderValidationResult {
2211
1131
  valid: boolean;
@@ -2217,73 +1137,6 @@ export interface OrderValidationError {
2217
1137
  required: number;
2218
1138
  actual: number;
2219
1139
  }
2220
- export interface PropertyGroupTranslation {
2221
- id: string;
2222
- languageCode: string;
2223
- name: string;
2224
- }
2225
- export interface PropertyTranslation {
2226
- id: string;
2227
- languageCode: string;
2228
- name: string;
2229
- helpText: string | null;
2230
- }
2231
- export interface PropertyFieldFacet {
2232
- fieldSlug: string;
2233
- fieldType: string;
2234
- facetId: string;
2235
- }
2236
- export interface PropertyConfig {
2237
- options?: Array<{
2238
- value: string;
2239
- label: string;
2240
- }>;
2241
- min?: number;
2242
- max?: number;
2243
- maxLength?: number;
2244
- allowedCollectionIds?: string[];
2245
- filterableFieldSlugs?: string[];
2246
- /**
2247
- * For `product` field type: strict filter applied in the admin UI to
2248
- * narrow the picker. Storefront callers can ignore this — the selected
2249
- * product IDs are already stored in `PropertyValue.value` (as `string[]`).
2250
- */
2251
- productFilter?: {
2252
- filters?: Array<{
2253
- property_slug: string;
2254
- facet_value_ids: string[];
2255
- }>;
2256
- collection_id?: string | null;
2257
- };
2258
- }
2259
- export interface Property {
2260
- id: string;
2261
- slug: string;
2262
- fieldType: string;
2263
- isFilterable: boolean;
2264
- isRequired: boolean;
2265
- position: number;
2266
- config: PropertyConfig | null;
2267
- facetId: string | null;
2268
- fieldFacets: PropertyFieldFacet[];
2269
- translations: PropertyTranslation[];
2270
- }
2271
- export interface PropertyGroup {
2272
- id: string;
2273
- position: number;
2274
- translations: PropertyGroupTranslation[];
2275
- properties: Property[];
2276
- }
2277
- export interface PropertyValue {
2278
- id: string;
2279
- propertyId: string;
2280
- languageCode: string | null;
2281
- value: unknown;
2282
- }
2283
- export interface ProductPropertyGroupValues {
2284
- group: PropertyGroup;
2285
- values: PropertyValue[];
2286
- }
2287
1140
  /**
2288
1141
  * A product's property values flattened to a `slug → value` record (the shape
2289
1142
  * a product-detail view actually renders). Produced by
@@ -2306,637 +1159,77 @@ export interface ResponsiveImageData {
2306
1159
  width: number;
2307
1160
  height: number;
2308
1161
  }
2309
- export interface ReviewAttribute {
2310
- id: string;
2311
- slug: string;
2312
- label: string;
2313
- inputType: 'rating' | 'selection';
2314
- options: string[] | null;
2315
- isRequired: boolean;
2316
- section: 'product' | 'demographic';
2317
- }
2318
- export interface ProductReview {
2319
- id: string;
2320
- rating: number | null;
2321
- title: string | null;
2322
- body: string | null;
2323
- variantId: string | null;
2324
- customerDisplayName: string | null;
2325
- isVerifiedPurchase: boolean;
2326
- isEdited: boolean;
2327
- attributeValues: Record<string, number | string> | null;
2328
- imageAssetIds: string[] | null;
2329
- videoAssetIds: string[] | null;
2330
- helpfulCount: number;
2331
- notHelpfulCount: number;
2332
- merchantReply: string | null;
2333
- merchantReplyAt: string | null;
2334
- myVote: boolean | null;
2335
- createdAt: string;
2336
- updatedAt: string;
2337
- }
2338
- export interface ReviewRatingDistribution {
2339
- one: number;
2340
- two: number;
2341
- three: number;
2342
- four: number;
2343
- five: number;
2344
- }
2345
- export interface ReviewRatingSummary {
2346
- averageRating: number | null;
2347
- reviewCount: number;
2348
- ratingCount: number;
2349
- distribution: ReviewRatingDistribution;
2350
- }
2351
- export interface ReviewAttributeAggregation {
2352
- attributeId: string;
2353
- label: string;
2354
- inputType: string;
2355
- averageRating: number | null;
2356
- distribution: Record<string, number> | null;
2357
- }
2358
- export interface ReviewChannelConfig {
2359
- reviewsEnabled: boolean;
2360
- reviewsRequireText: boolean;
2361
- reviewsAllowMedia: boolean;
2362
- reviewsAllowVoting: boolean;
2363
- reviewsAllowRating: boolean;
2364
- reviewMinBodyLength: number;
2365
- reviewMaxTitleLength: number;
2366
- reviewMaxImages: number;
2367
- reviewMaxVideos: number;
2368
- }
2369
- export interface CreateReviewInput {
2370
- productId: string;
2371
- variantId?: string;
2372
- rating?: number;
2373
- title?: string;
2374
- body?: string;
2375
- imageAssetIds?: string[];
2376
- videoAssetIds?: string[];
2377
- attributeValues?: Record<string, number | string>;
2378
- }
2379
- export interface UpdateReviewInput {
2380
- rating?: number;
2381
- title?: string;
2382
- body?: string;
2383
- imageAssetIds?: string[];
2384
- videoAssetIds?: string[];
2385
- attributeValues?: Record<string, number | string>;
2386
- }
2387
- export interface ReviewListOptions {
2388
- take?: number;
2389
- cursor?: string;
2390
- sort?: 'NEWEST' | 'OLDEST' | 'HIGHEST_RATING' | 'LOWEST_RATING' | 'MOST_HELPFUL';
2391
- rating?: number;
2392
- }
2393
- export interface RecentReviewsOptions {
2394
- limit?: number;
2395
- minRating?: number;
2396
- languageCode?: string;
2397
- }
2398
- export interface CreateReviewResult {
2399
- review: ProductReview;
2400
- requiresModeration: boolean;
2401
- }
2402
- export interface ReviewMediaUploadResult {
2403
- id: string;
2404
- preview: string;
2405
- mimeType: string;
2406
- }
2407
- export type CustomerSubscriptionStatus = 'incomplete' | 'trial' | 'active' | 'paused' | 'past_due' | 'cancelled' | 'expired' | 'completed' | 'INCOMPLETE' | 'TRIAL' | 'ACTIVE' | 'PAUSED' | 'PAST_DUE' | 'CANCELLED' | 'EXPIRED' | 'COMPLETED';
2408
- export type SubscriptionFirstChargeTiming = 'immediate' | 'after_interval';
1162
+ /** A subscription change a shopper can ask for. */
2409
1163
  export type SubscriptionLifecycleAction = 'pause' | 'resume' | 'skip' | 'reschedule' | 'cancel' | 'undoCancellation';
2410
- export interface SubscriptionProduct {
2411
- variantId: string;
2412
- quantity: number;
2413
- name: string;
2414
- sku: string;
2415
- }
2416
- export interface SubscriptionAllowedAction {
2417
- action: string;
2418
- allowed: boolean;
2419
- reason: string | null;
2420
- }
2421
- export interface SubscriptionUpcomingPayment {
2422
- dueAt: string | null;
2423
- amount: number;
2424
- currencyCode: string;
2425
- /**
2426
- * The outstanding cycle's payment state (`ready`, `processing`, `pending`,
2427
- * `action_required`, `unknown`, `failed`, or `charged_back` — a paid cycle the
2428
- * bank reversed), else a live checkout's state, else `scheduled`, `paused` or
2429
- * `none`. `failed` and `charged_back` are recovered with
2430
- * `recoverMySubscriptionPayment`.
2431
- */
2432
- state: string;
2433
- nextRetryAt: string | null;
2434
- checkoutUrl: string | null;
2435
- }
2436
- export interface SubscriptionPurchasePreview {
2437
- planId: string;
2438
- planName: string;
2439
- /**
2440
- * What the customer is charged per cycle, in minor units: products, shipping and
2441
- * the tax of their zone included. Pass it back as `expectedAmount` when starting.
2442
- */
2443
- amount: number;
2444
- /**
2445
- * Whether plan prices on this channel include tax. When false the plan price is
2446
- * net and `amount` adds the customer's VAT (none under reverse charge).
2447
- */
2448
- pricesIncludeTax: boolean;
2449
- /** `amount` without tax. */
2450
- netAmount: number;
2451
- /** The tax in `amount` for the customer's tax zone. */
2452
- taxAmount: number;
2453
- currencyCode: string;
2454
- firstPaymentAt: string;
2455
- firstChargeTiming: SubscriptionFirstChargeTiming;
2456
- billingInterval: string;
2457
- billingIntervalCount: number;
2458
- trialDays: number;
2459
- trialEndsAt: string | null;
2460
- minCycles: number | null;
2461
- maxCycles: number | null;
2462
- customerChangeCutoffHours: number;
2463
- cutoffAt: string | null;
2464
- mandateVerificationAmount: number;
2465
- products: SubscriptionProduct[];
2466
- }
2467
- export interface SubscriptionPurchaseInput {
2468
- planId: string;
2469
- provider?: 'mollie' | 'stripe';
2470
- mandateId?: string;
2471
- returnUrl: string;
2472
- /** Persist this key for the purchase; reuse it when retrying the same request. */
2473
- requestKey: string;
2474
- /**
2475
- * The previewed `amount`. When given, the purchase is rejected — before any
2476
- * payment starts — if the price changed since the preview; preview again.
2477
- */
2478
- expectedAmount?: number;
2479
- }
2480
- export interface SubscriptionPaymentActionInput {
2481
- requestKey: string;
2482
- returnUrl: string;
2483
- provider?: 'mollie' | 'stripe';
2484
- }
2485
- export interface SubscriptionLifecycleCommand {
1164
+ /**
1165
+ * A subscription change as a storefront sends it: the schema's
1166
+ * `SubscriptionLifecycleCommand` without `overrideReason` (staff only; the Shop
1167
+ * API refuses it), with `action` one of the storefront actions. Reuse
1168
+ * `requestKey` when retrying the same change.
1169
+ */
1170
+ export type SubscriptionLifecycleCommand = Omit<Shop.SubscriptionLifecycleCommand, 'action' | 'overrideReason'> & {
2486
1171
  action: SubscriptionLifecycleAction;
2487
- requestKey: string;
2488
- date?: string;
2489
- reason?: string;
2490
- }
2491
- export interface SubscriptionChangePreview {
2492
- allowed: boolean;
2493
- reason: string | null;
2494
- nextRenewalAt: string | null;
2495
- cancellationEffectiveAt: string | null;
2496
- committedPayment: boolean;
2497
- remainingPaidCycles: number;
2498
- }
2499
- export interface SubscriptionPurchaseResult {
2500
- id: string;
2501
- subscriptionId: string;
2502
- state: string;
2503
- checkoutUrl: string | null;
2504
- expiresAt: string | null;
2505
- currentStatus: string | null;
2506
- paymentActionRequired: boolean;
2507
- nextRenewalAt: string | null;
2508
- }
2509
- export interface CustomerSubscription {
2510
- billingIntervalCount: number;
2511
- trialEndsAt: string | null;
2512
- minCycles: number | null;
2513
- maxCycles: number | null;
2514
- paidCycleCount: number;
2515
- firstChargeTiming: SubscriptionFirstChargeTiming;
2516
- customerChangeCutoffHours: number;
2517
- cutoffAt: string | null;
2518
- cancellationRequested: boolean;
2519
- cancellationEffectiveAt: string | null;
2520
- earliestCancellationAt: string | null;
2521
- remainingPaidCycles: number;
2522
- committedPayment: boolean;
2523
- resumeAt: string | null;
2524
- retainedResumeAt: string | null;
2525
- earliestResumeAt: string;
2526
- allowedActions: SubscriptionAllowedAction[];
2527
- products: SubscriptionProduct[];
2528
- paymentActionRequired: boolean;
2529
- upcomingPayment: SubscriptionUpcomingPayment;
2530
- id: string;
2531
- planName: string;
2532
- currencyCode: string;
2533
- recurringPrice: number;
2534
- billingInterval: string;
2535
- currentStatus: CustomerSubscriptionStatus | null;
2536
- currentPeriodStart: string | null;
2537
- currentPeriodEnd: string | null;
2538
- nextRenewalAt: string | null;
2539
- cancelAtPeriodEnd: boolean;
2540
- createdAt: string;
2541
- }
2542
- /** Customer-safe subscription plan for the storefront catalogue. */
2543
- export interface SubscriptionPlanPublic {
2544
- firstChargeTiming: SubscriptionFirstChargeTiming;
2545
- customerChangeCutoffHours: number;
2546
- id: string;
2547
- name: string;
2548
- description: string | null;
2549
- currencyCode: string;
2550
- /**
2551
- * Price per cycle in minor units, shipping included, on the channel's price
2552
- * basis: gross when the channel's prices include tax, otherwise net. Use
2553
- * `previewSubscriptionPurchase` for the amount a customer is charged.
2554
- */
2555
- price: number;
2556
- billingInterval: string;
2557
- billingIntervalCount: number;
2558
- trialDays: number;
2559
- minCycles: number | null;
2560
- maxCycles: number | null;
2561
- }
2562
- /** Customer-safe view of a stored payment mandate. */
2563
- export interface MyPaymentMandate {
2564
- id: string;
2565
- provider: string;
2566
- mandateMethod: string | null;
2567
- /** 'pending' | 'valid' | 'invalid' | 'revoked' */
2568
- mandateStatus: string;
2569
- isDefault: boolean;
2570
- createdAt: string;
2571
- }
2572
- export interface SetupPaymentMandateResult {
2573
- mandate: MyPaymentMandate;
2574
- /** Mollie checkout URL to redirect the customer to (null for Stripe). */
2575
- checkoutUrl: string | null;
2576
- /** Stripe SetupIntent client secret (null for Mollie). */
2577
- clientSecret: string | null;
2578
- }
2579
- export type QuoteStatus = 'draft' | 'requested' | 'in_review' | 'approved' | 'declined' | 'expired' | 'converted_to_order' | 'cancelled';
2580
- export interface QuoteLine {
2581
- id: string;
2582
- productVariantId: string;
2583
- quantity: number;
2584
- /** Minor units in the quote currency. Null until a sales rep prices the line. */
2585
- unitPrice: number | null;
2586
- /**
2587
- * Line-level discount the rep applied. `percentage` is basis points
2588
- * (10000 = 100%); `fixed` is whole-line minor units. Null when no discount.
2589
- */
2590
- discountType: 'percentage' | 'fixed' | null;
2591
- /** Discount magnitude (basis points for `percentage`, minor units for `fixed`). */
2592
- discountValue: number;
2593
- discountLabel: string | null;
2594
- position: number;
2595
- /**
2596
- * Variant display name at read time, in the request's language. `null` when
2597
- * the variant has been deleted or left the channel — render a placeholder
2598
- * rather than scanning the catalogue for it.
2599
- *
2600
- * Optional, like the five fields below: they are `undefined` against a
2601
- * Vendure that predates them, which the client detects once and then stops
2602
- * asking for (see `createQuotesMethods`).
2603
- */
2604
- productName?: string | null;
2605
- /** Variant SKU at read time. `null` under the same conditions as `productName`. */
2606
- sku?: string | null;
2607
- /**
2608
- * Effective tax rate for this line as a PERCENT — 21 for 21%, and fractional
2609
- * where the statutory rate is (13.5 in IE, 8.1 in CH). It is the variant's
2610
- * own applied TaxRate, the rate the converted order is charged at; never
2611
- * assume a national rate. `null` when the variant is unavailable.
2612
- */
2613
- taxRate?: number | null;
2614
- /**
2615
- * Per-unit GROSS (incl. tax) price in minor units, with the whole-line
2616
- * discount already amortised across the units. `null` when the variant is
2617
- * unavailable, and while the line is still unpriced (`unitPrice` is `null`,
2618
- * i.e. a draft or requested quote) — render a placeholder, never `0`.
2619
- *
2620
- * Derived from `lineTotalWithTax / quantity`, so it is the quote's own
2621
- * agreed per-unit figure: `unitPriceWithTax × quantity` reconciles with the
2622
- * line total exactly, and may differ from the variant's catalogue gross
2623
- * unit price by a rounding unit.
2624
- */
2625
- unitPriceWithTax?: number | null;
2626
- /**
2627
- * NET (excl. tax) line total in minor units, after discount. `null` when the
2628
- * variant is unavailable or the line is still unpriced.
2629
- */
2630
- lineTotal?: number | null;
2631
- /**
2632
- * GROSS (incl. tax) line total in minor units, after discount — what this
2633
- * line adds to the payable total. `null` when the variant is unavailable or
2634
- * the line is still unpriced.
2635
- *
2636
- * This is the quote's OWN line maths. The order `acceptQuote` creates
2637
- * re-prices per unit, so an order total can differ from the sum of these by
2638
- * a minor unit per line when the discount does not divide evenly.
2639
- */
2640
- lineTotalWithTax?: number | null;
2641
- createdAt: string;
2642
- updatedAt: string;
2643
- }
2644
- export interface Quote {
2645
- id: string;
2646
- code: string;
2647
- channelId: string;
2648
- customerId: string;
2649
- currencyCode: string;
2650
- status: QuoteStatus;
2651
- expiresAt: string | null;
2652
- salesRepUserId: string | null;
2653
- customerNotes: string | null;
2654
- /** Set once the quote has been accepted and converted to an Order. */
2655
- convertedOrderId: string | null;
2656
- lines: QuoteLine[];
2657
- createdAt: string;
2658
- updatedAt: string;
2659
- }
2660
- export interface QuoteList {
2661
- items: Quote[];
2662
- totalItems: number;
2663
- }
2664
- export interface QuoteListOptions {
2665
- take?: number;
2666
- skip?: number;
2667
- status?: QuoteStatus;
2668
- }
2669
- export interface CreateQuoteRequestInput {
2670
- items: Array<{
2671
- productVariantId: string;
2672
- quantity: number;
2673
- }>;
2674
- customerNotes?: string;
2675
- }
1172
+ };
2676
1173
  /**
2677
- * Lifecycle state of a return, derived from its status log. Customers can
2678
- * only cancel while still `requested`; everything after that is merchant- or
2679
- * system-driven.
1174
+ * A subscription purchase as a storefront starts it: the schema's
1175
+ * `SubscriptionPurchaseInput` without `customerId` (always the signed-in
1176
+ * customer; the Shop API refuses another) and `sendPaymentEmail` (a staff
1177
+ * option the Shop API ignores), with `provider` one of the providers the plugin
1178
+ * has. Persist `requestKey` for the purchase and reuse it when retrying. Pass
1179
+ * the previewed `amount` as `expectedAmount` to have the purchase refused —
1180
+ * before any payment starts — if the price changed since the preview.
2680
1181
  */
2681
- export type CustomerReturnState = 'requested' | 'approved' | 'rejected' | 'cancelled' | 'items_received' | 'settlement_pending' | 'settlement_failed' | 'settled';
2682
- export type CustomerReturnSettlementMethod = 'refund' | 'store_credit';
2683
- export type CustomerReturnReasonCode = 'damaged' | 'defective' | 'wrong_item' | 'not_as_described' | 'arrived_late' | 'no_longer_needed' | 'order_error' | 'other';
2684
- export interface CustomerReturnLine {
2685
- id: string;
2686
- orderLineId: string;
2687
- productVariantId: string;
2688
- productVariantName: string;
2689
- productVariantSku: string;
2690
- requestedQty: number;
2691
- /** Null until the merchant approves; 0 means the line was declined. */
2692
- approvedQty: number | null;
2693
- /** Cumulative units received back by the merchant across all receipts. */
2694
- receivedQty: number;
2695
- restockQty: number;
2696
- writeOffQty: number;
2697
- reasonCode: CustomerReturnReasonCode;
2698
- reasonNote: string | null;
2699
- /** Snapshot of the order line's prorated unit price incl. tax (minor units). */
2700
- unitPriceWithTax: number;
2701
- /**
2702
- * The same snapshot before per-unit rounding; null for returns requested
2703
- * before the field existed. Multiply by a quantity and round ONCE to get
2704
- * that quantity's share, exactly as the order line totals itself.
2705
- */
2706
- unitPriceWithTaxUnrounded: number | null;
2707
- /** Refund amount for this line (minor units); null until approved. */
2708
- refundAmount: number | null;
2709
- }
2710
- /** A customer-facing return (RMA). All money fields are Int minor units. */
2711
- export interface CustomerReturn {
2712
- id: string;
2713
- /** Human-facing RMA code, e.g. RMA-000042. */
2714
- code: string;
2715
- state: CustomerReturnState;
2716
- orderId: string;
2717
- orderCode: string;
2718
- currencyCode: string;
2719
- preferredSettlementMethod: CustomerReturnSettlementMethod | null;
2720
- /** Settlement method actually used; null until settled. */
2721
- settlementMethod: CustomerReturnSettlementMethod | null;
2722
- /** Shipping refunded on top of line refunds (minor units). */
2723
- shippingRefundAmount: number;
2724
- /** Total actually settled (minor units); null until settled. */
2725
- settledAmount: number | null;
2726
- customerNote: string | null;
2727
- requestedAt: string;
2728
- resolvedAt: string | null;
2729
- lines: CustomerReturnLine[];
2730
- createdAt: string;
2731
- }
2732
- export interface CustomerReturnList {
2733
- items: CustomerReturn[];
2734
- totalItems: number;
2735
- }
2736
- export interface CustomerReturnListOptions {
2737
- take?: number;
2738
- skip?: number;
2739
- }
2740
- export interface RequestReturnLineInput {
2741
- orderLineId: string;
2742
- quantity: number;
2743
- reasonCode: CustomerReturnReasonCode;
2744
- reasonNote?: string;
2745
- }
2746
- export interface RequestReturnInput {
2747
- orderId: string;
2748
- lines: RequestReturnLineInput[];
2749
- customerNote?: string;
2750
- preferredSettlementMethod?: CustomerReturnSettlementMethod;
2751
- }
2752
- /** Per-order-line returnable quantities for the return-request flow. */
2753
- export interface ReturnableOrderLine {
2754
- orderLineId: string;
2755
- productVariantId: string;
2756
- productVariantName: string;
2757
- productVariantSku: string;
2758
- /** Units shipped or delivered for this order line. */
2759
- fulfilledQty: number;
2760
- /** fulfilledQty minus quantities tied up in active returns. */
2761
- returnableQty: number;
2762
- /** The order line's prorated unit price incl. tax (minor units). */
2763
- unitPriceWithTax: number;
2764
- /**
2765
- * The same price before per-unit rounding. Multiply by a quantity and round
2766
- * ONCE to preview that quantity's refund, exactly as the order line totals
2767
- * itself.
2768
- */
2769
- unitPriceWithTaxUnrounded: number;
2770
- }
2771
- export interface CustomerReturnEligibility {
2772
- orderId: string;
2773
- eligible: boolean;
2774
- /** Why the order is not eligible; null when eligible. */
2775
- reason: string | null;
2776
- returnWindowEndsAt: string | null;
2777
- /** Only lines with fulfilled quantity appear here. */
2778
- lines: ReturnableOrderLine[];
2779
- }
1182
+ export type SubscriptionPurchaseInput = Omit<Shop.SubscriptionPurchaseInput, 'customerId' | 'sendPaymentEmail' | 'provider'> & {
1183
+ provider?: 'mollie' | 'stripe' | null;
1184
+ };
2780
1185
  /**
2781
- * The authenticated customer's B2B accounts-receivable credit status in the
2782
- * current channel. All money fields are in minor units of `currencyCode`.
2783
- * Returned by `client.credit.getCreditStatus()`; `null` when the customer is
2784
- * not signed in, has no credit account, or the channel has B2B credit disabled.
1186
+ * A payment action on a subscription (`recoverMySubscriptionPayment`,
1187
+ * `replaceMySubscriptionMandate`): the schema's `SubscriptionPaymentActionInput`
1188
+ * with `provider` one of the providers the plugin has.
2785
1189
  */
2786
- export interface B2bCreditStatus {
2787
- customerId: string;
2788
- currencyCode: string;
2789
- /** Outstanding invoiced-but-unpaid ledger balance. */
2790
- balance: number;
2791
- /** Total value of placed B2B orders not yet invoiced. */
2792
- uninvoicedOrdersTotal: number;
2793
- /** Total credit exposure (`balance + uninvoicedOrdersTotal`). */
2794
- exposure: number;
2795
- /** Configured credit limit; `null` when no limit is set. */
2796
- creditLimit: number | null;
2797
- /** Remaining headroom (`creditLimit - exposure`); `null` when no limit is set. */
2798
- available: number | null;
2799
- overdueInvoiceCount: number;
2800
- overLimit: boolean;
2801
- hasOverdue: boolean;
2802
- /**
2803
- * Where `balance` was sourced from. `LOCAL_LEDGER` = computed from the local
2804
- * AR subledger; `ERP_LIVE` = read live from the ERP; `ERP_UNLINKED` = the
2805
- * channel is ERP-driven but this customer isn't linked yet (treat the balance
2806
- * as unavailable rather than zero, and surface a "not linked" notice).
2807
- */
2808
- balanceSource: CreditBalanceSource;
2809
- }
2810
- /** Where a {@link B2bCreditStatus.balanceSource} balance was sourced from. */
2811
- export type CreditBalanceSource = 'LOCAL_LEDGER' | 'ERP_LIVE' | 'ERP_UNLINKED';
2812
- /** How reliably the source payment condition could be interpreted. */
2813
- export type PaymentTermsClassification = 'SINGLE_DUE_DATE' | 'COMPLEX' | 'UNRESOLVED' | 'UNASSIGNED' | 'CONFLICT';
2814
- /** Assignment and freshness state for externally managed customer payment terms. */
2815
- export type PaymentTermsStatus = 'ASSIGNED' | 'UNASSIGNED' | 'UNRESOLVED' | 'STALE' | 'CONFLICT';
1190
+ export type SubscriptionPaymentActionInput = Omit<Shop.SubscriptionPaymentActionInput, 'provider'> & {
1191
+ provider?: 'mollie' | 'stripe' | null;
1192
+ };
2816
1193
  /**
2817
- * Source-aware payment terms for the authenticated customer. Exact-backed terms preserve the
2818
- * original condition code and complex-rule fields rather than reducing every condition to days.
1194
+ * A quote line as either quote document answers it. The client retries a quote
1195
+ * document without the six per-line fields — `productName`, `sku`, `taxRate`,
1196
+ * `unitPriceWithTax`, `lineTotal`, `lineTotalWithTax` — once an engine refuses
1197
+ * them (and then stops asking), so those six are optional: `undefined` against
1198
+ * such an engine, `null` where the engine has nothing (an unpriced line, a
1199
+ * variant that left the channel).
2819
1200
  */
2820
- export interface CustomerPaymentTerms {
2821
- customerId: string | null;
2822
- source: string;
2823
- managedExternally: boolean;
2824
- status: PaymentTermsStatus;
2825
- conditionCode: string | null;
2826
- conditionDescription: string | null;
2827
- summary: string;
2828
- classification: PaymentTermsClassification;
2829
- paymentDays: number | null;
2830
- paymentEndOfMonths: number | null;
2831
- paymentMethod: string | null;
2832
- percentage: number | null;
2833
- discountPaymentDays: number | null;
2834
- discountPercentage: number | null;
2835
- paymentDiscountType: string | null;
2836
- stale: boolean;
2837
- syncedAt: string | null;
2838
- error: string | null;
2839
- }
2840
- /** Payment terms frozen on an order at acceptance, including later remote confirmation metadata. */
2841
- export interface OrderPaymentTermsSnapshot extends Omit<CustomerPaymentTerms, 'customerId'> {
2842
- resolvedAt: string;
2843
- remoteConditionCode: string | null;
2844
- remoteConfirmedAt: string | null;
2845
- /** True after the ERP confirms a different condition than the accepted snapshot. */
2846
- remoteMismatch: boolean;
2847
- }
2848
- /** Assignment and freshness state for Exact-managed customer delivery terms. */
2849
- export type DeliveryTermsStatus = 'ASSIGNED' | 'UNASSIGNED' | 'UNRESOLVED' | 'STALE' | 'CONFLICT';
2850
- /** Exact's account-level partial-delivery policy, exposed as operational guidance. */
2851
- export type DeliveryAdvice = 'PARTIAL_ALLOWED' | 'COMPLETE_ORDER' | 'PARTIAL_WITHOUT_BACKORDER' | 'UNKNOWN';
2852
- /** Why the placed order uses its selected shipping method. */
2853
- export type DeliverySelectionSource = 'CUSTOMER_DEFAULT' | 'EXPLICIT_OVERRIDE' | 'IMPORTED' | 'UNKNOWN';
1201
+ export type QuoteLine = Shop.QuoteLegacyFragment['lines'][number] & Partial<Omit<Shop.QuoteFragment['lines'][number], keyof Shop.QuoteLegacyFragment['lines'][number]>>;
1202
+ /** A quote as either quote document answers it — see {@link QuoteLine}. */
1203
+ export type Quote = Omit<Shop.QuoteFragment, 'lines'> & {
1204
+ lines: QuoteLine[];
1205
+ };
1206
+ /** One page of `getMyQuotes`. */
1207
+ export type QuoteList = Omit<Shop.MyQuotesQuery['myQuotes'], 'items'> & {
1208
+ items: Quote[];
1209
+ };
2854
1210
  /**
2855
- * Exact-aware delivery terms for the authenticated customer in the current channel.
2856
- * The preferred method is a default, not an eligibility restriction; checkout pricing
2857
- * still comes from the platform's shipping calculator.
1211
+ * The authenticated customer's B2B accounts-receivable credit status in the
1212
+ * current channel, as either credit document answers it. All money fields are
1213
+ * in minor units of `currencyCode`, the credit account's currency (the credit
1214
+ * limit's) — NOT the session currency. Money the customer owes in another
1215
+ * currency (orders placed in it) is converted into `currencyCode` at the
1216
+ * store's exchange rate. Returned by `client.credit.getCreditStatus()`; `null`
1217
+ * when the customer is not signed in, has no credit account, or the channel has
1218
+ * B2B credit disabled. `balanceSource` `ERP_UNLINKED` means the balance is
1219
+ * unavailable, not zero.
1220
+ *
1221
+ * `unconvertedCurrencies`: currencies the customer owes money in that the store
1222
+ * has no exchange rate for, and that are therefore NOT in `balance` /
1223
+ * `uninvoicedOrdersTotal` / `exposure`. Only ever non-empty when there is no
1224
+ * credit limit (with a limit the status is refused instead). When non-empty,
1225
+ * say the figures are incomplete rather than show them as everything owed.
1226
+ * `undefined` from an engine released before 2026-10-01 — the client retries
1227
+ * that engine with a document without the field — which never leaves money out.
2858
1228
  */
2859
- export interface CustomerDeliveryTerms {
2860
- customerId: string | null;
2861
- source: string;
2862
- managedExternally: boolean;
2863
- status: DeliveryTermsStatus;
2864
- shippingMethodStatus: DeliveryTermsStatus;
2865
- policyStatus: DeliveryTermsStatus;
2866
- summary: string;
2867
- preferredShippingMethodId: string | null;
2868
- preferredShippingMethodCode: string | null;
2869
- preferredShippingMethodName: string | null;
2870
- preferredShippingMethodAvailable: boolean;
2871
- /** Active platform mappings that may be selected as deliberate overrides. */
2872
- eligibleShippingMethodIds: string[];
2873
- incotermStatus: DeliveryTermsStatus;
2874
- incotermCode: string | null;
2875
- incotermVersion: number | null;
2876
- incotermAddress: string | null;
2877
- incotermDescription: string | null;
2878
- /** Exact dispatch lead time in days; this is not a promised arrival date. */
2879
- shippingLeadDays: number | null;
2880
- deliveryAdvice: DeliveryAdvice | null;
2881
- stale: boolean;
2882
- syncedAt: string | null;
2883
- /** Customer-safe warning; raw synchronization errors remain Admin-only. */
2884
- warning: string | null;
2885
- }
2886
- /** Delivery terms frozen on an order at acceptance, plus later Exact readback metadata. */
2887
- export interface OrderDeliveryTermsSnapshot {
2888
- source: string;
2889
- managedExternally: boolean;
2890
- status: DeliveryTermsStatus;
2891
- shippingMethodStatus: DeliveryTermsStatus;
2892
- policyStatus: DeliveryTermsStatus;
2893
- summary: string;
2894
- selectionSource: DeliverySelectionSource;
2895
- selectedShippingMethodId: string | null;
2896
- selectedShippingMethodCode: string | null;
2897
- selectedShippingMethodName: string | null;
2898
- platformShippingMethodCode: string | null;
2899
- platformShippingMethodName: string | null;
2900
- platformShippingMethodDescription: string | null;
2901
- /** Accepted platform shipping quote in order-currency minor units. */
2902
- platformShippingPrice: number | null;
2903
- /** Accepted platform shipping quote including tax, in order-currency minor units. */
2904
- platformShippingPriceWithTax: number | null;
2905
- preferredShippingMethodId: string | null;
2906
- incotermStatus: DeliveryTermsStatus;
2907
- incotermCode: string | null;
2908
- incotermVersion: number | null;
2909
- incotermAddress: string | null;
2910
- incotermDescription: string | null;
2911
- shippingLeadDays: number | null;
2912
- deliveryAdvice: DeliveryAdvice | null;
2913
- stale: boolean;
2914
- syncedAt: string | null;
2915
- warning: string | null;
2916
- resolvedAt: string;
2917
- remoteShippingMethodCode: string | null;
2918
- remoteShippingMethodName: string | null;
2919
- remoteIncotermCode: string | null;
2920
- remoteIncotermVersion: number | null;
2921
- remoteIncotermAddress: string | null;
2922
- remoteDeliveryDate: string | null;
2923
- remoteConfirmedAt: string | null;
2924
- /** True after Exact confirms delivery fields that differ from the accepted snapshot. */
2925
- remoteMismatch: boolean;
2926
- }
2927
- export interface VatValidationResult {
2928
- status: string;
2929
- vatNumber: string;
2930
- countryCode: string;
2931
- companyName: string | null;
2932
- companyAddress: string | null;
2933
- validatedAt: string | null;
2934
- error: string | null;
2935
- }
2936
- export interface DropOffPointInput {
2937
- postalCode: string;
2938
- countryCode?: string;
2939
- carrierId?: string;
1229
+ export type B2bCreditStatus = Shop.B2bCreditStatusLegacyFragment & Partial<Pick<Shop.B2bCreditStatusFragment, 'unconvertedCurrencies'>>;
1230
+ export interface CustomerReturnListOptions {
1231
+ take?: number;
1232
+ skip?: number;
2940
1233
  }
2941
1234
  export interface DropOffPoint {
2942
1235
  locationCode: string;
@@ -2957,16 +1250,6 @@ export interface DropOffPoint {
2957
1250
  /** Distance from the postal code, in metres. */
2958
1251
  distance: number | null;
2959
1252
  }
2960
- export interface DeliveryOptionsInput {
2961
- postalCode: string;
2962
- countryCode?: string;
2963
- carrierId?: number;
2964
- deliveryDate?: string;
2965
- cutoffTime?: string;
2966
- mondayDelivery?: boolean;
2967
- saturdayDelivery?: boolean;
2968
- dropoffDays?: string;
2969
- }
2970
1253
  export interface DeliveryTimeFrame {
2971
1254
  start: string;
2972
1255
  end: string;
@@ -3013,19 +1296,6 @@ export interface PickupLocation {
3013
1296
  /** Carrier-specific extras. */
3014
1297
  details?: Record<string, unknown>;
3015
1298
  }
3016
- export interface PickupLocationSearchInput {
3017
- /** ISO 3166-1 alpha-2 country code. */
3018
- countryCode: string;
3019
- postalCode: string;
3020
- carrierId: number;
3021
- city?: string;
3022
- street?: string;
3023
- number?: string;
3024
- latitude?: number;
3025
- longitude?: number;
3026
- /** Search radius in metres. */
3027
- distance?: number;
3028
- }
3029
1299
  export interface ShipmentTrackingHistoryEntry {
3030
1300
  status: number;
3031
1301
  time: string;
@@ -3041,9 +1311,46 @@ export interface ShipmentTrackingInfo {
3041
1311
  consumerPortalLink: string | null;
3042
1312
  }
3043
1313
  export interface CommerceModule {
3044
- getProduct(slug: string, options?: RequestOptions): Promise<Product>;
3045
- getProductById(id: string, options?: RequestOptions): Promise<Product>;
3046
- getProducts(listOptions?: ProductListOptions, options?: RequestOptions): Promise<PaginatedList<ProductSummary>>;
1314
+ /**
1315
+ * A product by slug. `{ metafields: true }` (or `{ metafields: { namespace }
1316
+ * }`) also returns its storefront-visible metafields and each variant's in
1317
+ * the same request; it needs an engine serving `Product.metafields`.
1318
+ */
1319
+ getProduct(slug: string, options: import('./commerce/products.js').CatalogDetailOptions & {
1320
+ metafields: true | {
1321
+ namespace: string;
1322
+ };
1323
+ }): Promise<import('./commerce/products.js').ProductWithMetafields>;
1324
+ getProduct(slug: string, options?: import('./commerce/products.js').CatalogDetailOptions & {
1325
+ metafields?: false;
1326
+ }): Promise<Product>;
1327
+ getProduct(slug: string, options?: import('./commerce/products.js').CatalogDetailOptions): Promise<Product | import('./commerce/products.js').ProductWithMetafields>;
1328
+ /** {@link CommerceModule.getProduct} by id, tagged `product:<id>`. */
1329
+ getProductById(id: string, options: import('./commerce/products.js').CatalogDetailOptions & {
1330
+ metafields: true | {
1331
+ namespace: string;
1332
+ };
1333
+ }): Promise<import('./commerce/products.js').ProductWithMetafields>;
1334
+ getProductById(id: string, options?: import('./commerce/products.js').CatalogDetailOptions & {
1335
+ metafields?: false;
1336
+ }): Promise<Product>;
1337
+ getProductById(id: string, options?: import('./commerce/products.js').CatalogDetailOptions): Promise<Product | import('./commerce/products.js').ProductWithMetafields>;
1338
+ /** Grid-tile rows — see {@link ProductListOptions.detail}. */
1339
+ getProducts(listOptions: ProductListOptions & {
1340
+ detail: 'card';
1341
+ collectionSlug?: undefined;
1342
+ }, options?: RequestOptions): Promise<PaginatedList<Shop.ProductCardFragment>>;
1343
+ /** Full list rows, the default. */
1344
+ getProducts(listOptions?: ProductListOptions & {
1345
+ detail?: 'full';
1346
+ collectionSlug?: undefined;
1347
+ }, options?: RequestOptions): Promise<PaginatedList<Shop.ProductSummaryFragment>>;
1348
+ /**
1349
+ * Any other options — not literals, or the deprecated `collectionSlug`: any
1350
+ * of the three row shapes. `collectionSlug` reroutes to search rows only
1351
+ * when it is non-empty, which its type cannot say.
1352
+ */
1353
+ getProducts(listOptions?: ProductListOptions, options?: RequestOptions): Promise<ProductListPage>;
3047
1354
  getProductsInCollection(collectionSlug: string, listOptions?: CollectionProductListOptions, options?: RequestOptions): Promise<PaginatedList<CollectionProductSummary>>;
3048
1355
  /**
3049
1356
  * `getProductsInCollection` by collection id — typically `route.id` from the
@@ -3051,33 +1358,178 @@ export interface CommerceModule {
3051
1358
  * so `collection.membership_changed` purges the listing.
3052
1359
  */
3053
1360
  getProductsInCollectionById(collectionId: string, listOptions?: CollectionProductListOptions, options?: RequestOptions): Promise<PaginatedList<CollectionProductSummary>>;
3054
- getFacets(options?: RequestOptions): Promise<Facet[]>;
3055
- searchProducts(input: SearchInput, options?: RequestOptions): Promise<SearchResult>;
3056
- getActiveOrder(): Promise<Order | null>;
3057
- addToCart(variantId: string, quantity: number): Promise<Order>;
1361
+ getFacets(options?: RequestOptions): Promise<Shop.FacetFragment[]>;
1362
+ searchProducts(input: SearchInput, options?: RequestOptions): Promise<Shop.SearchResultFragment>;
1363
+ getActiveOrder(): Promise<Shop.OrderFragment | null>;
1364
+ /**
1365
+ * Refused with `StorefrontError` `VARIANT_NOT_FOR_SALE_IN_CURRENCY` (422) when
1366
+ * the store does not sell the product in the client's currency, and when the
1367
+ * cart holds a product it does not sell there (see `setOrderCurrency`). So are
1368
+ * `addItemsToCart` and `updateCartLine`; the cart is left as it was.
1369
+ *
1370
+ * Refused with `StorefrontError` `PRODUCT_EXCLUDED_FROM_STORE` (422, an engine
1371
+ * released on or after 2026-10-05) when the store no longer sells the product;
1372
+ * so are `addItemsToCart` (the whole call) and `updateCartLine` raising such a
1373
+ * line. Lowering or removing a line always works.
1374
+ */
1375
+ addToCart(variantId: string, quantity: number): Promise<Shop.OrderFragment>;
3058
1376
  /** Add several variants in one call (e.g. favourite-box bundles). */
3059
- addItemsToCart(items: Array<{
3060
- productVariantId: string;
3061
- quantity: number;
3062
- }>): Promise<Order>;
3063
- updateCartLine(lineId: string, quantity: number): Promise<Order>;
3064
- removeFromCart(lineId: string): Promise<Order>;
1377
+ addItemsToCart(items: Shop.AddItemInput[]): Promise<Shop.OrderFragment>;
1378
+ updateCartLine(lineId: string, quantity: number): Promise<Shop.OrderFragment>;
1379
+ removeFromCart(lineId: string): Promise<Shop.OrderFragment>;
3065
1380
  /** Remove every line from the active order, leaving an empty cart. */
3066
- clearCart(): Promise<Order>;
3067
- applyCouponCode(code: string): Promise<Order>;
3068
- removeCouponCode(code: string): Promise<Order>;
3069
- setCustomerForOrder(input: CustomerInput): Promise<Order>;
3070
- setShippingAddress(input: AddressInput): Promise<Order>;
3071
- setBillingAddress(input: AddressInput): Promise<Order>;
3072
- getEligibleShippingMethods(): Promise<ShippingMethod[]>;
1381
+ clearCart(): Promise<Shop.OrderFragment>;
1382
+ applyCouponCode(code: string): Promise<Shop.OrderFragment>;
1383
+ /** `null` when there is no active order to remove the code from. */
1384
+ removeCouponCode(code: string): Promise<Shop.OrderFragment | null>;
1385
+ setCustomerForOrder(input: Shop.CreateCustomerInput): Promise<Shop.OrderFragment>;
1386
+ setShippingAddress(input: Shop.CreateAddressInput): Promise<Shop.OrderFragment>;
1387
+ setBillingAddress(input: Shop.CreateAddressInput): Promise<Shop.OrderFragment>;
1388
+ /**
1389
+ * Remove the delivery address from the active order (engine 3.1+) and
1390
+ * return it re-priced: with no address the order falls back to the channel's
1391
+ * default tax zone. Drops the cached tax display mode, like
1392
+ * {@link CommerceModule.setShippingAddress}. `NO_ACTIVE_ORDER_ERROR` throws
1393
+ * `MutationError`.
1394
+ */
1395
+ unsetShippingAddress(options?: RequestOptions): Promise<Shop.OrderFragment>;
1396
+ /**
1397
+ * Remove the billing address from the active order (engine 3.1+).
1398
+ * `NO_ACTIVE_ORDER_ERROR` throws `MutationError`.
1399
+ */
1400
+ unsetBillingAddress(options?: RequestOptions): Promise<Shop.OrderFragment>;
1401
+ /**
1402
+ * Write order custom fields on the active order; returns the order with the
1403
+ * writable fields (`customFields`) as the engine stored them.
1404
+ *
1405
+ * Writable are exactly the members of `UpdateOrderCustomFieldsInput`
1406
+ * (the engine's public, non-read-only order fields): `isGift`, `giftNote`,
1407
+ * `hidePricesOnPackingSlip`, `poNumber` (≤ 255 characters),
1408
+ * `requestedDeliveryDate`, `orderNotes` (≤ 5000 characters) and the
1409
+ * sixtynine.email attribution fields `snTid`, `snUtmSource`, `snUtmMedium`,
1410
+ * `snUtmCampaign`, `snFlowId`, `snEnrollmentId`, `snStepId`. `null` clears
1411
+ * a field; one left out is left as it is.
1412
+ *
1413
+ * `requestedDeliveryDate` is a DAY, sent as midnight UTC of that day
1414
+ * (`2026-10-14T00:00:00.000Z`); the engine refuses a day before yesterday
1415
+ * (UTC) or more than 400 days ahead.
1416
+ *
1417
+ * `paymentIntent`, `orderScope` and `chargedParcelCount` are readable, never
1418
+ * writable here: set the intent with {@link CommerceModule.setPaymentIntent},
1419
+ * which re-prices the order in the same call. Naming one of them, or passing
1420
+ * a `fields` that is not an object, throws a 400 `INVALID_ARGUMENT` before
1421
+ * any request. A value the engine's validation refuses (a 256-character
1422
+ * `poNumber`, a past delivery day) throws its `StorefrontError`;
1423
+ * `NO_ACTIVE_ORDER_ERROR` throws `MutationError`.
1424
+ *
1425
+ * The returned `customFields` selects the attribution fields, so this call
1426
+ * needs an engine that has them (released 2026-09-22).
1427
+ */
1428
+ setOrderCustomFields(fields: Shop.UpdateOrderCustomFieldsInput, options?: RequestOptions): Promise<import('./commerce/checkout.js').OrderWithWritableCustomFields>;
1429
+ /**
1430
+ * Switch the shopper to another of the channel's currencies: the active
1431
+ * order comes back re-priced in it, and from then on this client names the
1432
+ * currency on every Shop API request (`?currencyCode=`), so catalogue prices,
1433
+ * later cart changes and checkout all stay in it and `pricing.format*`
1434
+ * default to it. (The engine re-prices an order into the REQUEST's currency
1435
+ * on every change; a request that names none is the channel default.)
1436
+ * Persist the code and pass it as `createStorefrontClient({ currencyCode })`
1437
+ * to restore the choice on a new client, e.g. on the next server render.
1438
+ *
1439
+ * Only while the order is a cart (`AddingItems`); later states throw
1440
+ * `MutationError` `ORDER_MODIFICATION_ERROR` and the client keeps its
1441
+ * currency. A currency the store does not offer
1442
+ * (`ActiveChannel.availableCurrencyCodes`) is refused with
1443
+ * `StorefrontError` `CURRENCY_NOT_AVAILABLE` (400); a value that is not three
1444
+ * upper-case letters throws a 400 `INVALID_ARGUMENT` before any request. The
1445
+ * order's current currency returns it unchanged. Like the engine, it creates
1446
+ * an empty active order when there is none.
1447
+ *
1448
+ * A cart holding a product the store does not sell in `currencyCode` (its
1449
+ * `forSaleInCurrency` is `false` there) is refused with `StorefrontError`
1450
+ * `VARIANT_NOT_FOR_SALE_IN_CURRENCY` (422, an engine released on or after
1451
+ * 2026-10-03): the cart and the client keep their currency, and the message
1452
+ * is a sentence for the buyer naming the currency. The buyer removes those
1453
+ * products, or stays in the current currency. The same refusal answers any
1454
+ * cart change sent in such a currency, e.g. a restored
1455
+ * `createStorefrontClient({ currencyCode })` the cart was never switched to;
1456
+ * `setOrderCurrency(order.currencyCode)` then puts the client back on the
1457
+ * cart's currency. Removing those products works in the cart's currency; in
1458
+ * another one the rest of the cart is re-priced into it, so a removal there
1459
+ * goes through only once no such product is left.
1460
+ *
1461
+ * Money the store sets in its DEFAULT currency, in another currency (an
1462
+ * engine released on or after 2026-09-30): order minimums (channel,
1463
+ * price-list and delivery-profile; `getOrderConstraints()`) are converted into
1464
+ * the order's currency at the rate checkout charges with. With no exchange
1465
+ * rate for that currency, checkout is refused while an amount minimum applies
1466
+ * (`PLACEMENT_BLOCKED`, `details[0].code` `EXCHANGE_RATE_UNAVAILABLE`) and the
1467
+ * shopper can switch back to the default currency. A price-list money figure
1468
+ * without its own currency (a fixed price, or a fixed amount off) applies
1469
+ * ONLY in the default currency: in another currency that entry is skipped and
1470
+ * the next applicable price-list rule applies, or else the product's own price
1471
+ * in that currency. Percentage discounts apply in every currency. An older
1472
+ * engine applied both minimums and those figures to another currency
1473
+ * unconverted, so there offer only the default currency. A fixed price or
1474
+ * amount the store set for THIS order (one-time pricing) applies only in the
1475
+ * currency it was set in (engine 2026-10-01): switching the cart away drops it.
1476
+ */
1477
+ setOrderCurrency(currencyCode: Shop.CurrencyCode, options?: RequestOptions): Promise<Shop.OrderFragment>;
1478
+ /**
1479
+ * The shipping methods the active order can ship with now. `metadata` is the
1480
+ * method's quote detail (a JSON value); `readParcelPricing(method.metadata)`
1481
+ * reads the extra-parcel charge from it.
1482
+ */
1483
+ getEligibleShippingMethods(): Promise<Shop.ShippingMethodsQuery['eligibleShippingMethods']>;
1484
+ /**
1485
+ * Every shipping method the channel offers in its storefront, whatever the
1486
+ * active order — for a delivery-options page. Methods switched off or
1487
+ * withheld from the storefront are left out by the engine.
1488
+ *
1489
+ * Not the checkout list: it ignores the order's address, weight and value.
1490
+ * Offer {@link CommerceModule.getEligibleShippingMethods} (or
1491
+ * `getEligibleShippingRates`) at checkout.
1492
+ */
1493
+ getActiveShippingMethods(options?: RequestOptions): Promise<Shop.PublicShippingMethodFragment[]>;
3073
1494
  /** Exact-aware delivery defaults for the signed-in customer, or null when unavailable. */
3074
- getDeliveryTerms(options?: RequestOptions): Promise<CustomerDeliveryTerms | null>;
3075
- setShippingMethod(ids: string[]): Promise<Order>;
1495
+ getDeliveryTerms(options?: RequestOptions): Promise<Shop.MyDeliveryTermsQuery['myDeliveryTerms']>;
1496
+ setShippingMethod(ids: string[]): Promise<Shop.OrderFragment>;
1497
+ /**
1498
+ * Every way the active order can ship now, cheapest first: each platform
1499
+ * method and each rate of each installed shipping-rates app (`source: 'app'`).
1500
+ * While an app cannot be asked, its rates are left out and the platform's
1501
+ * methods stay; the rate the order already carries is kept for 30 minutes
1502
+ * after the app last quoted it. `selected` marks the order's current choice.
1503
+ * Needs an engine with the `shipping.rates` hook (the query is new).
1504
+ */
1505
+ getEligibleShippingRates(): Promise<Shop.ShippingRatesQuery['eligibleShippingRates']>;
1506
+ /**
1507
+ * Ship the active order with a platform method (`rateCode` omitted) or one
1508
+ * rate of an app (`rateCode` from `getEligibleShippingRates`; omitted picks the
1509
+ * app's cheapest). Returns the re-priced order. A rate the app no longer
1510
+ * offers throws `MutationError` `INELIGIBLE_SHIPPING_METHOD_ERROR`; list the
1511
+ * rates again. Placement re-asks the app and refuses
1512
+ * `SHIPPING_RATE_UNAVAILABLE` when the chosen rate was withdrawn or re-priced,
1513
+ * or its app is down and the quote is older than 30 minutes.
1514
+ */
1515
+ setShippingRate(shippingMethodId: string, rateCode?: string | null): Promise<Shop.OrderFragment>;
3076
1516
  /** Apply the signed-in customer's currently eligible Exact default shipping method. */
3077
- applyPreferredShippingMethod(): Promise<Order>;
3078
- getEligiblePaymentMethods(): Promise<PaymentMethod[]>;
1517
+ applyPreferredShippingMethod(): Promise<Shop.OrderFragment>;
1518
+ getEligiblePaymentMethods(): Promise<Shop.PaymentMethodsQuery['eligiblePaymentMethods']>;
1519
+ /**
1520
+ * Every payment method the store offers in its storefront, whatever the
1521
+ * active order — for a "we accept" strip. The engine leaves out methods
1522
+ * withheld from the storefront and pay-later (net-terms) methods, which are
1523
+ * granted per customer. (An engine without the storefront filter, merged
1524
+ * 2026-09-30, listed every enabled method, staff-only ones included.)
1525
+ *
1526
+ * NOT the checkout list: it is not judged against the order, so a method
1527
+ * listed here can still be ineligible. Offer
1528
+ * {@link CommerceModule.getEligiblePaymentMethods} at checkout.
1529
+ */
1530
+ getActivePaymentMethods(options?: RequestOptions): Promise<Shop.PublicPaymentMethodFragment[]>;
3079
1531
  /** Order minimums on the active channel — display/pre-validation; server enforces. */
3080
- getOrderConstraints(): Promise<ActiveChannelOrderConstraints>;
1532
+ getOrderConstraints(): Promise<Shop.ActiveChannelOrderConstraintsQuery['activeChannelOrderConstraints']>;
3081
1533
  /**
3082
1534
  * Record how the buyer intends to settle this order and return the
3083
1535
  * **re-priced** order — a pay-now discount promotion only applies once the
@@ -3086,11 +1538,176 @@ export interface CommerceModule {
3086
1538
  * looking at were computed. Call it whenever the buyer picks or changes a
3087
1539
  * payment method, before {@link CommerceModule.transitionToArrangingPayment}.
3088
1540
  */
3089
- setPaymentIntent(intent: OrderPaymentIntent): Promise<Order>;
3090
- transitionToArrangingPayment(): Promise<Order>;
3091
- addPayment(input: PaymentInput): Promise<Order>;
1541
+ setPaymentIntent(intent: Shop.OrderPaymentIntent): Promise<Extract<Shop.SetOrderPaymentIntentMutation['setOrderPaymentIntent'], Shop.OrderFragment>>;
1542
+ transitionToArrangingPayment(): Promise<Shop.OrderFragment>;
1543
+ /**
1544
+ * The states the active order may move to next. A listed state can still be
1545
+ * refused by a guard when {@link CommerceModule.transitionOrder} asks for it:
1546
+ * this is the state machine's edges, not a promise. Like the engine, it
1547
+ * creates an empty active order (and a session) when there is none.
1548
+ */
1549
+ getNextOrderStates(options?: RequestOptions): Promise<string[]>;
1550
+ /**
1551
+ * Ask the engine to move the active order to `state` — the general form of
1552
+ * {@link CommerceModule.transitionToArrangingPayment}, e.g. `AddingItems` to
1553
+ * let the shopper edit the cart again after `ArrangingPayment`.
1554
+ *
1555
+ * The SDK decides nothing: the engine's order process and its guards (order
1556
+ * minimums, stock, app checks, a parked order's hold, payment) judge every
1557
+ * request, and a refusal throws `MutationError` `ORDER_STATE_TRANSITION_ERROR`
1558
+ * — `error.code` carries the structured reason when there is one and
1559
+ * `error.message` is safe to show the shopper. A blank `state` throws a 400
1560
+ * `INVALID_ARGUMENT` before any request.
1561
+ *
1562
+ * A placed state (`PaymentAuthorized`, `PaymentSettled`, …) is reached by
1563
+ * PAYING — {@link CommerceModule.addPayment} places the order once its
1564
+ * payments cover it. Asked for directly on an order that is not paid, it is
1565
+ * refused with `error.code === 'PLACEMENT_BLOCKED'` and
1566
+ * `error.placement.details[0].code === 'PAYMENT_REQUIRED'`. (An engine
1567
+ * without the shop payment guard, merged 2026-09-30, placed it unpaid.) A
1568
+ * zero-total order places without a payment.
1569
+ */
1570
+ transitionOrder(state: string, options?: RequestOptions): Promise<Shop.OrderFragment>;
1571
+ /**
1572
+ * Pay the active order (it must be in `ArrangingPayment`).
1573
+ *
1574
+ * Every call carries an idempotency key: yours, or a fresh UUIDv7 when you
1575
+ * pass none, and every error it throws carries it as `error.idempotencyKey`.
1576
+ * A repeat under the same key is answered with the FIRST attempt's result
1577
+ * (the placed order, or the same refusal) and never takes a second payment;
1578
+ * the same key with a different `input` is refused `IDEMPOTENCY_CONFLICT`.
1579
+ *
1580
+ * - **Pass one key per checkout attempt**: mint it when the buyer presses
1581
+ * Pay and reuse it for that press, so a double click is one payment too.
1582
+ * After a definite refusal (declined, ineligible), the next press is a new
1583
+ * attempt with a new key.
1584
+ * - **An error with `outcomeUnknown`** (the answer never came) is repeated
1585
+ * with `{ idempotencyKey: error.idempotencyKey }`. Never repeat it under a
1586
+ * new key: the first payment may have gone through.
1587
+ * - **`IDEMPOTENCY_IN_PROGRESS`** (the first attempt under this key is still
1588
+ * running) is waited out for you, for up to 20 seconds, and you get the
1589
+ * first attempt's answer.
1590
+ * - **`ORDER_BUSY`** (another change of the same cart was still being
1591
+ * applied, so this call paid nothing) is waited out the same way, inside
1592
+ * the same 20 seconds, and the payment then runs. Thrown after that, it is
1593
+ * repeated with `{ idempotencyKey: error.idempotencyKey }`.
1594
+ * - **`IDEMPOTENCY_OUTCOME_UNKNOWN`**: the first attempt reached a payment
1595
+ * provider and failed, so whether money moved is unknown. Read the order
1596
+ * before doing anything else; this key will not run again.
1597
+ *
1598
+ * A key belongs to one cart. Reused on another cart, a guest's key pays that
1599
+ * cart as a new payment, and a signed-in shopper's key is refused
1600
+ * `IDEMPOTENCY_CONFLICT` (never answered with the first cart's order): mint a
1601
+ * new key per attempt. The key travels as a header, which an engine older
1602
+ * than this release ignores (there a repeat is a second request, as before).
1603
+ *
1604
+ * **A deposit instead of the whole order:** pass `amount` (minor units of the
1605
+ * order's currency) and the call pays that much through
1606
+ * {@link CommerceModule.payDeposit} instead, under the same key handling —
1607
+ * read there who may, which methods, and what follows: the order leaves the
1608
+ * cart and the store HOLDS it. It resolves to that held order (`state`
1609
+ * `Parked`), in the same shape a full payment resolves to; call `payDeposit`
1610
+ * itself to get the payment and the position too.
1611
+ *
1612
+ * The SDK routes on the PRESENCE of `amount`, never on its size: it cannot
1613
+ * see what the order still bills without a second read, so the engine
1614
+ * judges. An amount equal to the whole balance is refused
1615
+ * `AMOUNT_NOT_A_DEPOSIT` — omit `amount` to pay in full — and more than the
1616
+ * balance `AMOUNT_EXCEEDS_OUTSTANDING`. A card deposit (Mollie) is opened
1617
+ * with {@link CommerceModule.createDepositPaymentIntent}, not here. An
1618
+ * `amount` that is not a whole number throws a 400 `INVALID_ARGUMENT` before
1619
+ * any request. Without `amount` the call is exactly the full payment above.
1620
+ */
1621
+ addPayment(input: Shop.PaymentInput, options?: RequestOptions & {
1622
+ idempotencyKey?: string;
1623
+ amount?: number;
1624
+ }): Promise<Extract<Shop.AddPaymentMutation['addPaymentToOrder'], Shop.OrderFragment>>;
1625
+ /**
1626
+ * Pay a DEPOSIT on the active order in checkout (it must be in
1627
+ * `ArrangingPayment`) with a method the store takes OFFLINE (bank transfer,
1628
+ * invoice), and have the store HOLD the order until the shopper pays the rest.
1629
+ *
1630
+ * Needs a signed-in shopper — a guest is refused `DEPOSIT_REQUIRES_SIGN_IN`,
1631
+ * since the rest is paid through {@link CommerceModule.payParkedOrder}, which
1632
+ * only a signed-in customer can call — and a store that takes deposits
1633
+ * (`DEPOSITS_NOT_ENABLED` otherwise), takes them online
1634
+ * (`STOREFRONT_DEPOSITS_NOT_ENABLED`), and takes them with this method
1635
+ * (`PAYMENT_METHOD_NOT_ALLOWED_FOR_DEPOSIT`).
1636
+ *
1637
+ * The order then leaves the cart: {@link CommerceModule.getActiveOrder}
1638
+ * returns a fresh one, and this order is a held order in
1639
+ * {@link CommerceModule.getParkedOrders}, its stock kept for the shopper,
1640
+ * paid off with {@link CommerceModule.payParkedOrder} (or
1641
+ * {@link CommerceModule.createParkedOrderPaymentIntent} for a card).
1642
+ * `settled` is `false`: nothing is placed until the rest is paid. `position`
1643
+ * is what the order bills, what is covered and what is left.
1644
+ *
1645
+ * A card method is refused `PAYMENT_METHOD_UNUSABLE_HERE`: open a card
1646
+ * deposit with {@link CommerceModule.createDepositPaymentIntent} (Mollie;
1647
+ * Stripe takes no deposits in this release —
1648
+ * `PAYMENT_METHOD_NOT_ALLOWED_FOR_DEPOSIT`).
1649
+ *
1650
+ * `amount` is in minor units of the order's currency and must be LESS than
1651
+ * what the order owes. Exactly the balance is `AMOUNT_NOT_A_DEPOSIT` (pay it
1652
+ * with {@link CommerceModule.addPayment} and no amount); more is
1653
+ * `AMOUNT_EXCEEDS_OUTSTANDING`; too little is `AMOUNT_BELOW_MINIMUM`, whose
1654
+ * shopper-safe message names the least deposit the store asks for. The
1655
+ * engine also sends that floor as `extensions.minimum` (the least the order
1656
+ * must be covered to, minor units of its currency), but this SDK's errors
1657
+ * carry a GraphQL error's `code`, `message` and `details` only — not its
1658
+ * other extensions — so `error.minimum` does not exist: show the message.
1659
+ * When the store's minimum is the whole order or more, no deposit can meet
1660
+ * it and every amount is `DEPOSIT_MINIMUM_COVERS_ORDER`: offer the full
1661
+ * payment instead.
1662
+ * A non-integer `amount` throws a 400 `INVALID_ARGUMENT` before any request.
1663
+ *
1664
+ * Keyed like {@link CommerceModule.addPayment}: pass one key per payment
1665
+ * attempt (or let the SDK mint a UUIDv7); a repeat under it returns the
1666
+ * first deposit instead of paying twice, `IDEMPOTENCY_IN_PROGRESS` and
1667
+ * `ORDER_BUSY` are waited out, and every error carries
1668
+ * `error.idempotencyKey`.
1669
+ *
1670
+ * The other refusals, each a `StorefrontError` with the reason as `code`:
1671
+ * `ORDER_NOT_FOUND` (no order in checkout), `ORDER_NOT_PARKABLE` (the order
1672
+ * is not in `ArrangingPayment`), `ORDER_HELD_FOR_REVIEW`,
1673
+ * `PAYMENT_METHOD_NOT_FOUND`, `AMOUNT_NOT_POSITIVE`,
1674
+ * `EXCHANGE_RATE_UNAVAILABLE`, `INSUFFICIENT_STOCK` (nothing was paid),
1675
+ * `PAYMENT_DECLINED`, and a placement rejection code (`PLACEMENT_BLOCKED`,
1676
+ * `PAYMENT_TERMS_UNAVAILABLE`, …) when the store's payment rules refuse the
1677
+ * method. An engine older than this release does not know the mutation
1678
+ * (`GRAPHQL_VALIDATION_FAILED`).
1679
+ */
1680
+ payDeposit(input: Shop.PayDepositInput, options?: RequestOptions & {
1681
+ idempotencyKey?: string;
1682
+ }): Promise<Shop.PayDepositMutation['payDeposit']>;
1683
+ /**
1684
+ * Open a CARD payment (Mollie) for a DEPOSIT on the active order in checkout,
1685
+ * and send the shopper to the returned `url`.
1686
+ *
1687
+ * Nothing is paid by this call and the order does not change: when the
1688
+ * provider confirms the payment, the deposit is recorded and the store holds
1689
+ * the order exactly as {@link CommerceModule.payDeposit} does. After the
1690
+ * shopper comes back to `redirectUrl`, read
1691
+ * {@link CommerceModule.getParkedOrders} — the provider's confirmation may
1692
+ * lag the redirect by a few seconds.
1693
+ *
1694
+ * Same conditions and refusals as `payDeposit` (signed-in shopper, deposits
1695
+ * and online deposits on, a method allowed for deposits, an amount below the
1696
+ * balance and at least the minimum), except that an OFFLINE method is
1697
+ * refused `PAYMENT_METHOD_UNUSABLE_HERE` (pay it with `payDeposit`), a method
1698
+ * that does not apply to this order is `PAYMENT_METHOD_NOT_FOUND`, and
1699
+ * `redirectUrl` must be on one of the store's own sites
1700
+ * (`REDIRECT_URL_NOT_ALLOWED`, checked first).
1701
+ *
1702
+ * Keyed like `payDeposit`: one key per payment attempt, and a double-tap or a
1703
+ * retry under it answers the SAME checkout rather than opening a second
1704
+ * payment.
1705
+ */
1706
+ createDepositPaymentIntent(input: Shop.DepositPaymentIntentInput, options?: RequestOptions & {
1707
+ idempotencyKey?: string;
1708
+ }): Promise<Shop.CreateDepositPaymentIntentMutation['createDepositPaymentIntent']>;
3092
1709
  createStripePaymentIntent(options?: RequestOptions): Promise<StripePaymentIntentResult>;
3093
- getMolliePaymentMethods(input: MolliePaymentMethodsInput, options?: RequestOptions): Promise<MolliePaymentMethod[]>;
1710
+ getMolliePaymentMethods(input: Shop.MolliePaymentMethodsInput, options?: RequestOptions): Promise<Shop.MolliePaymentMethodsQuery['molliePaymentMethods']>;
3094
1711
  /**
3095
1712
  * Mollie payment methods for the given PaymentMethod, ordered per the
3096
1713
  * channel's saved configuration and with hidden methods removed. Use this
@@ -3098,168 +1715,289 @@ export interface CommerceModule {
3098
1715
  * the merchant's curated order + visibility. Returns `[]` when no Mollie API
3099
1716
  * key is configured for the channel or Mollie is unreachable.
3100
1717
  */
3101
- getOrderedMolliePaymentMethods(paymentMethodCode: string, options?: RequestOptions): Promise<OrderedMollieMethod[]>;
3102
- createMolliePaymentIntent(input: CreateMolliePaymentIntentInput, options?: RequestOptions): Promise<MolliePaymentIntentResult>;
1718
+ getOrderedMolliePaymentMethods(paymentMethodCode: string, options?: RequestOptions): Promise<Shop.OrderedMolliePaymentMethodsQuery['orderedMolliePaymentMethods']>;
1719
+ createMolliePaymentIntent(input: Shop.MolliePaymentIntentInput, options?: RequestOptions): Promise<MolliePaymentIntentResult>;
3103
1720
  /**
3104
1721
  * Force-fetch the Mollie payment status and reconcile the order state.
3105
1722
  * Use as a fallback when the Mollie webhook is delayed or did not arrive
3106
1723
  * (e.g. local/staging without a public tunnel). Returns `null` when no
3107
1724
  * order matches `orderCode`.
3108
1725
  */
3109
- syncMolliePaymentStatus(orderCode: string, options?: RequestOptions): Promise<MollieOrderStatusResult | null>;
1726
+ syncMolliePaymentStatus(orderCode: string, options?: RequestOptions): Promise<Shop.SyncMolliePaymentStatusMutation['syncMolliePaymentStatus']>;
1727
+ /**
1728
+ * Orders the store is currently HOLDING for the signed-in shopper.
1729
+ *
1730
+ * A held order is NOT the active order — {@link CommerceModule.getActiveOrder}
1731
+ * returns a fresh cart while one is held, so the hold never blocks shopping,
1732
+ * and that is exactly why a storefront has to ask for these separately.
1733
+ * Empty for an anonymous visitor rather than an error.
1734
+ *
1735
+ * An order the store is REVIEWING after the shopper paid it (an app the store
1736
+ * uses could not confirm it) is left out until the store accepts it: nothing
1737
+ * can be paid on it before then.
1738
+ */
1739
+ getParkedOrders(options?: RequestOptions): Promise<Shop.ParkedOrderFragment[]>;
1740
+ /**
1741
+ * Pay some or all of what a held order still owes. Requires a signed-in
1742
+ * customer, and the order must be theirs.
1743
+ *
1744
+ * The order does NOT leave its hold to take the payment: the money lands
1745
+ * where it stands, and the order is settled (keeping the stock the store
1746
+ * reserved for it) only once it is really PAID. Read the result's `settled` to
1747
+ * tell a closed balance from a further deposit — and note it is also `false`
1748
+ * for a payment that is merely AUTHORIZED, which leaves the hold in place
1749
+ * until the authorization settles.
1750
+ *
1751
+ * This is for methods the store takes OFFLINE (bank transfer, invoice). A
1752
+ * card method is refused `PAYMENT_METHOD_UNUSABLE_HERE`; use
1753
+ * {@link CommerceModule.createParkedOrderPaymentIntent} for a card.
1754
+ *
1755
+ * Pass `idempotencyKey` for anything a shopper can double-tap: a repeat under
1756
+ * the same key returns the first payment instead of taking the money twice.
1757
+ *
1758
+ * `ORDER_HELD_FOR_REVIEW` means the store is reviewing the order after it
1759
+ * was paid and has not accepted it yet: tell the shopper the store will be in
1760
+ * touch. Once the store accepts it, it appears in
1761
+ * {@link CommerceModule.getParkedOrders} and can be paid here.
1762
+ */
1763
+ payParkedOrder(orderCode: string, input: Shop.PayParkedOrderInput, options?: RequestOptions & {
1764
+ idempotencyKey?: string;
1765
+ }): Promise<Shop.PayParkedOrderMutation['payParkedOrder']>;
1766
+ /**
1767
+ * Open a CARD payment for one of the signed-in shopper's held orders, for the
1768
+ * whole outstanding balance (or, where the store takes deposits, part of it),
1769
+ * and send the shopper to the returned `url`.
1770
+ *
1771
+ * Nothing is paid by this call and the order does not change: the money is
1772
+ * recorded on the order when the provider confirms it, and the order leaves
1773
+ * its hold only once it is fully paid. After the shopper comes back to
1774
+ * `redirectUrl`, read {@link CommerceModule.getParkedOrders} (or the order)
1775
+ * to see where it stands — the provider's confirmation may lag the redirect
1776
+ * by a few seconds.
1777
+ *
1778
+ * `redirectUrl` must be on one of the store's own sites. Pass
1779
+ * `idempotencyKey` so a double-tap or a retry answers the SAME checkout
1780
+ * rather than opening a second payment. `ORDER_HELD_FOR_REVIEW` is refused
1781
+ * as for {@link CommerceModule.payParkedOrder}.
1782
+ */
1783
+ createParkedOrderPaymentIntent(orderCode: string, input: Shop.ParkedOrderPaymentIntentInput, options?: RequestOptions & {
1784
+ idempotencyKey?: string;
1785
+ }): Promise<Shop.CreateParkedOrderPaymentIntentMutation['createParkedOrderPaymentIntent']>;
3110
1786
  login(email: string, password: string): Promise<LoginResult>;
3111
- register(input: RegisterInput): Promise<{
1787
+ /**
1788
+ * Sign in through a named authentication strategy — the general form of
1789
+ * {@link CommerceModule.login}. `strategy` is a member of the engine's
1790
+ * `AuthenticationInput` (`native` today, taking `{ username, password }`).
1791
+ * The session token is captured like login's (`onAuthToken` fires).
1792
+ *
1793
+ * Every refusal throws `MutationError`: `errorCode` is the result type
1794
+ * (`INVALID_CREDENTIALS_ERROR`, `NOT_VERIFIED_ERROR`), and `error.code`
1795
+ * carries the strategy's reason when it gave one — the native strategy
1796
+ * answers `PASSWORD_RESET_REQUIRED` (an imported account with no password;
1797
+ * a set-password email is on its way) and `ACCOUNT_NOT_VERIFIED`. Branch on
1798
+ * `error.code` before telling a shopper their password is wrong; `login`
1799
+ * does that branching for the native strategy.
1800
+ *
1801
+ * `rememberMe` only lengthens a COOKIE session; the SDK sends bearer tokens,
1802
+ * whose lifetime the engine's session duration decides. A blank `strategy`
1803
+ * or an `input` that is not an object throws a 400 `INVALID_ARGUMENT` before
1804
+ * any request.
1805
+ */
1806
+ authenticate<S extends AuthenticationStrategy>(strategy: S, input: AuthenticationStrategyInput<S>, options?: RequestOptions & {
1807
+ rememberMe?: boolean;
1808
+ }): Promise<Shop.CurrentUserFragment>;
1809
+ register(input: Shop.RegisterCustomerInput): Promise<{
3112
1810
  success: boolean;
3113
1811
  }>;
3114
1812
  logout(): Promise<void>;
3115
- getCurrentCustomer(): Promise<Customer | null>;
1813
+ getCurrentCustomer(): Promise<Shop.MeQuery['activeCustomer']>;
3116
1814
  /**
3117
1815
  * Price lists currently applying to the signed-in customer (identity only,
3118
1816
  * sorted by resolution priority). Empty for anonymous visitors with no
3119
1817
  * channel-wide lists.
3120
1818
  */
3121
- getActiveCustomerPriceLists(options?: RequestOptions): Promise<CustomerPriceList[]>;
3122
- getCustomerOrders(options?: OrderListOptions): Promise<PaginatedList<OrderSummary>>;
1819
+ getActiveCustomerPriceLists(options?: RequestOptions): Promise<Shop.ActiveCustomerPriceListsQuery['activeCustomerPriceLists']>;
1820
+ /**
1821
+ * The signed-in customer's placed orders, newest first: the order-history rows
1822
+ * with each line's `backorderedQuantity` and every parcel's barcode
1823
+ * (`fulfillments[].trackingCodes`). An empty page for an anonymous visitor.
1824
+ */
1825
+ getCustomerOrders(options?: OrderListOptions): Promise<MergedSelection<NonNullable<Shop.CustomerOrdersQuery['activeCustomer']>['orders']>>;
3123
1826
  /**
3124
1827
  * Add every line of a previous order to the active cart. Returns the new
3125
1828
  * active order plus a list of lines that could not be added (e.g. variant
3126
1829
  * removed, out of stock).
3127
1830
  */
3128
1831
  reorder(orderCode: string): Promise<ReorderResult>;
3129
- getCollections(listOptions?: CollectionListOptions, options?: RequestOptions): Promise<Collection[]>;
3130
- getCollection(slug: string, options?: RequestOptions): Promise<CollectionDetail>;
1832
+ getCollections(listOptions?: CollectionListOptions, options?: RequestOptions): Promise<Shop.CollectionFragment[]>;
1833
+ /**
1834
+ * A collection by slug. `{ metafields: true }` (or `{ metafields: {
1835
+ * namespace } }`) also returns its storefront-visible metafields; it needs an
1836
+ * engine serving `Collection.metafields`.
1837
+ */
1838
+ getCollection(slug: string, options: import('./commerce/products.js').CatalogDetailOptions & {
1839
+ metafields: true | {
1840
+ namespace: string;
1841
+ };
1842
+ }): Promise<import('./commerce/products.js').CollectionWithMetafields>;
1843
+ getCollection(slug: string, options?: import('./commerce/products.js').CatalogDetailOptions & {
1844
+ metafields?: false;
1845
+ }): Promise<Shop.CollectionDetailFragment>;
1846
+ getCollection(slug: string, options?: import('./commerce/products.js').CatalogDetailOptions): Promise<Shop.CollectionDetailFragment | import('./commerce/products.js').CollectionWithMetafields>;
3131
1847
  /**
3132
1848
  * A collection by id — typically `route.id` from the routes manifest. Tagged
3133
1849
  * `collection:<id>`; throws a `NOT_FOUND` StorefrontError (404) when absent.
1850
+ * `{ metafields }` as for {@link CommerceModule.getCollection}.
3134
1851
  */
3135
- getCollectionById(id: string, options?: RequestOptions): Promise<CollectionDetail>;
3136
- updateCustomer(input: UpdateCustomerInput): Promise<Customer>;
1852
+ getCollectionById(id: string, options: import('./commerce/products.js').CatalogDetailOptions & {
1853
+ metafields: true | {
1854
+ namespace: string;
1855
+ };
1856
+ }): Promise<import('./commerce/products.js').CollectionWithMetafields>;
1857
+ getCollectionById(id: string, options?: import('./commerce/products.js').CatalogDetailOptions & {
1858
+ metafields?: false;
1859
+ }): Promise<Shop.CollectionDetailFragment>;
1860
+ getCollectionById(id: string, options?: import('./commerce/products.js').CatalogDetailOptions): Promise<Shop.CollectionDetailFragment | import('./commerce/products.js').CollectionWithMetafields>;
1861
+ /** Resolves to the profile fields the mutation selects back — not the whole customer. */
1862
+ updateCustomer(input: Shop.UpdateCustomerInput): Promise<Shop.UpdateCustomerMutation['updateCustomer']>;
3137
1863
  updatePassword(currentPassword: string, newPassword: string): Promise<void>;
1864
+ /**
1865
+ * Set the signed-in customer's FIRST password (an account that signs in by
1866
+ * email link or code has none, so `updatePassword` cannot serve it). Throws
1867
+ * `MutationError` `PASSWORD_ALREADY_SET_ERROR` once one exists,
1868
+ * `PASSWORD_VALIDATION_ERROR` (reason in `fields.validationErrorMessage`),
1869
+ * `NATIVE_AUTH_STRATEGY_ERROR`, or `SET_PASSWORD_REQUIRES_EMAIL_SIGN_IN_ERROR`
1870
+ * when the session did not sign in to this store by email link or code. The
1871
+ * account is emailed a notice.
1872
+ */
1873
+ setPassword(newPassword: string): Promise<void>;
3138
1874
  requestPasswordReset(emailAddress: string): Promise<void>;
3139
- resetPassword(token: string, password: string): Promise<{
3140
- id: string;
3141
- identifier: string;
3142
- }>;
1875
+ resetPassword(token: string, password: string): Promise<Shop.CurrentUserFragment>;
3143
1876
  requestEmailUpdate(password: string, newEmailAddress: string): Promise<void>;
3144
1877
  updateEmail(token: string): Promise<void>;
3145
- verifyAccount(token: string, password?: string): Promise<{
3146
- id: string;
3147
- identifier: string;
3148
- }>;
1878
+ verifyAccount(token: string, password?: string): Promise<Shop.CurrentUserFragment>;
3149
1879
  refreshVerification(emailAddress: string): Promise<void>;
3150
- requestMagicLink(emailAddress: string): Promise<void>;
3151
- loginWithMagicLink(token: string): Promise<{
3152
- id: string;
3153
- identifier: string;
3154
- }>;
3155
- loginWithMagicCode(emailAddress: string, code: string): Promise<{
3156
- id: string;
3157
- identifier: string;
3158
- }>;
3159
- createAddress(input: AddressInput): Promise<CustomerAddress>;
3160
- updateAddress(input: UpdateAddressInput): Promise<CustomerAddress>;
1880
+ /**
1881
+ * Email a sign-in link and 6-digit code. Resolves whether or not an account
1882
+ * exists (anti-enumeration). Throws a `MutationError`
1883
+ * `MAGIC_LINK_RATE_LIMITED_ERROR` with `retryAfterSeconds` when the store's
1884
+ * magic-link limiter refuses, and a `StorefrontError` with `statusCode` 429
1885
+ * (`code: 'RATE_LIMITED'`, `retryAfterSeconds`) when the platform's
1886
+ * credential limiter does. Neither reveals whether the account exists.
1887
+ */
1888
+ requestMagicLink(emailAddress: string, options?: RequestMagicLinkOptions): Promise<void>;
1889
+ loginWithMagicLink(token: string): Promise<Shop.CurrentUserFragment>;
1890
+ loginWithMagicCode(emailAddress: string, code: string): Promise<Shop.CurrentUserFragment>;
1891
+ createAddress(input: Shop.CreateAddressInput): Promise<Shop.CreateAddressMutation['createCustomerAddress']>;
1892
+ updateAddress(input: Shop.UpdateAddressInput): Promise<Shop.UpdateAddressMutation['updateCustomerAddress']>;
3161
1893
  deleteAddress(id: string): Promise<void>;
3162
- getAvailableCountries(): Promise<Country[]>;
3163
- getOrderByCode(code: string): Promise<Order>;
1894
+ getAvailableCountries(): Promise<Shop.AvailableCountriesQuery['availableCountries']>;
1895
+ /**
1896
+ * One of the shopper's orders by code — the cart selection plus what a placed
1897
+ * order carries: `lines[].backorderedQuantity`, `customFields.chargedParcelCount`,
1898
+ * the fulfilments with every parcel's barcode, the external shipments and the
1899
+ * payment and delivery terms frozen at acceptance. Throws a `NOT_FOUND`
1900
+ * `StorefrontError` (404) when there is none.
1901
+ */
1902
+ getOrderByCode(code: string): Promise<MergedSelection<NonNullable<Shop.OrderByCodeQuery['orderByCode']>>>;
3164
1903
  /** Invoices for one of the signed-in customer's own orders. */
3165
- getMyOrderInvoices(orderCode: string): Promise<CustomerInvoice[]>;
1904
+ getMyOrderInvoices(orderCode: string): Promise<Shop.MyOrderInvoicesQuery['myOrderInvoices']>;
3166
1905
  /** Download one of the signed-in customer's own invoices as a base64 PDF. */
3167
- getMyInvoicePdf(invoiceId: string): Promise<CustomerInvoicePdf>;
3168
- getActiveChannel(): Promise<ActiveChannel>;
3169
- getPropertyGroups(options?: RequestOptions): Promise<PropertyGroup[]>;
3170
- getProductProperties(productId: string, options?: RequestOptions): Promise<ProductPropertyGroupValues[]>;
1906
+ getMyInvoicePdf(invoiceId: string): Promise<Shop.MyInvoicePdfQuery['myInvoicePdf']>;
1907
+ /** A five-minute signed download link for one of the signed-in customer's own invoices. */
1908
+ getMyInvoiceDownloadUrl(invoiceId: string): Promise<Shop.CreateInvoiceDownloadUrlMutation['createInvoiceDownloadUrl']>;
1909
+ /**
1910
+ * The retail credit notes of one of the signed-in customer's own orders, newest first. A
1911
+ * credit account's accounts-receivable credit notes are not listed.
1912
+ */
1913
+ getMyOrderCreditNotes(orderCode: string): Promise<Shop.MyOrderCreditNotesQuery['myOrderCreditNotes']>;
1914
+ /** A five-minute signed download link for one of the signed-in customer's own credit notes. */
1915
+ getMyCreditNoteDownloadUrl(creditNoteId: string): Promise<Shop.CreateCreditNoteDownloadUrlMutation['createCreditNoteDownloadUrl']>;
1916
+ getActiveChannel(): Promise<Shop.ActiveChannelQuery['activeChannel']>;
1917
+ getPropertyGroups(options?: RequestOptions): Promise<Shop.PropertyGroupFragment[]>;
1918
+ getProductProperties(productId: string, options?: RequestOptions): Promise<Shop.ProductPropertyGroupValuesFragment[]>;
3171
1919
  /**
3172
1920
  * Flatten `getProductProperties(...)` output into a `slug → value` record for
3173
1921
  * the product-detail view. Pure helper — see `ProductPropertyRecord` for the
3174
1922
  * `content_item` (producer) caveat.
3175
1923
  */
3176
- mapProductProperties(groups: ProductPropertyGroupValues[]): ProductPropertyRecord;
3177
- getMySavedLists(): Promise<SavedList[]>;
3178
- getMySavedList(id: string): Promise<SavedList | null>;
3179
- createSavedList(name: string): Promise<SavedList>;
3180
- renameSavedList(id: string, name: string): Promise<SavedList>;
1924
+ mapProductProperties(groups: Shop.ProductPropertyGroupValuesFragment[]): ProductPropertyRecord;
1925
+ getMySavedLists(): Promise<Shop.SavedListFragment[]>;
1926
+ getMySavedList(id: string): Promise<Shop.SavedListFragment | null>;
1927
+ createSavedList(name: string): Promise<Shop.SavedListFragment>;
1928
+ renameSavedList(id: string, name: string): Promise<Shop.SavedListFragment>;
3181
1929
  deleteSavedList(id: string): Promise<boolean>;
3182
- addItemToSavedList(listId: string, variantId: string, quantity: number): Promise<SavedList>;
3183
- updateSavedListItem(listId: string, variantId: string, quantity: number): Promise<SavedList>;
3184
- removeItemFromSavedList(listId: string, variantId: string): Promise<SavedList>;
1930
+ addItemToSavedList(listId: string, variantId: string, quantity: number): Promise<Shop.SavedListFragment>;
1931
+ updateSavedListItem(listId: string, variantId: string, quantity: number): Promise<Shop.SavedListFragment>;
1932
+ removeItemFromSavedList(listId: string, variantId: string): Promise<Shop.SavedListFragment>;
3185
1933
  getFavoriteVariantIds(): Promise<string[]>;
3186
- getMyFavorites(options?: {
3187
- take?: number;
3188
- skip?: number;
3189
- }): Promise<PaginatedList<FavoriteItem>>;
1934
+ getMyFavorites(options?: Shop.FavoriteListOptions): Promise<Shop.MyFavoritesQuery['myFavorites']>;
3190
1935
  toggleFavorite(productVariantId: string): Promise<boolean>;
3191
1936
  removeFavorite(productVariantId: string): Promise<boolean>;
3192
1937
  subscribeToStockNotification(productVariantId: string, emailAddress?: string): Promise<StockNotificationSubscriptionResult>;
3193
1938
  unsubscribeFromStockNotification(token: string): Promise<boolean>;
3194
- getProductRecommendations(productId: string, groupSlug?: string): Promise<RecommendedProductGroup[]>;
3195
- getAgeVerificationStatus(): Promise<AgeVerificationStatus>;
3196
- submitDateOfBirth(dateOfBirth: string): Promise<AgeVerificationStatus>;
3197
- confirmAge(): Promise<AgeVerificationStatus>;
3198
- getProductReviews(productId: string, options?: ReviewListOptions): Promise<{
3199
- items: ProductReview[];
3200
- totalItems: number;
3201
- nextCursor: string | null;
3202
- }>;
3203
- getRecentProductReviews(options?: RecentReviewsOptions): Promise<ProductReview[]>;
3204
- getReviewRatingSummary(productId: string): Promise<ReviewRatingSummary>;
3205
- getReviewAttributeAggregations(productId: string): Promise<ReviewAttributeAggregation[]>;
3206
- getReviewAttributes(productId?: string): Promise<ReviewAttribute[]>;
3207
- getMyReview(productId: string): Promise<ProductReview | null>;
3208
- getReviewChannelConfig(): Promise<ReviewChannelConfig>;
3209
- createReview(input: CreateReviewInput): Promise<CreateReviewResult>;
3210
- updateReview(id: string, input: UpdateReviewInput): Promise<ProductReview>;
1939
+ getProductRecommendations(productId: string, groupSlug?: string): Promise<Shop.RecommendedProductGroupFragment[]>;
1940
+ getAgeVerificationStatus(): Promise<Shop.AgeVerificationStatusQuery['ageVerificationStatus']>;
1941
+ submitDateOfBirth(dateOfBirth: string): Promise<Shop.SubmitDateOfBirthMutation['submitDateOfBirth']>;
1942
+ confirmAge(): Promise<Shop.ConfirmAgeMutation['confirmAge']>;
1943
+ getProductReviews(productId: string, options?: Shop.ProductReviewListOptions): Promise<Shop.ProductReviewsQuery['productReviews']>;
1944
+ getRecentProductReviews(options?: Shop.RecentReviewsOptions): Promise<Shop.ProductReviewFragment[]>;
1945
+ getReviewRatingSummary(productId: string): Promise<Shop.ProductRatingSummaryQuery['productRatingSummary']>;
1946
+ getReviewAttributeAggregations(productId: string): Promise<Shop.ProductReviewAttributeAggregationsQuery['productReviewAttributeAggregations']>;
1947
+ getReviewAttributes(productId?: string): Promise<Shop.ReviewAttributesQuery['reviewAttributes']>;
1948
+ getMyReview(productId: string): Promise<Shop.ProductReviewFragment | null>;
1949
+ getReviewChannelConfig(): Promise<Shop.ReviewChannelConfigQuery['reviewChannelConfig']>;
1950
+ createReview(input: Shop.CreateProductReviewInput): Promise<Shop.CreateProductReviewMutation['createProductReview']>;
1951
+ updateReview(id: string, input: Shop.UpdateProductReviewInput): Promise<Shop.ProductReviewFragment>;
3211
1952
  deleteReview(id: string): Promise<boolean>;
3212
1953
  voteReview(reviewId: string, isHelpful: boolean): Promise<boolean>;
3213
1954
  reportReview(reviewId: string, reason: string): Promise<boolean>;
3214
- uploadReviewMedia(files: File[]): Promise<ReviewMediaUploadResult[]>;
3215
- getMySubscription(id: string): Promise<CustomerSubscription | null>;
1955
+ uploadReviewMedia(files: File[]): Promise<Shop.UploadReviewMediaMutation['uploadReviewMedia']>;
1956
+ getMySubscription(id: string): Promise<Shop.CustomerSubscriptionFragment | null>;
3216
1957
  previewSubscriptionPurchase(planId: string, options?: {
3217
1958
  provider?: 'mollie' | 'stripe';
3218
1959
  mandateId?: string;
3219
- }): Promise<SubscriptionPurchasePreview>;
3220
- startSubscriptionPurchase(input: SubscriptionPurchaseInput): Promise<SubscriptionPurchaseResult>;
3221
- getSubscriptionPurchaseStatus(id: string): Promise<SubscriptionPurchaseResult>;
3222
- previewMySubscriptionChange(id: string, input: SubscriptionLifecycleCommand): Promise<SubscriptionChangePreview>;
3223
- manageMySubscription(id: string, input: SubscriptionLifecycleCommand): Promise<CustomerSubscription>;
3224
- skipMySubscription(id: string, requestKey: string): Promise<CustomerSubscription>;
3225
- rescheduleMySubscription(id: string, date: string, requestKey: string): Promise<CustomerSubscription>;
3226
- undoMySubscriptionCancellation(id: string, requestKey: string): Promise<CustomerSubscription>;
1960
+ }): Promise<Shop.SubscriptionPurchasePreviewQuery['subscriptionPurchasePreview']>;
1961
+ startSubscriptionPurchase(input: SubscriptionPurchaseInput): Promise<Shop.SubscriptionPurchaseResultFragment>;
1962
+ getSubscriptionPurchaseStatus(id: string): Promise<Shop.SubscriptionPurchaseResultFragment>;
1963
+ previewMySubscriptionChange(id: string, input: SubscriptionLifecycleCommand): Promise<Shop.PreviewMySubscriptionChangeQuery['previewMySubscriptionChange']>;
1964
+ manageMySubscription(id: string, input: SubscriptionLifecycleCommand): Promise<Shop.CustomerSubscriptionFragment>;
1965
+ skipMySubscription(id: string, requestKey: string): Promise<Shop.CustomerSubscriptionFragment>;
1966
+ rescheduleMySubscription(id: string, date: string, requestKey: string): Promise<Shop.CustomerSubscriptionFragment>;
1967
+ undoMySubscriptionCancellation(id: string, requestKey: string): Promise<Shop.CustomerSubscriptionFragment>;
3227
1968
  replaceMySubscriptionMandate(id: string, input: SubscriptionPaymentActionInput & {
3228
1969
  provider: 'mollie' | 'stripe';
3229
- }): Promise<SubscriptionPurchaseResult>;
1970
+ }): Promise<Shop.SubscriptionPurchaseResultFragment>;
3230
1971
  /**
3231
1972
  * A hosted link that pays the outstanding failed or charged-back cycle again,
3232
1973
  * without another delivery. Reuse `upcomingPayment.checkoutUrl` while it is live.
3233
1974
  */
3234
- recoverMySubscriptionPayment(id: string, input: SubscriptionPaymentActionInput): Promise<SubscriptionPurchaseResult>;
3235
- getMySubscriptions(): Promise<CustomerSubscription[]>;
1975
+ recoverMySubscriptionPayment(id: string, input: SubscriptionPaymentActionInput): Promise<Shop.SubscriptionPurchaseResultFragment>;
1976
+ getMySubscriptions(): Promise<Shop.CustomerSubscriptionFragment[]>;
3236
1977
  /**
3237
1978
  * Plans available to subscribe to in the current channel. Public —
3238
1979
  * works for anonymous visitors. Only enabled plans are returned.
3239
1980
  */
3240
- getSubscriptionPlans(): Promise<SubscriptionPlanPublic[]>;
1981
+ getSubscriptionPlans(): Promise<Shop.SubscriptionPlanPublicFragment[]>;
3241
1982
  /**
3242
1983
  * The active customer's valid or still-pending payment mandates. Poll this
3243
1984
  * after `setupPaymentMandate` until the mandate flips to `valid`.
3244
1985
  */
3245
- getMyPaymentMandates(): Promise<MyPaymentMandate[]>;
1986
+ getMyPaymentMandates(): Promise<Shop.MyPaymentMandateFragment[]>;
3246
1987
  /**
3247
1988
  * Begin establishing a payment mandate. Returns a `checkoutUrl` (Mollie) or
3248
1989
  * `clientSecret` (Stripe) for the frontend to complete the setup.
3249
1990
  */
3250
- setupPaymentMandate(input: {
3251
- provider: string;
3252
- redirectUrl: string;
3253
- }): Promise<SetupPaymentMandateResult>;
1991
+ setupPaymentMandate(input: Shop.SetupPaymentMandateInput): Promise<Shop.SetupPaymentMandateMutation['setupPaymentMandate']>;
3254
1992
  /**
3255
1993
  * Create a subscription for the active customer against an enabled plan
3256
1994
  * using one of their valid mandates.
3257
1995
  */
3258
- createSubscription(planId: string, mandateId: string, requestKey?: string): Promise<CustomerSubscription>;
1996
+ createSubscription(planId: string, mandateId: string, requestKey?: string): Promise<Shop.CustomerSubscriptionFragment>;
3259
1997
  /** Pause an active or trial subscription owned by the active customer. */
3260
- pauseMySubscription(id: string, reason?: string): Promise<CustomerSubscription>;
1998
+ pauseMySubscription(id: string, reason?: string): Promise<Shop.CustomerSubscriptionFragment>;
3261
1999
  /** Resume a paused subscription owned by the active customer. */
3262
- resumeMySubscription(id: string): Promise<CustomerSubscription>;
2000
+ resumeMySubscription(id: string): Promise<Shop.CustomerSubscriptionFragment>;
3263
2001
  /**
3264
2002
  * Cancel a subscription owned by the active customer. Defaults to
3265
2003
  * the earliest eligible cancellation date; minimum paid-cycle commitments still apply.
@@ -3267,65 +2005,78 @@ export interface CommerceModule {
3267
2005
  cancelMySubscription(id: string, options?: {
3268
2006
  reason?: string;
3269
2007
  immediate?: boolean;
3270
- }): Promise<CustomerSubscription>;
2008
+ }): Promise<Shop.CustomerSubscriptionFragment>;
3271
2009
  /** Returns the active customer's quotes in the current channel. */
3272
- getMyQuotes(options?: QuoteListOptions): Promise<QuoteList>;
2010
+ getMyQuotes(options?: Shop.QuoteListOptions): Promise<QuoteList>;
3273
2011
  /** Returns one of the active customer's quotes by id. */
3274
2012
  getMyQuote(id: string): Promise<Quote | null>;
3275
2013
  /**
3276
2014
  * Submits a new quote request. Lines are unpriced — a sales rep
3277
2015
  * prices them later. Requires the customer to belong to a configured
3278
- * B2B customer group.
2016
+ * B2B customer group. The quote is in the currency this client prices in
2017
+ * (`setOrderCurrency`, else the store's default; `Quote.currencyCode`).
3279
2018
  */
3280
- createQuoteRequest(input: CreateQuoteRequestInput): Promise<Quote>;
2019
+ createQuoteRequest(input: Shop.CreateQuoteRequestInput): Promise<Quote>;
3281
2020
  /**
3282
2021
  * Accepts a priced+approved quote, producing a real `Order` in
3283
- * `ArrangingPayment` with the quoted unit prices applied.
3284
- */
3285
- acceptQuote(id: string): Promise<Order>;
2022
+ * `ArrangingPayment` with the quoted unit prices applied, in the quote's
2023
+ * currency. This client must be pricing in that currency
2024
+ * (`Quote.currencyCode`; switch with `setOrderCurrency`), or the engine
2025
+ * refuses it with `QUOTE_CURRENCY_MISMATCH` and creates nothing: the quoted
2026
+ * prices are an agreement in the quote's currency and are never converted
2027
+ * (engine released on or after 2026-10-01; an older engine created the order
2028
+ * in the request's currency at the quoted figures).
2029
+ */
2030
+ acceptQuote(id: string): Promise<Shop.OrderFragment>;
3286
2031
  /** Cancels a quote owned by the active customer. */
3287
2032
  cancelMyQuote(id: string, reason?: string): Promise<Quote>;
3288
2033
  /**
3289
2034
  * Returns the active customer's returns (RMAs) in the current channel,
3290
2035
  * newest first. Requires an authenticated customer session.
3291
2036
  */
3292
- getMyReturns(options?: CustomerReturnListOptions): Promise<CustomerReturnList>;
2037
+ getMyReturns(options?: CustomerReturnListOptions): Promise<Shop.MyReturnsQuery['myReturns']>;
3293
2038
  /**
3294
2039
  * Returns one of the active customer's returns by id, or `null` when it
3295
2040
  * does not exist or belongs to another customer.
3296
2041
  */
3297
- getMyReturn(id: string): Promise<CustomerReturn | null>;
2042
+ getMyReturn(id: string): Promise<Shop.CustomerReturnFragment | null>;
3298
2043
  /**
3299
2044
  * Requests a return (RMA) for fulfilled lines of one of the active
3300
2045
  * customer's orders. Only allowed when the channel has returns enabled and
3301
2046
  * the order is inside the return window; quantities are capped at each
3302
2047
  * line's returnable quantity (see `getReturnableLinesForOrder`).
3303
2048
  */
3304
- requestReturn(input: RequestReturnInput): Promise<CustomerReturn>;
2049
+ requestReturn(input: Shop.RequestReturnInput): Promise<Shop.CustomerReturnFragment>;
3305
2050
  /**
3306
2051
  * Cancels a return owned by the active customer. Only possible while the
3307
2052
  * return is still in the `requested` state.
3308
2053
  */
3309
- cancelMyReturn(id: string): Promise<CustomerReturn>;
2054
+ cancelMyReturn(id: string): Promise<Shop.CustomerReturnFragment>;
3310
2055
  /**
3311
2056
  * Per-line returnable quantities and the return window for one of the
3312
2057
  * active customer's orders — drives the return-request UI. Lines only
3313
2058
  * appear once they have shipped/delivered quantity.
3314
2059
  */
3315
- getReturnableLinesForOrder(orderId: string): Promise<CustomerReturnEligibility>;
3316
- getMyVatValidationStatus(): Promise<VatValidationResult | null>;
3317
- setMyVatNumber(vatNumber: string): Promise<VatValidationResult>;
2060
+ getReturnableLinesForOrder(orderId: string): Promise<Shop.ReturnableLinesForOrderQuery['returnableLinesForOrder']>;
2061
+ getMyVatValidationStatus(): Promise<Shop.VatValidationResultFragment | null>;
2062
+ setMyVatNumber(vatNumber: string): Promise<Shop.VatValidationResultFragment>;
3318
2063
  clearMyVatNumber(): Promise<boolean>;
3319
- getDropOffPoints(input: DropOffPointInput): Promise<DropOffPoint[]>;
3320
- getDeliveryOptions(input: DeliveryOptionsInput): Promise<DeliveryOption[]>;
2064
+ getDropOffPoints(input: Shop.MyparcelDropOffPointInput): Promise<DropOffPoint[]>;
2065
+ getDeliveryOptions(input: Shop.MyparcelDeliveryOptionsInput): Promise<DeliveryOption[]>;
3321
2066
  trackShipment(barcode: string, postalCode: string): Promise<ShipmentTrackingInfo | null>;
3322
2067
  /**
3323
2068
  * Carrier-agnostic pickup-location search. Currently MyParcel-backed;
3324
2069
  * future providers (Sendcloud, Hendriks) implement the same shape.
3325
2070
  */
3326
- findPickupLocations(input: PickupLocationSearchInput): Promise<PickupLocation[]>;
3327
- /** Persist the customer's chosen pickup location on the active order. */
3328
- selectPickupLocation(location: PickupLocation): Promise<Order>;
2071
+ findPickupLocations(input: Shop.PickupLocationSearchInput): Promise<PickupLocation[]>;
2072
+ /**
2073
+ * Persist the customer's chosen pickup location on the active order. Resolves
2074
+ * to the order's `__typename`, `id`, `code` and `state` — all the document
2075
+ * selects; read the order again (`getActiveOrder`) to render it.
2076
+ */
2077
+ selectPickupLocation(location: PickupLocation): Promise<Extract<Shop.SetActiveOrderPickupLocationMutation['setActiveOrderPickupLocation'], {
2078
+ __typename: 'Order';
2079
+ }>>;
3329
2080
  /** Read the pickup location stored on the active order, or `null`. */
3330
2081
  getActivePickupLocation(): Promise<PickupLocation | null>;
3331
2082
  /**
@@ -3338,20 +2089,38 @@ export interface CommerceModule {
3338
2089
  * validation and at storefront runtime for footer/header/SEO rendering.
3339
2090
  */
3340
2091
  getBranding(options?: RequestOptions): Promise<BrandingInfo>;
2092
+ /**
2093
+ * The store's capability manifest as a storefront sees it: `{ ready }` per
2094
+ * storefront-facing capability (`catalog`, `search`, `routes`, `menus`,
2095
+ * `content_pages`, `checkout`, `branding`, `age_gate`, `reviews`,
2096
+ * `subscriptions`). Branch on it before rendering a feature whose backing is
2097
+ * optional. A key can be absent; treat that as not ready.
2098
+ *
2099
+ * Always the anonymous projection, even for a signed-in shopper: the
2100
+ * shopper's session is never sent. Cached by the server for up to 60 s.
2101
+ * `generated_at` is when the probes ran, not a freshness signal: an unchanged
2102
+ * manifest answers 304 under conditional reads and keeps the first answer's
2103
+ * timestamp.
2104
+ */
2105
+ getCapabilities(options?: RequestOptions): Promise<Plugins.PublicCapabilityManifestDto>;
3341
2106
  }
3342
2107
  export interface ContentModule {
3343
- resolvePath(path: string, locale?: string, options?: RequestOptions): Promise<ResolvedContent>;
2108
+ resolvePath(path: string, locale?: string, options?: RequestOptions): Promise<Cms.PublicResolvedContentDto>;
3344
2109
  getContent(queryOptions: ContentQueryOptions, options?: RequestOptions): Promise<Record<string, unknown>>;
3345
2110
  /**
3346
2111
  * Typed channel-wide CMS content search. Pass `collectionId`/`collectionSlug`
3347
2112
  * to scope, or omit both to search across every collection.
3348
2113
  */
3349
- searchContent(query: ContentSearchQuery, options?: RequestOptions): Promise<ContentSearchResult>;
3350
- getAsset(id: string, options?: RequestOptions): Promise<CmsAsset>;
3351
- lookupAssets(ids: string[], options?: RequestOptions): Promise<CmsAsset[]>;
3352
- lookupVendureAssetDescriptions(vendureAssetIds: string[], options?: RequestOptions): Promise<Record<string, VendureAssetDescriptionTranslation[]>>;
3353
- /** Discover the channel's forms (public projection). See {@link FormSummary}. */
3354
- listForms(options?: FormListOptions & RequestOptions): Promise<FormListResult>;
2114
+ searchContent(query: ContentSearchQuery, options?: RequestOptions): Promise<Cms.PublicCollectionItemSearchResultDto>;
2115
+ getAsset(id: string, options?: RequestOptions): Promise<Cms.PublicAssetDto>;
2116
+ lookupAssets(ids: string[], options?: RequestOptions): Promise<Cms.PublicAssetDto[]>;
2117
+ lookupVendureAssetDescriptions(vendureAssetIds: string[], options?: RequestOptions): Promise<Record<string, Cms.PublicVendureAssetDescriptionDto[]>>;
2118
+ /**
2119
+ * Discover the channel's forms (public projection), with the list envelope
2120
+ * as the CMS sends it. `fields` and `translations` are EMPTY on every form
2121
+ * here — fetch one form (`getForm`/`getFormBySlug`) for them.
2122
+ */
2123
+ listForms(options?: FormListOptions & RequestOptions): Promise<Cms.PublicFormListResponseDto>;
3355
2124
  getForm(id: string, options?: RequestOptions): Promise<FormDefinition>;
3356
2125
  getFormBySlug(slug: string, options?: RequestOptions): Promise<FormDefinition>;
3357
2126
  /**
@@ -3359,7 +2128,7 @@ export interface ContentModule {
3359
2128
  * and its config/validation schema. Prefer the static {@link FORM_FIELD_TYPES}
3360
2129
  * constant when a round-trip isn't warranted.
3361
2130
  */
3362
- getFormFieldTypes(options?: RequestOptions): Promise<FormFieldTypeDescriptor[]>;
2131
+ getFormFieldTypes(options?: RequestOptions): Promise<Cms.PublicFormFieldTypeDto[]>;
3363
2132
  /**
3364
2133
  * The same request as {@link ContentModule.getFormFieldTypes}, but keeping the
3365
2134
  * slug rules the response carries alongside the field types — use it when
@@ -3367,22 +2136,36 @@ export interface ContentModule {
3367
2136
  */
3368
2137
  getFormFieldTypeRegistry(options?: RequestOptions): Promise<FormFieldTypeRegistry>;
3369
2138
  submitForm(id: string, values: Record<string, unknown>, options?: RequestOptions): Promise<FormSubmissionResult>;
3370
- getContentStrings(format?: 'list' | 'export', options?: RequestOptions): Promise<ContentStrings>;
3371
- getMenus(options?: RequestOptions): Promise<Menu[]>;
2139
+ /**
2140
+ * Every content string of the channel. `'export'` (the default) is the map
2141
+ * `key → language code → value` a page renders from; `'list'` is the CMS's
2142
+ * paginated list envelope, one entity per string with its values.
2143
+ */
2144
+ getContentStrings(format: 'list', options?: RequestOptions): Promise<Cms.PublicContentStringListResponseDto>;
2145
+ getContentStrings(format?: 'export', options?: RequestOptions): Promise<ContentStrings>;
2146
+ getContentStrings(format?: 'list' | 'export', options?: RequestOptions): Promise<ContentStrings | Cms.PublicContentStringListResponseDto>;
2147
+ /**
2148
+ * One content string by id, with its value in every language. Throws a
2149
+ * `VALIDATION_ERROR` before any request when `id` is not a UUID, and
2150
+ * `NOT_FOUND` when the channel has no live string with that id. To render a
2151
+ * page, `getContentStrings('export')` fetches every string in one request.
2152
+ */
2153
+ getContentString(id: string, options?: RequestOptions): Promise<Cms.PublicContentStringDto>;
2154
+ getMenus(options?: RequestOptions): Promise<Cms.PublicMenuSummaryDto[]>;
3372
2155
  getMenu(slugOrId: string, options?: RequestOptions): Promise<Menu>;
3373
- getSitemap(languageCode?: string, options?: RequestOptions): Promise<SitemapEntry[]>;
3374
- lookupContentItems(ids: string[], options?: RequestOptions): Promise<ContentItemSummary[]>;
3375
- lookupContentItemsWithFields(ids: string[], fieldSlugs: string[], options?: RequestOptions): Promise<ContentItemWithFields[]>;
3376
- getCollectionPageValues(collectionId: string, languageCode?: string, options?: RequestOptions): Promise<CollectionPageValues>;
3377
- getCollections(options?: RequestOptions): Promise<CmsCollection[]>;
3378
- getCollection(collectionId: string, options?: RequestOptions): Promise<CmsCollectionDetail>;
2156
+ getSitemap(languageCode?: string, options?: RequestOptions): Promise<Cms.PublicSitemapEntryDto[]>;
2157
+ lookupContentItems(ids: string[], options?: RequestOptions): Promise<Cms.PublicItemSummaryDto[]>;
2158
+ lookupContentItemsWithFields(ids: string[], fieldSlugs: string[], options?: RequestOptions): Promise<Cms.PublicItemWithFieldsDto[]>;
2159
+ getCollectionPageValues(collectionId: string, languageCode?: string, options?: RequestOptions): Promise<Cms.PublicCollectionPageValuesDto>;
2160
+ getCollections(options?: RequestOptions): Promise<Cms.PublicCollectionDto[]>;
2161
+ getCollection(collectionId: string, options?: RequestOptions): Promise<Cms.PublicCollectionDetailDto>;
3379
2162
  getCollectionItems(collectionId: string, query?: CollectionItemsQuery, options?: RequestOptions): Promise<CmsCollectionItemList>;
3380
- getCollectionItem(collectionId: string, itemId: string, languageCode?: string, options?: RequestOptions): Promise<CmsCollectionItem>;
2163
+ getCollectionItem(collectionId: string, itemId: string, languageCode?: string, options?: RequestOptions): Promise<Cms.PublicCollectionItemDetailDto>;
3381
2164
  }
3382
2165
  export interface NavigationModule {
3383
- getRoutes(languageCode?: string, options?: RequestOptions): Promise<RoutesResponse>;
2166
+ getRoutes(languageCode?: string, options?: RequestOptions): Promise<Plugins.PublicRoutesResponseDto>;
3384
2167
  findRoute(path: string, languageCode?: string, options?: RequestOptions): Promise<ResolvedRoute | null>;
3385
- getRoutesByType(type: 'cms' | 'collection' | 'product', languageCode?: string, options?: RequestOptions): Promise<RouteEntry[]>;
2168
+ getRoutesByType(type: Plugins.PublicRouteEntryDto['type'], languageCode?: string, options?: RequestOptions): Promise<Plugins.PublicRouteEntryDto[]>;
3386
2169
  }
3387
2170
  export interface PricingModule {
3388
2171
  /**
@@ -3395,7 +2178,7 @@ export interface PricingModule {
3395
2178
  readonly pricesIncludeTax: boolean;
3396
2179
  formatPrice(amount: number, currencyCode?: string, locale?: string): string;
3397
2180
  formatPriceRange(min: number, max: number, currencyCode?: string, locale?: string): string;
3398
- getTierForQuantity(tiers: PriceTier[], quantity: number): PriceTier | null;
2181
+ getTierForQuantity(tiers: Shop.PriceTierFragment[], quantity: number): Shop.PriceTierFragment | null;
3399
2182
  computeTierTable(variant: VariantPriceData): TierTableEntry[];
3400
2183
  getPriceDisplay(variant: VariantPriceData): PriceDisplay;
3401
2184
  /**
@@ -3446,19 +2229,36 @@ export interface PricingModule {
3446
2229
  */
3447
2230
  parseTaxDisplayPolicy(fields: unknown): TaxDisplayPolicy;
3448
2231
  /**
3449
- * Pre-validate the cart against the channel's order minimums. Pass the object
3450
- * from `getOrderConstraints()` straight through. The server enforces at the
3451
- * `ArrangingPayment` transition regardless.
2232
+ * Pre-validate the cart against the channel's order minimums. Pass the order
2233
+ * and the object from `getOrderConstraints()` straight through. The server
2234
+ * enforces at the `ArrangingPayment` transition regardless.
2235
+ *
2236
+ * It checks the figures the engine checks: the gross minimum against the
2237
+ * lines' gross total (`subTotalWithTax`, no shipping), the net minimum and
2238
+ * the delivery minimum (`fulfillmentMinOrderNet`, skipped for an exempt
2239
+ * customer) against the lines' net total (`subTotal`), and the item count.
2240
+ *
2241
+ * Amounts are formatted in `constraints.currencyCode` and compared only with
2242
+ * an order in that currency; when the two differ (constraints fetched before
2243
+ * a currency switch, or no exchange rate on the engine) the amount checks are
2244
+ * skipped and only the quantity is checked. Re-fetch the constraints after a
2245
+ * currency switch.
3452
2246
  */
3453
2247
  validateOrderMinimums(order: {
3454
2248
  totalWithTax: number;
2249
+ /**
2250
+ * Gross total of the lines, minor units — the gross minimum's basis.
2251
+ * Without it the check falls back to `totalWithTax`, which includes
2252
+ * shipping and can call a cart valid that checkout refuses.
2253
+ */
2254
+ subTotalWithTax?: number;
3455
2255
  currencyCode: string;
3456
2256
  totalQuantity?: number;
3457
2257
  /**
3458
2258
  * Net (tax-exclusive) total, minor units — required for the
3459
- * `minOrderAmountNet` check. `subTotal` is preferred over `total` because
3460
- * the server compares line totals, which exclude shipping. Without one of
3461
- * them the net check is skipped.
2259
+ * `minOrderAmountNet` and `fulfillmentMinOrderNet` checks. `subTotal` is
2260
+ * preferred over `total` because the server compares line totals, which
2261
+ * exclude shipping. Without one of them those checks are skipped.
3462
2262
  */
3463
2263
  subTotal?: number;
3464
2264
  total?: number;
@@ -3466,13 +2266,21 @@ export interface PricingModule {
3466
2266
  minOrderAmountGross?: number | null;
3467
2267
  minOrderAmountNet?: number | null;
3468
2268
  minOrderQuantity?: number | null;
2269
+ /** The default delivery profile's NET minimum, as returned by `getOrderConstraints()`. */
2270
+ fulfillmentMinOrderNet?: number | null;
2271
+ /** True skips the delivery minimum, as the engine does for an exempt customer. */
2272
+ customerIsExempt?: boolean | null;
3469
2273
  /** @deprecated Use `minOrderAmountGross`. */
3470
2274
  minOrderAmount?: number | null;
2275
+ /** The currency the amounts are in, as returned by `getOrderConstraints()`. */
2276
+ currencyCode?: string | null;
3471
2277
  }): OrderValidationResult;
3472
2278
  /**
3473
- * The quantity ceiling for a variant: `max(0, saleable) + backorderAllowance`.
3474
- * `null` when the channel hides stock — no ceiling to show, let the server
3475
- * decide, exactly as before backorders. Clamp quantity steppers to it.
2279
+ * The quantity ceiling for a variant: `max(0, saleable) + backorderAllowance`,
2280
+ * or `0` when the merchant is not accepting orders at all
2281
+ * (`availability.orderable === false`, i.e. coming soon). `null` when the
2282
+ * channel hides stock — no ceiling to show, let the server decide, exactly as
2283
+ * before backorders. Clamp quantity steppers to it.
3476
2284
  */
3477
2285
  maxOrderableQuantity(variant: OrderableStockInput): number | null;
3478
2286
  /**
@@ -3480,6 +2288,24 @@ export interface PricingModule {
3480
2288
  * allowance. The signal to label "Backorder" instead of "Out of stock".
3481
2289
  */
3482
2290
  isBackorderOnly(variant: OrderableStockInput): boolean;
2291
+ /**
2292
+ * Whether the merchant shows this variant as "coming soon": visible, ordered
2293
+ * by nobody, not even from stock on hand. Badge it and disable add-to-cart.
2294
+ */
2295
+ isComingSoon(variant: OrderableStockInput): boolean;
2296
+ /**
2297
+ * Whether this variant is available only as a pre-order: the state is
2298
+ * `'preorder'` and there is nothing saleable to buy outright. Label
2299
+ * "Pre-order", not "Out of stock".
2300
+ */
2301
+ isPreorderOnly(variant: OrderableStockInput): boolean;
2302
+ /**
2303
+ * Whether the buy button should be enabled for this shopper: the ceiling is
2304
+ * anything but `0`. The one rule a storefront needs — NOT
2305
+ * `availability.orderable`, which is `true` for an anonymous shopper who
2306
+ * cannot pre-order beyond stock.
2307
+ */
2308
+ canAddToCart(variant: OrderableStockInput): boolean;
3483
2309
  /**
3484
2310
  * Units of a cart line stock will not cover — the "N on backorder" hint
3485
2311
  * before placement, as the server will stamp it. `null` when the channel
@@ -3487,10 +2313,32 @@ export interface PricingModule {
3487
2313
  */
3488
2314
  backorderedQuantityForCart(variant: Pick<OrderableStockInput, 'saleable'>, quantity: number): number | null;
3489
2315
  }
3490
- /** The two fields the quantity ceiling reads; satisfied by every SDK variant shape. */
2316
+ /** The fields the orderability helpers read; satisfied by every SDK variant shape. */
3491
2317
  export interface OrderableStockInput {
3492
2318
  saleable?: number | null;
3493
2319
  backorderAllowance?: number | null;
2320
+ /**
2321
+ * The merchant publication state. Optional and nullable so a search row
2322
+ * (which may not know) and a hand-built object both satisfy this — an absent
2323
+ * state means "nothing in force", which is what every variant reported
2324
+ * before pre-orders existed.
2325
+ */
2326
+ availability?: Shop.ProductAvailabilityFragment | null;
2327
+ /**
2328
+ * Vendure's coarse display string (`'IN_STOCK'` / `'OUT_OF_STOCK'`). Selected
2329
+ * by every VARIANT document, where it is present even when `saleable` is
2330
+ * `null` (the channel does not expose stock numbers, which is the default) —
2331
+ * so on such a channel it is the stock signal `isPreorderOnly` reads. A
2332
+ * SEARCH row does not carry it; see `inStock`.
2333
+ */
2334
+ stockLevel?: string | null;
2335
+ /**
2336
+ * A search row's stock flag — the ONLY stock signal `SEARCH_PRODUCTS` selects
2337
+ * (it asks for neither `saleable` nor `stockLevel`). Without it a search grid
2338
+ * cannot tell a 0-stock pre-order from one with stock, and labels the first
2339
+ * "Out of stock": the exact grid bug the availability field exists to fix.
2340
+ */
2341
+ inStock?: boolean | null;
3494
2342
  }
3495
2343
  export interface MediaModule {
3496
2344
  assetUrl(path: string): string;
@@ -3505,16 +2353,20 @@ export interface MediaModule {
3505
2353
  getResponsiveImageData(asset: Asset, presets?: PresetName[]): ResponsiveImageData;
3506
2354
  }
3507
2355
  export interface CurrencyModule {
3508
- getExchangeRates(): Promise<ExchangeRate[]>;
2356
+ getExchangeRates(): Promise<Shop.ExchangeRatesQuery['exchangeRates']>;
3509
2357
  /** Current rate for a single base→target pair, or `null` when unknown. */
3510
- getExchangeRate(targetCurrency: string): Promise<ExchangeRate | null>;
3511
- convertCurrency(amount: string, fromCurrency: string, toCurrency: string): Promise<ConvertedAmount>;
3512
- /** Convert from the base currency (EUR) to a target currency. */
3513
- convertFromBase(amount: string, targetCurrency: string): Promise<ConvertedAmount>;
3514
- /** Convert from a source currency to the base currency (EUR). */
3515
- convertToBase(amount: string, sourceCurrency: string): Promise<ConvertedAmount>;
2358
+ getExchangeRate(targetCurrency: string): Promise<Shop.ExchangeRateQuery['exchangeRate']>;
2359
+ /**
2360
+ * `null` is the schema's (the field is nullable): today the engine answers a
2361
+ * currency it has no rate for with an error, which this throws.
2362
+ */
2363
+ convertCurrency(amount: string, fromCurrency: string, toCurrency: string): Promise<Shop.ConvertedAmountFragment | null>;
2364
+ /** Convert from the base currency (EUR) to a target currency (`null`: see `convertCurrency`). */
2365
+ convertFromBase(amount: string, targetCurrency: string): Promise<Shop.ConvertedAmountFragment | null>;
2366
+ /** Convert from a source currency to the base currency (EUR) (`null`: see `convertCurrency`). */
2367
+ convertToBase(amount: string, sourceCurrency: string): Promise<Shop.ConvertedAmountFragment | null>;
3516
2368
  /** Convert one amount into several currencies in a single roundtrip. */
3517
- convertToMultiple(amount: string, fromCurrency: string, toCurrencies: string[]): Promise<BulkConversionResult[]>;
2369
+ convertToMultiple(amount: string, fromCurrency: string, toCurrencies: string[]): Promise<Shop.ConvertToMultipleQuery['convertToMultiple']>;
3518
2370
  }
3519
2371
  export interface CreditModule {
3520
2372
  /**
@@ -3522,13 +2374,19 @@ export interface CreditModule {
3522
2374
  * channel, or `null` when not signed in, no credit account exists, or the
3523
2375
  * channel has B2B credit disabled. Soft-enforcement only — display the
3524
2376
  * `overLimit` / `hasOverdue` flags as warnings; the SDK never blocks checkout.
2377
+ * Format the figures with `status.currencyCode`, not the session currency.
2378
+ * Refused with code `EXCHANGE_RATE_UNAVAILABLE` when the customer has a credit
2379
+ * limit and owes money in a currency the store has no exchange rate for: the
2380
+ * exposure cannot be measured against the limit, so treat the status as
2381
+ * unavailable, never as 0. Without a limit such money is left out of the
2382
+ * figures instead.
3525
2383
  */
3526
2384
  getCreditStatus(options?: RequestOptions): Promise<B2bCreditStatus | null>;
3527
2385
  /**
3528
2386
  * Returns the signed-in customer's source-aware payment terms (including local B2B terms), or
3529
2387
  * `null` when the customer is not signed in or has no payment-terms account in this channel.
3530
2388
  */
3531
- getPaymentTerms(options?: RequestOptions): Promise<CustomerPaymentTerms | null>;
2389
+ getPaymentTerms(options?: RequestOptions): Promise<Shop.CustomerPaymentTermsFragment | null>;
3532
2390
  }
3533
2391
  export interface StorefrontClient {
3534
2392
  readonly context: StoreContext;
@@ -3542,6 +2400,7 @@ export interface StorefrontClient {
3542
2400
  readonly seo: import('./seo/types.js').SeoModule;
3543
2401
  /** Platform-managed URL redirects for this channel. */
3544
2402
  readonly redirects: import('./redirects/types.js').RedirectStore;
2403
+ readonly feeds: import('./feeds/types.js').FeedsModule;
3545
2404
  readonly maintenanceMode: boolean;
3546
2405
  setLanguage(code: string): void;
3547
2406
  getLanguage(): string;
@@ -3555,6 +2414,24 @@ export interface StorefrontClient {
3555
2414
  setOrderScope(scope: OrderScope | null): void;
3556
2415
  /** The scope currently sent as `x-order-scope`, or `null` when none is set. */
3557
2416
  getOrderScope(): OrderScope | null;
2417
+ /**
2418
+ * Send a raw Shop API document and return its `data`.
2419
+ *
2420
+ * @deprecated Call the typed methods instead; this keeps working until 1.0 and announces
2421
+ * itself once per process (`onDeprecation` routes or silences that). The common uses all
2422
+ * have a method now: a collection or product by id → `commerce.getCollectionById(id)` /
2423
+ * `commerce.getProductById(id)`; storefront metafields → `commerce.getProduct(slug, {
2424
+ * metafields: true })` (also on `getProductById`, `getCollection`, `getCollectionById`); the
2425
+ * session currency → `createStorefrontClient({ currencyCode })` and
2426
+ * `commerce.setOrderCurrency(code)`; what the store is ready to serve →
2427
+ * `commerce.getCapabilities()`; one content string → `content.getContentString(id)`; logo,
2428
+ * cover and favicon → `commerce.getBranding()`, a CMS asset → `content.getAsset(id)`; sign-in
2429
+ * with a named strategy, order custom fields, unsetting addresses and order-state moves →
2430
+ * `commerce.authenticate`, `setOrderCustomFields`, `unsetShippingAddress` /
2431
+ * `unsetBillingAddress`, `getNextOrderStates` / `transitionOrder`. The Shop API fields no
2432
+ * method sends yet are listed in the MCP capability catalog
2433
+ * (`storefront://capability-catalog`).
2434
+ */
3558
2435
  graphql<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T>;
3559
2436
  }
3560
2437
  //# sourceMappingURL=types.d.ts.map