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