@sixtyninecommerce/client 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. package/README.md +556 -16
  2. package/dist/admin/http.d.ts.map +1 -1
  3. package/dist/admin/http.js.map +1 -1
  4. package/dist/admin/types.d.ts.map +1 -1
  5. package/dist/build-client.d.ts +9 -0
  6. package/dist/build-client.d.ts.map +1 -0
  7. package/dist/build-client.js +58 -0
  8. package/dist/build-client.js.map +1 -0
  9. package/dist/cache-tags.d.ts +35 -1
  10. package/dist/cache-tags.d.ts.map +1 -1
  11. package/dist/cache-tags.js +39 -1
  12. package/dist/cache-tags.js.map +1 -1
  13. package/dist/client.d.ts +25 -0
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/client.js +9 -62
  16. package/dist/client.js.map +1 -1
  17. package/dist/commerce/age-verification.d.ts +7 -4
  18. package/dist/commerce/age-verification.d.ts.map +1 -1
  19. package/dist/commerce/age-verification.js +6 -4
  20. package/dist/commerce/age-verification.js.map +1 -1
  21. package/dist/commerce/arguments.d.ts +13 -0
  22. package/dist/commerce/arguments.d.ts.map +1 -0
  23. package/dist/commerce/arguments.js +19 -0
  24. package/dist/commerce/arguments.js.map +1 -0
  25. package/dist/commerce/branding.d.ts.map +1 -1
  26. package/dist/commerce/branding.js.map +1 -1
  27. package/dist/commerce/capabilities.d.ts +40 -0
  28. package/dist/commerce/capabilities.d.ts.map +1 -0
  29. package/dist/commerce/capabilities.js +41 -0
  30. package/dist/commerce/capabilities.js.map +1 -0
  31. package/dist/commerce/cart.d.ts +9 -12
  32. package/dist/commerce/cart.d.ts.map +1 -1
  33. package/dist/commerce/cart.js +6 -1
  34. package/dist/commerce/cart.js.map +1 -1
  35. package/dist/commerce/checkout.d.ts +95 -15
  36. package/dist/commerce/checkout.d.ts.map +1 -1
  37. package/dist/commerce/checkout.js +230 -10
  38. package/dist/commerce/checkout.js.map +1 -1
  39. package/dist/commerce/customer.d.ts +82 -38
  40. package/dist/commerce/customer.d.ts.map +1 -1
  41. package/dist/commerce/customer.js +146 -10
  42. package/dist/commerce/customer.js.map +1 -1
  43. package/dist/commerce/favorites.d.ts +2 -5
  44. package/dist/commerce/favorites.d.ts.map +1 -1
  45. package/dist/commerce/favorites.js.map +1 -1
  46. package/dist/commerce/index.d.ts +189 -133
  47. package/dist/commerce/index.d.ts.map +1 -1
  48. package/dist/commerce/index.js +9 -0
  49. package/dist/commerce/index.js.map +1 -1
  50. package/dist/commerce/order-states.d.ts +18 -0
  51. package/dist/commerce/order-states.d.ts.map +1 -0
  52. package/dist/commerce/order-states.js +30 -0
  53. package/dist/commerce/order-states.js.map +1 -0
  54. package/dist/commerce/parcel-pricing.d.ts +48 -0
  55. package/dist/commerce/parcel-pricing.d.ts.map +1 -0
  56. package/dist/commerce/parcel-pricing.js +39 -0
  57. package/dist/commerce/parcel-pricing.js.map +1 -0
  58. package/dist/commerce/parked-orders.d.ts +22 -0
  59. package/dist/commerce/parked-orders.d.ts.map +1 -0
  60. package/dist/commerce/parked-orders.js +47 -0
  61. package/dist/commerce/parked-orders.js.map +1 -0
  62. package/dist/commerce/payments.d.ts +12 -5
  63. package/dist/commerce/payments.d.ts.map +1 -1
  64. package/dist/commerce/payments.js +10 -1
  65. package/dist/commerce/payments.js.map +1 -1
  66. package/dist/commerce/placement-error.d.ts +17 -0
  67. package/dist/commerce/placement-error.d.ts.map +1 -1
  68. package/dist/commerce/placement-error.js.map +1 -1
  69. package/dist/commerce/products.d.ts +92 -38
  70. package/dist/commerce/products.d.ts.map +1 -1
  71. package/dist/commerce/products.js +162 -123
  72. package/dist/commerce/products.js.map +1 -1
  73. package/dist/commerce/queries.d.ts +204 -49
  74. package/dist/commerce/queries.d.ts.map +1 -1
  75. package/dist/commerce/queries.js +1296 -737
  76. package/dist/commerce/queries.js.map +1 -1
  77. package/dist/commerce/quotes.d.ts +5 -4
  78. package/dist/commerce/quotes.d.ts.map +1 -1
  79. package/dist/commerce/quotes.js +1 -36
  80. package/dist/commerce/quotes.js.map +1 -1
  81. package/dist/commerce/recommendations.d.ts +3 -3
  82. package/dist/commerce/recommendations.d.ts.map +1 -1
  83. package/dist/commerce/recommendations.js +3 -1
  84. package/dist/commerce/recommendations.js.map +1 -1
  85. package/dist/commerce/returns.d.ts +7 -6
  86. package/dist/commerce/returns.d.ts.map +1 -1
  87. package/dist/commerce/returns.js.map +1 -1
  88. package/dist/commerce/reviews.d.ts +24 -15
  89. package/dist/commerce/reviews.d.ts.map +1 -1
  90. package/dist/commerce/reviews.js +67 -50
  91. package/dist/commerce/reviews.js.map +1 -1
  92. package/dist/commerce/saved-lists.d.ts +15 -15
  93. package/dist/commerce/saved-lists.d.ts.map +1 -1
  94. package/dist/commerce/saved-lists.js +67 -55
  95. package/dist/commerce/saved-lists.js.map +1 -1
  96. package/dist/commerce/search.d.ts +3 -2
  97. package/dist/commerce/search.d.ts.map +1 -1
  98. package/dist/commerce/search.js +10 -2
  99. package/dist/commerce/search.js.map +1 -1
  100. package/dist/commerce/shipping.d.ts +11 -4
  101. package/dist/commerce/shipping.d.ts.map +1 -1
  102. package/dist/commerce/shipping.js +17 -2
  103. package/dist/commerce/shipping.js.map +1 -1
  104. package/dist/commerce/stock-notifications.d.ts +2 -0
  105. package/dist/commerce/stock-notifications.d.ts.map +1 -1
  106. package/dist/commerce/stock-notifications.js +2 -2
  107. package/dist/commerce/stock-notifications.js.map +1 -1
  108. package/dist/commerce/subscriptions.d.ts +35 -37
  109. package/dist/commerce/subscriptions.d.ts.map +1 -1
  110. package/dist/commerce/subscriptions.js +159 -120
  111. package/dist/commerce/subscriptions.js.map +1 -1
  112. package/dist/commerce/vat-validation.d.ts +6 -3
  113. package/dist/commerce/vat-validation.d.ts.map +1 -1
  114. package/dist/commerce/vat-validation.js +24 -19
  115. package/dist/commerce/vat-validation.js.map +1 -1
  116. package/dist/constants.d.ts.map +1 -1
  117. package/dist/constants.js.map +1 -1
  118. package/dist/content/assets.d.ts +5 -4
  119. package/dist/content/assets.d.ts.map +1 -1
  120. package/dist/content/assets.js.map +1 -1
  121. package/dist/content/collection-pages.d.ts +3 -2
  122. package/dist/content/collection-pages.d.ts.map +1 -1
  123. package/dist/content/collection-pages.js.map +1 -1
  124. package/dist/content/collections.d.ts +5 -4
  125. package/dist/content/collections.d.ts.map +1 -1
  126. package/dist/content/collections.js.map +1 -1
  127. package/dist/content/filtered-products.d.ts.map +1 -1
  128. package/dist/content/filtered-products.js.map +1 -1
  129. package/dist/content/form-field-types.d.ts +3 -3
  130. package/dist/content/form-field-types.d.ts.map +1 -1
  131. package/dist/content/form-field-types.js.map +1 -1
  132. package/dist/content/forms.d.ts +4 -3
  133. package/dist/content/forms.d.ts.map +1 -1
  134. package/dist/content/forms.js +3 -0
  135. package/dist/content/forms.js.map +1 -1
  136. package/dist/content/index.d.ts +18 -17
  137. package/dist/content/index.d.ts.map +1 -1
  138. package/dist/content/items.d.ts +5 -4
  139. package/dist/content/items.d.ts.map +1 -1
  140. package/dist/content/items.js +2 -0
  141. package/dist/content/items.js.map +1 -1
  142. package/dist/content/menus.d.ts +3 -2
  143. package/dist/content/menus.d.ts.map +1 -1
  144. package/dist/content/menus.js +7 -1
  145. package/dist/content/menus.js.map +1 -1
  146. package/dist/content/resolve.d.ts +3 -2
  147. package/dist/content/resolve.d.ts.map +1 -1
  148. package/dist/content/resolve.js +1 -1
  149. package/dist/content/resolve.js.map +1 -1
  150. package/dist/content/sitemap.d.ts +3 -2
  151. package/dist/content/sitemap.d.ts.map +1 -1
  152. package/dist/content/sitemap.js.map +1 -1
  153. package/dist/content/strings.d.ts +16 -2
  154. package/dist/content/strings.d.ts.map +1 -1
  155. package/dist/content/strings.js +32 -4
  156. package/dist/content/strings.js.map +1 -1
  157. package/dist/core/context.d.ts +127 -1
  158. package/dist/core/context.d.ts.map +1 -1
  159. package/dist/core/context.js +436 -45
  160. package/dist/core/context.js.map +1 -1
  161. package/dist/core/currency.d.ts +14 -0
  162. package/dist/core/currency.d.ts.map +1 -0
  163. package/dist/core/currency.js +52 -0
  164. package/dist/core/currency.js.map +1 -0
  165. package/dist/core/deprecation.d.ts +23 -0
  166. package/dist/core/deprecation.d.ts.map +1 -0
  167. package/dist/core/deprecation.js +81 -0
  168. package/dist/core/deprecation.js.map +1 -0
  169. package/dist/core/http.d.ts +15 -1
  170. package/dist/core/http.d.ts.map +1 -1
  171. package/dist/core/http.js +55 -3
  172. package/dist/core/http.js.map +1 -1
  173. package/dist/core/public-artifact.d.ts +72 -0
  174. package/dist/core/public-artifact.d.ts.map +1 -0
  175. package/dist/core/public-artifact.js +122 -0
  176. package/dist/core/public-artifact.js.map +1 -0
  177. package/dist/core/unknown-field-rejection.d.ts +18 -0
  178. package/dist/core/unknown-field-rejection.d.ts.map +1 -0
  179. package/dist/core/unknown-field-rejection.js +37 -0
  180. package/dist/core/unknown-field-rejection.js.map +1 -0
  181. package/dist/credit/credit-status.d.ts +2 -0
  182. package/dist/credit/credit-status.d.ts.map +1 -1
  183. package/dist/credit/credit-status.js +71 -19
  184. package/dist/credit/credit-status.js.map +1 -1
  185. package/dist/credit/index.d.ts +1 -1
  186. package/dist/credit/payment-terms.d.ts +3 -3
  187. package/dist/credit/payment-terms.d.ts.map +1 -1
  188. package/dist/credit/payment-terms.js +28 -24
  189. package/dist/credit/payment-terms.js.map +1 -1
  190. package/dist/currency/exchange.d.ts +7 -7
  191. package/dist/currency/exchange.d.ts.map +1 -1
  192. package/dist/currency/exchange.js +5 -1
  193. package/dist/currency/exchange.js.map +1 -1
  194. package/dist/errors.d.ts +17 -0
  195. package/dist/errors.d.ts.map +1 -1
  196. package/dist/errors.js +13 -0
  197. package/dist/errors.js.map +1 -1
  198. package/dist/events/index.d.ts +20 -7
  199. package/dist/events/index.d.ts.map +1 -1
  200. package/dist/events/index.js +17 -5
  201. package/dist/events/index.js.map +1 -1
  202. package/dist/events/payloads.d.ts +7 -4
  203. package/dist/events/payloads.d.ts.map +1 -1
  204. package/dist/events/payloads.js +6 -3
  205. package/dist/events/payloads.js.map +1 -1
  206. package/dist/feeds/index.d.ts +5 -0
  207. package/dist/feeds/index.d.ts.map +1 -0
  208. package/dist/feeds/index.js +12 -0
  209. package/dist/feeds/index.js.map +1 -0
  210. package/dist/feeds/types.d.ts +18 -0
  211. package/dist/feeds/types.d.ts.map +1 -0
  212. package/dist/feeds/types.js +8 -0
  213. package/dist/feeds/types.js.map +1 -0
  214. package/dist/generated/cms.d.ts +2136 -0
  215. package/dist/generated/cms.d.ts.map +1 -0
  216. package/dist/generated/cms.js +4 -0
  217. package/dist/generated/cms.js.map +1 -0
  218. package/dist/generated/plugins.d.ts +550 -0
  219. package/dist/generated/plugins.d.ts.map +1 -0
  220. package/dist/generated/plugins.js +4 -0
  221. package/dist/generated/plugins.js.map +1 -0
  222. package/dist/generated/shop.d.ts +5539 -0
  223. package/dist/generated/shop.d.ts.map +1 -0
  224. package/dist/generated/shop.js +5 -0
  225. package/dist/generated/shop.js.map +1 -0
  226. package/dist/graphql-document.d.ts +29 -0
  227. package/dist/graphql-document.d.ts.map +1 -0
  228. package/dist/graphql-document.js +21 -0
  229. package/dist/graphql-document.js.map +1 -0
  230. package/dist/index.d.ts +9 -4
  231. package/dist/index.d.ts.map +1 -1
  232. package/dist/index.js +4 -2
  233. package/dist/index.js.map +1 -1
  234. package/dist/media/urls.d.ts.map +1 -1
  235. package/dist/media/urls.js +12 -1
  236. package/dist/media/urls.js.map +1 -1
  237. package/dist/media/video.d.ts.map +1 -1
  238. package/dist/media/video.js.map +1 -1
  239. package/dist/multi-store.d.ts +200 -0
  240. package/dist/multi-store.d.ts.map +1 -0
  241. package/dist/multi-store.js +558 -0
  242. package/dist/multi-store.js.map +1 -0
  243. package/dist/navigation/routes.d.ts +4 -3
  244. package/dist/navigation/routes.d.ts.map +1 -1
  245. package/dist/navigation/routes.js.map +1 -1
  246. package/dist/next/artifact-handler.d.ts +21 -13
  247. package/dist/next/artifact-handler.d.ts.map +1 -1
  248. package/dist/next/artifact-handler.js +28 -66
  249. package/dist/next/artifact-handler.js.map +1 -1
  250. package/dist/next/event-revalidate-handler.d.ts +26 -6
  251. package/dist/next/event-revalidate-handler.d.ts.map +1 -1
  252. package/dist/next/event-revalidate-handler.js +126 -19
  253. package/dist/next/event-revalidate-handler.js.map +1 -1
  254. package/dist/next/feed-handler.d.ts +50 -0
  255. package/dist/next/feed-handler.d.ts.map +1 -0
  256. package/dist/next/feed-handler.js +61 -0
  257. package/dist/next/feed-handler.js.map +1 -0
  258. package/dist/next/index.d.ts +3 -1
  259. package/dist/next/index.d.ts.map +1 -1
  260. package/dist/next/index.js +1 -0
  261. package/dist/next/index.js.map +1 -1
  262. package/dist/next/metadata.d.ts.map +1 -1
  263. package/dist/next/metadata.js.map +1 -1
  264. package/dist/next/redirect-middleware.d.ts +5 -31
  265. package/dist/next/redirect-middleware.d.ts.map +1 -1
  266. package/dist/next/redirect-middleware.js +4 -46
  267. package/dist/next/redirect-middleware.js.map +1 -1
  268. package/dist/next/revalidate-handler.d.ts.map +1 -1
  269. package/dist/next/revalidate-handler.js.map +1 -1
  270. package/dist/pricing/index.d.ts +1 -1
  271. package/dist/pricing/index.d.ts.map +1 -1
  272. package/dist/pricing/index.js +5 -2
  273. package/dist/pricing/index.js.map +1 -1
  274. package/dist/pricing/tax-display.js +1 -1
  275. package/dist/pricing/tax-display.js.map +1 -1
  276. package/dist/pricing/tiers.d.ts +3 -2
  277. package/dist/pricing/tiers.d.ts.map +1 -1
  278. package/dist/pricing/tiers.js.map +1 -1
  279. package/dist/pricing/validation.d.ts +152 -13
  280. package/dist/pricing/validation.d.ts.map +1 -1
  281. package/dist/pricing/validation.js +167 -13
  282. package/dist/pricing/validation.js.map +1 -1
  283. package/dist/redirects/index.d.ts.map +1 -1
  284. package/dist/redirects/index.js +2 -1
  285. package/dist/redirects/index.js.map +1 -1
  286. package/dist/redirects/store.d.ts.map +1 -1
  287. package/dist/redirects/store.js +6 -2
  288. package/dist/redirects/store.js.map +1 -1
  289. package/dist/redirects/types.d.ts +5 -2
  290. package/dist/redirects/types.d.ts.map +1 -1
  291. package/dist/revalidation/event-plan.d.ts +55 -4
  292. package/dist/revalidation/event-plan.d.ts.map +1 -1
  293. package/dist/revalidation/event-plan.js +115 -8
  294. package/dist/revalidation/event-plan.js.map +1 -1
  295. package/dist/revalidation/event-verify.d.ts +8 -37
  296. package/dist/revalidation/event-verify.d.ts.map +1 -1
  297. package/dist/revalidation/event-verify.js +7 -97
  298. package/dist/revalidation/event-verify.js.map +1 -1
  299. package/dist/revalidation/types.d.ts.map +1 -1
  300. package/dist/revalidation/url-context.d.ts +17 -0
  301. package/dist/revalidation/url-context.d.ts.map +1 -1
  302. package/dist/revalidation/url-context.js +35 -2
  303. package/dist/revalidation/url-context.js.map +1 -1
  304. package/dist/seo/ai.d.ts.map +1 -1
  305. package/dist/seo/ai.js.map +1 -1
  306. package/dist/seo/artifacts.d.ts +86 -4
  307. package/dist/seo/artifacts.d.ts.map +1 -1
  308. package/dist/seo/artifacts.js +115 -16
  309. package/dist/seo/artifacts.js.map +1 -1
  310. package/dist/seo/availability.d.ts +95 -0
  311. package/dist/seo/availability.d.ts.map +1 -0
  312. package/dist/seo/availability.js +89 -0
  313. package/dist/seo/availability.js.map +1 -0
  314. package/dist/seo/index.d.ts +4 -0
  315. package/dist/seo/index.d.ts.map +1 -1
  316. package/dist/seo/index.js +6 -1
  317. package/dist/seo/index.js.map +1 -1
  318. package/dist/seo/json-ld.d.ts.map +1 -1
  319. package/dist/seo/json-ld.js +34 -1
  320. package/dist/seo/json-ld.js.map +1 -1
  321. package/dist/seo/meta-tags.d.ts +40 -1
  322. package/dist/seo/meta-tags.d.ts.map +1 -1
  323. package/dist/seo/meta-tags.js +8 -1
  324. package/dist/seo/meta-tags.js.map +1 -1
  325. package/dist/seo/metadata-parser.d.ts.map +1 -1
  326. package/dist/seo/metadata-parser.js.map +1 -1
  327. package/dist/seo/metadata-types.d.ts.map +1 -1
  328. package/dist/seo/robots.d.ts.map +1 -1
  329. package/dist/seo/robots.js.map +1 -1
  330. package/dist/seo/types.d.ts +20 -2
  331. package/dist/seo/types.d.ts.map +1 -1
  332. package/dist/seo/url-builder.d.ts +5 -3
  333. package/dist/seo/url-builder.d.ts.map +1 -1
  334. package/dist/seo/url-builder.js +3 -1
  335. package/dist/seo/url-builder.js.map +1 -1
  336. package/dist/types.d.ts +1306 -2429
  337. package/dist/types.d.ts.map +1 -1
  338. package/dist/web/artifact-responder.d.ts +69 -0
  339. package/dist/web/artifact-responder.d.ts.map +1 -0
  340. package/dist/web/artifact-responder.js +90 -0
  341. package/dist/web/artifact-responder.js.map +1 -0
  342. package/dist/web/feed-responder.d.ts +72 -0
  343. package/dist/web/feed-responder.d.ts.map +1 -0
  344. package/dist/web/feed-responder.js +81 -0
  345. package/dist/web/feed-responder.js.map +1 -0
  346. package/dist/web/index.d.ts +23 -0
  347. package/dist/web/index.d.ts.map +1 -0
  348. package/dist/web/index.js +19 -0
  349. package/dist/web/index.js.map +1 -0
  350. package/dist/web/redirect-middleware.d.ts +76 -0
  351. package/dist/web/redirect-middleware.d.ts.map +1 -0
  352. package/dist/web/redirect-middleware.js +94 -0
  353. package/dist/web/redirect-middleware.js.map +1 -0
  354. package/dist/web/respond.d.ts +20 -0
  355. package/dist/web/respond.d.ts.map +1 -0
  356. package/dist/web/respond.js +52 -0
  357. package/dist/web/respond.js.map +1 -0
  358. package/package.json +19 -3
