@vendure-platform/create 0.5.0 → 1.0.0-major.202609091053.0.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 (463) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +53 -41
  3. package/dist/add-to-existing.d.ts +19 -13
  4. package/dist/add-to-existing.js +1 -1
  5. package/dist/assets/demo-data/assets/branding/logo.svg +4 -0
  6. package/dist/assets/demo-data/assets/images/absorbent-pad.webp +0 -0
  7. package/dist/assets/demo-data/assets/images/adjustable-wrench.webp +0 -0
  8. package/dist/assets/demo-data/assets/images/anchor-bolt.webp +0 -0
  9. package/dist/assets/demo-data/assets/images/angle-grinder.webp +0 -0
  10. package/dist/assets/demo-data/assets/images/barrier-tape.webp +0 -0
  11. package/dist/assets/demo-data/assets/images/bench-grinder.webp +0 -0
  12. package/dist/assets/demo-data/assets/images/bracket.webp +0 -0
  13. package/dist/assets/demo-data/assets/images/broom.webp +0 -0
  14. package/dist/assets/demo-data/assets/images/bucket.webp +0 -0
  15. package/dist/assets/demo-data/assets/images/cable-gland.webp +0 -0
  16. package/dist/assets/demo-data/assets/images/cable-tie.webp +0 -0
  17. package/dist/assets/demo-data/assets/images/cable-tray.webp +0 -0
  18. package/dist/assets/demo-data/assets/images/cable.webp +0 -0
  19. package/dist/assets/demo-data/assets/images/chimney-base-kit.webp +0 -0
  20. package/dist/assets/demo-data/assets/images/chimney-cowl-bird-guard.webp +0 -0
  21. package/dist/assets/demo-data/assets/images/chimney-cowl-open.webp +0 -0
  22. package/dist/assets/demo-data/assets/images/chimney-storm-collar.webp +0 -0
  23. package/dist/assets/demo-data/assets/images/chimney-wall-bracket.webp +0 -0
  24. package/dist/assets/demo-data/assets/images/circular-saw.webp +0 -0
  25. package/dist/assets/demo-data/assets/images/cleaning-spray.webp +0 -0
  26. package/dist/assets/demo-data/assets/images/conduit.webp +0 -0
  27. package/dist/assets/demo-data/assets/images/cordless-drill.webp +0 -0
  28. package/dist/assets/demo-data/assets/images/drill-bits.webp +0 -0
  29. package/dist/assets/demo-data/assets/images/dust-mask.webp +0 -0
  30. package/dist/assets/demo-data/assets/images/ear-defenders.webp +0 -0
  31. package/dist/assets/demo-data/assets/images/ear-plugs.webp +0 -0
  32. package/dist/assets/demo-data/assets/images/extension-lead.webp +0 -0
  33. package/dist/assets/demo-data/assets/images/eye-wash-station.webp +0 -0
  34. package/dist/assets/demo-data/assets/images/face-shield.webp +0 -0
  35. package/dist/assets/demo-data/assets/images/file-set.webp +0 -0
  36. package/dist/assets/demo-data/assets/images/first-aid-kit.webp +0 -0
  37. package/dist/assets/demo-data/assets/images/floor-sign.webp +0 -0
  38. package/dist/assets/demo-data/assets/images/flue-bend-45.webp +0 -0
  39. package/dist/assets/demo-data/assets/images/flue-bend-90.webp +0 -0
  40. package/dist/assets/demo-data/assets/images/flue-section-1000mm.webp +0 -0
  41. package/dist/assets/demo-data/assets/images/flue-section-250mm.webp +0 -0
  42. package/dist/assets/demo-data/assets/images/flue-section-500mm.webp +0 -0
  43. package/dist/assets/demo-data/assets/images/fuse.webp +0 -0
  44. package/dist/assets/demo-data/assets/images/glove-dispenser.webp +0 -0
  45. package/dist/assets/demo-data/assets/images/grinding-disc.webp +0 -0
  46. package/dist/assets/demo-data/assets/images/hacksaw.webp +0 -0
  47. package/dist/assets/demo-data/assets/images/hammer.webp +0 -0
  48. package/dist/assets/demo-data/assets/images/hand-sanitiser.webp +0 -0
  49. package/dist/assets/demo-data/assets/images/head-torch.webp +0 -0
  50. package/dist/assets/demo-data/assets/images/heat-gun.webp +0 -0
  51. package/dist/assets/demo-data/assets/images/hex-bolt.webp +0 -0
  52. package/dist/assets/demo-data/assets/images/hex-key-set.webp +0 -0
  53. package/dist/assets/demo-data/assets/images/hex-nut.webp +0 -0
  54. package/dist/assets/demo-data/assets/images/hi-vis-jacket.webp +0 -0
  55. package/dist/assets/demo-data/assets/images/hi-vis-vest.webp +0 -0
  56. package/dist/assets/demo-data/assets/images/hose-clamp.webp +0 -0
  57. package/dist/assets/demo-data/assets/images/impact-driver.webp +0 -0
  58. package/dist/assets/demo-data/assets/images/jigsaw.webp +0 -0
  59. package/dist/assets/demo-data/assets/images/junction-box.webp +0 -0
  60. package/dist/assets/demo-data/assets/images/knee-pads.webp +0 -0
  61. package/dist/assets/demo-data/assets/images/machine-screw.webp +0 -0
  62. package/dist/assets/demo-data/assets/images/made-to-order-configurable-chimney.webp +0 -0
  63. package/dist/assets/demo-data/assets/images/mallet.webp +0 -0
  64. package/dist/assets/demo-data/assets/images/mcb.webp +0 -0
  65. package/dist/assets/demo-data/assets/images/mop.webp +0 -0
  66. package/dist/assets/demo-data/assets/images/paper-towels.webp +0 -0
  67. package/dist/assets/demo-data/assets/images/pipe-wrench.webp +0 -0
  68. package/dist/assets/demo-data/assets/images/pliers-set.webp +0 -0
  69. package/dist/assets/demo-data/assets/images/pry-bar.webp +0 -0
  70. package/dist/assets/demo-data/assets/images/rcd.webp +0 -0
  71. package/dist/assets/demo-data/assets/images/reciprocating-saw.webp +0 -0
  72. package/dist/assets/demo-data/assets/images/rivet.webp +0 -0
  73. package/dist/assets/demo-data/assets/images/roof-flashing-high-pitch.webp +0 -0
  74. package/dist/assets/demo-data/assets/images/roof-flashing-low-pitch.webp +0 -0
  75. package/dist/assets/demo-data/assets/images/safety-boots.webp +0 -0
  76. package/dist/assets/demo-data/assets/images/safety-glasses.webp +0 -0
  77. package/dist/assets/demo-data/assets/images/safety-harness.webp +0 -0
  78. package/dist/assets/demo-data/assets/images/safety-helmet.webp +0 -0
  79. package/dist/assets/demo-data/assets/images/safety-sign.webp +0 -0
  80. package/dist/assets/demo-data/assets/images/sanding-disc.webp +0 -0
  81. package/dist/assets/demo-data/assets/images/saw-blade.webp +0 -0
  82. package/dist/assets/demo-data/assets/images/screwdriver-set.webp +0 -0
  83. package/dist/assets/demo-data/assets/images/screwdriver.webp +0 -0
  84. package/dist/assets/demo-data/assets/images/self-tapping-screw.webp +0 -0
  85. package/dist/assets/demo-data/assets/images/socket-set.webp +0 -0
  86. package/dist/assets/demo-data/assets/images/socket.webp +0 -0
  87. package/dist/assets/demo-data/assets/images/spanner-set.webp +0 -0
  88. package/dist/assets/demo-data/assets/images/spanner.webp +0 -0
  89. package/dist/assets/demo-data/assets/images/spill-kit.webp +0 -0
  90. package/dist/assets/demo-data/assets/images/spirit-level.webp +0 -0
  91. package/dist/assets/demo-data/assets/images/switch.webp +0 -0
  92. package/dist/assets/demo-data/assets/images/tape-measure.webp +0 -0
  93. package/dist/assets/demo-data/assets/images/terminal-block.webp +0 -0
  94. package/dist/assets/demo-data/assets/images/threaded-rod.webp +0 -0
  95. package/dist/assets/demo-data/assets/images/torque-wrench.webp +0 -0
  96. package/dist/assets/demo-data/assets/images/utility-knife.webp +0 -0
  97. package/dist/assets/demo-data/assets/images/wall-pass-sleeve.webp +0 -0
  98. package/dist/assets/demo-data/assets/images/wall-plug.webp +0 -0
  99. package/dist/assets/demo-data/assets/images/washer.webp +0 -0
  100. package/dist/assets/demo-data/assets/images/waste-bin.webp +0 -0
  101. package/dist/assets/demo-data/assets/images/wire-connector.webp +0 -0
  102. package/dist/assets/demo-data/assets/images/wire-cutters.webp +0 -0
  103. package/dist/assets/demo-data/assets/images/wood-screw.webp +0 -0
  104. package/dist/assets/demo-data/assets/images/work-gloves.webp +0 -0
  105. package/dist/assets/demo-data/assets/images/work-light.webp +0 -0
  106. package/dist/assets/demo-data/assets/initial-data.json +667 -0
  107. package/dist/assets/demo-data/assets/products.csv +779 -0
  108. package/dist/assets/demo-data/initial-data.json +663 -663
  109. package/dist/assets/storefront/components.json +20 -20
  110. package/dist/assets/storefront/eslint.config.mjs +10 -10
  111. package/dist/assets/storefront/graphql.config.yml +1 -1
  112. package/dist/assets/storefront/next-env.d.ts +2 -1
  113. package/dist/assets/storefront/next.config.ts +19 -17
  114. package/dist/assets/storefront/package.json +3 -2
  115. package/dist/assets/storefront/postcss.config.mjs +1 -1
  116. package/dist/assets/storefront/src/app/[locale]/(catalog)/catalog/page.tsx +17 -21
  117. package/dist/assets/storefront/src/app/[locale]/(catalog)/collection/[slug]/page.tsx +64 -42
  118. package/dist/assets/storefront/src/app/[locale]/(catalog)/layout.tsx +1 -5
  119. package/dist/assets/storefront/src/app/[locale]/(catalog)/product/[slug]/actions.ts +69 -65
  120. package/dist/assets/storefront/src/app/[locale]/(catalog)/product/[slug]/page.tsx +64 -38
  121. package/dist/assets/storefront/src/app/[locale]/(catalog)/search/page.tsx +24 -27
  122. package/dist/assets/storefront/src/app/[locale]/(catalog)/search/search-results.tsx +11 -9
  123. package/dist/assets/storefront/src/app/[locale]/(catalog)/search/search-term.tsx +4 -4
  124. package/dist/assets/storefront/src/app/[locale]/(scenario)/[...path]/page.tsx +1 -1
  125. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/accept-invitation-client.tsx +8 -13
  126. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/actions.ts +11 -14
  127. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/page.tsx +30 -33
  128. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/sign-out-and-retry.tsx +6 -6
  129. package/dist/assets/storefront/src/app/[locale]/account/addresses/actions.ts +30 -45
  130. package/dist/assets/storefront/src/app/[locale]/account/addresses/address-form.tsx +166 -159
  131. package/dist/assets/storefront/src/app/[locale]/account/addresses/addresses-client.tsx +35 -26
  132. package/dist/assets/storefront/src/app/[locale]/account/addresses/loading.tsx +1 -3
  133. package/dist/assets/storefront/src/app/[locale]/account/addresses/page.tsx +18 -18
  134. package/dist/assets/storefront/src/app/[locale]/account/approvals/actions.ts +5 -8
  135. package/dist/assets/storefront/src/app/[locale]/account/approvals/page.tsx +79 -69
  136. package/dist/assets/storefront/src/app/[locale]/account/company/actions.ts +10 -11
  137. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/actions.ts +6 -15
  138. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/address-form.tsx +57 -49
  139. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/addresses-client.tsx +23 -25
  140. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/page.tsx +30 -30
  141. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/actions.ts +20 -29
  142. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/business-unit-form.tsx +32 -37
  143. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/business-units-client.tsx +32 -25
  144. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/page.tsx +26 -24
  145. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/types.ts +7 -4
  146. package/dist/assets/storefront/src/app/[locale]/account/company/edit-company-form.tsx +11 -21
  147. package/dist/assets/storefront/src/app/[locale]/account/company/page.tsx +25 -28
  148. package/dist/assets/storefront/src/app/[locale]/account/company/payment-methods/page.tsx +26 -24
  149. package/dist/assets/storefront/src/app/[locale]/account/company/payment-methods/payment-methods-client.tsx +5 -7
  150. package/dist/assets/storefront/src/app/[locale]/account/company/roles/page.tsx +24 -25
  151. package/dist/assets/storefront/src/app/[locale]/account/company/roles/roles-client.tsx +11 -26
  152. package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/actions.ts +6 -10
  153. package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/page.tsx +18 -16
  154. package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/tax-ids-client.tsx +74 -67
  155. package/dist/assets/storefront/src/app/[locale]/account/company/users/actions.ts +16 -25
  156. package/dist/assets/storefront/src/app/[locale]/account/company/users/edit-user-form.tsx +27 -25
  157. package/dist/assets/storefront/src/app/[locale]/account/company/users/invite-user-form.tsx +27 -19
  158. package/dist/assets/storefront/src/app/[locale]/account/company/users/page.tsx +34 -29
  159. package/dist/assets/storefront/src/app/[locale]/account/company/users/users-client.tsx +35 -38
  160. package/dist/assets/storefront/src/app/[locale]/account/error.tsx +1 -3
  161. package/dist/assets/storefront/src/app/[locale]/account/layout.tsx +16 -22
  162. package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/page.tsx +151 -103
  163. package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/reorder-actions.ts +6 -7
  164. package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/reorder-dialog.tsx +22 -48
  165. package/dist/assets/storefront/src/app/[locale]/account/orders/loading.tsx +8 -8
  166. package/dist/assets/storefront/src/app/[locale]/account/orders/page.tsx +101 -61
  167. package/dist/assets/storefront/src/app/[locale]/account/profile/actions.ts +32 -23
  168. package/dist/assets/storefront/src/app/[locale]/account/profile/change-password-form.tsx +6 -16
  169. package/dist/assets/storefront/src/app/[locale]/account/profile/edit-email-form.tsx +7 -17
  170. package/dist/assets/storefront/src/app/[locale]/account/profile/edit-profile-form.tsx +6 -16
  171. package/dist/assets/storefront/src/app/[locale]/account/profile/loading.tsx +12 -18
  172. package/dist/assets/storefront/src/app/[locale]/account/profile/page.tsx +17 -15
  173. package/dist/assets/storefront/src/app/[locale]/account/quick-order/file-upload-tab.tsx +2 -6
  174. package/dist/assets/storefront/src/app/[locale]/account/quick-order/manual-entry-tab.tsx +18 -15
  175. package/dist/assets/storefront/src/app/[locale]/account/quick-order/page.tsx +5 -6
  176. package/dist/assets/storefront/src/app/[locale]/account/quick-order/preview-table.tsx +10 -2
  177. package/dist/assets/storefront/src/app/[locale]/account/quick-order/save-to-list-dialog.tsx +24 -26
  178. package/dist/assets/storefront/src/app/[locale]/account/quick-order/sku-autocomplete.tsx +19 -10
  179. package/dist/assets/storefront/src/app/[locale]/account/quick-order/text-input-tab.tsx +3 -8
  180. package/dist/assets/storefront/src/app/[locale]/account/quotes/[id]/page.tsx +93 -62
  181. package/dist/assets/storefront/src/app/[locale]/account/quotes/actions.ts +38 -45
  182. package/dist/assets/storefront/src/app/[locale]/account/quotes/new/new-quote-form.tsx +3 -5
  183. package/dist/assets/storefront/src/app/[locale]/account/quotes/new/page.tsx +6 -6
  184. package/dist/assets/storefront/src/app/[locale]/account/quotes/page.tsx +92 -59
  185. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/add-item-search.tsx +11 -9
  186. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/add-member-form.tsx +31 -15
  187. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/members-panel.tsx +52 -33
  188. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/page.tsx +22 -14
  189. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/rename-dialog.tsx +34 -13
  190. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/actions.ts +117 -72
  191. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/new/new-shared-cart-form.tsx +21 -14
  192. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/new/page.tsx +10 -10
  193. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/page.tsx +54 -41
  194. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/[id]/page.tsx +22 -8
  195. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/[id]/shopping-list-detail-client.tsx +62 -49
  196. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/actions.ts +9 -4
  197. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/create-shopping-list-form.tsx +5 -11
  198. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/loading.tsx +1 -1
  199. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/page.tsx +32 -42
  200. package/dist/assets/storefront/src/app/[locale]/account/store-credits/actions.ts +8 -8
  201. package/dist/assets/storefront/src/app/[locale]/account/store-credits/claim-form.tsx +6 -10
  202. package/dist/assets/storefront/src/app/[locale]/account/store-credits/page.tsx +76 -55
  203. package/dist/assets/storefront/src/app/[locale]/account/store-credits/reveal-code.tsx +10 -6
  204. package/dist/assets/storefront/src/app/[locale]/account/verify-email/page.tsx +32 -39
  205. package/dist/assets/storefront/src/app/[locale]/cart/actions.ts +29 -23
  206. package/dist/assets/storefront/src/app/[locale]/cart/cart-items.tsx +111 -40
  207. package/dist/assets/storefront/src/app/[locale]/cart/cart-line-actions.tsx +9 -9
  208. package/dist/assets/storefront/src/app/[locale]/cart/cart-quantity-control.tsx +61 -48
  209. package/dist/assets/storefront/src/app/[locale]/cart/cart-remove-button.tsx +15 -9
  210. package/dist/assets/storefront/src/app/[locale]/cart/cart.tsx +38 -41
  211. package/dist/assets/storefront/src/app/[locale]/cart/code-input.tsx +8 -8
  212. package/dist/assets/storefront/src/app/[locale]/cart/order-summary.tsx +56 -35
  213. package/dist/assets/storefront/src/app/[locale]/cart/page.tsx +11 -11
  214. package/dist/assets/storefront/src/app/[locale]/cart/promotion-code.tsx +56 -47
  215. package/dist/assets/storefront/src/app/[locale]/cart/reapproval-confirm.tsx +22 -20
  216. package/dist/assets/storefront/src/app/[locale]/cart/request-quote-button.tsx +7 -16
  217. package/dist/assets/storefront/src/app/[locale]/checkout/actions.ts +39 -65
  218. package/dist/assets/storefront/src/app/[locale]/checkout/cancel-quote-checkout-button.tsx +5 -5
  219. package/dist/assets/storefront/src/app/[locale]/checkout/checkout-flow.tsx +202 -202
  220. package/dist/assets/storefront/src/app/[locale]/checkout/checkout-provider.tsx +142 -142
  221. package/dist/assets/storefront/src/app/[locale]/checkout/order-summary.tsx +158 -139
  222. package/dist/assets/storefront/src/app/[locale]/checkout/page.tsx +58 -47
  223. package/dist/assets/storefront/src/app/[locale]/checkout/steps/delivery-step.tsx +86 -88
  224. package/dist/assets/storefront/src/app/[locale]/checkout/steps/payment-step.tsx +90 -91
  225. package/dist/assets/storefront/src/app/[locale]/checkout/steps/review-step.tsx +166 -161
  226. package/dist/assets/storefront/src/app/[locale]/checkout/steps/shipping-address-step.tsx +573 -494
  227. package/dist/assets/storefront/src/app/[locale]/error.tsx +3 -5
  228. package/dist/assets/storefront/src/app/[locale]/forgot-password/actions.ts +10 -7
  229. package/dist/assets/storefront/src/app/[locale]/forgot-password/forgot-password-form.tsx +10 -25
  230. package/dist/assets/storefront/src/app/[locale]/forgot-password/page.tsx +5 -5
  231. package/dist/assets/storefront/src/app/[locale]/globals.css +48 -48
  232. package/dist/assets/storefront/src/app/[locale]/layout.tsx +56 -50
  233. package/dist/assets/storefront/src/app/[locale]/not-found.tsx +3 -5
  234. package/dist/assets/storefront/src/app/[locale]/order-confirmation/[code]/order-confirmation.tsx +71 -102
  235. package/dist/assets/storefront/src/app/[locale]/order-confirmation/[code]/page.tsx +7 -5
  236. package/dist/assets/storefront/src/app/[locale]/page.tsx +33 -35
  237. package/dist/assets/storefront/src/app/[locale]/register/actions.ts +7 -7
  238. package/dist/assets/storefront/src/app/[locale]/register/page.tsx +22 -16
  239. package/dist/assets/storefront/src/app/[locale]/register/registration-form.tsx +22 -34
  240. package/dist/assets/storefront/src/app/[locale]/register-company/actions.ts +15 -19
  241. package/dist/assets/storefront/src/app/[locale]/register-company/page.tsx +17 -15
  242. package/dist/assets/storefront/src/app/[locale]/register-company/registration-form.tsx +9 -15
  243. package/dist/assets/storefront/src/app/[locale]/reset-password/actions.ts +7 -8
  244. package/dist/assets/storefront/src/app/[locale]/reset-password/page.tsx +18 -12
  245. package/dist/assets/storefront/src/app/[locale]/reset-password/reset-password-form.tsx +8 -16
  246. package/dist/assets/storefront/src/app/[locale]/shopping-list/[code]/add-to-cart-button.tsx +10 -4
  247. package/dist/assets/storefront/src/app/[locale]/shopping-list/[code]/page.tsx +62 -30
  248. package/dist/assets/storefront/src/app/[locale]/sign-in/actions.ts +14 -16
  249. package/dist/assets/storefront/src/app/[locale]/sign-in/login-form.tsx +17 -30
  250. package/dist/assets/storefront/src/app/[locale]/sign-in/page.tsx +35 -30
  251. package/dist/assets/storefront/src/app/[locale]/verify/actions.ts +8 -8
  252. package/dist/assets/storefront/src/app/[locale]/verify/page.tsx +18 -14
  253. package/dist/assets/storefront/src/app/[locale]/verify/verify-content.tsx +25 -27
  254. package/dist/assets/storefront/src/app/[locale]/verify-pending/page.tsx +23 -23
  255. package/dist/assets/storefront/src/app/api/clear-company-context/route.ts +6 -3
  256. package/dist/assets/storefront/src/app/api/revalidate/route.ts +19 -28
  257. package/dist/assets/storefront/src/app/api/search-analytics/route.ts +1 -1
  258. package/dist/assets/storefront/src/components/commerce/account-nav-items.ts +43 -18
  259. package/dist/assets/storefront/src/components/commerce/account-sidebar.tsx +30 -22
  260. package/dist/assets/storefront/src/components/commerce/active-filters.tsx +1 -1
  261. package/dist/assets/storefront/src/components/commerce/add-to-shared-cart.tsx +49 -27
  262. package/dist/assets/storefront/src/components/commerce/approval-decision-form.tsx +9 -13
  263. package/dist/assets/storefront/src/components/commerce/approval-status-badge.tsx +23 -15
  264. package/dist/assets/storefront/src/components/commerce/business-unit-switcher.tsx +11 -11
  265. package/dist/assets/storefront/src/components/commerce/catalog-search-bar.tsx +2 -2
  266. package/dist/assets/storefront/src/components/commerce/category-product-section.tsx +28 -16
  267. package/dist/assets/storefront/src/components/commerce/category-sidebar.tsx +31 -18
  268. package/dist/assets/storefront/src/components/commerce/collection-hero-banner.tsx +2 -4
  269. package/dist/assets/storefront/src/components/commerce/company-state-badge.tsx +10 -16
  270. package/dist/assets/storefront/src/components/commerce/company-switcher.tsx +12 -12
  271. package/dist/assets/storefront/src/components/commerce/configurator-form.tsx +188 -79
  272. package/dist/assets/storefront/src/components/commerce/facet-filters.tsx +29 -49
  273. package/dist/assets/storefront/src/components/commerce/gift-card-pdp.tsx +4 -4
  274. package/dist/assets/storefront/src/components/commerce/gift-card-product-info.tsx +20 -30
  275. package/dist/assets/storefront/src/components/commerce/instant-search-dropdown.tsx +258 -227
  276. package/dist/assets/storefront/src/components/commerce/order-status-badge.tsx +27 -19
  277. package/dist/assets/storefront/src/components/commerce/packaging-unit-selector.tsx +27 -26
  278. package/dist/assets/storefront/src/components/commerce/permission-gate.tsx +4 -4
  279. package/dist/assets/storefront/src/components/commerce/price-range-filter.tsx +5 -5
  280. package/dist/assets/storefront/src/components/commerce/price-tiers.tsx +38 -21
  281. package/dist/assets/storefront/src/components/commerce/price.tsx +3 -3
  282. package/dist/assets/storefront/src/components/commerce/product-card-list.tsx +39 -16
  283. package/dist/assets/storefront/src/components/commerce/product-card.tsx +35 -18
  284. package/dist/assets/storefront/src/components/commerce/product-carousel.tsx +20 -12
  285. package/dist/assets/storefront/src/components/commerce/product-grid.tsx +14 -13
  286. package/dist/assets/storefront/src/components/commerce/product-image-carousel.tsx +10 -8
  287. package/dist/assets/storefront/src/components/commerce/product-info.tsx +118 -74
  288. package/dist/assets/storefront/src/components/commerce/product-list-expansion.tsx +102 -74
  289. package/dist/assets/storefront/src/components/commerce/product-list-view.tsx +1 -1
  290. package/dist/assets/storefront/src/components/commerce/product-sidebar.tsx +36 -11
  291. package/dist/assets/storefront/src/components/commerce/product-view-switcher.tsx +33 -21
  292. package/dist/assets/storefront/src/components/commerce/quote-action-buttons.tsx +80 -45
  293. package/dist/assets/storefront/src/components/commerce/quote-activity-timeline.tsx +126 -50
  294. package/dist/assets/storefront/src/components/commerce/quote-comment-form.tsx +9 -13
  295. package/dist/assets/storefront/src/components/commerce/quote-csv-export-button.tsx +6 -6
  296. package/dist/assets/storefront/src/components/commerce/quote-product-search.tsx +22 -18
  297. package/dist/assets/storefront/src/components/commerce/quote-request-form.tsx +28 -27
  298. package/dist/assets/storefront/src/components/commerce/quote-status-badge.tsx +26 -18
  299. package/dist/assets/storefront/src/components/commerce/quote-validity-indicator.tsx +7 -7
  300. package/dist/assets/storefront/src/components/commerce/quote-version-comparison.tsx +50 -30
  301. package/dist/assets/storefront/src/components/commerce/related-products.tsx +37 -28
  302. package/dist/assets/storefront/src/components/commerce/shared-cart-status-badge.tsx +12 -8
  303. package/dist/assets/storefront/src/components/commerce/shop-by-category.tsx +8 -7
  304. package/dist/assets/storefront/src/components/commerce/shopping-list-toggle.tsx +14 -20
  305. package/dist/assets/storefront/src/components/commerce/sort-dropdown.tsx +9 -16
  306. package/dist/assets/storefront/src/components/commerce/store-credit-summary.tsx +30 -32
  307. package/dist/assets/storefront/src/components/commerce/subcollection-tiles.tsx +11 -13
  308. package/dist/assets/storefront/src/components/layout/auth-page-shell.tsx +2 -2
  309. package/dist/assets/storefront/src/components/layout/draft-mode-indicator.tsx +2 -7
  310. package/dist/assets/storefront/src/components/layout/draft-mode-link.tsx +4 -2
  311. package/dist/assets/storefront/src/components/layout/footer.tsx +70 -28
  312. package/dist/assets/storefront/src/components/layout/navbar/actions.ts +9 -12
  313. package/dist/assets/storefront/src/components/layout/navbar/cart-icon.tsx +9 -9
  314. package/dist/assets/storefront/src/components/layout/navbar/channel-picker-wrapper.tsx +4 -9
  315. package/dist/assets/storefront/src/components/layout/navbar/channel-picker.tsx +13 -8
  316. package/dist/assets/storefront/src/components/layout/navbar/currency-picker-wrapper.tsx +4 -4
  317. package/dist/assets/storefront/src/components/layout/navbar/currency-picker.tsx +11 -6
  318. package/dist/assets/storefront/src/components/layout/navbar/language-picker.tsx +7 -7
  319. package/dist/assets/storefront/src/components/layout/navbar/login-button.tsx +24 -21
  320. package/dist/assets/storefront/src/components/layout/navbar/mobile-nav.tsx +8 -8
  321. package/dist/assets/storefront/src/components/layout/navbar/nav-menu-items.tsx +4 -6
  322. package/dist/assets/storefront/src/components/layout/navbar/navbar-cart.tsx +1 -1
  323. package/dist/assets/storefront/src/components/layout/navbar/navbar-collections.tsx +41 -42
  324. package/dist/assets/storefront/src/components/layout/navbar/navbar-link.tsx +7 -10
  325. package/dist/assets/storefront/src/components/layout/navbar/navbar-user.tsx +18 -23
  326. package/dist/assets/storefront/src/components/layout/navbar/theme-switcher.tsx +9 -9
  327. package/dist/assets/storefront/src/components/layout/navbar.tsx +36 -31
  328. package/dist/assets/storefront/src/components/layout/search-input.tsx +35 -32
  329. package/dist/assets/storefront/src/components/providers/awaiting-approval-banner.tsx +12 -10
  330. package/dist/assets/storefront/src/components/providers/cart-count-server.tsx +14 -12
  331. package/dist/assets/storefront/src/components/providers/company-context-guard.tsx +4 -4
  332. package/dist/assets/storefront/src/components/providers/company-permissions-server.tsx +2 -6
  333. package/dist/assets/storefront/src/components/providers/theme-provider.tsx +3 -3
  334. package/dist/assets/storefront/src/components/shared/breadcrumbs.tsx +4 -1
  335. package/dist/assets/storefront/src/components/shared/country-select.tsx +63 -67
  336. package/dist/assets/storefront/src/components/shared/pagination.tsx +15 -28
  337. package/dist/assets/storefront/src/components/shared/prefetch-link.tsx +1 -1
  338. package/dist/assets/storefront/src/components/shared/skeletons/search-input-skeleton.tsx +1 -3
  339. package/dist/assets/storefront/src/components/ui/accordion.tsx +46 -51
  340. package/dist/assets/storefront/src/components/ui/alert-dialog.tsx +94 -121
  341. package/dist/assets/storefront/src/components/ui/alert.tsx +48 -54
  342. package/dist/assets/storefront/src/components/ui/aspect-ratio.tsx +5 -7
  343. package/dist/assets/storefront/src/components/ui/avatar.tsx +29 -44
  344. package/dist/assets/storefront/src/components/ui/badge.tsx +28 -37
  345. package/dist/assets/storefront/src/components/ui/breadcrumb.tsx +82 -89
  346. package/dist/assets/storefront/src/components/ui/button.tsx +43 -49
  347. package/dist/assets/storefront/src/components/ui/calendar.tsx +157 -198
  348. package/dist/assets/storefront/src/components/ui/card.tsx +53 -76
  349. package/dist/assets/storefront/src/components/ui/carousel.tsx +194 -212
  350. package/dist/assets/storefront/src/components/ui/chart.tsx +274 -317
  351. package/dist/assets/storefront/src/components/ui/checkbox.tsx +24 -27
  352. package/dist/assets/storefront/src/components/ui/collapsible.tsx +9 -21
  353. package/dist/assets/storefront/src/components/ui/command.tsx +114 -159
  354. package/dist/assets/storefront/src/components/ui/context-menu.tsx +167 -199
  355. package/dist/assets/storefront/src/components/ui/dialog.tsx +97 -114
  356. package/dist/assets/storefront/src/components/ui/drawer.tsx +93 -107
  357. package/dist/assets/storefront/src/components/ui/dropdown-menu.tsx +171 -206
  358. package/dist/assets/storefront/src/components/ui/empty-state.tsx +5 -5
  359. package/dist/assets/storefront/src/components/ui/field.tsx +196 -208
  360. package/dist/assets/storefront/src/components/ui/form.tsx +115 -139
  361. package/dist/assets/storefront/src/components/ui/hover-card.tsx +27 -33
  362. package/dist/assets/storefront/src/components/ui/input-otp.tsx +50 -59
  363. package/dist/assets/storefront/src/components/ui/input.tsx +17 -17
  364. package/dist/assets/storefront/src/components/ui/kbd-shortcut.tsx +3 -1
  365. package/dist/assets/storefront/src/components/ui/label.tsx +16 -19
  366. package/dist/assets/storefront/src/components/ui/menubar.tsx +193 -223
  367. package/dist/assets/storefront/src/components/ui/navigation-menu.tsx +123 -130
  368. package/dist/assets/storefront/src/components/ui/pagination.tsx +87 -108
  369. package/dist/assets/storefront/src/components/ui/popover.tsx +29 -35
  370. package/dist/assets/storefront/src/components/ui/progress.tsx +19 -26
  371. package/dist/assets/storefront/src/components/ui/radio-group.tsx +32 -38
  372. package/dist/assets/storefront/src/components/ui/resizable.tsx +37 -42
  373. package/dist/assets/storefront/src/components/ui/scroll-area.tsx +41 -47
  374. package/dist/assets/storefront/src/components/ui/select.tsx +130 -152
  375. package/dist/assets/storefront/src/components/ui/separator.tsx +21 -21
  376. package/dist/assets/storefront/src/components/ui/sheet.tsx +90 -111
  377. package/dist/assets/storefront/src/components/ui/sidebar.tsx +611 -649
  378. package/dist/assets/storefront/src/components/ui/skeleton.tsx +10 -10
  379. package/dist/assets/storefront/src/components/ui/slider.tsx +50 -55
  380. package/dist/assets/storefront/src/components/ui/sonner.tsx +20 -20
  381. package/dist/assets/storefront/src/components/ui/switch.tsx +23 -26
  382. package/dist/assets/storefront/src/components/ui/table.tsx +65 -97
  383. package/dist/assets/storefront/src/components/ui/tabs.tsx +39 -55
  384. package/dist/assets/storefront/src/components/ui/textarea.tsx +14 -14
  385. package/dist/assets/storefront/src/components/ui/toggle-group.tsx +56 -62
  386. package/dist/assets/storefront/src/components/ui/toggle.tsx +37 -38
  387. package/dist/assets/storefront/src/components/ui/tooltip.tsx +38 -46
  388. package/dist/assets/storefront/src/config/capabilities.ts +41 -0
  389. package/dist/assets/storefront/src/config/scenario-meta.ts +2 -2
  390. package/dist/assets/storefront/src/config/scenario.ts +24 -16
  391. package/dist/assets/storefront/src/contexts/auth-context.tsx +5 -6
  392. package/dist/assets/storefront/src/graphql-env.d.ts +47 -41
  393. package/dist/assets/storefront/src/graphql.ts +5 -5
  394. package/dist/assets/storefront/src/hooks/use-mobile.ts +13 -13
  395. package/dist/assets/storefront/src/i18n/locale-utils.ts +3 -3
  396. package/dist/assets/storefront/src/i18n/navigation.ts +4 -4
  397. package/dist/assets/storefront/src/i18n/request.ts +4 -4
  398. package/dist/assets/storefront/src/i18n/routing.ts +5 -5
  399. package/dist/assets/storefront/src/i18n/server.ts +35 -7
  400. package/dist/assets/storefront/src/lib/actions/switch-channel.ts +9 -9
  401. package/dist/assets/storefront/src/lib/actions/switch-currency.ts +7 -7
  402. package/dist/assets/storefront/src/lib/auth.ts +1 -1
  403. package/dist/assets/storefront/src/lib/backend-health.ts +14 -6
  404. package/dist/assets/storefront/src/lib/cart-count-context.tsx +10 -4
  405. package/dist/assets/storefront/src/lib/cart-guard-utils.ts +2 -1
  406. package/dist/assets/storefront/src/lib/cart-guard.ts +7 -6
  407. package/dist/assets/storefront/src/lib/channel-server.ts +4 -4
  408. package/dist/assets/storefront/src/lib/company-context.ts +1 -1
  409. package/dist/assets/storefront/src/lib/company-permissions-context.tsx +1 -5
  410. package/dist/assets/storefront/src/lib/currency-server.ts +4 -4
  411. package/dist/assets/storefront/src/lib/format.ts +16 -7
  412. package/dist/assets/storefront/src/lib/metadata.ts +39 -44
  413. package/dist/assets/storefront/src/lib/quantity.ts +2 -4
  414. package/dist/assets/storefront/src/lib/search-bar-context.tsx +7 -4
  415. package/dist/assets/storefront/src/lib/use-recent-searches.ts +8 -6
  416. package/dist/assets/storefront/src/lib/utils.ts +3 -3
  417. package/dist/assets/storefront/src/lib/vendure/actions.ts +18 -16
  418. package/dist/assets/storefront/src/lib/vendure/api.ts +36 -23
  419. package/dist/assets/storefront/src/lib/vendure/approval-utils.ts +9 -8
  420. package/dist/assets/storefront/src/lib/vendure/cached.ts +20 -15
  421. package/dist/assets/storefront/src/lib/vendure/capability-documents.ts +246 -0
  422. package/dist/assets/storefront/src/lib/vendure/capability-schema.ts +358 -0
  423. package/dist/assets/storefront/src/lib/vendure/capability-ui.ts +15 -0
  424. package/dist/assets/storefront/src/lib/vendure/mutations.ts +835 -532
  425. package/dist/assets/storefront/src/lib/vendure/queries.ts +877 -524
  426. package/dist/assets/storefront/src/proxy.ts +11 -0
  427. package/dist/assets/storefront/src/scenarios/customer/hero.tsx +2 -2
  428. package/dist/assets/storefront/src/scenarios/customer/meta.ts +1 -1
  429. package/dist/assets/storefront/src/schema.graphql +337 -243
  430. package/dist/assets/templates/README.md.hbs +25 -1
  431. package/dist/assets/templates/docker-compose.yml.hbs +4 -0
  432. package/dist/assets/templates/env.hbs +34 -9
  433. package/dist/assets/templates/environment.d.ts.hbs +1 -0
  434. package/dist/assets/templates/gitignore.hbs +7 -4
  435. package/dist/assets/templates/migrate.ts.hbs +55 -0
  436. package/dist/assets/templates/npmrc.hbs +7 -2
  437. package/dist/assets/templates/platform-edition.ts.hbs +21 -0
  438. package/dist/assets/templates/server-package.json.hbs +15 -8
  439. package/dist/assets/templates/vendure-config.ts.hbs +18 -0
  440. package/dist/bin/run.js +1 -1
  441. package/dist/cli.d.ts +1 -1
  442. package/dist/cli.js +1 -1
  443. package/dist/console-onboarding.d.ts +44 -0
  444. package/dist/console-onboarding.js +1 -0
  445. package/dist/hub-projects.d.ts +48 -0
  446. package/dist/hub-projects.js +1 -0
  447. package/dist/index.d.ts +5 -5
  448. package/dist/index.js +1 -1
  449. package/dist/plugin-registry.d.ts +61 -2
  450. package/dist/plugin-registry.js +1 -1
  451. package/dist/registry.d.ts +16 -13
  452. package/dist/registry.js +1 -1
  453. package/dist/scaffold-shared.js +1 -1
  454. package/dist/scaffold-storefront-only.js +1 -1
  455. package/dist/scaffolder.d.ts +11 -0
  456. package/dist/scaffolder.js +1 -1
  457. package/dist/storefront-copier.d.ts +7 -2
  458. package/dist/storefront-copier.js +1 -1
  459. package/dist/template-renderer.d.ts +26 -5
  460. package/dist/template-renderer.js +1 -1
  461. package/dist/types.d.ts +54 -23
  462. package/package.json +14 -2
  463. package/dist/assets/storefront/src/middleware.ts +0 -11
@@ -4,11 +4,11 @@ import type { introspection } from './graphql-env.d.ts';
4
4
  export const graphql = initGraphQLTada<{
5
5
  introspection: introspection;
6
6
  scalars: {
7
- DateTime: string,
8
- JSON: Record<string, unknown>,
9
- Money: number
10
- }
7
+ DateTime: string;
8
+ JSON: Record<string, unknown>;
9
+ Money: number;
10
+ };
11
11
  }>();
12
12
 
13
+ export { readFragment } from 'gql.tada';
13
14
  export type { FragmentOf, ResultOf, VariablesOf } from 'gql.tada';
14
- export { readFragment } from 'gql.tada';
@@ -1,19 +1,19 @@
1
- import * as React from "react"
1
+ import * as React from 'react';
2
2
 
3
- const MOBILE_BREAKPOINT = 768
3
+ const MOBILE_BREAKPOINT = 768;
4
4
 
5
5
  export function useIsMobile() {
6
- const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);
7
7
 
8
- React.useEffect(() => {
9
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
- const onChange = () => {
11
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
- }
13
- mql.addEventListener("change", onChange)
14
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
- return () => mql.removeEventListener("change", onChange)
16
- }, [])
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
12
+ };
13
+ mql.addEventListener('change', onChange);
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
15
+ return () => mql.removeEventListener('change', onChange);
16
+ }, []);
17
17
 