@@ -1,12 +1,54 @@
1
- // --- Product Queries ---
1
+ import { fragment, withFragments } from '../graphql-document.js';
2
+ // Every document and fragment below is tagged `/* GraphQL */` and read by
3
+ // codegen (codegen.ts), which ERASES `${…}` interpolations: a selection shared
4
+ // between documents is a named `fragment`, composed with `withFragments`.
5
+ // Regenerate `src/generated/shop.ts` after any edit: `pnpm codegen`.
6
+ // --- Catalog fragments ---
7
+ /** The merchant publication state — the same three fields wherever it is read. */
8
+ export const PRODUCT_AVAILABILITY_FRAGMENT = fragment(/* GraphQL */ `
9
+ fragment ProductAvailability on ProductAvailability {
10
+ state availableFrom orderable
11
+ }
12
+ `);
13
+ export const PRICE_TIER_FRAGMENT = fragment(/* GraphQL */ `
14
+ fragment PriceTier on PriceTier {
15
+ minQuantity price priceWithTax discountLabel
16
+ }
17
+ `);
18
+ export const VARIANT_LOCATION_AVAILABILITY_FRAGMENT = fragment(/* GraphQL */ `
19
+ fragment VariantLocationAvailability on VariantLocationAvailability {
20
+ locationId locationName inStock
21
+ }
22
+ `);
23
+ export const FACET_VALUE_FRAGMENT = fragment(/* GraphQL */ `
24
+ fragment FacetValue on FacetValue {
25
+ id name code facet { id name code }
26
+ }
27
+ `);
28
+ /**
29
+ * A product's collections, as canonical/hreflang resolution reads them.
30
+ *
31
+ * The parent's `slug` is load-bearing: a top-level collection is parented to
32
+ * the `__root_collection__` SENTINEL (Vendure resolves `parent` to null only
33
+ * when the real parent is PRIVATE), so the slug is what tells "root" from
34
+ * "nested" — see `isUserFacingRoot`.
35
+ */
36
+ export const COLLECTION_REF_FRAGMENT = fragment(/* GraphQL */ `
37
+ fragment CollectionRef on Collection {
38
+ id name slug position
39
+ parent { id slug }
40
+ translations { languageCode name slug }
41
+ customFields { isRoutable isCanonical }
42
+ }
43
+ `);
2
44
  /**
3
- * Fragment for `Product.metadata` (vendure-plugin-product-metadata). The
4
- * server already picks the active-language translation and composes
5
- * `metaRobots` + `resolvedBotDirectives` — the SDK only needs to validate +
6
- * type-narrow the JSON-scalar fields at the boundary.
45
+ * `Product.metadata` (vendure-plugin-product-metadata). The server already
46
+ * picks the active-language translation and composes `metaRobots` +
47
+ * `resolvedBotDirectives` — the SDK only validates and type-narrows the
48
+ * JSON-scalar fields at the boundary (`parseProductMetadata`).
7
49
  */
8
- const PRODUCT_METADATA_FRAGMENT = `
9
- metadata {
50
+ export const PRODUCT_METADATA_FRAGMENT = fragment(/* GraphQL */ `
51
+ fragment ProductMetadata on ProductMetadataShop {
10
52
  seoTitle seoDescription canonicalUrl
11
53
  socialTitle socialDescription socialImageAlt socialOgType
12
54
  socialImage {
@@ -31,70 +73,41 @@ const PRODUCT_METADATA_FRAGMENT = `
31
73
  metaRobots resolvedBotDirectives
32
74
  includeReviewsInJsonld
33
75
  }
34
- `;
35
- export const GET_PRODUCT = `
36
- query GetProduct($slug: String!) {
37
- product(slug: $slug) {
38
- id name slug description
76
+ `);
77
+ /** A variant as the product DETAIL read returns it. */
78
+ export const PRODUCT_VARIANT_FRAGMENT = fragment(
79
+ /* GraphQL */ `
80
+ fragment ProductVariant on ProductVariant {
81
+ id name sku
82
+ price priceWithTax currencyCode stockLevel
83
+ stockOnHand stockAllocated saleable
84
+ incomingStock projectedSaleable nextExpectedArrival
85
+ backorderAllowance
86
+ availability { ...ProductAvailability }
87
+ forSaleInCurrency
88
+ priceListName retailPrice retailPriceWithTax taxRateApplied { value }
89
+ priceTiers { ...PriceTier }
90
+ availabilityByLocation { ...VariantLocationAvailability }
91
+ options { id code name group { id name code } }
92
+ customFields { minOrderQuantity salesUnit position }
39
93
  featuredAsset {
40
94
  source name width height
41
95
  customFields { altText }
42
- presets {
43
- xxs { url webpUrl } xs { url webpUrl }
44
- s { url webpUrl } m { url webpUrl }
45
- l { url webpUrl } xl { url webpUrl }
46
- }
96
+ presets { xs { url webpUrl } m { url webpUrl } }
47
97
  }
48
98
  assets {
49
99
  source name width height
50
100
  customFields { altText }
51
- presets {
52
- xs { url webpUrl } m { url webpUrl }
53
- l { url webpUrl } xl { url webpUrl }
54
- }
101
+ presets { m { url webpUrl } l { url webpUrl } }
55
102
  }
56
- variants {
57
- id name sku
58
- price priceWithTax currencyCode stockLevel
59
- stockOnHand stockAllocated saleable
60
- incomingStock projectedSaleable nextExpectedArrival
61
- backorderAllowance
62
- priceListName retailPrice retailPriceWithTax taxRateApplied { value }
63
- priceTiers { minQuantity price priceWithTax discountLabel }
64
- availabilityByLocation { locationId locationName inStock }
65
- options { id code name group { id name code } }
66
- customFields { minOrderQuantity salesUnit position }
67
- featuredAsset {
68
- source name width height
69
- customFields { altText }
70
- presets { xs { url webpUrl } m { url webpUrl } }
71
- }
72
- assets {
73
- source name width height
74
- customFields { altText }
75
- presets { m { url webpUrl } l { url webpUrl } }
76
- }
77
- }
78
- optionGroups { id name code options { id name code } }
79
- facetValues { id name code facet { id name code } }
80
- translations { languageCode name slug description }
81
- collections {
82
- id name slug position
83
- parent { id slug }
84
- translations { languageCode name slug }
85
- customFields { isRoutable isCanonical }
86
- }
87
- documents {
88
- id position title description fileUrl fileMimeType fileSize fileName requiresAuth
89
- }
90
- ${PRODUCT_METADATA_FRAGMENT}
91
103
  }
92
- }
93
- `;
94
- export const GET_PRODUCT_BY_ID = `
95
- query GetProductById($id: ID!) {
96
- product(id: $id) {
104
+ `, PRODUCT_AVAILABILITY_FRAGMENT, PRICE_TIER_FRAGMENT, VARIANT_LOCATION_AVAILABILITY_FRAGMENT);
105
+ /** The product DETAIL read (`getProduct`, `getProductById`). */
106
+ export const PRODUCT_FRAGMENT = fragment(
107
+ /* GraphQL */ `
108
+ fragment Product on Product {
97
109
  id name slug description
110
+ availability { ...ProductAvailability }
98
111
  featuredAsset {
99
112
  source name width height
100
113
  customFields { altText }
@@ -112,78 +125,45 @@ export const GET_PRODUCT_BY_ID = `
112
125
  l { url webpUrl } xl { url webpUrl }
113
126
  }
114
127
  }
128
+ variants { ...ProductVariant }
129
+ optionGroups { id name code options { id name code } }
130
+ facetValues { ...FacetValue }
131
+ translations { languageCode name slug description }
132
+ collections { ...CollectionRef }
133
+ documents {
134
+ id position title description fileUrl fileMimeType fileSize fileName requiresAuth
135
+ }
136
+ metadata { ...ProductMetadata }
137
+ }
138
+ `, PRODUCT_AVAILABILITY_FRAGMENT, PRODUCT_VARIANT_FRAGMENT, FACET_VALUE_FRAGMENT, COLLECTION_REF_FRAGMENT, PRODUCT_METADATA_FRAGMENT);
139
+ /** A row of the full product LIST (`getProducts`, the default `detail`). */
140
+ export const PRODUCT_SUMMARY_FRAGMENT = fragment(
141
+ /* GraphQL */ `
142
+ fragment ProductSummary on Product {
143
+ id name slug description enabled
144
+ featuredAsset {
145
+ source name width height
146
+ customFields { altText }
147
+ presets { xs { url webpUrl } m { url webpUrl } l { url webpUrl } }
148
+ }
115
149
  variants {
116
150
  id name sku
117
151
  price priceWithTax currencyCode stockLevel
118
- stockOnHand stockAllocated saleable
119
- incomingStock projectedSaleable nextExpectedArrival
120
- backorderAllowance
152
+ stockOnHand stockAllocated saleable
153
+ incomingStock projectedSaleable nextExpectedArrival
154
+ backorderAllowance
155
+ availability { ...ProductAvailability }
156
+ forSaleInCurrency
121
157
  priceListName retailPrice retailPriceWithTax taxRateApplied { value }
122
- priceTiers { minQuantity price priceWithTax discountLabel }
123
- availabilityByLocation { locationId locationName inStock }
124
- options { id code name group { id name code } }
158
+ priceTiers { ...PriceTier }
159
+ availabilityByLocation { ...VariantLocationAvailability }
125
160
  customFields { minOrderQuantity salesUnit position }
126
- featuredAsset {
127
- source name width height
128
- customFields { altText }
129
- presets { xs { url webpUrl } m { url webpUrl } }
130
- }
131
- assets {
132
- source name width height
133
- customFields { altText }
134
- presets { m { url webpUrl } l { url webpUrl } }
135
- }
136
161
  }
137
- optionGroups { id name code options { id name code } }
138
- facetValues { id name code facet { id name code } }
162
+ facetValues { ...FacetValue }
139
163
  translations { languageCode name slug description }
140
- collections {
141
- id name slug position
142
- parent { id slug }
143
- translations { languageCode name slug }
144
- customFields { isRoutable isCanonical }
145
- }
146
- documents {
147
- id position title description fileUrl fileMimeType fileSize fileName requiresAuth
148
- }
149
- ${PRODUCT_METADATA_FRAGMENT}
150
- }
151
- }
152
- `;
153
- export const LIST_PRODUCTS = `
154
- query ListProducts($options: ProductListOptions) {
155
- products(options: $options) {
156
- items {
157
- id name slug description enabled
158
- featuredAsset {
159
- source name width height
160
- customFields { altText }
161
- presets { xs { url webpUrl } m { url webpUrl } l { url webpUrl } }
162
- }
163
- variants {
164
- id name sku
165
- price priceWithTax currencyCode stockLevel
166
- stockOnHand stockAllocated saleable
167
- incomingStock projectedSaleable nextExpectedArrival
168
- backorderAllowance
169
- priceListName retailPrice retailPriceWithTax taxRateApplied { value }
170
- priceTiers { minQuantity price priceWithTax discountLabel }
171
- availabilityByLocation { locationId locationName inStock }
172
- customFields { minOrderQuantity salesUnit position }
173
- }
174
- facetValues { id name code facet { id name code } }
175
- translations { languageCode name slug description }
176
- collections {
177
- id name slug position
178
- parent { id slug }
179
- translations { languageCode name slug }
180
- customFields { isRoutable isCanonical }
181
- }
182
- }
183
- totalItems
164
+ collections { ...CollectionRef }
184
165
  }
185
- }
186
- `;
166
+ `, PRODUCT_AVAILABILITY_FRAGMENT, PRICE_TIER_FRAGMENT, VARIANT_LOCATION_AVAILABILITY_FRAGMENT, FACET_VALUE_FRAGMENT, COLLECTION_REF_FRAGMENT);
187
167
  /**
188
168
  * The card selection: what a product GRID tile renders, and nothing else.
189
169
  *
@@ -212,15 +192,27 @@ export const LIST_PRODUCTS = `
212
192
  * the default everywhere — and an anonymous visitor cost neither). A grid
213
193
  * that must not label a backorderable SKU "out of stock" pays that either
214
194
  * way: asking for it in a second document would cost the same.
195
+ * - `availability` — the merchant publication state. A grid is exactly where
196
+ * a coming-soon or pre-orderable SKU must not read "out of stock", and the
197
+ * card has no other signal for it: `stockLevel`/`saleable` say 0 for both.
198
+ * One batched product read per request for the whole page (variants with
199
+ * their own state cost nothing extra), and unlike `backorderAllowance` it
200
+ * is buyer-independent, so a cached grid keeps working.
215
201
  * - The whole `collections { … parent … translations … customFields }` block
216
202
  * and `translations { languageCode name slug }` — `pickCanonicalRoot` /
217
203
  * `isUserFacingRoot` (src/seo) derive a product's canonical URL from
218
204
  * `customFields.isCanonical` + `parent.slug` + `position`, and its localized
219
205
  * slug from the translations. A card row still satisfies `ProductForSeo`
220
206
  * structurally, so omitting these does not fail to compile — it silently
221
- * hands every product the FLAT path. Note these cost bytes, not queries:
222
- * Vendure resolves `Product.collections` in one query per product whichever
223
- * subfields are asked for.
207
+ * hands every product the FLAT path. Cost: a constant number of queries per
208
+ * page, not per row. The platform batches `Product.collections` for every
209
+ * product of the page into ONE statement and `parent` for every listed
210
+ * collection into one more (`services/vendure/src/collection-batching`),
211
+ * and `translations` / `customFields` come back in those same rows. Core
212
+ * Vendure alone ran one query per product plus one per listed collection
213
+ * — measured 419 statements for an 80-product page, 2 with the batching.
214
+ * Not batched: `featuredAsset`, `children`, `breadcrumbs` or
215
+ * `productVariants` under `collections` still cost a query per collection.
224
216
  * - `priceTiers` — the SDK's own `getPriceDisplay()` reads
225
217
  * `variant.priceTiers?.length ? … : null`, so an ABSENT ladder is
226
218
  * indistinguishable from "this variant has no tiers": a tile would quietly
@@ -234,73 +226,64 @@ export const LIST_PRODUCTS = `
234
226
  * Reached with `getProducts(..., { detail: 'card' })`. The default stays
235
227
  * `LIST_PRODUCTS`, so no existing caller changes behaviour.
236
228
  */