18
- return !!isMobile
18
+ return !!isMobile;
19
19
  }
@@ -1,7 +1,7 @@
1
- import {routing, type Locale} from './routing';
1
+ import { routing, type Locale } from './routing';
2
2
 
3
- const INTL_LOCALE_MAP: Record<Locale, string> = {en: 'en-US', de: 'de-DE'};
4
- const OG_LOCALE_MAP: Record<Locale, string> = {en: 'en_US', de: 'de_DE'};
3
+ const INTL_LOCALE_MAP: Record<Locale, string> = { en: 'en-US', de: 'de-DE' };
4
+ const OG_LOCALE_MAP: Record<Locale, string> = { en: 'en_US', de: 'de_DE' };
5
5
 
6
6
  /** Map a routing locale to a full BCP-47 tag for Intl APIs. Falls back to the raw locale. */
7
7
  export function toIntlLocale(locale: string): string {
@@ -1,5 +1,5 @@
1
- import {createNavigation} from 'next-intl/navigation';
2
- import {routing} from './routing';
1
+ import { createNavigation } from 'next-intl/navigation';
2
+ import { routing } from './routing';
3
3
 
4
4
  const nav = createNavigation(routing);
5
5
 
@@ -29,7 +29,7 @@ export const getPathname = nav.getPathname;
29
29
  * bundling since this module also exports Link).