237
- export const LIST_PRODUCT_CARDS = `
238
- query ListProductCards($options: ProductListOptions) {
239
- products(options: $options) {
240
- items {
241
- id name slug enabled
242
- featuredAsset {
243
- source name width height
244
- customFields { altText }
245
- presets { xs { url webpUrl } m { url webpUrl } l { url webpUrl } }
246
- }
247
- variants {
248
- id name sku
249
- price priceWithTax currencyCode stockLevel saleable backorderAllowance
250
- priceListName retailPrice retailPriceWithTax taxRateApplied { value }
251
- priceTiers { minQuantity price priceWithTax discountLabel }
252
- customFields { minOrderQuantity salesUnit position }
253
- }
254
- facetValues { id name code facet { id name code } }
255
- translations { languageCode name slug }
256
- collections {
257
- id name slug position
258
- parent { id slug }
259
- translations { languageCode name slug }
260
- customFields { isRoutable isCanonical }
261
- }
229
+ export const PRODUCT_CARD_FRAGMENT = fragment(
230
+ /* GraphQL */ `
231
+ fragment ProductCard on Product {
232
+ id name slug enabled
233
+ featuredAsset {
234
+ source name width height
235
+ customFields { altText }
236
+ presets { xs { url webpUrl } m { url webpUrl } l { url webpUrl } }
262
237
  }
263
- totalItems
264
- }
265
- }
266
- `;
267
- export const LIST_FACETS = `
268
- query ListFacets {
269
- facets {
270
- items {
271
- id name code
272
- values { id name code }
238
+ variants {
239
+ id name sku
240
+ price priceWithTax currencyCode stockLevel saleable backorderAllowance
241
+ availability { ...ProductAvailability }
242
+ forSaleInCurrency
243
+ priceListName retailPrice retailPriceWithTax taxRateApplied { value }
244
+ priceTiers { ...PriceTier }
245
+ customFields { minOrderQuantity salesUnit position }
273
246
  }
274
- totalItems
275
- }
276
- }
277
- `;
278
- // --- Collection Queries ---
279
- export const LIST_COLLECTIONS = `
280
- query ListCollections($options: CollectionListOptions) {
281
- collections(options: $options) {
282
- items {
283
- id name slug description
284
- breadcrumbs { id name slug }
285
- featuredAsset {
286
- source width height
287
- presets { xs { url webpUrl } m { url webpUrl } }
288
- }
289
- parent { id name slug }
290
- children { id name slug }
247
+ facetValues { ...FacetValue }
248
+ translations { languageCode name slug }
249
+ collections { ...CollectionRef }
250
+ }
251
+ `, PRODUCT_AVAILABILITY_FRAGMENT, PRICE_TIER_FRAGMENT, FACET_VALUE_FRAGMENT, COLLECTION_REF_FRAGMENT);
252
+ export const FACET_FRAGMENT = fragment(/* GraphQL */ `
253
+ fragment Facet on Facet {
254
+ id name code
255
+ values { id name code }
256
+ }
257
+ `);
258
+ export const BREADCRUMB_FRAGMENT = fragment(/* GraphQL */ `
259
+ fragment Breadcrumb on CollectionBreadcrumb {
260
+ id name slug
261
+ }
262
+ `);
263
+ /** A row of the collection LIST (`getCollections`). */
264
+ export const COLLECTION_FRAGMENT = fragment(
265
+ /* GraphQL */ `
266
+ fragment Collection on Collection {
267
+ id name slug description
268
+ breadcrumbs { ...Breadcrumb }
269
+ featuredAsset {
270
+ source width height
271
+ presets { xs { url webpUrl } m { url webpUrl } }
291
272
  }
292
- totalItems
273
+ parent { id name slug }
274
+ children { id name slug }
293
275
  }
294
- }
295
- `;
296
- /** The collection-detail selection, shared by the slug and the id lookup. */
297
- const COLLECTION_DETAIL_FIELDS = `
276
+ `, BREADCRUMB_FRAGMENT);
277
+ /** The collection DETAIL read, shared by the slug and the id lookup. */
278
+ export const COLLECTION_DETAIL_FRAGMENT = fragment(
279
+ /* GraphQL */ `
280
+ fragment CollectionDetail on Collection {
298
281
  id name slug description position
299
282
  featuredAsset {
300
283
  source width height
301
284
  presets { l { url webpUrl } xl { url webpUrl } }
302
285
  }
303
- breadcrumbs { id name slug }
286
+ breadcrumbs { ...Breadcrumb }
304
287
  parent { id }
305
288
  children { id name slug }
306
289
  customFields {
@@ -337,144 +320,324 @@ const COLLECTION_DETAIL_FIELDS = `
337
320
  stockOnHand stockAllocated saleable
338
321
  incomingStock projectedSaleable nextExpectedArrival
339
322
  backorderAllowance
323
+ availability { ...ProductAvailability }
324
+ forSaleInCurrency
340
325
  priceListName retailPrice retailPriceWithTax taxRateApplied { value }
341
- priceTiers { minQuantity price priceWithTax discountLabel }
342
- availabilityByLocation { locationId locationName inStock }
326
+ priceTiers { ...PriceTier }
327
+ availabilityByLocation { ...VariantLocationAvailability }
343
328
  customFields { minOrderQuantity salesUnit position }
344
329
  }
345
330
  totalItems
346
331
  }
347
- `;
348
- export const GET_COLLECTION = `
349
- query GetCollection($slug: String!) {
350
- collection(slug: $slug) {${COLLECTION_DETAIL_FIELDS} }
351
- }
352
- `;
353
- export const GET_COLLECTION_BY_ID = `
354
- query GetCollectionById($id: ID!) {
355
- collection(id: $id) {${COLLECTION_DETAIL_FIELDS} }
356
- }
357
- `;
358
- // --- Search Query ---
359
- export const SEARCH_PRODUCTS = `
360
- query SearchProducts($input: SearchInput!) {
361
- search(input: $input) {
362
- items {
363
- productId productVariantId productName slug description
364
- price { ... on SinglePrice { value } ... on PriceRange { min max } }
365
- priceWithTax { ... on SinglePrice { value } ... on PriceRange { min max } }
366
- currencyCode
367
- productAsset { preview focalPoint { x y } }
368
- collectionIds
369
- inStock
370
- }
332
+ }
333
+ `, BREADCRUMB_FRAGMENT, PRODUCT_AVAILABILITY_FRAGMENT, PRICE_TIER_FRAGMENT, VARIANT_LOCATION_AVAILABILITY_FRAGMENT);
334
+ /**
335
+ * One search hit. `productVariantId` is the orderable id (never pass
336
+ * `productId` to `addToCart`); `availability` is null for a document indexed
337
+ * before the attribute existed, until the channel is fully reindexed.
338
+ */
339
+ export const SEARCH_RESULT_ITEM_FRAGMENT = fragment(
340
+ /* GraphQL */ `
341
+ fragment SearchResultItem on SearchResult {
342
+ productId productVariantId productName slug description
343
+ price { ... on SinglePrice { value } ... on PriceRange { min max } }
344
+ priceWithTax { ... on SinglePrice { value } ... on PriceRange { min max } }
345
+ currencyCode
346
+ productAsset { preview focalPoint { x y } }
347
+ collectionIds
348
+ inStock
349
+ availability { ...ProductAvailability }
350
+ forSaleInCurrency
351
+ }
352
+ `, PRODUCT_AVAILABILITY_FRAGMENT);
353
+ export const SEARCH_RESULT_FRAGMENT = fragment(
354
+ /* GraphQL */ `
355
+ fragment SearchResult on SearchResponse {
356
+ items { ...SearchResultItem }
371
357
  totalItems
372
- facetValues { facetValue { id name code facet { id name code } } count }
358
+ facetValues { facetValue { ...FacetValue } count }
373
359
  }
360
+ `, SEARCH_RESULT_ITEM_FRAGMENT, FACET_VALUE_FRAGMENT);
361
+ // --- Product Queries ---
362
+ export const GET_PRODUCT = withFragments(
363
+ /* GraphQL */ `
364
+ query GetProduct($slug: String!) {
365
+ product(slug: $slug) { ...Product }
366
+ }
367
+ `, PRODUCT_FRAGMENT);
368
+ export const GET_PRODUCT_BY_ID = withFragments(
369
+ /* GraphQL */ `
370
+ query GetProductById($id: ID!) {
371
+ product(id: $id) { ...Product }
372
+ }
373
+ `, PRODUCT_FRAGMENT);
374
+ /**
375
+ * A storefront-visible metafield as it arrives ON an entity: the
376
+ * `storefront: read` values an app or the store published (headless spec
377
+ * §8.13). `value` is whatever the definition's type describes.
378
+ */
379
+ export const METAFIELD_FRAGMENT = fragment(/* GraphQL */ `
380
+ fragment Metafield on Metafield {
381
+ namespace key value
374
382
  }
375
- `;
383
+ `);
384
+ /**
385
+ * OPT-IN product reads, chosen by `getProduct(slug, { metafields })` and
386
+ * `getProductById(id, { metafields })`: the default `Product` selection plus
387
+ * the product's own metafields and every variant's, `$namespace` narrowing
388
+ * both to one app (`null` is every namespace).
389
+ *
390
+ * Separate documents, never a `metafields` selection in `PRODUCT_FRAGMENT`
391
+ * (the rule `ORDER_FULFILLMENT_PARCELS_FRAGMENT` follows): `Product.metafields`
392
+ * is an additive Shop API field, and an engine without it fails the WHOLE
393
+ * document at validation. Selected by default, an SDK upgraded ahead of the
394
+ * engine deploy would 400 every product page; selected here, only a caller
395
+ * that asked for metafields needs the newer engine. GraphQL merges this
396
+ * `variants` selection with the fragment's, so each variant still comes back
397
+ * whole.
398
+ *
399
+ * The server reads every product's (and every variant's) metafields of the
400
+ * request in one statement per owner type, so the variant selection costs one
401
+ * read, not one per variant.
402
+ */
403
+ export const GET_PRODUCT_WITH_METAFIELDS = withFragments(
404
+ /* GraphQL */ `
405
+ query GetProductWithMetafields($slug: String!, $namespace: String) {
406
+ product(slug: $slug) {
407
+ ...Product
408
+ metafields(namespace: $namespace) { ...Metafield }
409
+ variants { id metafields(namespace: $namespace) { ...Metafield } }
410
+ }
411
+ }
412
+ `, PRODUCT_FRAGMENT, METAFIELD_FRAGMENT);
413
+ /** {@link GET_PRODUCT_WITH_METAFIELDS} by id. */
414
+ export const GET_PRODUCT_BY_ID_WITH_METAFIELDS = withFragments(
415
+ /* GraphQL */ `
416
+ query GetProductByIdWithMetafields($id: ID!, $namespace: String) {
417
+ product(id: $id) {
418
+ ...Product
419
+ metafields(namespace: $namespace) { ...Metafield }
420
+ variants { id metafields(namespace: $namespace) { ...Metafield } }
421
+ }
422
+ }
423
+ `, PRODUCT_FRAGMENT, METAFIELD_FRAGMENT);
424
+ export const LIST_PRODUCTS = withFragments(
425
+ /* GraphQL */ `
426
+ query ListProducts($options: ProductListOptions) {
427
+ products(options: $options) {
428
+ items { ...ProductSummary }
429
+ totalItems
430
+ }
431
+ }
432
+ `, PRODUCT_SUMMARY_FRAGMENT);
433
+ export const LIST_PRODUCT_CARDS = withFragments(
434
+ /* GraphQL */ `
435
+ query ListProductCards($options: ProductListOptions) {
436
+ products(options: $options) {
437
+ items { ...ProductCard }
438
+ totalItems
439
+ }
440
+ }
441
+ `, PRODUCT_CARD_FRAGMENT);
442
+ export const LIST_FACETS = withFragments(
443
+ /* GraphQL */ `
444
+ query ListFacets {
445
+ facets {
446
+ items { ...Facet }
447
+ totalItems
448
+ }
449
+ }
450
+ `, FACET_FRAGMENT);
451
+ // --- Collection Queries ---
452
+ export const LIST_COLLECTIONS = withFragments(
453
+ /* GraphQL */ `
454
+ query ListCollections($options: CollectionListOptions) {
455
+ collections(options: $options) {
456
+ items { ...Collection }
457
+ totalItems
458
+ }
459
+ }
460
+ `, COLLECTION_FRAGMENT);
461
+ export const GET_COLLECTION = withFragments(
462
+ /* GraphQL */ `
463
+ query GetCollection($slug: String!) {
464
+ collection(slug: $slug) { ...CollectionDetail }
465
+ }
466
+ `, COLLECTION_DETAIL_FRAGMENT);
467
+ export const GET_COLLECTION_BY_ID = withFragments(
468
+ /* GraphQL */ `
469
+ query GetCollectionById($id: ID!) {
470
+ collection(id: $id) { ...CollectionDetail }
471
+ }
472
+ `, COLLECTION_DETAIL_FRAGMENT);
473
+ /**
474
+ * OPT-IN collection reads with the collection's own metafields, chosen by
475
+ * `getCollection(slug, { metafields })` and `getCollectionById(id, {
476
+ * metafields })`. Separate documents for the reason
477
+ * {@link GET_PRODUCT_WITH_METAFIELDS} gives.
478
+ */
479
+ export const GET_COLLECTION_WITH_METAFIELDS = withFragments(
480
+ /* GraphQL */ `
481
+ query GetCollectionWithMetafields($slug: String!, $namespace: String) {
482
+ collection(slug: $slug) {
483
+ ...CollectionDetail
484
+ metafields(namespace: $namespace) { ...Metafield }
485
+ }
486
+ }
487
+ `, COLLECTION_DETAIL_FRAGMENT, METAFIELD_FRAGMENT);
488
+ /** {@link GET_COLLECTION_WITH_METAFIELDS} by id. */
489
+ export const GET_COLLECTION_BY_ID_WITH_METAFIELDS = withFragments(
490
+ /* GraphQL */ `
491
+ query GetCollectionByIdWithMetafields($id: ID!, $namespace: String) {
492
+ collection(id: $id) {
493
+ ...CollectionDetail
494
+ metafields(namespace: $namespace) { ...Metafield }
495
+ }
496
+ }
497
+ `, COLLECTION_DETAIL_FRAGMENT, METAFIELD_FRAGMENT);
498
+ // --- Search Query ---
499
+ export const SEARCH_PRODUCTS = withFragments(
500
+ /* GraphQL */ `
501
+ query SearchProducts($input: SearchInput!) {
502
+ search(input: $input) { ...SearchResult }
503
+ }
504
+ `, SEARCH_RESULT_FRAGMENT);
376
505
  // --- Cart Mutations ---
377
506
  // Shared selection set for full Order objects. Used by ACTIVE_ORDER, ADD_TO_CART,
378
507
  // ADJUST_ORDER_LINE, REMOVE_ORDER_LINE, APPLY_COUPON, REMOVE_COUPON, ORDER_BY_CODE.
379
508
  // Keep in one place so adding fields (e.g. discounts) lands everywhere consistently.
380
- const ORDER_FIELDS = `
381
- id code state active
382
- createdAt orderPlacedAt
383
- totalQuantity
384
- subTotal subTotalWithTax
385
- shipping shippingWithTax
386
- total totalWithTax
387
- currencyCode
388
- lines {
389
- id quantity
390
- unitPrice unitPriceWithTax taxRate
391
- linePrice linePriceWithTax
392
- discountedLinePrice discountedLinePriceWithTax
509
+ const ORDER_FRAGMENT = fragment(/* GraphQL */ `
510
+ fragment Order on Order {
511
+ id code state active
512
+ createdAt orderPlacedAt
513
+ totalQuantity
514
+ subTotal subTotalWithTax
515
+ shipping shippingWithTax
516
+ total totalWithTax
517
+ currencyCode
518
+ lines {
519
+ id quantity
520
+ unitPrice unitPriceWithTax taxRate
521
+ linePrice linePriceWithTax
522
+ discountedLinePrice discountedLinePriceWithTax
523
+ discounts { adjustmentSource type description amount amountWithTax }
524
+ productVariant {
525
+ id name sku saleable
526
+ product { id name slug }
527
+ options { id name group { name } }
528
+ }
529
+ featuredAsset { source presets { xs { url webpUrl } } }
530
+ }
393
531
  discounts { adjustmentSource type description amount amountWithTax }
394
- productVariant {
395
- id name sku saleable
396
- product { id name slug }
397
- options { id name group { name } }
398
- }
399
- featuredAsset { source presets { xs { url webpUrl } } }
400
- }
401
- discounts { adjustmentSource type description amount amountWithTax }
402
- taxSummary { description taxRate taxBase taxTotal }
403
- promotions { id name couponCode description }
404
- shippingLines { shippingMethod { id name code } priceWithTax }
405
- payments { id method amount state transactionId }
406
- shippingAddress { fullName company streetLine1 streetLine2 city province postalCode countryCode phoneNumber }
407
- billingAddress { fullName company streetLine1 streetLine2 city province postalCode countryCode phoneNumber }
408
- customer { id firstName lastName emailAddress }
409
- couponCodes
410
- `;
532
+ taxSummary { description taxRate taxBase taxTotal }
533
+ promotions { id name couponCode description }
534
+ shippingLines { shippingMethod { id name code } priceWithTax }
535
+ payments { id method amount state transactionId }
536
+ shippingAddress { fullName company streetLine1 streetLine2 city province postalCode countryCode phoneNumber }
537
+ billingAddress { fullName company streetLine1 streetLine2 city province postalCode countryCode phoneNumber }
538
+ customer { id firstName lastName emailAddress }
539
+ couponCodes
540
+ }
541
+ `);
411
542
  /**
412
- * Fulfillment/tracking selection for placed orders. Kept out of ORDER_FIELDS
543
+ * Fulfillment/tracking selection for placed orders. Kept out of ORDER_FRAGMENT
413
544
  * so cart mutations don't pay for it — active carts have no fulfillments.
414
545
  * `trackingCode` feeds `trackShipment(barcode, postalCode)`.
415
546
  *
416
547
  * `externalShipments` is the carrier-agnostic list pushed by an external
417
548
  * fulfilment system, and is the right thing to render for tracking: one
418
549
  * fulfilment can cover SEVERAL parcels, which a single `trackingCode` cannot
419
- * express. Render `reference` as a link when `isLink` is true and as a text block
420
- * otherwise — a pallet carrier's reference or ex-works pickup instructions are
421
- * prose, not URLs. The flag is derived server-side so the storefront never has
422
- * to guess.
550
+ * express — though `fulfillments[].trackingCodes` does for a carrier we book
551
+ * ourselves (see {@link ORDER_FULFILLMENT_PARCELS_FRAGMENT}). Render
552
+ * `reference` as a link when `isLink` is true and as a text block otherwise — a
553
+ * pallet carrier's reference or ex-works pickup instructions are prose, not
554
+ * URLs. The flag is derived server-side so the storefront never has to guess.
423
555
  */
424
- const ORDER_FULFILLMENTS_FRAGMENT = `
425
- fulfillments {
426
- id state method trackingCode createdAt updatedAt
427
- lines { orderLineId quantity }
556
+ const ORDER_FULFILLMENTS_FRAGMENT = fragment(/* GraphQL */ `
557
+ fragment OrderFulfillments on Order {
558
+ fulfillments {
559
+ id state method trackingCode createdAt updatedAt
560
+ lines { orderLineId quantity }
561
+ }
562
+ externalShipments {
563
+ carrier reference isLink shippedAt deliveryNumber
564
+ }
428
565
  }
429
- externalShipments {
430
- carrier reference isLink shippedAt deliveryNumber
566
+ `);
567
+ /**
568
+ * OPTIONAL per-parcel barcodes, selected by the two PLACED-order reads
569
+ * (`ORDER_BY_CODE`, `GET_CUSTOMER_ORDERS`) and nowhere else — the same rule
570
+ * `lines { backorderedQuantity }` and `customFields { paymentIntent }` follow.
571
+ *
572
+ * `Fulfillment.trackingCodes` is an additive Shop API field that only an engine
573
+ * shipping the MyParcel plugin's multi-parcel release answers. In the shared
574
+ * `ORDER_FULFILLMENTS_FRAGMENT` it also reached `ORDER_SUMMARY_FRAGMENT` and so
575
+ * `GET_CURRENT_CUSTOMER` — the customer-session read every page makes. An SDK
576
+ * upgrade ahead of the engine deploy would then 400 the whole document at
577
+ * GraphQL validation and log every customer out of their account area, for a
578
+ * field that only enriches a tracking list. GraphQL merges this `fulfillments`
579
+ * selection with the fragment's, so the fulfillment still comes back whole.
580
+ *
581
+ * Needs the engine release named in this package's changeset; against an older
582
+ * one these two reads fail validation while the rest of the SDK keeps working.
583
+ */
584
+ const ORDER_FULFILLMENT_PARCELS_FRAGMENT = fragment(/* GraphQL */ `
585
+ fragment OrderFulfillmentParcels on Order {
586
+ fulfillments { id trackingCodes }
431
587
  }
432
- `;
588
+ `);
433
589
  /** Immutable payment condition captured when a placed order was accepted. */
434
- const ORDER_PAYMENT_TERMS_FRAGMENT = `
435
- paymentTerms {
436
- source managedExternally status
437
- conditionCode conditionDescription summary classification
438
- paymentDays paymentEndOfMonths paymentMethod percentage
439
- discountPaymentDays discountPercentage paymentDiscountType
440
- stale syncedAt error
441
- resolvedAt remoteConditionCode remoteConfirmedAt remoteMismatch
442
- }
443
- `;
590
+ const ORDER_PAYMENT_TERMS_FRAGMENT = fragment(/* GraphQL */ `
591
+ fragment OrderPaymentTerms on Order {
592
+ paymentTerms {
593
+ source managedExternally status
594
+ conditionCode conditionDescription summary classification
595
+ paymentDays paymentEndOfMonths paymentMethod percentage
596
+ discountPaymentDays discountPercentage paymentDiscountType
597
+ stale syncedAt error
598
+ resolvedAt remoteConditionCode remoteConfirmedAt remoteMismatch
599
+ }
600
+ }
601
+ `);
444
602
  /** Immutable delivery terms captured when a placed order was accepted. */
445
- const ORDER_DELIVERY_TERMS_FRAGMENT = `
446
- deliveryTerms {
447
- source managedExternally status shippingMethodStatus policyStatus summary selectionSource
448
- selectedShippingMethodId selectedShippingMethodCode selectedShippingMethodName
449
- platformShippingMethodCode platformShippingMethodName platformShippingMethodDescription
450
- platformShippingPrice platformShippingPriceWithTax
451
- preferredShippingMethodId
452
- incotermStatus incotermCode incotermVersion incotermAddress incotermDescription
453
- shippingLeadDays deliveryAdvice stale syncedAt warning resolvedAt
454
- remoteShippingMethodCode remoteShippingMethodName
455
- remoteIncotermCode remoteIncotermVersion remoteIncotermAddress remoteDeliveryDate
456
- remoteConfirmedAt remoteMismatch
603
+ const ORDER_DELIVERY_TERMS_FRAGMENT = fragment(/* GraphQL */ `
604
+ fragment OrderDeliveryTerms on Order {
605
+ deliveryTerms {
606
+ source managedExternally status shippingMethodStatus policyStatus summary selectionSource
607
+ selectedShippingMethodId selectedShippingMethodCode selectedShippingMethodName
608
+ platformShippingMethodCode platformShippingMethodName platformShippingMethodDescription
609
+ platformShippingPrice platformShippingPriceWithTax
610
+ preferredShippingMethodId
611
+ incotermStatus incotermCode incotermVersion incotermAddress incotermDescription
612
+ shippingLeadDays deliveryAdvice stale syncedAt warning resolvedAt
613
+ remoteShippingMethodCode remoteShippingMethodName
614
+ remoteIncotermCode remoteIncotermVersion remoteIncotermAddress remoteDeliveryDate
615
+ remoteConfirmedAt remoteMismatch
616
+ }
457
617
  }
458
- `;
618
+ `);
459
619
  /**
460
620
  * Order-history list-item selection (customer order history). Enriched beyond a
461
621
  * bare line count so a storefront can render thumbnails + per-line totals
462
622
  * without a follow-up fetch. Shared by GET_CURRENT_CUSTOMER and
463
623
  * GET_CUSTOMER_ORDERS — both map to OrderSummary.
464
624
  */
465
- const ORDER_SUMMARY_FIELDS = `
466
- id code state total totalWithTax currencyCode createdAt
467
- lines {
468
- id quantity linePriceWithTax
469
- productVariant {
470
- id name sku
471
- product { slug featuredAsset { preview presets { xs { webpUrl } } } }
625
+ const ORDER_SUMMARY_FRAGMENT = fragment(
626
+ /* GraphQL */ `
627
+ fragment OrderSummary on Order {
628
+ id code state total totalWithTax currencyCode createdAt
629
+ lines {
630
+ id quantity linePriceWithTax
631
+ productVariant {
632
+ id name sku
633
+ product { slug featuredAsset { preview presets { xs { webpUrl } } } }
634
+ }
635
+ }
636
+ ...OrderFulfillments
637
+ ...OrderPaymentTerms
638
+ ...OrderDeliveryTerms
472
639
  }
473
- }
474
- ${ORDER_FULFILLMENTS_FRAGMENT}
475
- ${ORDER_PAYMENT_TERMS_FRAGMENT}
476
- ${ORDER_DELIVERY_TERMS_FRAGMENT}
477
- `;
640
+ `, ORDER_FULFILLMENTS_FRAGMENT, ORDER_PAYMENT_TERMS_FRAGMENT, ORDER_DELIVERY_TERMS_FRAGMENT);
478
641
  /**
479
642
  * The structured half of a placement rejection, selected wherever the Shop API
480
643
  * can answer one.
@@ -485,28 +648,30 @@ const ORDER_SUMMARY_FIELDS = `
485
648
  * are populated per code and null otherwise, so selecting all of them costs
486
649
  * one flat response object and saves a second round of documents per feature.
487
650
  */
488
- const PLACEMENT_FIELDS = `
489
- code
490
- customerMessage
491
- linesTruncated
492
- requiredAmount
493
- currencyCode
494
- amountBasis
495
- requiredQuantity
496
- priceListName
497
- salesUnit
498
- minimumAge
499
- lines {
500
- orderLineId
501
- productVariantId
502
- sku
503
- productName
504
- productVariantName
505
- quantityRequested
506
- quantityAvailable
507
- }
508
- details { field code message }
509
- `;
651
+ const PLACEMENT_REJECTION_FRAGMENT = fragment(/* GraphQL */ `
652
+ fragment PlacementRejection on PlacementRejection {
653
+ code
654
+ customerMessage
655
+ linesTruncated
656
+ requiredAmount
657
+ currencyCode
658
+ amountBasis
659
+ requiredQuantity
660
+ priceListName
661
+ salesUnit
662
+ minimumAge
663
+ lines {
664
+ orderLineId
665
+ productVariantId
666
+ sku
667
+ productName
668
+ productVariantName
669
+ quantityRequested
670
+ quantityAvailable
671
+ }
672
+ details { field code message }
673
+ }
674
+ `);
510
675
  /**
511
676
  * WHICH line an `InsufficientStockError` is about.
512
677
  *
@@ -516,124 +681,157 @@ const PLACEMENT_FIELDS = `
516
681
  * — an error raised outside the overridden cart mutations answers null to all
517
682
  * of them. `inputIndex` is only ever non-null inside `addItemsToOrder`.
518
683
  */
519
- const INSUFFICIENT_STOCK_FIELDS = `
520
- errorCode message quantityAvailable
521
- productVariantId orderLineId sku productName productVariantName
522
- quantityRequested inputIndex
523
- `;
524
- export const ACTIVE_ORDER = `
525
- query ActiveOrder {
526
- activeOrder { ${ORDER_FIELDS} }
527
- }
528
- `;
529
- export const ADD_TO_CART = `
530
- mutation AddToCart($variantId: ID!, $quantity: Int!) {
531
- addItemToOrder(productVariantId: $variantId, quantity: $quantity) {
532
- ... on Order { ${ORDER_FIELDS} }
533
- ... on OrderModificationError { errorCode message }
534
- ... on OrderLimitError { errorCode message maxItems }
535
- ... on NegativeQuantityError { errorCode message }
536
- ... on InsufficientStockError { ${INSUFFICIENT_STOCK_FIELDS} order { id } }
684
+ const INSUFFICIENT_STOCK_ERROR_FRAGMENT = fragment(/* GraphQL */ `
685
+ fragment InsufficientStockError on InsufficientStockError {
686
+ errorCode message quantityAvailable
687
+ productVariantId orderLineId sku productName productVariantName
688
+ quantityRequested inputIndex
689
+ }
690
+ `);
691
+ export const ACTIVE_ORDER = withFragments(
692
+ /* GraphQL */ `
693
+ query ActiveOrder {
694
+ activeOrder { ...Order }
695
+ }
696
+ `, ORDER_FRAGMENT);
697
+ export const ADD_TO_CART = withFragments(
698
+ /* GraphQL */ `
699
+ mutation AddToCart($variantId: ID!, $quantity: Int!) {
700
+ addItemToOrder(productVariantId: $variantId, quantity: $quantity) {
701
+ ... on Order { ...Order }
702
+ ... on OrderModificationError { errorCode message }
703
+ ... on OrderLimitError { errorCode message maxItems }
704
+ ... on NegativeQuantityError { errorCode message }
705
+ ... on InsufficientStockError { ...InsufficientStockError order { id } }
706
+ }
537
707
  }
538
- }
539
- `;
540
- export const ADJUST_ORDER_LINE = `
541
- mutation AdjustOrderLine($lineId: ID!, $quantity: Int!) {
542
- adjustOrderLine(orderLineId: $lineId, quantity: $quantity) {
543
- ... on Order { ${ORDER_FIELDS} }
544
- ... on OrderModificationError { errorCode message }
545
- ... on OrderLimitError { errorCode message maxItems }
546
- ... on NegativeQuantityError { errorCode message }
547
- ... on InsufficientStockError { ${INSUFFICIENT_STOCK_FIELDS} }
708
+ `, ORDER_FRAGMENT, INSUFFICIENT_STOCK_ERROR_FRAGMENT);
709
+ export const ADJUST_ORDER_LINE = withFragments(
710
+ /* GraphQL */ `
711
+ mutation AdjustOrderLine($lineId: ID!, $quantity: Int!) {
712
+ adjustOrderLine(orderLineId: $lineId, quantity: $quantity) {
713
+ ... on Order { ...Order }
714
+ ... on OrderModificationError { errorCode message }
715
+ ... on OrderLimitError { errorCode message maxItems }
716
+ ... on NegativeQuantityError { errorCode message }
717
+ ... on InsufficientStockError { ...InsufficientStockError }
718
+ }
548
719
  }
549
- }
550
- `;
551
- export const REMOVE_ORDER_LINE = `
552
- mutation RemoveOrderLine($lineId: ID!) {
553
- removeOrderLine(orderLineId: $lineId) {
554
- ... on Order { ${ORDER_FIELDS} }
555
- ... on OrderModificationError { errorCode message }
720
+ `, ORDER_FRAGMENT, INSUFFICIENT_STOCK_ERROR_FRAGMENT);
721
+ export const REMOVE_ORDER_LINE = withFragments(
722
+ /* GraphQL */ `
723
+ mutation RemoveOrderLine($lineId: ID!) {
724
+ removeOrderLine(orderLineId: $lineId) {
725
+ ... on Order { ...Order }
726
+ ... on OrderModificationError { errorCode message }
727
+ }
556
728
  }
557
- }
558
- `;
559
- export const APPLY_COUPON = `
560
- mutation ApplyCoupon($code: String!) {
561
- applyCouponCode(couponCode: $code) {
562
- ... on Order { ${ORDER_FIELDS} }
563
- ... on CouponCodeExpiredError { errorCode message couponCode }
564
- ... on CouponCodeInvalidError { errorCode message couponCode }
565
- ... on CouponCodeLimitError { errorCode message couponCode limit }
729
+ `, ORDER_FRAGMENT);
730
+ export const APPLY_COUPON = withFragments(
731
+ /* GraphQL */ `
732
+ mutation ApplyCoupon($code: String!) {
733
+ applyCouponCode(couponCode: $code) {
734
+ ... on Order { ...Order }
735
+ ... on CouponCodeExpiredError { errorCode message couponCode }
736
+ ... on CouponCodeInvalidError { errorCode message couponCode }
737
+ ... on CouponCodeLimitError { errorCode message couponCode limit }
738
+ }
566
739
  }
567
- }
568
- `;
569
- export const REMOVE_COUPON = `
570
- mutation RemoveCoupon($code: String!) {
571
- removeCouponCode(couponCode: $code) { ${ORDER_FIELDS} }
572
- }
573
- `;
574
- export const REMOVE_ALL_ORDER_LINES = `
575
- mutation RemoveAllOrderLines {
576
- removeAllOrderLines {
577
- ... on Order { ${ORDER_FIELDS} }
578
- ... on OrderModificationError { errorCode message }
740
+ `, ORDER_FRAGMENT);
741
+ export const REMOVE_COUPON = withFragments(
742
+ /* GraphQL */ `
743
+ mutation RemoveCoupon($code: String!) {
744
+ removeCouponCode(couponCode: $code) { ...Order }
745
+ }
746
+ `, ORDER_FRAGMENT);
747
+ export const REMOVE_ALL_ORDER_LINES = withFragments(
748
+ /* GraphQL */ `
749
+ mutation RemoveAllOrderLines {
750
+ removeAllOrderLines {
751
+ ... on Order { ...Order }
752
+ ... on OrderModificationError { errorCode message }
753
+ }
579
754
  }
580
- }
581
- `;
755
+ `, ORDER_FRAGMENT);
582
756
  /**
583
757
  * Bulk add (favourite-box bundles). `addItemsToOrder` returns
584
758
  * UpdateMultipleOrderItemsResult: a single resulting Order plus a per-input
585
759
  * `errorResults` list — partial success is possible, so surface both.
586
760
  */
587
- export const ADD_ITEMS_TO_CART = `
588
- mutation AddItemsToCart($inputs: [AddItemInput!]!) {
589
- addItemsToOrder(inputs: $inputs) {
590
- order { ${ORDER_FIELDS} }
591
- errorResults {
592
- ... on OrderModificationError { errorCode message }
593
- ... on OrderLimitError { errorCode message maxItems }
594
- ... on NegativeQuantityError { errorCode message }
595
- ... on InsufficientStockError { ${INSUFFICIENT_STOCK_FIELDS} }
596
- ... on OrderInterceptorError { errorCode message interceptorError }
761
+ export const ADD_ITEMS_TO_CART = withFragments(
762
+ /* GraphQL */ `
763
+ mutation AddItemsToCart($inputs: [AddItemInput!]!) {
764
+ addItemsToOrder(inputs: $inputs) {
765
+ order { ...Order }
766
+ errorResults {
767
+ ... on OrderModificationError { errorCode message }
768
+ ... on OrderLimitError { errorCode message maxItems }
769
+ ... on NegativeQuantityError { errorCode message }
770
+ ... on InsufficientStockError { ...InsufficientStockError }
771
+ ... on OrderInterceptorError { errorCode message interceptorError }
772
+ }
597
773
  }
598
774
  }
599
- }
600
- `;
775
+ `, ORDER_FRAGMENT, INSUFFICIENT_STOCK_ERROR_FRAGMENT);
601
776
  // --- Checkout Mutations ---
602
- export const SET_CUSTOMER = `
603
- mutation SetCustomer($input: CreateCustomerInput!) {
604
- setCustomerForOrder(input: $input) {
605
- ... on Order { ${ORDER_FIELDS} }
606
- ... on AlreadyLoggedInError { errorCode message }
607
- ... on EmailAddressConflictError { errorCode message }
608
- ... on GuestCheckoutError { errorCode message }
609
- ... on NoActiveOrderError { errorCode message }
777
+ export const SET_CUSTOMER = withFragments(
778
+ /* GraphQL */ `
779
+ mutation SetCustomer($input: CreateCustomerInput!) {
780
+ setCustomerForOrder(input: $input) {
781
+ ... on Order { ...Order }
782
+ ... on AlreadyLoggedInError { errorCode message }
783
+ ... on EmailAddressConflictError { errorCode message }
784
+ ... on GuestCheckoutError { errorCode message }
785
+ ... on NoActiveOrderError { errorCode message }
786
+ }
610
787
  }
611
- }
612
- `;
613
- export const SET_SHIPPING_ADDRESS = `
614
- mutation SetShippingAddress($input: CreateAddressInput!) {
615
- setOrderShippingAddress(input: $input) {
616
- ... on Order { ${ORDER_FIELDS} }
617
- ... on NoActiveOrderError { errorCode message }
788
+ `, ORDER_FRAGMENT);
789
+ export const SET_SHIPPING_ADDRESS = withFragments(
790
+ /* GraphQL */ `
791
+ mutation SetShippingAddress($input: CreateAddressInput!) {
792
+ setOrderShippingAddress(input: $input) {
793
+ ... on Order { ...Order }
794
+ ... on NoActiveOrderError { errorCode message }
795
+ }
618
796
  }
619
- }
620
- `;
621
- export const SET_BILLING_ADDRESS = `
622
- mutation SetBillingAddress($input: CreateAddressInput!) {
623
- setOrderBillingAddress(input: $input) {
624
- ... on Order { ${ORDER_FIELDS} }
625
- ... on NoActiveOrderError { errorCode message }
797
+ `, ORDER_FRAGMENT);
798
+ export const SET_BILLING_ADDRESS = withFragments(
799
+ /* GraphQL */ `
800
+ mutation SetBillingAddress($input: CreateAddressInput!) {
801
+ setOrderBillingAddress(input: $input) {
802
+ ... on Order { ...Order }
803
+ ... on NoActiveOrderError { errorCode message }
804
+ }
626
805
  }
627
- }
628
- `;
629
- export const ELIGIBLE_SHIPPING_METHODS = `
806
+ `, ORDER_FRAGMENT);
807
+ export const ELIGIBLE_SHIPPING_METHODS = /* GraphQL */ `
630
808
  query ShippingMethods {
631
809
  eligibleShippingMethods {
632
810
  id name description price priceWithTax metadata isPreferred isDeliveryTermsEligible
633
811
  }
634
812
  }
635
813
  `;
636
- export const MY_DELIVERY_TERMS = `
814
+ /** Every platform method and every app rate the active order can ship with (`shipping.rates`). */
815
+ export const ELIGIBLE_SHIPPING_RATES = /* GraphQL */ `
816
+ query ShippingRates {
817
+ eligibleShippingRates {
818
+ shippingMethodId code rateCode name description price priceWithTax source appSlug selected
819
+ isPreferred isDeliveryTermsEligible
820
+ }
821
+ }
822
+ `;
823
+ export const SET_SHIPPING_RATE = withFragments(
824
+ /* GraphQL */ `
825
+ mutation SetShippingRate($shippingMethodId: ID!, $rateCode: String) {
826
+ setOrderShippingRate(shippingMethodId: $shippingMethodId, rateCode: $rateCode) {
827
+ ... on Order { ...Order }
828
+ ... on OrderModificationError { errorCode message }
829
+ ... on IneligibleShippingMethodError { errorCode message }
830
+ ... on NoActiveOrderError { errorCode message }
831
+ }
832
+ }
833
+ `, ORDER_FRAGMENT);
834
+ export const MY_DELIVERY_TERMS = /* GraphQL */ `
637
835
  query MyDeliveryTerms {
638
836
  myDeliveryTerms {
639
837
  customerId source managedExternally status shippingMethodStatus policyStatus summary
@@ -645,44 +843,161 @@ export const MY_DELIVERY_TERMS = `
645
843
  }
646
844
  }
647
845
  `;
648
- export const SET_SHIPPING_METHOD = `
649
- mutation SetShippingMethod($ids: [ID!]!) {
650
- selectOrderDeliveryMethod(shippingMethodIds: $ids) {
651
- ... on Order { ${ORDER_FIELDS} }
652
- ... on OrderModificationError { errorCode message }
653
- ... on IneligibleShippingMethodError { errorCode message }
654
- ... on NoActiveOrderError { errorCode message }
846
+ export const SET_SHIPPING_METHOD = withFragments(
847
+ /* GraphQL */ `
848
+ mutation SetShippingMethod($ids: [ID!]!) {
849
+ selectOrderDeliveryMethod(shippingMethodIds: $ids) {
850
+ ... on Order { ...Order }
851
+ ... on OrderModificationError { errorCode message }
852
+ ... on IneligibleShippingMethodError { errorCode message }
853
+ ... on NoActiveOrderError { errorCode message }
854
+ }
655
855
  }
656
- }
657
- `;
658
- export const APPLY_PREFERRED_SHIPPING_METHOD = `
659
- mutation ApplyPreferredShippingMethod {
660
- applyPreferredDeliveryMethod {
661
- ... on Order { ${ORDER_FIELDS} }
662
- ... on OrderModificationError { errorCode message }
663
- ... on IneligibleShippingMethodError { errorCode message }
664
- ... on NoActiveOrderError { errorCode message }
856
+ `, ORDER_FRAGMENT);
857
+ export const APPLY_PREFERRED_SHIPPING_METHOD = withFragments(
858
+ /* GraphQL */ `
859
+ mutation ApplyPreferredShippingMethod {
860
+ applyPreferredDeliveryMethod {
861
+ ... on Order { ...Order }
862
+ ... on OrderModificationError { errorCode message }
863
+ ... on IneligibleShippingMethodError { errorCode message }
864
+ ... on NoActiveOrderError { errorCode message }
865
+ }
665
866
  }
666
- }
667
- `;
668
- export const ELIGIBLE_PAYMENT_METHODS = `
867
+ `, ORDER_FRAGMENT);
868
+ export const ELIGIBLE_PAYMENT_METHODS = /* GraphQL */ `
669
869
  query PaymentMethods {
670
870
  eligiblePaymentMethods {
671
871
  id name code description isEligible eligibilityMessage
672
872
  }
673
873
  }
674
874
  `;
675
- export const TRANSITION_TO_ARRANGING_PAYMENT = `
676
- mutation TransitionToArrangingPayment {
677
- transitionOrderToState(state: "ArrangingPayment") {
678
- ... on Order { ${ORDER_FIELDS} }
679
- ... on OrderStateTransitionError {
680
- errorCode message transitionError
681
- placement { ${PLACEMENT_FIELDS} }
875
+ export const TRANSITION_TO_ARRANGING_PAYMENT = withFragments(
876
+ /* GraphQL */ `
877
+ mutation TransitionToArrangingPayment {
878
+ transitionOrderToState(state: "ArrangingPayment") {
879
+ ... on Order { ...Order }
880
+ ... on OrderStateTransitionError {
881
+ errorCode message transitionError
882
+ placement { ...PlacementRejection }
883
+ }
682
884
  }
683
885
  }
886
+ `, ORDER_FRAGMENT, PLACEMENT_REJECTION_FRAGMENT);
887
+ /**
888
+ * `TRANSITION_TO_ARRANGING_PAYMENT` with the target state as a variable. The
889
+ * engine's order process and its placement guards decide which targets a
890
+ * shopper may reach; the document only carries the request.
891
+ */
892
+ export const TRANSITION_ORDER = withFragments(
893
+ /* GraphQL */ `
894
+ mutation TransitionOrder($state: String!) {
895
+ transitionOrderToState(state: $state) {
896
+ ... on Order { ...Order }
897
+ ... on OrderStateTransitionError {
898
+ errorCode message transitionError
899
+ placement { ...PlacementRejection }
900
+ }
901
+ }
902
+ }
903
+ `, ORDER_FRAGMENT, PLACEMENT_REJECTION_FRAGMENT);
904
+ export const NEXT_ORDER_STATES = /* GraphQL */ `
905
+ query NextOrderStates {
906
+ nextOrderStates
684
907
  }
685
908
  `;
909
+ /**
910
+ * Every payment method enabled on the channel, whatever the active order.
911
+ * `customFields` is NOT selected: it is a raw JSON passthrough of the entity's
912
+ * custom fields, which are all private on this platform.
913
+ */
914
+ const PUBLIC_PAYMENT_METHOD_FRAGMENT = fragment(/* GraphQL */ `
915
+ fragment PublicPaymentMethod on PublicPaymentMethod {
916
+ id code name description
917
+ }
918
+ `);
919
+ export const ACTIVE_PAYMENT_METHODS = withFragments(
920
+ /* GraphQL */ `
921
+ query ActivePaymentMethods {
922
+ activePaymentMethods { ...PublicPaymentMethod }
923
+ }
924
+ `, PUBLIC_PAYMENT_METHOD_FRAGMENT);
925
+ const PUBLIC_SHIPPING_METHOD_FRAGMENT = fragment(/* GraphQL */ `
926
+ fragment PublicShippingMethod on PublicShippingMethod {
927
+ id code name description
928
+ }
929
+ `);
930
+ /** Every shipping method offered on the channel's storefront, whatever the active order. */
931
+ export const ACTIVE_SHIPPING_METHODS = withFragments(
932
+ /* GraphQL */ `
933
+ query ActiveShippingMethods {
934
+ activeShippingMethods { ...PublicShippingMethod }
935
+ }
936
+ `, PUBLIC_SHIPPING_METHOD_FRAGMENT);
937
+ /**
938
+ * The order custom fields the Shop API lets a shopper write — exactly the
939
+ * members of `UpdateOrderCustomFieldsInput` (public, not read-only) — selected
940
+ * back on `setOrderCustomFields` so the caller sees what the engine stored.
941
+ *
942
+ * Selected on that ONE document: the shared `ORDER_FRAGMENT` stays free of
943
+ * custom fields, so an engine that predates one of these fields fails only the
944
+ * call that writes them, never every cart read.
945
+ */
946
+ const ORDER_WRITABLE_CUSTOM_FIELDS_FRAGMENT = fragment(/* GraphQL */ `
947
+ fragment OrderWritableCustomFields on OrderCustomFields {
948
+ isGift giftNote hidePricesOnPackingSlip
949
+ poNumber requestedDeliveryDate orderNotes
950
+ snTid snUtmSource snUtmMedium snUtmCampaign snFlowId snEnrollmentId snStepId
951
+ }
952
+ `);
953
+ export const SET_ORDER_CUSTOM_FIELDS = withFragments(
954
+ /* GraphQL */ `
955
+ mutation SetOrderCustomFields($input: UpdateOrderInput!) {
956
+ setOrderCustomFields(input: $input) {
957
+ ... on Order {
958
+ ...Order
959
+ customFields { ...OrderWritableCustomFields }
960
+ }
961
+ ... on NoActiveOrderError { errorCode message }
962
+ }
963
+ }
964
+ `, ORDER_FRAGMENT, ORDER_WRITABLE_CUSTOM_FIELDS_FRAGMENT);
965
+ export const UNSET_SHIPPING_ADDRESS = withFragments(
966
+ /* GraphQL */ `
967
+ mutation UnsetShippingAddress {
968
+ unsetOrderShippingAddress {
969
+ ... on Order { ...Order }
970
+ ... on NoActiveOrderError { errorCode message }
971
+ }
972
+ }
973
+ `, ORDER_FRAGMENT);
974
+ export const UNSET_BILLING_ADDRESS = withFragments(
975
+ /* GraphQL */ `
976
+ mutation UnsetBillingAddress {
977
+ unsetOrderBillingAddress {
978
+ ... on Order { ...Order }
979
+ ... on NoActiveOrderError { errorCode message }
980
+ }
981
+ }
982
+ `, ORDER_FRAGMENT);
983
+ /**
984
+ * `setCurrencyCodeForOrder` answers `UpdateOrderItemsResult`, so every member of
985
+ * that union is selected: an unselected member comes back as `{}`, which
986
+ * carries no `errorCode` and would read as success.
987
+ */
988
+ export const SET_ORDER_CURRENCY = withFragments(
989
+ /* GraphQL */ `
990
+ mutation SetOrderCurrency($currencyCode: CurrencyCode!) {
991
+ setCurrencyCodeForOrder(currencyCode: $currencyCode) {
992
+ ... on Order { ...Order }
993
+ ... on OrderModificationError { errorCode message }
994
+ ... on OrderLimitError { errorCode message maxItems }
995
+ ... on NegativeQuantityError { errorCode message }
996
+ ... on InsufficientStockError { ...InsufficientStockError }
997
+ ... on OrderInterceptorError { errorCode message interceptorError }
998
+ }
999
+ }
1000
+ `, ORDER_FRAGMENT, INSUFFICIENT_STOCK_ERROR_FRAGMENT);
686
1001
  /**
687
1002
  * Record how the buyer intends to pay AND re-price the order in one round trip.
688
1003
  *
@@ -694,85 +1009,91 @@ export const TRANSITION_TO_ARRANGING_PAYMENT = `
694
1009
  * the pay-now discount.
695
1010
  *
696
1011
  * `customFields { paymentIntent }` is selected HERE and nowhere else, and that
697
- * is deliberate. Putting it in the shared `ORDER_FIELDS` would make every order
1012
+ * is deliberate. Putting it in the shared `ORDER_FRAGMENT` would make every order
698
1013
  * query and cart mutation in this client fail GraphQL validation against an
699
1014
  * engine that predates the field — one missing feature would take the whole cart
700
1015
  * down. Confined to this document, only the call that needs the field is
701
1016
  * coupled to an engine that has it.
702
1017
  */
703
- export const SET_PAYMENT_INTENT = `
704
- mutation SetOrderPaymentIntent($intent: OrderPaymentIntent!) {
705
- setOrderPaymentIntent(intent: $intent) {
706
- ... on Order {
707
- ${ORDER_FIELDS}
708
- customFields { paymentIntent }
1018
+ export const SET_PAYMENT_INTENT = withFragments(
1019
+ /* GraphQL */ `
1020
+ mutation SetOrderPaymentIntent($intent: OrderPaymentIntent!) {
1021
+ setOrderPaymentIntent(intent: $intent) {
1022
+ ... on Order {
1023
+ ...Order
1024
+ customFields { paymentIntent }
1025
+ }
1026
+ ... on NoActiveOrderError { errorCode message }
709
1027
  }
710
- ... on NoActiveOrderError { errorCode message }
711
1028
  }
712
- }
713
- `;
714
- export const ADD_PAYMENT = `
715
- mutation AddPayment($input: PaymentInput!) {
716
- addPaymentToOrder(input: $input) {
717
- ... on Order {
718
- ${ORDER_FIELDS}
719
- ${ORDER_PAYMENT_TERMS_FRAGMENT}
720
- ${ORDER_DELIVERY_TERMS_FRAGMENT}
721
- }
722
- ... on OrderPaymentStateError { errorCode message }
723
- ... on IneligiblePaymentMethodError { errorCode message }
724
- ... on PaymentFailedError {
725
- errorCode message paymentErrorMessage
726
- placement { ${PLACEMENT_FIELDS} }
727
- }
728
- ... on PaymentDeclinedError {
729
- errorCode message paymentErrorMessage
730
- placement { ${PLACEMENT_FIELDS} }
731
- }
732
- ... on OrderStateTransitionError {
733
- errorCode message transitionError
734
- placement { ${PLACEMENT_FIELDS} }
1029
+ `, ORDER_FRAGMENT);
1030
+ export const ADD_PAYMENT = withFragments(
1031
+ /* GraphQL */ `
1032
+ mutation AddPayment($input: PaymentInput!) {
1033
+ addPaymentToOrder(input: $input) {
1034
+ ... on Order {
1035
+ ...Order
1036
+ ...OrderPaymentTerms
1037
+ ...OrderDeliveryTerms
1038
+ }
1039
+ ... on OrderPaymentStateError { errorCode message }
1040
+ ... on IneligiblePaymentMethodError { errorCode message }
1041
+ ... on PaymentFailedError {
1042
+ errorCode message paymentErrorMessage
1043
+ placement { ...PlacementRejection }
1044
+ }
1045
+ ... on PaymentDeclinedError {
1046
+ errorCode message paymentErrorMessage
1047
+ placement { ...PlacementRejection }
1048
+ }
1049
+ ... on OrderStateTransitionError {
1050
+ errorCode message transitionError
1051
+ placement { ...PlacementRejection }
1052
+ }
1053
+ ... on NoActiveOrderError { errorCode message }
735
1054
  }
736
- ... on NoActiveOrderError { errorCode message }
737
1055
  }
738
- }
739
- `;
1056
+ `, ORDER_FRAGMENT, ORDER_PAYMENT_TERMS_FRAGMENT, ORDER_DELIVERY_TERMS_FRAGMENT, PLACEMENT_REJECTION_FRAGMENT);
740
1057
  // --- Carrier-agnostic pickup locations (vendure-plugin-myparcel Phase 6) ---
741
- const PICKUP_LOCATION_FIELDS = `
742
- provider
743
- carrier
744
- locationCode
745
- name
746
- address {
747
- streetLine1
748
- number
749
- postalCode
750
- city
751
- countryCode
752
- region
753
- }
754
- openingHours {
755
- weekday
756
- open
757
- close
758
- }
759
- details
760
- `;
761
- export const PICKUP_LOCATIONS = `
762
- query PickupLocations($input: PickupLocationSearchInput!) {
763
- pickupLocations(input: $input) {
764
- ${PICKUP_LOCATION_FIELDS}
1058
+ const PICKUP_LOCATION_FRAGMENT = fragment(/* GraphQL */ `
1059
+ fragment PickupLocation on PickupLocation {
1060
+ provider
1061
+ carrier
1062
+ locationCode
1063
+ name
1064
+ address {
1065
+ streetLine1
1066
+ number
1067
+ postalCode
1068
+ city
1069
+ countryCode
1070
+ region
1071
+ }
1072
+ openingHours {
1073
+ weekday
1074
+ open
1075
+ close
1076
+ }
1077
+ details
1078
+ }
1079
+ `);
1080
+ export const PICKUP_LOCATIONS = withFragments(
1081
+ /* GraphQL */ `
1082
+ query PickupLocations($input: PickupLocationSearchInput!) {
1083
+ pickupLocations(input: $input) {
1084
+ ...PickupLocation
1085
+ }
765
1086
  }
766
- }
767
- `;
768
- export const ACTIVE_ORDER_PICKUP_LOCATION = `
769
- query ActiveOrderPickupLocation {
770
- activeOrderPickupLocation {
771
- ${PICKUP_LOCATION_FIELDS}
1087
+ `, PICKUP_LOCATION_FRAGMENT);
1088
+ export const ACTIVE_ORDER_PICKUP_LOCATION = withFragments(
1089
+ /* GraphQL */ `
1090
+ query ActiveOrderPickupLocation {
1091
+ activeOrderPickupLocation {
1092
+ ...PickupLocation
1093
+ }
772
1094
  }
773
- }
774
- `;
775
- export const SET_ACTIVE_ORDER_PICKUP_LOCATION = `
1095
+ `, PICKUP_LOCATION_FRAGMENT);
1096
+ export const SET_ACTIVE_ORDER_PICKUP_LOCATION = /* GraphQL */ `
776
1097
  mutation SetActiveOrderPickupLocation($location: StoredPickupLocationInput!) {
777
1098
  setActiveOrderPickupLocation(location: $location) {
778
1099
  __typename
@@ -787,13 +1108,13 @@ export const SET_ACTIVE_ORDER_PICKUP_LOCATION = `
787
1108
  }
788
1109
  `;
789
1110
  // --- Stripe (@vendure-community/stripe-plugin) ---
790
- export const CREATE_STRIPE_PAYMENT_INTENT = `
1111
+ export const CREATE_STRIPE_PAYMENT_INTENT = /* GraphQL */ `
791
1112
  mutation CreateStripePaymentIntent {
792
1113
  createStripePaymentIntent
793
1114
  }
794
1115
  `;
795
1116
  // --- Mollie (@vendure-community/mollie-plugin) ---
796
- export const MOLLIE_PAYMENT_METHODS = `
1117
+ export const MOLLIE_PAYMENT_METHODS = /* GraphQL */ `
797
1118
  query MolliePaymentMethods($input: MolliePaymentMethodsInput!) {
798
1119
  molliePaymentMethods(input: $input) {
799
1120
  id
@@ -806,7 +1127,7 @@ export const MOLLIE_PAYMENT_METHODS = `
806
1127
  }
807
1128
  }
808
1129
  `;
809
- export const ORDERED_MOLLIE_PAYMENT_METHODS = `
1130
+ export const ORDERED_MOLLIE_PAYMENT_METHODS = /* GraphQL */ `
810
1131
  query OrderedMolliePaymentMethods($paymentMethodCode: String!) {
811
1132
  orderedMolliePaymentMethods(paymentMethodCode: $paymentMethodCode) {
812
1133
  id
@@ -817,7 +1138,7 @@ export const ORDERED_MOLLIE_PAYMENT_METHODS = `
817
1138
  }
818
1139
  }
819
1140
  `;
820
- export const CREATE_MOLLIE_PAYMENT_INTENT = `
1141
+ export const CREATE_MOLLIE_PAYMENT_INTENT = /* GraphQL */ `
821
1142
  mutation CreateMolliePaymentIntent($input: MolliePaymentIntentInput!) {
822
1143
  createMolliePaymentIntent(input: $input) {
823
1144
  ... on MolliePaymentIntent { url }
@@ -825,7 +1146,7 @@ export const CREATE_MOLLIE_PAYMENT_INTENT = `
825
1146
  }
826
1147
  }
827
1148
  `;
828
- export const SYNC_MOLLIE_PAYMENT_STATUS = `
1149
+ export const SYNC_MOLLIE_PAYMENT_STATUS = /* GraphQL */ `
829
1150
  mutation SyncMolliePaymentStatus($orderCode: String!) {
830
1151
  syncMolliePaymentStatus(orderCode: $orderCode) {
831
1152
  id
@@ -834,8 +1155,101 @@ export const SYNC_MOLLIE_PAYMENT_STATUS = `
834
1155
  }
835
1156
  }
836
1157
  `;
1158
+ // --- Parked (held) orders ---
1159
+ /**
1160
+ * The money on a held order, as the storefront sees it: what it bills, what is
1161
+ * covered, what is left, and the currency all three are in. Narrower than the
1162
+ * merchant's own view of the same order — settled-vs-authorized and per-payment
1163
+ * refunds are bookkeeping a shopper is not shown.
1164
+ */
1165
+ const PARKED_ORDER_FRAGMENT = fragment(/* GraphQL */ `
1166
+ fragment ParkedOrder on ParkedOrder {
1167
+ id
1168
+ code
1169
+ state
1170
+ position { total covered outstanding currencyCode }
1171
+ reason
1172
+ }
1173
+ `);
1174
+ export const PARKED_ORDERS_QUERY = withFragments(
1175
+ /* GraphQL */ `
1176
+ query ParkedOrders {
1177
+ parkedOrders {
1178
+ ...ParkedOrder
1179
+ }
1180
+ }
1181
+ `, PARKED_ORDER_FRAGMENT);
1182
+ export const PAY_PARKED_ORDER_MUTATION = /* GraphQL */ `
1183
+ mutation PayParkedOrder(
1184
+ $orderCode: String!
1185
+ $input: PayParkedOrderInput!
1186
+ $idempotencyKey: String
1187
+ ) {
1188
+ payParkedOrder(orderCode: $orderCode, input: $input, idempotencyKey: $idempotencyKey) {
1189
+ order { id code state }
1190
+ payment { id state amount method metadata }
1191
+ position { total covered outstanding currencyCode }
1192
+ settled
1193
+ }
1194
+ }
1195
+ `;
1196
+ export const CREATE_PARKED_ORDER_PAYMENT_INTENT_MUTATION = /* GraphQL */ `
1197
+ mutation CreateParkedOrderPaymentIntent(
1198
+ $orderCode: String!
1199
+ $input: ParkedOrderPaymentIntentInput!
1200
+ $idempotencyKey: String
1201
+ ) {
1202
+ createParkedOrderPaymentIntent(
1203
+ orderCode: $orderCode
1204
+ input: $input
1205
+ idempotencyKey: $idempotencyKey
1206
+ ) {
1207
+ provider
1208
+ url
1209
+ clientSecret
1210
+ amount
1211
+ currencyCode
1212
+ }
1213
+ }
1214
+ `;
1215
+ /**
1216
+ * A deposit paid in checkout, which parks the active order (W8-13).
1217
+ *
1218
+ * `order` selects exactly what `ADD_PAYMENT` selects for its `Order` member, so
1219
+ * `addPayment(input, { amount })` — which routes here — resolves to the same
1220
+ * type whether it paid in full or paid a deposit. No `idempotencyKey` argument:
1221
+ * like `addPaymentToOrder`, this mutation is keyed by the `Idempotency-Key`
1222
+ * header (the W8-12 contract), unlike the parked-order calls above.
1223
+ */
1224
+ export const PAY_DEPOSIT_MUTATION = withFragments(
1225
+ /* GraphQL */ `
1226
+ mutation PayDeposit($input: PayDepositInput!) {
1227
+ payDeposit(input: $input) {
1228
+ order {
1229
+ ...Order
1230
+ ...OrderPaymentTerms
1231
+ ...OrderDeliveryTerms
1232
+ }
1233
+ payment { id state amount method metadata }
1234
+ position { total covered outstanding currencyCode }
1235
+ settled
1236
+ }
1237
+ }
1238
+ `, ORDER_FRAGMENT, ORDER_PAYMENT_TERMS_FRAGMENT, ORDER_DELIVERY_TERMS_FRAGMENT);
1239
+ /** A card (Mollie) deposit in checkout; keyed by the header, as `PAY_DEPOSIT_MUTATION`. */
1240
+ export const CREATE_DEPOSIT_PAYMENT_INTENT_MUTATION = /* GraphQL */ `
1241
+ mutation CreateDepositPaymentIntent($input: DepositPaymentIntentInput!) {
1242
+ createDepositPaymentIntent(input: $input) {
1243
+ provider
1244
+ url
1245
+ clientSecret
1246
+ amount
1247
+ currencyCode
1248
+ }
1249
+ }
1250
+ `;
837
1251
  // --- Customer Queries/Mutations ---
838
- export const LOGIN = `
1252
+ export const LOGIN = /* GraphQL */ `
839
1253
  mutation Login($email: String!, $password: String!) {
840
1254
  login(username: $email, password: $password) {
841
1255
  ... on CurrentUser { id identifier }
@@ -845,7 +1259,29 @@ export const LOGIN = `
845
1259
  }
846
1260
  }
847
1261
  `;
848
- export const REGISTER = `
1262
+ const CURRENT_USER_FRAGMENT = fragment(/* GraphQL */ `
1263
+ fragment CurrentUser on CurrentUser {
1264
+ id identifier
1265
+ }
1266
+ `);
1267
+ /**
1268
+ * Sign in through a named authentication strategy (`native` is the only one the
1269
+ * engine registers today). Every `AuthenticationResult` member is selected, and
1270
+ * `authenticationError` with it: the engine's native strategy reports an
1271
+ * imported account with no password (`PASSWORD_RESET_REQUIRED`) or an
1272
+ * unverified one (`ACCOUNT_NOT_VERIFIED`) there, not as an error type.
1273
+ */
1274
+ export const AUTHENTICATE = withFragments(
1275
+ /* GraphQL */ `
1276
+ mutation Authenticate($input: AuthenticationInput!, $rememberMe: Boolean) {
1277
+ authenticate(input: $input, rememberMe: $rememberMe) {
1278
+ ... on CurrentUser { ...CurrentUser }
1279
+ ... on InvalidCredentialsError { errorCode message authenticationError }
1280
+ ... on NotVerifiedError { errorCode message }
1281
+ }
1282
+ }
1283
+ `, CURRENT_USER_FRAGMENT);
1284
+ export const REGISTER = /* GraphQL */ `
849
1285
  mutation Register($input: RegisterCustomerInput!) {
850
1286
  registerCustomerAccount(input: $input) {
851
1287
  ... on Success { success }
@@ -855,58 +1291,62 @@ export const REGISTER = `
855
1291
  }
856
1292
  }
857
1293
  `;
858
- export const GET_CURRENT_CUSTOMER = `
859
- query Me {
860
- activeCustomer {
861
- id firstName lastName emailAddress phoneNumber
862
- groups { id name }
863
- isB2B
864
- addresses {
865
- id fullName streetLine1 streetLine2 city province postalCode
866
- country { code name }
867
- defaultShippingAddress defaultBillingAddress
868
- }
869
- orders(options: { take: 10, sort: { createdAt: DESC } }) {
870
- items {
871
- ${ORDER_SUMMARY_FIELDS}
1294
+ export const GET_CURRENT_CUSTOMER = withFragments(
1295
+ /* GraphQL */ `
1296
+ query Me {
1297
+ activeCustomer {
1298
+ id firstName lastName emailAddress phoneNumber
1299
+ groups { id name }
1300
+ isB2B
1301
+ hasPassword
1302
+ addresses {
1303
+ id fullName streetLine1 streetLine2 city province postalCode
1304
+ country { code name }
1305
+ defaultShippingAddress defaultBillingAddress
1306
+ }
1307
+ orders(options: { take: 10, sort: { createdAt: DESC } }) {
1308
+ items {
1309
+ ...OrderSummary
1310
+ }
1311
+ totalItems
872
1312
  }
873
- totalItems
874
1313
  }
875
1314
  }
876
- }
877
- `;
878
- export const ACTIVE_CUSTOMER_PRICE_LISTS = `
1315
+ `, ORDER_SUMMARY_FRAGMENT);
1316
+ export const ACTIVE_CUSTOMER_PRICE_LISTS = /* GraphQL */ `
879
1317
  query ActiveCustomerPriceLists {
880
1318
  activeCustomerPriceLists { id name isContract }
881
1319
  }
882
1320
  `;
883
- export const GET_CUSTOMER_ORDERS = `
884
- query CustomerOrders($options: OrderListOptions) {
885
- activeCustomer {
886
- orders(options: $options) {
887
- items {
888
- ${ORDER_SUMMARY_FIELDS}
889
- lines { id backorderedQuantity }
1321
+ export const GET_CUSTOMER_ORDERS = withFragments(
1322
+ /* GraphQL */ `
1323
+ query CustomerOrders($options: OrderListOptions) {
1324
+ activeCustomer {
1325
+ orders(options: $options) {
1326
+ items {
1327
+ ...OrderSummary
1328
+ lines { id backorderedQuantity }
1329
+ ...OrderFulfillmentParcels
1330
+ }
1331
+ totalItems
890
1332
  }
891
- totalItems
892
1333
  }
893
1334
  }
894
- }
895
- `;
896
- export const LOGOUT = `
1335
+ `, ORDER_FULFILLMENT_PARCELS_FRAGMENT, ORDER_SUMMARY_FRAGMENT);
1336
+ export const LOGOUT = /* GraphQL */ `
897
1337
  mutation Logout {
898
1338
  logout { success }
899
1339
  }
900
1340
  `;
901
1341
  // --- Customer Account Management ---
902
- export const UPDATE_CUSTOMER = `
1342
+ export const UPDATE_CUSTOMER = /* GraphQL */ `
903
1343
  mutation UpdateCustomer($input: UpdateCustomerInput!) {
904
1344
  updateCustomer(input: $input) {
905
1345
  id firstName lastName emailAddress phoneNumber
906
1346
  }
907
1347
  }
908
1348
  `;
909
- export const UPDATE_PASSWORD = `
1349
+ export const UPDATE_PASSWORD = /* GraphQL */ `
910
1350
  mutation UpdatePassword($currentPassword: String!, $newPassword: String!) {
911
1351
  updateCustomerPassword(currentPassword: $currentPassword, newPassword: $newPassword) {
912
1352
  ... on Success { success }
@@ -916,7 +1356,24 @@ export const UPDATE_PASSWORD = `
916
1356
  }
917
1357
  }
918
1358
  `;
919
- export const REQUEST_PASSWORD_RESET = `
1359
+ /**
1360
+ * The signed-in customer's FIRST password, for an account that signed in by
1361
+ * email link or code and has none (`updatePassword` needs the current one).
1362
+ * Every member is selected: an unselected error member arrives as `{}` and the
1363
+ * wrapper would read a refused password as set.
1364
+ */
1365
+ export const SET_CUSTOMER_PASSWORD = /* GraphQL */ `
1366
+ mutation SetCustomerPassword($newPassword: String!) {
1367
+ setCustomerPassword(newPassword: $newPassword) {
1368
+ ... on Success { success }
1369
+ ... on PasswordValidationError { errorCode message validationErrorMessage }
1370
+ ... on PasswordAlreadySetError { errorCode message }
1371
+ ... on NativeAuthStrategyError { errorCode message }
1372
+ ... on SetPasswordRequiresEmailSignInError { errorCode message }
1373
+ }
1374
+ }
1375
+ `;
1376
+ export const REQUEST_PASSWORD_RESET = /* GraphQL */ `
920
1377
  mutation RequestPasswordReset($emailAddress: String!) {
921
1378
  requestPasswordReset(emailAddress: $emailAddress) {
922
1379
  ... on Success { success }
@@ -924,7 +1381,7 @@ export const REQUEST_PASSWORD_RESET = `
924
1381
  }
925
1382
  }
926
1383
  `;
927
- export const RESET_PASSWORD = `
1384
+ export const RESET_PASSWORD = /* GraphQL */ `
928
1385
  mutation ResetPassword($token: String!, $password: String!) {
929
1386
  resetPassword(token: $token, password: $password) {
930
1387
  ... on CurrentUser { id identifier }
@@ -936,15 +1393,18 @@ export const RESET_PASSWORD = `
936
1393
  }
937
1394
  }
938
1395
  `;
939
- export const REQUEST_MAGIC_LINK = `
940
- mutation RequestMagicLink($emailAddress: String!) {
941
- requestMagicLink(emailAddress: $emailAddress) {
1396
+ // `MagicLinkRateLimitedError` must stay selected: an unselected union member
1397
+ // comes back as `{}`, which carries no `errorCode` and reads as success.
1398
+ export const REQUEST_MAGIC_LINK = /* GraphQL */ `
1399
+ mutation RequestMagicLink($emailAddress: String!, $portal: MagicLinkPortal) {
1400
+ requestMagicLink(emailAddress: $emailAddress, portal: $portal) {
942
1401
  ... on Success { success }
943
1402
  ... on NativeAuthStrategyError { errorCode message }
1403
+ ... on MagicLinkRateLimitedError { errorCode message retryAfterSeconds }
944
1404
  }
945
1405
  }
946
1406
  `;
947
- export const LOGIN_WITH_MAGIC_LINK = `
1407
+ export const LOGIN_WITH_MAGIC_LINK = /* GraphQL */ `
948
1408
  mutation LoginWithMagicLink($token: String!) {
949
1409
  loginWithMagicLink(token: $token) {
950
1410
  ... on CurrentUser { id identifier }
@@ -956,7 +1416,7 @@ export const LOGIN_WITH_MAGIC_LINK = `
956
1416
  }
957
1417
  }
958
1418
  `;
959
- export const LOGIN_WITH_MAGIC_CODE = `
1419
+ export const LOGIN_WITH_MAGIC_CODE = /* GraphQL */ `
960
1420
  mutation LoginWithMagicCode($emailAddress: String!, $code: String!) {
961
1421
  loginWithMagicCode(emailAddress: $emailAddress, code: $code) {
962
1422
  ... on CurrentUser { id identifier }
@@ -968,7 +1428,7 @@ export const LOGIN_WITH_MAGIC_CODE = `
968
1428
  }
969
1429
  }
970
1430
  `;
971
- export const REQUEST_EMAIL_UPDATE = `
1431
+ export const REQUEST_EMAIL_UPDATE = /* GraphQL */ `
972
1432
  mutation RequestEmailUpdate($password: String!, $newEmailAddress: String!) {
973
1433
  requestUpdateCustomerEmailAddress(password: $password, newEmailAddress: $newEmailAddress) {
974
1434
  ... on Success { success }
@@ -980,7 +1440,7 @@ export const REQUEST_EMAIL_UPDATE = `
980
1440
  }
981
1441
  }
982
1442
  `;
983
- export const UPDATE_EMAIL = `
1443
+ export const UPDATE_EMAIL = /* GraphQL */ `
984
1444
  mutation UpdateEmail($token: String!) {
985
1445
  updateCustomerEmailAddress(token: $token) {
986
1446
  ... on Success { success }
@@ -990,7 +1450,7 @@ export const UPDATE_EMAIL = `
990
1450
  }
991
1451
  }
992
1452
  `;
993
- export const VERIFY_ACCOUNT = `
1453
+ export const VERIFY_ACCOUNT = /* GraphQL */ `
994
1454
  mutation VerifyAccount($token: String!, $password: String) {
995
1455
  verifyCustomerAccount(token: $token, password: $password) {
996
1456
  ... on CurrentUser { id identifier }
@@ -1003,7 +1463,7 @@ export const VERIFY_ACCOUNT = `
1003
1463
  }
1004
1464
  }
1005
1465
  `;
1006
- export const REFRESH_VERIFICATION = `
1466
+ export const REFRESH_VERIFICATION = /* GraphQL */ `
1007
1467
  mutation RefreshVerification($emailAddress: String!) {
1008
1468
  refreshCustomerVerification(emailAddress: $emailAddress) {
1009
1469
  ... on Success { success }
@@ -1012,7 +1472,7 @@ export const REFRESH_VERIFICATION = `
1012
1472
  }
1013
1473
  `;
1014
1474
  // --- Address Management ---
1015
- export const CREATE_ADDRESS = `
1475
+ export const CREATE_ADDRESS = /* GraphQL */ `
1016
1476
  mutation CreateAddress($input: CreateAddressInput!) {
1017
1477
  createCustomerAddress(input: $input) {
1018
1478
  id fullName streetLine1 streetLine2 city province postalCode
@@ -1021,7 +1481,7 @@ export const CREATE_ADDRESS = `
1021
1481
  }