30
30
  */
31
31
  export async function redirect(pathname: string, type?: 'push' | 'replace'): Promise<never> {
32
- const {getLocale} = await import('next-intl/server');
32
+ const { getLocale } = await import('next-intl/server');
33
33
  const locale = await getLocale();
34
- return nav.redirect({href: pathname, locale}, type);
34
+ return nav.redirect({ href: pathname, locale }, type);
35
35
  }
@@ -1,6 +1,6 @@
1
- import {hasLocale} from 'next-intl';
2
- import {getRequestConfig} from 'next-intl/server';
3
- import {routing} from './routing';
1
+ import { hasLocale } from 'next-intl';
2
+ import { getRequestConfig } from 'next-intl/server';
3
+ import { routing } from './routing';
4
4
 
5
5
  // Static per-locale imports. When adding a new locale to routing.locales,
6
6
  // add a corresponding entry here.
@@ -9,7 +9,7 @@ const messageImports = {
9
9
  de: () => import('../../messages/de.json'),
10
10
  } as const;
11
11
 
12
- export default getRequestConfig(async ({requestLocale}) => {
12
+ export default getRequestConfig(async ({ requestLocale }) => {
13
13
  const requested = await requestLocale;
14
14
  const locale = hasLocale(routing.locales, requested) ? requested : routing.defaultLocale;
15
15
  return {
@@ -1,6 +1,6 @@
1
- import {defineRouting} from 'next-intl/routing';
2
- import {getScenarioMeta} from '@/config/scenario-meta';
3
- import {LOCALES, type Locale, localeNames} from './locales';
1
+ import { getScenarioMeta } from '@/config/scenario-meta';
2
+ import { defineRouting } from 'next-intl/routing';
3
+ import { LOCALES, type Locale, localeNames } from './locales';
4
4
 
5
5
  // Scenarios declare their preferred default locale in their own
6
6
  // `meta.ts` (a client-safe projection that never imports React or
@@ -15,5 +15,5 @@ export const routing = defineRouting({
15
15
  defaultLocale: scenarioDefaultLocale,
16
16
  });
17
17
 
18
- export type {Locale};
19
- export {localeNames};
18
+ export { localeNames };
19
+ export type { Locale };
@@ -1,16 +1,44 @@
1
- import {getLocale} from 'next-intl/server';
2
- import {hasLocale} from 'next-intl';
3
- import {routing, type Locale} from './routing';
1
+ import { hasLocale } from 'next-intl';
2
+ import { getLocale, setRequestLocale } from 'next-intl/server';
3
+ import { locale as rootLocale } from 'next/root-params';
4
+ import { routing, type Locale } from './routing';
4
5
 
5
6
  /**
6
- * Resolve the current locale from request context with validation.
7
+ * Resolve the current locale from the `[locale]` root param, with validation.
8
+ * Falls back to defaultLocale if the segment isn't in routing config.
9
+ *
10
+ * This is the default on the server, including 'use cache' scopes. Root params
11
+ * carry no request state, so a component that resolves the locale this way
12
+ * still prerenders.
13
+ */
14
+ export async function getRootLocale(): Promise<Locale> {
15
+ const loc = await rootLocale();
16
+ return hasLocale(routing.locales, loc) ? (loc as Locale) : routing.defaultLocale;
17
+ }
18
+
19
+ /**
20
+ * Resolve the current locale from request context, with validation.
7
21
  * Falls back to defaultLocale if the resolved locale isn't in routing config.
8
22
  *
9
- * Use this in non-cached server components and server actions.
10
- * For 'use cache' scopes or route files (layout/page), prefer rootLocale()
11
- * from 'next/root-params' directly (the SWC transform only works in route files).
23
+ * Only for scopes root params cannot reach: Client Components, Server Actions
24
+ * and Route Handlers, plus server code that already renders dynamically.
25
+ * Reading request state blocks prerendering, so a Server Component that calls
26
+ * this serves no static shell — call `getRootLocale()` there instead.
12
27
  */
13
28
  export async function getRouteLocale(): Promise<Locale> {
14
29
  const loc = await getLocale();
15
30
  return hasLocale(routing.locales, loc) ? (loc as Locale) : routing.defaultLocale;
16
31
  }
32
+
33
+ /**
34
+ * Pin the `[locale]` root param as next-intl's request locale.
35
+ *
36
+ * Call this before the first next-intl call in a Server Component that does not
37
+ * already pin the locale from `params`. Without it, `getTranslations()` resolves
38
+ * the locale through next-intl's request scope, which under `cacheComponents` is
39
+ * uncached request state: the route then fails `next build --debug-prerender`
40
+ * and serves no static shell.
41
+ */
42
+ export async function pinRootLocale(): Promise<void> {
43
+ setRequestLocale(await getRootLocale());
44
+ }
@@ -1,18 +1,18 @@
1
1
  'use server';
2
2
 
3
- import {cookies} from 'next/headers';
4
- import {revalidatePath} from 'next/cache';
5
- import {CHANNEL_COOKIE} from '@/lib/channel';
6
- import {CURRENCY_COOKIE} from '@/lib/currency';
7
- import {getChannelsConfig} from '@/config/scenario';
3
+ import { getChannelsConfig } from '@/config/scenario';
4
+ import { CHANNEL_COOKIE } from '@/lib/channel';
5
+ import { CURRENCY_COOKIE } from '@/lib/currency';
6
+ import { revalidatePath } from 'next/cache';
7
+ import { cookies } from 'next/headers';
8
8
 
9
9
  export async function switchChannel(token: string) {
10
10
  const channelsConfig = getChannelsConfig();
11
11
  if (!channelsConfig) {
12
- return {success: false, message: 'Channel switching not configured'};
12
+ return { success: false, message: 'Channel switching not configured' };
13
13
  }
14
- if (!channelsConfig.available.some(c => c.token === token)) {
15
- return {success: false, message: 'Invalid channel token'};
14
+ if (!channelsConfig.available.some((c) => c.token === token)) {
15
+ return { success: false, message: 'Invalid channel token' };
16
16
  }
17
17
 
18
18
  const jar = await cookies();
@@ -28,5 +28,5 @@ export async function switchChannel(token: string) {
28
28
  jar.delete(CURRENCY_COOKIE);
29
29
 
30
30
  revalidatePath('/', 'layout');
31
- return {success: true};
31
+ return { success: true };
32
32
  }
@@ -1,16 +1,16 @@
1
1
  'use server';
2
2
 
3
- import {cookies} from 'next/headers';
4
- import {revalidatePath} from 'next/cache';
5
- import {CURRENCY_COOKIE} from '@/lib/currency';
6
- import {getActiveChannelCached} from '@/lib/vendure/cached';
3
+ import { CURRENCY_COOKIE } from '@/lib/currency';
4
+ import { getActiveChannelCached } from '@/lib/vendure/cached';
5
+ import { revalidatePath } from 'next/cache';
6
+ import { cookies } from 'next/headers';
7
7
 
8
8
  export async function switchCurrency(currencyCode: string) {
9
- const {getActiveChannelToken} = await import('@/lib/channel-server');
9
+ const { getActiveChannelToken } = await import('@/lib/channel-server');
10
10
  const channelToken = await getActiveChannelToken();
11
11
  const channel = await getActiveChannelCached(channelToken);
12
12
  if (!channel.availableCurrencyCodes.includes(currencyCode as never)) {
13
- return {success: false, message: 'Invalid currency code'};
13
+ return { success: false, message: 'Invalid currency code' };
14
14
  }
15
15
 
16
16
  const jar = await cookies();
@@ -21,5 +21,5 @@ export async function switchCurrency(currencyCode: string) {
21
21
  });
22
22
 
23
23
  revalidatePath('/', 'layout');
24
- return {success: true};
24
+ return { success: true };
25
25
  }
@@ -1,4 +1,4 @@
1
- import {cookies} from 'next/headers';
1
+ import { cookies } from 'next/headers';
2
2
 
3
3
  const AUTH_TOKEN_COOKIE = process.env.VENDURE_AUTH_TOKEN_COOKIE || 'vendure-auth-token';
4
4
 
@@ -1,4 +1,4 @@
1
- import {cacheLife} from 'next/cache';
1
+ import { cacheLife } from 'next/cache';
2
2
 
3
3
  const HEALTH_CHECK_TIMEOUT_MS = 3000;
4
4
 
@@ -10,12 +10,20 @@ const HEALTH_CHECK_TIMEOUT_MS = 3000;
10
10
  * on Vercel) but every API call fails, leaving the user with a branded but
11
11
  * empty shell. When this returns false we render a "Demo Paused" page instead.
12
12
  *
13
- * Cached for 15s (cacheLife('seconds')) so a stop/start of the backend is
14
- * reflected quickly without hammering the API on every request.
13
+ * This is cacheLife('seconds') with one field changed: `expire` goes from 60 to
14
+ * 300. The preset's 60s expire is too short for Next 16.3's build-time cache,
15
+ * which drops the entry between the cache-warming phase and the final prerender
16
+ * phase, and every prerendered page that mounts this gate then logs an
17
+ * "Unexpected cache miss" during `next build`. Measured on 16.3: expire 300 is
18
+ * retained, 120 is not.
19
+ *
20
+ * `stale` and `revalidate` keep the preset's values, so how fast a stop/start of
21
+ * the backend is picked up is unchanged. `expire` only bounds how long a stale
22
+ * value may be served when revalidation never runs.
15
23
  */
16
24
  export async function isBackendReachable(): Promise<boolean> {
17
25
  'use cache';
18
- cacheLife('seconds');
26
+ cacheLife({ stale: 30, revalidate: 1, expire: 300 });
19
27
 
20
28
  const apiUrl = process.env.VENDURE_SHOP_API_URL || process.env.NEXT_PUBLIC_VENDURE_SHOP_API_URL;
21
29
  if (!apiUrl) return true;
@@ -25,8 +33,8 @@ export async function isBackendReachable(): Promise<boolean> {
25
33
  try {
26
34
  const res = await fetch(apiUrl, {
27
35
  method: 'POST',
28
- headers: {'Content-Type': 'application/json'},
29
- body: JSON.stringify({query: '{ __typename }'}),
36
+ headers: { 'Content-Type': 'application/json' },
37
+ body: JSON.stringify({ query: '{ __typename }' }),
30
38
  signal: controller.signal,
31
39
  });
32
40
  return res.ok;
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { createContext, useContext, useState, useCallback, useEffect } from 'react';
3
+ import { createContext, useCallback, useContext, useEffect, useState } from 'react';
4
4
 
5
5
  interface CartCountContextType {
6
6
  count: number;
@@ -13,11 +13,17 @@ interface CartCountContextType {
13
13
 
14
14
  const CartCountContext = createContext<CartCountContextType | null>(null);
15
15
 
16
- export function CartCountProvider({ initialCount, children }: { initialCount: number; children: React.ReactNode }) {
16
+ export function CartCountProvider({
17
+ initialCount,
18
+ children,
19
+ }: {
20
+ initialCount: number;
21
+ children: React.ReactNode;
22
+ }) {
17
23
  const [count, setCount] = useState(initialCount);
18
24
  const [awaitingApprovalOrderCode, setAwaitingApprovalOrderCode] = useState<string | null>(null);
19
- const increment = useCallback(() => setCount(c => c + 1), []);
20
- const decrement = useCallback(() => setCount(c => Math.max(0, c - 1)), []);
25
+ const increment = useCallback(() => setCount((c) => c + 1), []);
26
+ const decrement = useCallback(() => setCount((c) => Math.max(0, c - 1)), []);
21
27
 
22
28
  return (
23
29
  <CartCountContext.Provider
@@ -6,5 +6,6 @@ import type { CartGuardResult } from './cart-guard';
6
6
  */
7
7
  export function getGuardError(guard: CartGuardResult): string | undefined {
8
8
  if (guard.blocked) return 'Order is awaiting approval and cannot be modified';
9
- if (guard.quoteLocked) return 'You have a quote checkout in progress. Complete checkout or cancel the quote checkout to modify your cart.';
9
+ if (guard.quoteLocked)
10
+ return 'You have a quote checkout in progress. Complete checkout or cancel the quote checkout to modify your cart.';
10
11
  }
@@ -1,8 +1,8 @@
1
1
  'use server';
2
2
 
3
3
  import { client } from '@/lib/vendure/api';
4
- import { GetActiveOrderQuery, GetApprovalHistoryForEntityQuery } from '@/lib/vendure/queries';
5
4
  import { TransitionOrderToStateMutation } from '@/lib/vendure/mutations';
5
+ import { GetActiveOrderQuery, GetApprovalHistoryForEntityQuery } from '@/lib/vendure/queries';
6
6
 
7
7
  export interface CartGuardResult {
8
8
  /** Whether the order was in a non-AddingItems state and had to be transitioned */
@@ -23,12 +23,13 @@ export interface CartGuardResult {
23
23
  * and the full cart guard.
24
24
  */
25
25
  async function checkOrderApprovalStatus(orderId: string): Promise<boolean> {
26
- const [approvalResult] = await client.query(
27
- GetApprovalHistoryForEntityQuery,
28
- { entityType: 'Order', entityId: orderId },
26
+ const [approvalResult] = await client.query(GetApprovalHistoryForEntityQuery, {
27
+ entityType: 'Order',
28
+ entityId: orderId,
29
+ });
30
+ const history = [...(approvalResult?.data?.approvalHistoryForEntity ?? [])].sort(
31
+ (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
29
32
  );
30
- const history = [...(approvalResult?.data?.approvalHistoryForEntity ?? [])]
31
- .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
32
33
  const latestApproval = history[0] ?? null;
33
34
  return latestApproval?.status === 'APPROVED';
34
35
  }
@@ -1,6 +1,6 @@
1
- import {cookies} from 'next/headers';
2
- import {CHANNEL_COOKIE} from './channel';
3
- import {getChannelsConfig} from '@/config/scenario';
1
+ import { getChannelsConfig } from '@/config/scenario';
2
+ import { cookies } from 'next/headers';
3
+ import { CHANNEL_COOKIE } from './channel';
4
4
 
5
5
  const FALLBACK_TOKEN = process.env.VENDURE_CHANNEL_TOKEN || process.env.NEXT_PUBLIC_VENDURE_CHANNEL_TOKEN;
6
6
 
@@ -20,7 +20,7 @@ export async function getActiveChannelToken(): Promise<string | undefined> {
20
20
  const cookie = jar.get(CHANNEL_COOKIE)?.value;
21
21
 
22
22
  // Validate: cookie token must be one of the declared available tokens
23
- if (cookie && channelsConfig.available.some(c => c.token === cookie)) {
23
+ if (cookie && channelsConfig.available.some((c) => c.token === cookie)) {
24
24
  return cookie;
25
25
  }
26
26
 
@@ -1,4 +1,4 @@
1
- import {cookies} from 'next/headers';
1
+ import { cookies } from 'next/headers';
2
2
 
3
3
  const COMPANY_ID_COOKIE = 'vendure-company-id';
4
4
  const BUSINESS_UNIT_ID_COOKIE = 'vendure-business-unit-id';
@@ -28,11 +28,7 @@ export function CompanyPermissionsProvider({
28
28
  },
29
29
  };
30
30
 
31
- return (
32
- <CompanyPermissionsContext.Provider value={value}>
33
- {children}
34
- </CompanyPermissionsContext.Provider>
35
- );
31
+ return <CompanyPermissionsContext.Provider value={value}>{children}</CompanyPermissionsContext.Provider>;
36
32
  }
37
33
 
38
34
  export function useCompanyPermissions() {
@@ -1,6 +1,6 @@
1
- import {cookies} from 'next/headers';
2
- import {CURRENCY_COOKIE} from './currency';
3
- import {getActiveChannelCached} from './vendure/cached';
1
+ import { cookies } from 'next/headers';
2
+ import { CURRENCY_COOKIE } from './currency';
3
+ import { getActiveChannelCached } from './vendure/cached';
4
4
 
5
5
  /**
6
6
  * Resolve the active currency code from the cookie, falling back to the
@@ -13,7 +13,7 @@ export async function getActiveCurrencyCode(): Promise<string> {
13
13
  // Dynamic import to avoid circular dependency: currencyMiddleware (api.ts)
14
14
  // → getActiveCurrencyCode → channel-server → scenario.ts. Do NOT import
15
15
  // anything from api.ts in channel-server.ts or this chain becomes circular.
16
- const {getActiveChannelToken} = await import('./channel-server');
16
+ const { getActiveChannelToken } = await import('./channel-server');
17
17
  const channelToken = await getActiveChannelToken();
18
18
  const channel = await getActiveChannelCached(channelToken);
19
19
  return channel.defaultCurrencyCode;
@@ -1,4 +1,4 @@
1
- import {toIntlLocale} from '@/i18n/locale-utils';
1
+ import { toIntlLocale } from '@/i18n/locale-utils';
2
2
 
3
3
  /**
4
4
  * Format a price value
@@ -6,7 +6,12 @@ import {toIntlLocale} from '@/i18n/locale-utils';
6
6
  * @param locale Routing locale (e.g. 'en', 'de')
7
7
  * @param currencyCode ISO 4217 currency code (e.g. 'EUR', 'USD')
8
8
  */
9
- export function formatPrice(price: number, locale: string, currencyCode = 'EUR', options?: Intl.NumberFormatOptions): string {
9
+ export function formatPrice(
10
+ price: number,
11
+ locale: string,
12
+ currencyCode = 'EUR',
13
+ options?: Intl.NumberFormatOptions,
14
+ ): string {
10
15
  return new Intl.NumberFormat(toIntlLocale(locale), {
11
16
  style: 'currency',
12
17
  currency: currencyCode,
@@ -23,9 +28,10 @@ type DateFormat = 'short' | 'long';
23
28
  * @param format 'short' (Jan 15, 2024) or 'long' (January 15, 2024)
24
29
  */
25
30
  export function formatDate(dateString: string, locale: string, format: DateFormat = 'short'): string {
26
- const options: Intl.DateTimeFormatOptions = format === 'long'
27
- ? { year: 'numeric', month: 'long', day: 'numeric' }
28
- : { year: 'numeric', month: 'short', day: 'numeric' };
31
+ const options: Intl.DateTimeFormatOptions =
32
+ format === 'long'
33
+ ? { year: 'numeric', month: 'long', day: 'numeric' }
34
+ : { year: 'numeric', month: 'short', day: 'numeric' };
29
35
 
30
36
  return new Date(dateString).toLocaleDateString(toIntlLocale(locale), options);
31
37
  }
@@ -37,8 +43,11 @@ export function formatDate(dateString: string, locale: string, format: DateForma
37
43
  */
38
44
  export function formatDateTime(dateString: string, locale: string): string {
39
45
  return new Date(dateString).toLocaleString(toIntlLocale(locale), {
40
- month: 'short', day: 'numeric', year: 'numeric',
41
- hour: 'numeric', minute: '2-digit',
46
+ month: 'short',
47
+ day: 'numeric',
48
+ year: 'numeric',
49
+ hour: 'numeric',
50
+ minute: '2-digit',
42
51
  });
43
52
  }
44
53
 
@@ -1,6 +1,6 @@
1
- import type { Metadata } from 'next';
2
1
  import { getBranding } from '@/config/branding';
3
2
  import { routing } from '@/i18n/routing';
3
+ import type { Metadata } from 'next';
4
4
 
5
5
  export const SITE_NAME = process.env.NEXT_PUBLIC_SITE_NAME || getBranding().siteName;
6
6
  export const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://example.com';
@@ -9,77 +9,72 @@ export const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://example.com
9
9
  * Truncate text to a maximum length, preserving word boundaries.
10
10
  * Strips HTML tags and is ideal for meta descriptions (recommended 150-160 chars).
11
11
  */
12
- export function truncateDescription(
13
- text: string | null | undefined,
14
- maxLength = 155
15
- ): string {
16
- if (!text) return '';
12
+ export function truncateDescription(text: string | null | undefined, maxLength = 155): string {
13
+ if (!text) return '';
17
14
 
18
- // Strip HTML tags if present
19
- const cleanText = text.replace(/<[^>]*>/g, '').trim();
15
+ // Strip HTML tags if present
16
+ const cleanText = text.replace(/<[^>]*>/g, '').trim();
20
17
 
21
- if (cleanText.length <= maxLength) return cleanText;
18
+ if (cleanText.length <= maxLength) return cleanText;
22
19
 
23
- // Find the last space before maxLength to avoid cutting words
24
- const truncated = cleanText.substring(0, maxLength);
25
- const lastSpaceIndex = truncated.lastIndexOf(' ');
20
+ // Find the last space before maxLength to avoid cutting words
21
+ const truncated = cleanText.substring(0, maxLength);
22
+ const lastSpaceIndex = truncated.lastIndexOf(' ');
26
23
 
27
- return lastSpaceIndex > 0
28
- ? truncated.substring(0, lastSpaceIndex) + '...'
29
- : truncated + '...';
24
+ return lastSpaceIndex > 0 ? truncated.substring(0, lastSpaceIndex) + '...' : truncated + '...';
30
25
  }
31
26
 
32
27
  /**
33
28
  * Build a canonical URL for a given path, optionally prefixed with locale.
34
29
  */
35
30
  export function buildCanonicalUrl(path: string, locale?: string): string {
36
- const baseUrl = SITE_URL.replace(/\/$/, '');
37
- const cleanPath = path.startsWith('/') ? path : `/${path}`;
38
- const prefix = locale ? `/${locale}` : '';
39
- return `${baseUrl}${prefix}${cleanPath}`;
31
+ const baseUrl = SITE_URL.replace(/\/$/, '');
32
+ const cleanPath = path.startsWith('/') ? path : `/${path}`;
33
+ const prefix = locale ? `/${locale}` : '';
34
+ return `${baseUrl}${prefix}${cleanPath}`;
40
35
  }
41
36
 
42
37
  /**
43
38
  * Build hreflang alternates for all configured locales.
44
39
  */
45
40
  export function buildAlternates(path: string, currentLocale?: string): Metadata['alternates'] {
46
- const languages: Record<string, string> = {};
47
- for (const loc of routing.locales) {
48
- languages[loc] = buildCanonicalUrl(path, loc);
49
- }
50
- return {
51
- canonical: buildCanonicalUrl(path, currentLocale),
52
- languages,
53
- };
41
+ const languages: Record<string, string> = {};
42
+ for (const loc of routing.locales) {
43
+ languages[loc] = buildCanonicalUrl(path, loc);
44
+ }
45
+ return {
46
+ canonical: buildCanonicalUrl(path, currentLocale),
47
+ languages,
48
+ };
54
49
  }
55
50
 
56
51
  /**
57
52
  * Build Open Graph image array from an image URL.
58
53
  */
59
54
  export function buildOgImages(
60
- imageUrl: string | null | undefined,
61
- alt?: string
55
+ imageUrl: string | null | undefined,
56
+ alt?: string,
62
57
  ): NonNullable<Metadata['openGraph']>['images'] {
63
- if (!imageUrl) return undefined;
58
+ if (!imageUrl) return undefined;
64
59
 
65
- return [
66
- {
67
- url: imageUrl,
68
- alt: alt || 'Product image',
69
- },
70
- ];
60
+ return [
61
+ {
62
+ url: imageUrl,
63
+ alt: alt || 'Product image',
64
+ },
65
+ ];
71
66
  }
72
67
 
73
68
  /**
74
69
  * Create noindex/nofollow robots config for protected pages.
75
70
  */
76
71
  export function noIndexRobots(): Metadata['robots'] {
77
- return {
78
- index: false,
79
- follow: false,
80
- googleBot: {
81
- index: false,
82
- follow: false,
83
- },
84
- };
72
+ return {
73
+ index: false,
74
+ follow: false,
75
+ googleBot: {
76
+ index: false,
77
+ follow: false,
78
+ },
79
+ };
85
80
  }
@@ -8,13 +8,11 @@ export function normalizeQuantity(
8
8
  value: number | string | null | undefined,
9
9
  minimum: number = MIN_ORDER_QUANTITY,
10
10
  ) {
11
- const parsed = typeof value === 'number'
12
- ? value
13
- : Number.parseInt(value ?? '', 10);
11
+ const parsed = typeof value === 'number' ? value : Number.parseInt(value ?? '', 10);
14
12
 
15
13
  if (!Number.isFinite(parsed)) {
16
14
  return minimum;
17
15
  }
18
16
 
19
17
  return Math.max(minimum, Math.floor(parsed));
20
- }
18
+ }
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { createContext, useContext, useState, useCallback, useRef, useEffect } from 'react';
3
+ import { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
4
4
 
5
5
  interface SearchBarContextType {
6
6
  hasInlineSearch: boolean;
@@ -22,8 +22,9 @@ export function SearchBarProvider({ children }: { children: React.ReactNode }) {
22
22
  function handleKeyDown(e: KeyboardEvent) {
23
23
  if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
24
24
  e.preventDefault();
25
- const input = searchInputRef.current
26
- ?? document.querySelector<HTMLInputElement>('input[type="search"]');
25
+ const input =
26
+ searchInputRef.current ??
27
+ document.querySelector<HTMLInputElement>('input[type="search"]');
27
28
  input?.focus();
28
29
  }
29
30
  }
@@ -32,7 +33,9 @@ export function SearchBarProvider({ children }: { children: React.ReactNode }) {
32
33
  }, []);
33
34
 
34
35
  return (
35
- <SearchBarContext.Provider value={{ hasInlineSearch, registerInlineSearch, unregisterInlineSearch, searchInputRef }}>
36
+ <SearchBarContext.Provider
37
+ value={{ hasInlineSearch, registerInlineSearch, unregisterInlineSearch, searchInputRef }}
38
+ >
36
39
  {children}
37
40
  </SearchBarContext.Provider>
38
41
  );