1022
1482
  }
1023
1483
  `;
1024
- export const UPDATE_ADDRESS = `
1484
+ export const UPDATE_ADDRESS = /* GraphQL */ `
1025
1485
  mutation UpdateAddress($input: UpdateAddressInput!) {
1026
1486
  updateCustomerAddress(input: $input) {
1027
1487
  id fullName streetLine1 streetLine2 city province postalCode
@@ -1030,7 +1490,7 @@ export const UPDATE_ADDRESS = `
1030
1490
  }
1031
1491
  }
1032
1492
  `;
1033
- export const DELETE_ADDRESS = `
1493
+ export const DELETE_ADDRESS = /* GraphQL */ `
1034
1494
  mutation DeleteAddress($id: ID!) {
1035
1495
  deleteCustomerAddress(id: $id) {
1036
1496
  success
@@ -1038,7 +1498,7 @@ export const DELETE_ADDRESS = `
1038
1498
  }
1039
1499
  `;
1040
1500
  // --- Utility Queries ---
1041
- export const AVAILABLE_COUNTRIES = `
1501
+ export const AVAILABLE_COUNTRIES = /* GraphQL */ `
1042
1502
  query AvailableCountries {
1043
1503
  availableCountries {
1044
1504
  id code name
@@ -1048,30 +1508,38 @@ export const AVAILABLE_COUNTRIES = `
1048
1508
  /**
1049
1509
  * `lines { backorderedQuantity }` is selected HERE and on `GET_CUSTOMER_ORDERS`,
1050
1510
  * and nowhere else — the same rule `customFields { paymentIntent }` follows
1051
- * below. In the shared `ORDER_FIELDS` fragment it would make every cart read
1511
+ * below. In the shared `ORDER_FRAGMENT` fragment it would make every cart read
1052
1512
  * and mutation fail validation against an engine that predates the backorders
1053
1513
  * plugin, taking the whole cart down for a field a cart line never carries a
1054
1514
  * value for (the stamp is written at placement). GraphQL merges this `lines`
1055
1515
  * selection with the fragment's, so the line still comes back whole.
1516
+ *
1517
+ * `customFields { chargedParcelCount }` follows the same rule: frozen when the
1518
+ * order leaves the cart, so it belongs to this placed-order read alone. It
1519
+ * does make this document need an engine with the extra-parcel charge: a
1520
+ * client release carrying it publishes after that engine is deployed.
1056
1521
  */
1057
- export const ORDER_BY_CODE = `
1058
- query OrderByCode($code: String!) {
1059
- orderByCode(code: $code) {
1060
- ${ORDER_FIELDS}
1061
- lines { id backorderedQuantity }
1062
- ${ORDER_FULFILLMENTS_FRAGMENT}
1063
- ${ORDER_PAYMENT_TERMS_FRAGMENT}
1064
- ${ORDER_DELIVERY_TERMS_FRAGMENT}
1522
+ export const ORDER_BY_CODE = withFragments(
1523
+ /* GraphQL */ `
1524
+ query OrderByCode($code: String!) {
1525
+ orderByCode(code: $code) {
1526
+ ...Order
1527
+ lines { id backorderedQuantity }
1528
+ customFields { chargedParcelCount }
1529
+ ...OrderFulfillments
1530
+ ...OrderFulfillmentParcels
1531
+ ...OrderPaymentTerms
1532
+ ...OrderDeliveryTerms
1533
+ }
1065
1534
  }
1066
- }
1067
- `;
1535
+ `, ORDER_FRAGMENT, ORDER_FULFILLMENTS_FRAGMENT, ORDER_FULFILLMENT_PARCELS_FRAGMENT, ORDER_PAYMENT_TERMS_FRAGMENT, ORDER_DELIVERY_TERMS_FRAGMENT);
1068
1536
  // --- Favorites ---
1069
- export const FAVORITE_VARIANT_IDS = `
1537
+ export const FAVORITE_VARIANT_IDS = /* GraphQL */ `
1070
1538
  query FavoriteVariantIds {
1071
1539
  favoriteProductVariantIds
1072
1540
  }
1073
1541
  `;
1074
- export const MY_FAVORITES = `
1542
+ export const MY_FAVORITES = /* GraphQL */ `
1075
1543
  query MyFavorites($options: FavoriteListOptions) {
1076
1544
  myFavorites(options: $options) {
1077
1545
  items {
@@ -1084,6 +1552,7 @@ export const MY_FAVORITES = `
1084
1552
  stockOnHand stockAllocated saleable
1085
1553
  incomingStock projectedSaleable nextExpectedArrival
1086
1554
  backorderAllowance
1555
+ availability { state availableFrom orderable }
1087
1556
  priceListName retailPrice retailPriceWithTax taxRateApplied { value }
1088
1557
  priceTiers { minQuantity price priceWithTax discountLabel }
1089
1558
  availabilityByLocation { locationId locationName inStock }
@@ -1103,12 +1572,12 @@ export const MY_FAVORITES = `
1103
1572
  }
1104
1573
  }
1105
1574
  `;
1106
- export const TOGGLE_FAVORITE = `
1575
+ export const TOGGLE_FAVORITE = /* GraphQL */ `
1107
1576
  mutation ToggleFavorite($productVariantId: ID!) {
1108
1577
  toggleFavorite(productVariantId: $productVariantId)
1109
1578
  }
1110
1579
  `;
1111
- export const REMOVE_FAVORITE = `
1580
+ export const REMOVE_FAVORITE = /* GraphQL */ `
1112
1581
  mutation RemoveFavorite($productVariantId: ID!) {
1113
1582
  removeFavorite(productVariantId: $productVariantId)
1114
1583
  }
@@ -1120,8 +1589,8 @@ export const REMOVE_FAVORITE = `
1120
1589
  * in types.ts and the `public: true` Channel customFields configured on
1121
1590
  * the Vendure side.
1122
1591
  */
1123
- const CHANNEL_CUSTOM_FIELDS_FRAGMENT = `
1124
- customFields {
1592
+ const CHANNEL_CUSTOM_FIELDS_FRAGMENT = fragment(/* GraphQL */ `
1593
+ fragment ChannelCustomFields on ChannelCustomFields {
1125
1594
  businessName businessDescription
1126
1595
  logoAssetId darkLogoAssetId coverAssetId faviconAssetId
1127
1596
  websiteUrl primaryColor
@@ -1137,57 +1606,68 @@ const CHANNEL_CUSTOM_FIELDS_FRAGMENT = `
1137
1606
  returnsEnabled returnWindowDays
1138
1607
  taxDisplayDefault taxDisplayB2b taxExclusiveCountries
1139
1608
  }
1140
- `;
1141
- export const GET_ACTIVE_CHANNEL = `
1142
- query ActiveChannel {
1143
- activeChannel {
1144
- id code
1145
- defaultLanguageCode
1146
- availableLanguageCodes
1147
- defaultCurrencyCode
1148
- availableCurrencyCodes
1149
- ${CHANNEL_CUSTOM_FIELDS_FRAGMENT}
1609
+ `);
1610
+ export const GET_ACTIVE_CHANNEL = withFragments(
1611
+ /* GraphQL */ `
1612
+ query ActiveChannel {
1613
+ activeChannel {
1614
+ id code
1615
+ defaultLanguageCode
1616
+ availableLanguageCodes
1617
+ defaultCurrencyCode
1618
+ availableCurrencyCodes
1619
+ customFields { ...ChannelCustomFields }
1620
+ }
1150
1621
  }
1151
- }
1152
- `;
1622
+ `, CHANNEL_CUSTOM_FIELDS_FRAGMENT);
1153
1623
  // --- Product Properties ---
1154
- export const PROPERTY_GROUPS = `
1155
- query PropertyGroups {
1156
- productPropertyGroups {
1624
+ /** Every property group, with each property's full config (`getPropertyGroups`). */
1625
+ export const PROPERTY_GROUP_FRAGMENT = fragment(/* GraphQL */ `
1626
+ fragment PropertyGroup on PropertyGroup {
1627
+ id position
1628
+ translations { id languageCode name }
1629
+ properties {
1630
+ id slug fieldType isFilterable isRequired position
1631
+ config { options { value label } min max maxLength allowedCollectionIds filterableFieldSlugs }
1632
+ facetId
1633
+ fieldFacets { fieldSlug fieldType facetId }
1634
+ translations { id languageCode name helpText }
1635
+ }
1636
+ }
1637
+ `);
1638
+ /** One product's values per group (`getProductProperties`); the group config is narrower. */
1639
+ export const PRODUCT_PROPERTY_GROUP_VALUES_FRAGMENT = fragment(/* GraphQL */ `
1640
+ fragment ProductPropertyGroupValues on ProductPropertyGroupValues {
1641
+ group {
1157
1642
  id position
1158
1643
  translations { id languageCode name }
1159
1644
  properties {
1160
1645
  id slug fieldType isFilterable isRequired position
1161
- config { options { value label } min max maxLength allowedCollectionIds filterableFieldSlugs }
1646
+ config { options { value label } min max maxLength }
1162
1647
  facetId
1163
1648
  fieldFacets { fieldSlug fieldType facetId }
1164
1649
  translations { id languageCode name helpText }
1165
1650
  }
1166
1651
  }
1652
+ values { id propertyId languageCode value }
1167
1653
  }
1168
- `;
1169
- export const PRODUCT_PROPERTIES = `
1170
- query ProductProperties($productId: ID!) {
1171
- productPropertyValues(productId: $productId) {
1172
- group {
1173
- id position
1174
- translations { id languageCode name }
1175
- properties {
1176
- id slug fieldType isFilterable isRequired position
1177
- config { options { value label } min max maxLength }
1178
- facetId
1179
- fieldFacets { fieldSlug fieldType facetId }
1180
- translations { id languageCode name helpText }
1181
- }
1182
- }
1183
- values { id propertyId languageCode value }
1654
+ `);
1655
+ export const PROPERTY_GROUPS = withFragments(
1656
+ /* GraphQL */ `
1657
+ query PropertyGroups {
1658
+ productPropertyGroups { ...PropertyGroup }
1184
1659
  }
1185
- }
1186
- `;
1660
+ `, PROPERTY_GROUP_FRAGMENT);
1661
+ export const PRODUCT_PROPERTIES = withFragments(
1662
+ /* GraphQL */ `
1663
+ query ProductProperties($productId: ID!) {
1664
+ productPropertyValues(productId: $productId) { ...ProductPropertyGroupValues }
1665
+ }
1666
+ `, PRODUCT_PROPERTY_GROUP_VALUES_FRAGMENT);
1187
1667
  // --- Product Recommendations ---
1188
- export const GET_PRODUCT_RECOMMENDATIONS = `
1189
- query ProductRecommendations($productId: ID!, $groupSlug: String) {
1190
- productRecommendations(productId: $productId, groupSlug: $groupSlug) {
1668
+ export const RECOMMENDED_PRODUCT_GROUP_FRAGMENT = fragment(
1669
+ /* GraphQL */ `
1670
+ fragment RecommendedProductGroup on RecommendedProducts {
1191
1671
  groupName
1192
1672
  groupSlug
1193
1673
  products {
@@ -1203,17 +1683,26 @@ export const GET_PRODUCT_RECOMMENDATIONS = `
1203
1683
  stockOnHand stockAllocated saleable
1204
1684
  incomingStock projectedSaleable nextExpectedArrival
1205
1685
  backorderAllowance
1686
+ availability { ...ProductAvailability }
1687
+ forSaleInCurrency
1206
1688
  priceListName retailPrice retailPriceWithTax taxRateApplied { value }
1207
- priceTiers { minQuantity price priceWithTax discountLabel }
1208
- availabilityByLocation { locationId locationName inStock }
1689
+ priceTiers { ...PriceTier }
1690
+ availabilityByLocation { ...VariantLocationAvailability }
1209
1691
  customFields { minOrderQuantity salesUnit position }
1210
1692
  }
1211
1693
  }
1212
1694
  }
1213
- }
1214
- `;
1695
+ `, PRODUCT_AVAILABILITY_FRAGMENT, PRICE_TIER_FRAGMENT, VARIANT_LOCATION_AVAILABILITY_FRAGMENT);
1696
+ export const GET_PRODUCT_RECOMMENDATIONS = withFragments(
1697
+ /* GraphQL */ `
1698
+ query ProductRecommendations($productId: ID!, $groupSlug: String) {
1699
+ productRecommendations(productId: $productId, groupSlug: $groupSlug) {
1700
+ ...RecommendedProductGroup
1701
+ }
1702
+ }
1703
+ `, RECOMMENDED_PRODUCT_GROUP_FRAGMENT);
1215
1704
  // --- Exchange Rates ---
1216
- export const GET_EXCHANGE_RATES = `
1705
+ export const GET_EXCHANGE_RATES = /* GraphQL */ `
1217
1706
  query ExchangeRates {
1218
1707
  exchangeRates {
1219
1708
  baseCurrency targetCurrency rate inverseRate rateDate
@@ -1221,38 +1710,43 @@ export const GET_EXCHANGE_RATES = `
1221
1710
  }
1222
1711
  `;
1223
1712
  // Shared selection for the exchange-rates plugin's ConvertedAmount type.
1224
- const CONVERTED_AMOUNT_FIELDS = `
1225
- originalAmount originalCurrency convertedAmount targetCurrency rate rateDate
1226
- `;
1227
- export const CONVERT_CURRENCY = `
1228
- query ConvertCurrency($amount: String!, $from: String!, $to: String!) {
1229
- convertCurrency(amount: $amount, fromCurrency: $from, toCurrency: $to) {
1230
- ${CONVERTED_AMOUNT_FIELDS}
1713
+ const CONVERTED_AMOUNT_FRAGMENT = fragment(/* GraphQL */ `
1714
+ fragment ConvertedAmount on ConvertedAmount {
1715
+ originalAmount originalCurrency convertedAmount targetCurrency rate rateDate
1716
+ }
1717
+ `);
1718
+ export const CONVERT_CURRENCY = withFragments(
1719
+ /* GraphQL */ `
1720
+ query ConvertCurrency($amount: String!, $from: String!, $to: String!) {
1721
+ convertCurrency(amount: $amount, fromCurrency: $from, toCurrency: $to) {
1722
+ ...ConvertedAmount
1723
+ }
1231
1724
  }
1232
- }
1233
- `;
1234
- export const GET_EXCHANGE_RATE = `
1725
+ `, CONVERTED_AMOUNT_FRAGMENT);
1726
+ export const GET_EXCHANGE_RATE = /* GraphQL */ `
1235
1727
  query ExchangeRate($targetCurrency: String!) {
1236
1728
  exchangeRate(targetCurrency: $targetCurrency) {
1237
1729
  baseCurrency targetCurrency rate inverseRate rateDate
1238
1730
  }
1239
1731
  }
1240
1732
  `;
1241
- export const CONVERT_FROM_BASE = `
1242
- query ConvertFromBase($amount: String!, $targetCurrency: String!) {
1243
- convertFromBase(amount: $amount, targetCurrency: $targetCurrency) {
1244
- ${CONVERTED_AMOUNT_FIELDS}
1733
+ export const CONVERT_FROM_BASE = withFragments(
1734
+ /* GraphQL */ `
1735
+ query ConvertFromBase($amount: String!, $targetCurrency: String!) {
1736
+ convertFromBase(amount: $amount, targetCurrency: $targetCurrency) {
1737
+ ...ConvertedAmount
1738
+ }
1245
1739
  }
1246
- }
1247
- `;
1248
- export const CONVERT_TO_BASE = `
1249
- query ConvertToBase($amount: String!, $sourceCurrency: String!) {
1250
- convertToBase(amount: $amount, sourceCurrency: $sourceCurrency) {
1251
- ${CONVERTED_AMOUNT_FIELDS}
1740
+ `, CONVERTED_AMOUNT_FRAGMENT);
1741
+ export const CONVERT_TO_BASE = withFragments(
1742
+ /* GraphQL */ `
1743
+ query ConvertToBase($amount: String!, $sourceCurrency: String!) {
1744
+ convertToBase(amount: $amount, sourceCurrency: $sourceCurrency) {
1745
+ ...ConvertedAmount
1746
+ }
1252
1747
  }
1253
- }
1254
- `;
1255
- export const CONVERT_TO_MULTIPLE = `
1748
+ `, CONVERTED_AMOUNT_FRAGMENT);
1749
+ export const CONVERT_TO_MULTIPLE = /* GraphQL */ `
1256
1750
  query ConvertToMultiple($amount: String!, $from: String!, $to: [String!]!) {
1257
1751
  convertToMultiple(amount: $amount, fromCurrency: $from, toCurrencies: $to) {
1258
1752
  currency amount rate
@@ -1261,69 +1755,106 @@ export const CONVERT_TO_MULTIPLE = `
1261
1755
  `;
1262
1756
  // --- B2B Quotes ---
1263
1757
  /**
1264
- * Per-line tax + product identity. These fields reach the Shop API with the
1758
+ * Per-line tax + product identity (`productName sku taxRate unitPriceWithTax
1759
+ * lineTotal lineTotalWithTax`). These fields reach the Shop API with the
1265
1760
  * `vendure-plugin-quotes` release that introduced them, and the SDK can be
1266
1761
  * upgraded before a tenant's Vendure is: an older server rejects the WHOLE
1267
1762
  * document at validation ("Cannot query field ..."), taking the quote page
1268
1763
  * down rather than dropping a column. So every quote document has a legacy
1269
- * twin without them, and `createQuotesMethods` retries with it once — see
1270
- * the fallback there. Keep the twins identical apart from this line.
1764
+ * twin spreading `QuoteLegacy` instead, and `createQuotesMethods` retries with
1765
+ * it once — see the fallback there. Keep the two fragments identical apart
1766
+ * from that line, and each legacy document identical to its twin apart from
1767
+ * the fragment it spreads and its `Legacy` operation name.
1271
1768
  */
1272
- const QUOTE_LINE_TAX_FIELDS = 'productName sku taxRate unitPriceWithTax lineTotal lineTotalWithTax';
1273
- const quoteFields = (lineTaxFields) => `
1274
- id code channelId customerId currencyCode status
1275
- expiresAt salesRepUserId customerNotes convertedOrderId
1276
- createdAt updatedAt
1277
- lines {
1278
- id productVariantId quantity unitPrice discountType discountValue discountLabel position
1279
- ${lineTaxFields}
1769
+ const QUOTE_FRAGMENT = fragment(/* GraphQL */ `
1770
+ fragment Quote on Quote {
1771
+ id code channelId customerId currencyCode status
1772
+ expiresAt salesRepUserId customerNotes convertedOrderId
1280
1773
  createdAt updatedAt
1281
- }
1282
- `;
1283
- const QUOTE_FIELDS = quoteFields(QUOTE_LINE_TAX_FIELDS);
1284
- const QUOTE_FIELDS_LEGACY = quoteFields('');
1285
- const myQuotesDocument = (fields) => `
1286
- query MyQuotes($options: QuoteListOptions) {
1287
- myQuotes(options: $options) {
1288
- items { ${fields} }
1289
- totalItems
1774
+ lines {
1775
+ id productVariantId quantity unitPrice discountType discountValue discountLabel position
1776
+ productName sku taxRate unitPriceWithTax lineTotal lineTotalWithTax
1777
+ createdAt updatedAt
1290
1778
  }
1291
1779
  }
1292
- `;
1293
- const myQuoteDocument = (fields) => `
1294
- query MyQuote($id: ID!) {
1295
- myQuote(id: $id) { ${fields} }
1296
- }
1297
- `;
1298
- const createQuoteRequestDocument = (fields) => `
1299
- mutation CreateQuoteRequest($input: CreateQuoteRequestInput!) {
1300
- createQuoteRequest(input: $input) { ${fields} }
1301
- }
1302
- `;
1303
- const cancelMyQuoteDocument = (fields) => `
1304
- mutation CancelMyQuote($id: ID!, $reason: String) {
1305
- cancelMyQuote(id: $id, reason: $reason) { ${fields} }
1306
- }
1307
- `;
1308
- export const MY_QUOTES = myQuotesDocument(QUOTE_FIELDS);
1309
- export const MY_QUOTES_LEGACY = myQuotesDocument(QUOTE_FIELDS_LEGACY);
1310
- export const MY_QUOTE = myQuoteDocument(QUOTE_FIELDS);
1311
- export const MY_QUOTE_LEGACY = myQuoteDocument(QUOTE_FIELDS_LEGACY);
1312
- export const CREATE_QUOTE_REQUEST = createQuoteRequestDocument(QUOTE_FIELDS);
1313
- export const CREATE_QUOTE_REQUEST_LEGACY = createQuoteRequestDocument(QUOTE_FIELDS_LEGACY);
1314
- export const ACCEPT_QUOTE = `
1315
- mutation AcceptQuote($id: ID!) {
1316
- acceptQuote(id: $id) { ${ORDER_FIELDS} }
1780
+ `);
1781
+ const QUOTE_LEGACY_FRAGMENT = fragment(/* GraphQL */ `
1782
+ fragment QuoteLegacy on Quote {
1783
+ id code channelId customerId currencyCode status
1784
+ expiresAt salesRepUserId customerNotes convertedOrderId
1785
+ createdAt updatedAt
1786
+ lines {
1787
+ id productVariantId quantity unitPrice discountType discountValue discountLabel position
1788
+ createdAt updatedAt
1789
+ }
1317
1790
  }
1318
- `;
1319
- export const CANCEL_MY_QUOTE = cancelMyQuoteDocument(QUOTE_FIELDS);
1320
- export const CANCEL_MY_QUOTE_LEGACY = cancelMyQuoteDocument(QUOTE_FIELDS_LEGACY);
1791
+ `);
1792
+ export const MY_QUOTES = withFragments(
1793
+ /* GraphQL */ `
1794
+ query MyQuotes($options: QuoteListOptions) {
1795
+ myQuotes(options: $options) {
1796
+ items { ...Quote }
1797
+ totalItems
1798
+ }
1799
+ }
1800
+ `, QUOTE_FRAGMENT);
1801
+ export const MY_QUOTES_LEGACY = withFragments(
1802
+ /* GraphQL */ `
1803
+ query MyQuotesLegacy($options: QuoteListOptions) {
1804
+ myQuotes(options: $options) {
1805
+ items { ...QuoteLegacy }
1806
+ totalItems
1807
+ }
1808
+ }
1809
+ `, QUOTE_LEGACY_FRAGMENT);
1810
+ export const MY_QUOTE = withFragments(
1811
+ /* GraphQL */ `
1812
+ query MyQuote($id: ID!) {
1813
+ myQuote(id: $id) { ...Quote }
1814
+ }
1815
+ `, QUOTE_FRAGMENT);
1816
+ export const MY_QUOTE_LEGACY = withFragments(
1817
+ /* GraphQL */ `
1818
+ query MyQuoteLegacy($id: ID!) {
1819
+ myQuote(id: $id) { ...QuoteLegacy }
1820
+ }
1821
+ `, QUOTE_LEGACY_FRAGMENT);
1822
+ export const CREATE_QUOTE_REQUEST = withFragments(
1823
+ /* GraphQL */ `
1824
+ mutation CreateQuoteRequest($input: CreateQuoteRequestInput!) {
1825
+ createQuoteRequest(input: $input) { ...Quote }
1826
+ }
1827
+ `, QUOTE_FRAGMENT);
1828
+ export const CREATE_QUOTE_REQUEST_LEGACY = withFragments(
1829
+ /* GraphQL */ `
1830
+ mutation CreateQuoteRequestLegacy($input: CreateQuoteRequestInput!) {
1831
+ createQuoteRequest(input: $input) { ...QuoteLegacy }
1832
+ }
1833
+ `, QUOTE_LEGACY_FRAGMENT);
1834
+ export const ACCEPT_QUOTE = withFragments(
1835
+ /* GraphQL */ `
1836
+ mutation AcceptQuote($id: ID!) {
1837
+ acceptQuote(id: $id) { ...Order }
1838
+ }
1839
+ `, ORDER_FRAGMENT);
1840
+ export const CANCEL_MY_QUOTE = withFragments(
1841
+ /* GraphQL */ `
1842
+ mutation CancelMyQuote($id: ID!, $reason: String) {
1843
+ cancelMyQuote(id: $id, reason: $reason) { ...Quote }
1844
+ }
1845
+ `, QUOTE_FRAGMENT);
1846
+ export const CANCEL_MY_QUOTE_LEGACY = withFragments(
1847
+ /* GraphQL */ `
1848
+ mutation CancelMyQuoteLegacy($id: ID!, $reason: String) {
1849
+ cancelMyQuote(id: $id, reason: $reason) { ...QuoteLegacy }
1850
+ }
1851
+ `, QUOTE_LEGACY_FRAGMENT);
1321
1852
  /**
1322
1853
  * Single-roundtrip branding query. activeChannel + fontResources (with
1323
1854
  * resolved file Assets) + brandingAssets for the channel-level logo, favicon,
1324
1855
  * and cover IDs already on ctx.channel.customFields.
1325
1856
  */
1326
- export const GET_BRANDING = `
1857
+ export const GET_BRANDING = /* GraphQL */ `
1327
1858
  query GetBranding($ids: [ID!]!) {
1328
1859
  activeChannel {
1329
1860
  id
@@ -1353,7 +1884,7 @@ export const GET_BRANDING = `
1353
1884
  }
1354
1885
  `;
1355
1886
  // --- Order constraints (inline order-constraints plugin) ---
1356
- export const ACTIVE_CHANNEL_ORDER_CONSTRAINTS = `
1887
+ export const ACTIVE_CHANNEL_ORDER_CONSTRAINTS = /* GraphQL */ `
1357
1888
  query ActiveChannelOrderConstraints {
1358
1889
  activeChannelOrderConstraints {
1359
1890
  minOrderAmountGross
@@ -1366,76 +1897,104 @@ export const ACTIVE_CHANNEL_ORDER_CONSTRAINTS = `
1366
1897
  }
1367
1898
  `;
1368
1899
  // --- Customer invoices (vendure-plugin-order-documents shop surface) ---
1369
- export const MY_ORDER_INVOICES = `
1900
+ export const MY_ORDER_INVOICES = /* GraphQL */ `
1370
1901
  query MyOrderInvoices($orderCode: String!) {
1371
1902
  myOrderInvoices(orderCode: $orderCode) {
1372
1903
  id invoiceNumber invoicedOn totalWithTax currencyCode languageCode createdAt
1373
1904
  }
1374
1905
  }
1375
1906
  `;
1376
- export const MY_INVOICE_PDF = `
1907
+ export const MY_INVOICE_PDF = /* GraphQL */ `
1377
1908
  query MyInvoicePdf($invoiceId: ID!) {
1378
1909
  myInvoicePdf(invoiceId: $invoiceId) {
1379
1910
  base64 filename invoiceNumber
1380
1911
  }
1381
1912
  }
1382
1913
  `;
1383
- // --- Order returns (vendure-plugin-returns shop surface) ---
1384
- /**
1385
- * Shared selection set for customer-facing OrderReturn objects. The Shop API
1386
- * never exposes the admin-only fields (`adminNote`, `history`) — do not add
1387
- * them here. Money values are Int minor units.
1388
- */
1389
- const RETURN_FIELDS = `
1390
- id code state
1391
- orderId orderCode currencyCode
1392
- preferredSettlementMethod settlementMethod
1393
- shippingRefundAmount settledAmount
1394
- customerNote requestedAt resolvedAt createdAt
1395
- lines {
1396
- id orderLineId
1397
- productVariantId productVariantName productVariantSku
1398
- requestedQty approvedQty receivedQty restockQty writeOffQty
1399
- reasonCode reasonNote
1400
- unitPriceWithTax unitPriceWithTaxUnrounded refundAmount
1914
+ export const CREATE_INVOICE_DOWNLOAD_URL = /* GraphQL */ `
1915
+ mutation CreateInvoiceDownloadUrl($invoiceId: ID!) {
1916
+ createInvoiceDownloadUrl(invoiceId: $invoiceId) {
1917
+ url expiresAt filename invoiceNumber
1918
+ }
1401
1919
  }
1402
1920
  `;
1403
- export const MY_RETURNS = `
1404
- query MyReturns($take: Int, $skip: Int) {
1405
- myReturns(options: { take: $take, skip: $skip }) {
1406
- items { ${RETURN_FIELDS} }
1407
- totalItems
1921
+ // --- Customer credit notes (vendure-plugin-order-documents shop surface) ---
1922
+ export const MY_ORDER_CREDIT_NOTES = /* GraphQL */ `
1923
+ query MyOrderCreditNotes($orderCode: String!) {
1924
+ myOrderCreditNotes(orderCode: $orderCode) {
1925
+ id creditNoteNumber issuedOn totalWithTax currencyCode kind reason invoiceNumber createdAt
1408
1926
  }
1409
1927
  }
1410
1928
  `;
1411
- export const MY_RETURN = `
1412
- query MyReturn($id: ID!) {
1413
- myReturn(id: $id) { ${RETURN_FIELDS} }
1929
+ export const CREATE_CREDIT_NOTE_DOWNLOAD_URL = /* GraphQL */ `
1930
+ mutation CreateCreditNoteDownloadUrl($creditNoteId: ID!) {
1931
+ createCreditNoteDownloadUrl(creditNoteId: $creditNoteId) {
1932
+ url expiresAt filename creditNoteNumber
1933
+ }
1414
1934
  }
1415
1935
  `;
1416
- export const REQUEST_RETURN = `
1417
- mutation RequestReturn(
1418
- $orderId: ID!
1419
- $lines: [ReturnRequestLineInput!]!
1420
- $customerNote: String
1421
- $preferredSettlementMethod: OrderReturnSettlementMethod
1422
- ) {
1423
- requestReturn(
1424
- input: {
1425
- orderId: $orderId
1426
- lines: $lines
1427
- customerNote: $customerNote
1428
- preferredSettlementMethod: $preferredSettlementMethod
1936
+ // --- Order returns (vendure-plugin-returns shop surface) ---
1937
+ /**
1938
+ * Shared selection set for customer-facing OrderReturn objects. The Shop API
1939
+ * never exposes the admin-only fields (`adminNote`, `history`) — do not add
1940
+ * them here. Money values are Int minor units.
1941
+ */
1942
+ const CUSTOMER_RETURN_FRAGMENT = fragment(/* GraphQL */ `
1943
+ fragment CustomerReturn on OrderReturn {
1944
+ id code state
1945
+ orderId orderCode currencyCode
1946
+ preferredSettlementMethod settlementMethod
1947
+ shippingRefundAmount settledAmount
1948
+ customerNote requestedAt resolvedAt createdAt
1949
+ lines {
1950
+ id orderLineId
1951
+ productVariantId productVariantName productVariantSku
1952
+ requestedQty approvedQty receivedQty restockQty writeOffQty
1953
+ reasonCode reasonNote
1954
+ unitPriceWithTax unitPriceWithTaxUnrounded refundAmount
1955
+ }
1956
+ }
1957
+ `);
1958
+ export const MY_RETURNS = withFragments(
1959
+ /* GraphQL */ `
1960
+ query MyReturns($take: Int, $skip: Int) {
1961
+ myReturns(options: { take: $take, skip: $skip }) {
1962
+ items { ...CustomerReturn }
1963
+ totalItems
1429
1964
  }
1430
- ) { ${RETURN_FIELDS} }
1431
- }
1432
- `;
1433
- export const CANCEL_MY_RETURN = `
1434
- mutation CancelMyReturn($id: ID!) {
1435
- cancelMyReturn(id: $id) { ${RETURN_FIELDS} }
1436
- }
1437
- `;
1438
- export const RETURNABLE_LINES_FOR_ORDER = `
1965
+ }
1966
+ `, CUSTOMER_RETURN_FRAGMENT);
1967
+ export const MY_RETURN = withFragments(
1968
+ /* GraphQL */ `
1969
+ query MyReturn($id: ID!) {
1970
+ myReturn(id: $id) { ...CustomerReturn }
1971
+ }
1972
+ `, CUSTOMER_RETURN_FRAGMENT);
1973
+ export const REQUEST_RETURN = withFragments(
1974
+ /* GraphQL */ `
1975
+ mutation RequestReturn(
1976
+ $orderId: ID!
1977
+ $lines: [ReturnRequestLineInput!]!
1978
+ $customerNote: String
1979
+ $preferredSettlementMethod: OrderReturnSettlementMethod
1980
+ ) {
1981
+ requestReturn(
1982
+ input: {
1983
+ orderId: $orderId
1984
+ lines: $lines
1985
+ customerNote: $customerNote
1986
+ preferredSettlementMethod: $preferredSettlementMethod
1987
+ }
1988
+ ) { ...CustomerReturn }
1989
+ }
1990
+ `, CUSTOMER_RETURN_FRAGMENT);
1991
+ export const CANCEL_MY_RETURN = withFragments(
1992
+ /* GraphQL */ `
1993
+ mutation CancelMyReturn($id: ID!) {
1994
+ cancelMyReturn(id: $id) { ...CustomerReturn }
1995
+ }
1996
+ `, CUSTOMER_RETURN_FRAGMENT);
1997
+ export const RETURNABLE_LINES_FOR_ORDER = /* GraphQL */ `
1439
1998
  query ReturnableLinesForOrder($orderId: ID!) {
1440
1999
  returnableLinesForOrder(orderId: $orderId) {
1441
2000
  orderId eligible reason returnWindowEndsAt