@vendure-platform/create 0.4.0 → 0.5.1

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 (334) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +39 -39
  3. package/dist/add-to-existing.js +1 -1
  4. package/dist/assets/demo-data/initial-data.json +663 -663
  5. package/dist/assets/storefront/components.json +20 -20
  6. package/dist/assets/storefront/eslint.config.mjs +10 -10
  7. package/dist/assets/storefront/graphql.config.yml +1 -1
  8. package/dist/assets/storefront/messages/de.json +2 -0
  9. package/dist/assets/storefront/messages/en.json +2 -0
  10. package/dist/assets/storefront/next.config.ts +5 -4
  11. package/dist/assets/storefront/package.json +1 -1
  12. package/dist/assets/storefront/postcss.config.mjs +1 -1
  13. package/dist/assets/storefront/src/app/[locale]/(catalog)/catalog/page.tsx +17 -21
  14. package/dist/assets/storefront/src/app/[locale]/(catalog)/collection/[slug]/page.tsx +64 -42
  15. package/dist/assets/storefront/src/app/[locale]/(catalog)/layout.tsx +1 -5
  16. package/dist/assets/storefront/src/app/[locale]/(catalog)/product/[slug]/actions.ts +69 -65
  17. package/dist/assets/storefront/src/app/[locale]/(catalog)/product/[slug]/page.tsx +68 -37
  18. package/dist/assets/storefront/src/app/[locale]/(catalog)/search/page.tsx +24 -27
  19. package/dist/assets/storefront/src/app/[locale]/(catalog)/search/search-results.tsx +11 -9
  20. package/dist/assets/storefront/src/app/[locale]/(catalog)/search/search-term.tsx +4 -4
  21. package/dist/assets/storefront/src/app/[locale]/(scenario)/[...path]/page.tsx +1 -1
  22. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/accept-invitation-client.tsx +8 -13
  23. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/actions.ts +11 -14
  24. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/page.tsx +30 -33
  25. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/sign-out-and-retry.tsx +6 -6
  26. package/dist/assets/storefront/src/app/[locale]/account/addresses/actions.ts +30 -45
  27. package/dist/assets/storefront/src/app/[locale]/account/addresses/address-form.tsx +166 -159
  28. package/dist/assets/storefront/src/app/[locale]/account/addresses/addresses-client.tsx +35 -26
  29. package/dist/assets/storefront/src/app/[locale]/account/addresses/loading.tsx +1 -3
  30. package/dist/assets/storefront/src/app/[locale]/account/addresses/page.tsx +16 -18
  31. package/dist/assets/storefront/src/app/[locale]/account/approvals/actions.ts +5 -8
  32. package/dist/assets/storefront/src/app/[locale]/account/approvals/page.tsx +77 -69
  33. package/dist/assets/storefront/src/app/[locale]/account/company/actions.ts +10 -11
  34. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/actions.ts +6 -15
  35. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/address-form.tsx +57 -49
  36. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/addresses-client.tsx +23 -25
  37. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/page.tsx +30 -30
  38. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/actions.ts +20 -29
  39. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/business-unit-form.tsx +32 -37
  40. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/business-units-client.tsx +32 -25
  41. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/page.tsx +24 -24
  42. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/types.ts +7 -4
  43. package/dist/assets/storefront/src/app/[locale]/account/company/edit-company-form.tsx +11 -21
  44. package/dist/assets/storefront/src/app/[locale]/account/company/page.tsx +23 -28
  45. package/dist/assets/storefront/src/app/[locale]/account/company/payment-methods/page.tsx +24 -24
  46. package/dist/assets/storefront/src/app/[locale]/account/company/payment-methods/payment-methods-client.tsx +5 -7
  47. package/dist/assets/storefront/src/app/[locale]/account/company/roles/page.tsx +22 -25
  48. package/dist/assets/storefront/src/app/[locale]/account/company/roles/roles-client.tsx +11 -26
  49. package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/actions.ts +6 -10
  50. package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/page.tsx +18 -16
  51. package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/tax-ids-client.tsx +74 -67
  52. package/dist/assets/storefront/src/app/[locale]/account/company/users/actions.ts +16 -25
  53. package/dist/assets/storefront/src/app/[locale]/account/company/users/edit-user-form.tsx +27 -25
  54. package/dist/assets/storefront/src/app/[locale]/account/company/users/invite-user-form.tsx +27 -19
  55. package/dist/assets/storefront/src/app/[locale]/account/company/users/page.tsx +32 -29
  56. package/dist/assets/storefront/src/app/[locale]/account/company/users/users-client.tsx +35 -38
  57. package/dist/assets/storefront/src/app/[locale]/account/error.tsx +1 -3
  58. package/dist/assets/storefront/src/app/[locale]/account/layout.tsx +16 -22
  59. package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/page.tsx +151 -103
  60. package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/reorder-actions.ts +6 -7
  61. package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/reorder-dialog.tsx +22 -48
  62. package/dist/assets/storefront/src/app/[locale]/account/orders/loading.tsx +8 -8
  63. package/dist/assets/storefront/src/app/[locale]/account/orders/page.tsx +101 -61
  64. package/dist/assets/storefront/src/app/[locale]/account/profile/actions.ts +32 -23
  65. package/dist/assets/storefront/src/app/[locale]/account/profile/change-password-form.tsx +6 -16
  66. package/dist/assets/storefront/src/app/[locale]/account/profile/edit-email-form.tsx +7 -17
  67. package/dist/assets/storefront/src/app/[locale]/account/profile/edit-profile-form.tsx +6 -16
  68. package/dist/assets/storefront/src/app/[locale]/account/profile/loading.tsx +12 -18
  69. package/dist/assets/storefront/src/app/[locale]/account/profile/page.tsx +15 -15
  70. package/dist/assets/storefront/src/app/[locale]/account/quick-order/file-upload-tab.tsx +2 -6
  71. package/dist/assets/storefront/src/app/[locale]/account/quick-order/manual-entry-tab.tsx +18 -15
  72. package/dist/assets/storefront/src/app/[locale]/account/quick-order/page.tsx +3 -6
  73. package/dist/assets/storefront/src/app/[locale]/account/quick-order/preview-table.tsx +10 -2
  74. package/dist/assets/storefront/src/app/[locale]/account/quick-order/save-to-list-dialog.tsx +24 -26
  75. package/dist/assets/storefront/src/app/[locale]/account/quick-order/sku-autocomplete.tsx +19 -10
  76. package/dist/assets/storefront/src/app/[locale]/account/quick-order/text-input-tab.tsx +3 -8
  77. package/dist/assets/storefront/src/app/[locale]/account/quotes/[id]/page.tsx +86 -59
  78. package/dist/assets/storefront/src/app/[locale]/account/quotes/actions.ts +38 -45
  79. package/dist/assets/storefront/src/app/[locale]/account/quotes/new/new-quote-form.tsx +3 -5
  80. package/dist/assets/storefront/src/app/[locale]/account/quotes/new/page.tsx +6 -6
  81. package/dist/assets/storefront/src/app/[locale]/account/quotes/page.tsx +92 -59
  82. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/activity-feed.tsx +152 -0
  83. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/add-item-search.tsx +132 -0
  84. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/add-member-form.tsx +140 -0
  85. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/members-panel.tsx +259 -0
  86. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/page.tsx +55 -0
  87. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/rename-dialog.tsx +117 -0
  88. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/shared-cart-detail-client.tsx +555 -0
  89. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/actions.ts +305 -0
  90. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/new/new-shared-cart-form.tsx +84 -0
  91. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/new/page.tsx +47 -0
  92. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/page.tsx +276 -0
  93. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/[id]/page.tsx +22 -8
  94. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/[id]/shopping-list-detail-client.tsx +62 -49
  95. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/actions.ts +9 -4
  96. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/create-shopping-list-form.tsx +5 -11
  97. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/loading.tsx +1 -1
  98. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/page.tsx +32 -42
  99. package/dist/assets/storefront/src/app/[locale]/account/store-credits/actions.ts +8 -8
  100. package/dist/assets/storefront/src/app/[locale]/account/store-credits/claim-form.tsx +6 -10
  101. package/dist/assets/storefront/src/app/[locale]/account/store-credits/page.tsx +76 -55
  102. package/dist/assets/storefront/src/app/[locale]/account/store-credits/reveal-code.tsx +10 -6
  103. package/dist/assets/storefront/src/app/[locale]/account/verify-email/page.tsx +32 -39
  104. package/dist/assets/storefront/src/app/[locale]/cart/actions.ts +29 -23
  105. package/dist/assets/storefront/src/app/[locale]/cart/cart-items.tsx +111 -40
  106. package/dist/assets/storefront/src/app/[locale]/cart/cart-line-actions.tsx +9 -9
  107. package/dist/assets/storefront/src/app/[locale]/cart/cart-quantity-control.tsx +61 -48
  108. package/dist/assets/storefront/src/app/[locale]/cart/cart-remove-button.tsx +15 -9
  109. package/dist/assets/storefront/src/app/[locale]/cart/cart.tsx +38 -41
  110. package/dist/assets/storefront/src/app/[locale]/cart/code-input.tsx +8 -8
  111. package/dist/assets/storefront/src/app/[locale]/cart/order-summary.tsx +70 -29
  112. package/dist/assets/storefront/src/app/[locale]/cart/page.tsx +11 -11
  113. package/dist/assets/storefront/src/app/[locale]/cart/promotion-code.tsx +48 -42
  114. package/dist/assets/storefront/src/app/[locale]/cart/reapproval-confirm.tsx +22 -20
  115. package/dist/assets/storefront/src/app/[locale]/cart/request-quote-button.tsx +7 -16
  116. package/dist/assets/storefront/src/app/[locale]/checkout/actions.ts +39 -65
  117. package/dist/assets/storefront/src/app/[locale]/checkout/cancel-quote-checkout-button.tsx +5 -5
  118. package/dist/assets/storefront/src/app/[locale]/checkout/checkout-flow.tsx +202 -202
  119. package/dist/assets/storefront/src/app/[locale]/checkout/checkout-provider.tsx +142 -142
  120. package/dist/assets/storefront/src/app/[locale]/checkout/order-summary.tsx +158 -139
  121. package/dist/assets/storefront/src/app/[locale]/checkout/page.tsx +56 -47
  122. package/dist/assets/storefront/src/app/[locale]/checkout/steps/delivery-step.tsx +86 -88
  123. package/dist/assets/storefront/src/app/[locale]/checkout/steps/payment-step.tsx +90 -91
  124. package/dist/assets/storefront/src/app/[locale]/checkout/steps/review-step.tsx +166 -161
  125. package/dist/assets/storefront/src/app/[locale]/checkout/steps/shipping-address-step.tsx +573 -494
  126. package/dist/assets/storefront/src/app/[locale]/error.tsx +3 -5
  127. package/dist/assets/storefront/src/app/[locale]/forgot-password/actions.ts +10 -7
  128. package/dist/assets/storefront/src/app/[locale]/forgot-password/forgot-password-form.tsx +10 -25
  129. package/dist/assets/storefront/src/app/[locale]/forgot-password/page.tsx +5 -5
  130. package/dist/assets/storefront/src/app/[locale]/globals.css +48 -48
  131. package/dist/assets/storefront/src/app/[locale]/layout.tsx +53 -47
  132. package/dist/assets/storefront/src/app/[locale]/not-found.tsx +3 -5
  133. package/dist/assets/storefront/src/app/[locale]/order-confirmation/[code]/order-confirmation.tsx +71 -44
  134. package/dist/assets/storefront/src/app/[locale]/order-confirmation/[code]/page.tsx +7 -5
  135. package/dist/assets/storefront/src/app/[locale]/page.tsx +33 -35
  136. package/dist/assets/storefront/src/app/[locale]/register/actions.ts +7 -7
  137. package/dist/assets/storefront/src/app/[locale]/register/page.tsx +22 -16
  138. package/dist/assets/storefront/src/app/[locale]/register/registration-form.tsx +22 -34
  139. package/dist/assets/storefront/src/app/[locale]/register-company/actions.ts +15 -19
  140. package/dist/assets/storefront/src/app/[locale]/register-company/page.tsx +17 -15
  141. package/dist/assets/storefront/src/app/[locale]/register-company/registration-form.tsx +9 -15
  142. package/dist/assets/storefront/src/app/[locale]/reset-password/actions.ts +7 -8
  143. package/dist/assets/storefront/src/app/[locale]/reset-password/page.tsx +18 -12
  144. package/dist/assets/storefront/src/app/[locale]/reset-password/reset-password-form.tsx +8 -16
  145. package/dist/assets/storefront/src/app/[locale]/shopping-list/[code]/add-to-cart-button.tsx +10 -4
  146. package/dist/assets/storefront/src/app/[locale]/shopping-list/[code]/page.tsx +62 -30
  147. package/dist/assets/storefront/src/app/[locale]/sign-in/actions.ts +14 -16
  148. package/dist/assets/storefront/src/app/[locale]/sign-in/login-form.tsx +17 -30
  149. package/dist/assets/storefront/src/app/[locale]/sign-in/page.tsx +35 -30
  150. package/dist/assets/storefront/src/app/[locale]/verify/actions.ts +8 -8
  151. package/dist/assets/storefront/src/app/[locale]/verify/page.tsx +18 -14
  152. package/dist/assets/storefront/src/app/[locale]/verify/verify-content.tsx +25 -27
  153. package/dist/assets/storefront/src/app/[locale]/verify-pending/page.tsx +23 -23
  154. package/dist/assets/storefront/src/app/api/clear-company-context/route.ts +6 -3
  155. package/dist/assets/storefront/src/app/api/revalidate/route.ts +19 -28
  156. package/dist/assets/storefront/src/app/api/search-analytics/route.ts +1 -1
  157. package/dist/assets/storefront/src/components/commerce/account-nav-items.ts +44 -17
  158. package/dist/assets/storefront/src/components/commerce/account-sidebar.tsx +30 -22
  159. package/dist/assets/storefront/src/components/commerce/active-filters.tsx +1 -1
  160. package/dist/assets/storefront/src/components/commerce/add-to-shared-cart.tsx +247 -0
  161. package/dist/assets/storefront/src/components/commerce/approval-decision-form.tsx +9 -13
  162. package/dist/assets/storefront/src/components/commerce/approval-status-badge.tsx +23 -15
  163. package/dist/assets/storefront/src/components/commerce/business-unit-switcher.tsx +11 -11
  164. package/dist/assets/storefront/src/components/commerce/catalog-search-bar.tsx +2 -2
  165. package/dist/assets/storefront/src/components/commerce/category-product-section.tsx +28 -16
  166. package/dist/assets/storefront/src/components/commerce/category-sidebar.tsx +31 -18
  167. package/dist/assets/storefront/src/components/commerce/collection-hero-banner.tsx +2 -4
  168. package/dist/assets/storefront/src/components/commerce/company-state-badge.tsx +10 -16
  169. package/dist/assets/storefront/src/components/commerce/company-switcher.tsx +12 -12
  170. package/dist/assets/storefront/src/components/commerce/configurator-form.tsx +188 -79
  171. package/dist/assets/storefront/src/components/commerce/facet-filters.tsx +29 -49
  172. package/dist/assets/storefront/src/components/commerce/gift-card-pdp.tsx +4 -4
  173. package/dist/assets/storefront/src/components/commerce/gift-card-product-info.tsx +20 -30
  174. package/dist/assets/storefront/src/components/commerce/instant-search-dropdown.tsx +258 -227
  175. package/dist/assets/storefront/src/components/commerce/order-status-badge.tsx +27 -19
  176. package/dist/assets/storefront/src/components/commerce/packaging-unit-selector.tsx +27 -26
  177. package/dist/assets/storefront/src/components/commerce/permission-gate.tsx +4 -4
  178. package/dist/assets/storefront/src/components/commerce/price-range-filter.tsx +5 -5
  179. package/dist/assets/storefront/src/components/commerce/price-tiers.tsx +38 -21
  180. package/dist/assets/storefront/src/components/commerce/price.tsx +3 -3
  181. package/dist/assets/storefront/src/components/commerce/product-card-list.tsx +35 -14
  182. package/dist/assets/storefront/src/components/commerce/product-card.tsx +31 -16
  183. package/dist/assets/storefront/src/components/commerce/product-carousel.tsx +20 -12
  184. package/dist/assets/storefront/src/components/commerce/product-grid.tsx +14 -13
  185. package/dist/assets/storefront/src/components/commerce/product-image-carousel.tsx +10 -8
  186. package/dist/assets/storefront/src/components/commerce/product-info.tsx +129 -72
  187. package/dist/assets/storefront/src/components/commerce/product-list-expansion.tsx +102 -74
  188. package/dist/assets/storefront/src/components/commerce/product-list-view.tsx +1 -1
  189. package/dist/assets/storefront/src/components/commerce/product-sidebar.tsx +36 -11
  190. package/dist/assets/storefront/src/components/commerce/product-view-switcher.tsx +33 -21
  191. package/dist/assets/storefront/src/components/commerce/quote-action-buttons.tsx +54 -36
  192. package/dist/assets/storefront/src/components/commerce/quote-activity-timeline.tsx +126 -50
  193. package/dist/assets/storefront/src/components/commerce/quote-comment-form.tsx +9 -13
  194. package/dist/assets/storefront/src/components/commerce/quote-csv-export-button.tsx +6 -6
  195. package/dist/assets/storefront/src/components/commerce/quote-product-search.tsx +22 -18
  196. package/dist/assets/storefront/src/components/commerce/quote-request-form.tsx +28 -27
  197. package/dist/assets/storefront/src/components/commerce/quote-status-badge.tsx +26 -18
  198. package/dist/assets/storefront/src/components/commerce/quote-validity-indicator.tsx +7 -7
  199. package/dist/assets/storefront/src/components/commerce/quote-version-comparison.tsx +50 -30
  200. package/dist/assets/storefront/src/components/commerce/related-products.tsx +37 -28
  201. package/dist/assets/storefront/src/components/commerce/shared-cart-role.ts +39 -0
  202. package/dist/assets/storefront/src/components/commerce/shared-cart-status-badge.tsx +28 -0
  203. package/dist/assets/storefront/src/components/commerce/shop-by-category.tsx +8 -7
  204. package/dist/assets/storefront/src/components/commerce/shopping-list-toggle.tsx +14 -20
  205. package/dist/assets/storefront/src/components/commerce/sort-dropdown.tsx +9 -16
  206. package/dist/assets/storefront/src/components/commerce/store-credit-summary.tsx +30 -32
  207. package/dist/assets/storefront/src/components/commerce/subcollection-tiles.tsx +11 -13
  208. package/dist/assets/storefront/src/components/layout/auth-page-shell.tsx +2 -2
  209. package/dist/assets/storefront/src/components/layout/draft-mode-indicator.tsx +2 -7
  210. package/dist/assets/storefront/src/components/layout/draft-mode-link.tsx +4 -2
  211. package/dist/assets/storefront/src/components/layout/footer.tsx +70 -28
  212. package/dist/assets/storefront/src/components/layout/navbar/actions.ts +9 -12
  213. package/dist/assets/storefront/src/components/layout/navbar/cart-icon.tsx +9 -9
  214. package/dist/assets/storefront/src/components/layout/navbar/channel-picker-wrapper.tsx +4 -9
  215. package/dist/assets/storefront/src/components/layout/navbar/channel-picker.tsx +13 -8
  216. package/dist/assets/storefront/src/components/layout/navbar/currency-picker-wrapper.tsx +4 -4
  217. package/dist/assets/storefront/src/components/layout/navbar/currency-picker.tsx +11 -6
  218. package/dist/assets/storefront/src/components/layout/navbar/language-picker.tsx +7 -7
  219. package/dist/assets/storefront/src/components/layout/navbar/login-button.tsx +24 -21
  220. package/dist/assets/storefront/src/components/layout/navbar/mobile-nav.tsx +8 -8
  221. package/dist/assets/storefront/src/components/layout/navbar/nav-menu-items.tsx +4 -6
  222. package/dist/assets/storefront/src/components/layout/navbar/navbar-cart.tsx +1 -1
  223. package/dist/assets/storefront/src/components/layout/navbar/navbar-collections.tsx +41 -42
  224. package/dist/assets/storefront/src/components/layout/navbar/navbar-link.tsx +7 -10
  225. package/dist/assets/storefront/src/components/layout/navbar/navbar-user.tsx +18 -23
  226. package/dist/assets/storefront/src/components/layout/navbar/theme-switcher.tsx +9 -9
  227. package/dist/assets/storefront/src/components/layout/navbar.tsx +36 -31
  228. package/dist/assets/storefront/src/components/layout/search-input.tsx +35 -32
  229. package/dist/assets/storefront/src/components/providers/awaiting-approval-banner.tsx +12 -10
  230. package/dist/assets/storefront/src/components/providers/cart-count-server.tsx +14 -12
  231. package/dist/assets/storefront/src/components/providers/company-context-guard.tsx +4 -4
  232. package/dist/assets/storefront/src/components/providers/company-permissions-server.tsx +2 -6
  233. package/dist/assets/storefront/src/components/providers/theme-provider.tsx +3 -3
  234. package/dist/assets/storefront/src/components/shared/breadcrumbs.tsx +4 -1
  235. package/dist/assets/storefront/src/components/shared/country-select.tsx +63 -67
  236. package/dist/assets/storefront/src/components/shared/pagination.tsx +15 -28
  237. package/dist/assets/storefront/src/components/shared/prefetch-link.tsx +1 -1
  238. package/dist/assets/storefront/src/components/shared/skeletons/search-input-skeleton.tsx +1 -3
  239. package/dist/assets/storefront/src/components/ui/accordion.tsx +46 -51
  240. package/dist/assets/storefront/src/components/ui/alert-dialog.tsx +94 -121
  241. package/dist/assets/storefront/src/components/ui/alert.tsx +48 -54
  242. package/dist/assets/storefront/src/components/ui/aspect-ratio.tsx +5 -7
  243. package/dist/assets/storefront/src/components/ui/avatar.tsx +29 -44
  244. package/dist/assets/storefront/src/components/ui/badge.tsx +28 -37
  245. package/dist/assets/storefront/src/components/ui/breadcrumb.tsx +82 -89
  246. package/dist/assets/storefront/src/components/ui/button.tsx +43 -49
  247. package/dist/assets/storefront/src/components/ui/calendar.tsx +157 -198
  248. package/dist/assets/storefront/src/components/ui/card.tsx +53 -76
  249. package/dist/assets/storefront/src/components/ui/carousel.tsx +194 -212
  250. package/dist/assets/storefront/src/components/ui/chart.tsx +274 -317
  251. package/dist/assets/storefront/src/components/ui/checkbox.tsx +24 -27
  252. package/dist/assets/storefront/src/components/ui/collapsible.tsx +9 -21
  253. package/dist/assets/storefront/src/components/ui/command.tsx +114 -159
  254. package/dist/assets/storefront/src/components/ui/context-menu.tsx +167 -199
  255. package/dist/assets/storefront/src/components/ui/dialog.tsx +97 -114
  256. package/dist/assets/storefront/src/components/ui/drawer.tsx +93 -107
  257. package/dist/assets/storefront/src/components/ui/dropdown-menu.tsx +171 -206
  258. package/dist/assets/storefront/src/components/ui/empty-state.tsx +5 -5
  259. package/dist/assets/storefront/src/components/ui/field.tsx +196 -208
  260. package/dist/assets/storefront/src/components/ui/form.tsx +115 -139
  261. package/dist/assets/storefront/src/components/ui/hover-card.tsx +27 -33
  262. package/dist/assets/storefront/src/components/ui/input-otp.tsx +50 -59
  263. package/dist/assets/storefront/src/components/ui/input.tsx +17 -17
  264. package/dist/assets/storefront/src/components/ui/kbd-shortcut.tsx +3 -1
  265. package/dist/assets/storefront/src/components/ui/label.tsx +16 -19
  266. package/dist/assets/storefront/src/components/ui/menubar.tsx +193 -223
  267. package/dist/assets/storefront/src/components/ui/navigation-menu.tsx +123 -130
  268. package/dist/assets/storefront/src/components/ui/pagination.tsx +87 -108
  269. package/dist/assets/storefront/src/components/ui/popover.tsx +29 -35
  270. package/dist/assets/storefront/src/components/ui/progress.tsx +19 -26
  271. package/dist/assets/storefront/src/components/ui/radio-group.tsx +32 -38
  272. package/dist/assets/storefront/src/components/ui/resizable.tsx +37 -42
  273. package/dist/assets/storefront/src/components/ui/scroll-area.tsx +41 -47
  274. package/dist/assets/storefront/src/components/ui/select.tsx +130 -152
  275. package/dist/assets/storefront/src/components/ui/separator.tsx +21 -21
  276. package/dist/assets/storefront/src/components/ui/sheet.tsx +90 -111
  277. package/dist/assets/storefront/src/components/ui/sidebar.tsx +611 -649
  278. package/dist/assets/storefront/src/components/ui/skeleton.tsx +10 -10
  279. package/dist/assets/storefront/src/components/ui/slider.tsx +50 -55
  280. package/dist/assets/storefront/src/components/ui/sonner.tsx +20 -20
  281. package/dist/assets/storefront/src/components/ui/switch.tsx +23 -26
  282. package/dist/assets/storefront/src/components/ui/table.tsx +65 -97
  283. package/dist/assets/storefront/src/components/ui/tabs.tsx +39 -55
  284. package/dist/assets/storefront/src/components/ui/textarea.tsx +14 -14
  285. package/dist/assets/storefront/src/components/ui/toggle-group.tsx +56 -62
  286. package/dist/assets/storefront/src/components/ui/toggle.tsx +37 -38
  287. package/dist/assets/storefront/src/components/ui/tooltip.tsx +38 -46
  288. package/dist/assets/storefront/src/config/scenario-meta.ts +2 -2
  289. package/dist/assets/storefront/src/config/scenario.ts +14 -16
  290. package/dist/assets/storefront/src/contexts/auth-context.tsx +5 -6
  291. package/dist/assets/storefront/src/graphql-env.d.ts +18 -5
  292. package/dist/assets/storefront/src/graphql.ts +5 -5
  293. package/dist/assets/storefront/src/hooks/use-mobile.ts +13 -13
  294. package/dist/assets/storefront/src/i18n/locale-utils.ts +3 -3
  295. package/dist/assets/storefront/src/i18n/navigation.ts +4 -4
  296. package/dist/assets/storefront/src/i18n/request.ts +4 -4
  297. package/dist/assets/storefront/src/i18n/routing.ts +5 -5
  298. package/dist/assets/storefront/src/i18n/server.ts +3 -3
  299. package/dist/assets/storefront/src/lib/actions/switch-channel.ts +9 -9
  300. package/dist/assets/storefront/src/lib/actions/switch-currency.ts +7 -7
  301. package/dist/assets/storefront/src/lib/auth.ts +1 -1
  302. package/dist/assets/storefront/src/lib/backend-health.ts +3 -3
  303. package/dist/assets/storefront/src/lib/cart-count-context.tsx +10 -4
  304. package/dist/assets/storefront/src/lib/cart-guard-utils.ts +2 -1
  305. package/dist/assets/storefront/src/lib/cart-guard.ts +7 -6
  306. package/dist/assets/storefront/src/lib/channel-server.ts +4 -4
  307. package/dist/assets/storefront/src/lib/company-context.ts +1 -1
  308. package/dist/assets/storefront/src/lib/company-permissions-context.tsx +1 -5
  309. package/dist/assets/storefront/src/lib/currency-server.ts +4 -4
  310. package/dist/assets/storefront/src/lib/format.ts +16 -7
  311. package/dist/assets/storefront/src/lib/metadata.ts +39 -44
  312. package/dist/assets/storefront/src/lib/quantity.ts +2 -4
  313. package/dist/assets/storefront/src/lib/search-bar-context.tsx +7 -4
  314. package/dist/assets/storefront/src/lib/use-recent-searches.ts +8 -6
  315. package/dist/assets/storefront/src/lib/utils.ts +3 -3
  316. package/dist/assets/storefront/src/lib/vendure/actions.ts +18 -16
  317. package/dist/assets/storefront/src/lib/vendure/api.ts +44 -27
  318. package/dist/assets/storefront/src/lib/vendure/approval-utils.ts +9 -8
  319. package/dist/assets/storefront/src/lib/vendure/cached.ts +20 -15
  320. package/dist/assets/storefront/src/lib/vendure/mutations.ts +96 -0
  321. package/dist/assets/storefront/src/lib/vendure/queries.ts +157 -5
  322. package/dist/assets/storefront/src/middleware.ts +1 -1
  323. package/dist/assets/storefront/src/scenarios/customer/hero.tsx +2 -2
  324. package/dist/assets/storefront/src/scenarios/customer/meta.ts +1 -1
  325. package/dist/assets/storefront/src/schema.graphql +134 -0
  326. package/dist/bin/run.js +1 -1
  327. package/dist/cli.d.ts +1 -1
  328. package/dist/index.d.ts +5 -5
  329. package/dist/index.js +1 -1
  330. package/dist/plugin-registry.js +1 -1
  331. package/dist/scaffold-storefront-only.js +1 -1
  332. package/dist/scaffolder.js +1 -1
  333. package/dist/template-renderer.js +1 -1
  334. package/package.json +2 -2
@@ -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
  );
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { useState, useCallback } from 'react';
3
+ import { useCallback, useState } from 'react';
4
4
 
5
5
  const STORAGE_KEY = 'vendure-recent-searches';
6
6
  const MAX_RECENT = 5;
@@ -11,7 +11,9 @@ function readFromStorage(): string[] {
11
11
  const raw = localStorage.getItem(STORAGE_KEY);
12
12
  if (!raw) return [];
13
13
  const parsed = JSON.parse(raw);
14
- return Array.isArray(parsed) ? parsed.filter((s): s is string => typeof s === 'string').slice(0, MAX_RECENT) : [];
14
+ return Array.isArray(parsed)
15
+ ? parsed.filter((s): s is string => typeof s === 'string').slice(0, MAX_RECENT)
16
+ : [];
15
17
  } catch {
16
18
  return [];
17
19
  }
@@ -31,16 +33,16 @@ export function useRecentSearches() {
31
33
  const addSearch = useCallback((term: string) => {
32
34
  const trimmed = term.trim();
33
35
  if (!trimmed) return;
34
- setSearches(prev => {
35
- const next = [trimmed, ...prev.filter(s => s !== trimmed)].slice(0, MAX_RECENT);
36
+ setSearches((prev) => {
37
+ const next = [trimmed, ...prev.filter((s) => s !== trimmed)].slice(0, MAX_RECENT);
36
38
  writeToStorage(next);
37
39
  return next;
38
40
  });
39
41
  }, []);
40
42
 
41
43
  const removeSearch = useCallback((term: string) => {
42
- setSearches(prev => {
43
- const next = prev.filter(s => s !== term);
44
+ setSearches((prev) => {
45
+ const next = prev.filter((s) => s !== term);
44
46
  writeToStorage(next);
45
47
  return next;
46
48
  });
@@ -1,6 +1,6 @@
1
- import { clsx, type ClassValue } from "clsx"
2
- import { twMerge } from "tailwind-merge"
1
+ import { clsx, type ClassValue } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
3
 
4
4
  export function cn(...inputs: ClassValue[]) {
5
- return twMerge(clsx(inputs))
5
+ return twMerge(clsx(inputs));
6
6
  }
@@ -1,8 +1,4 @@
1
- import {client} from './api';
2
- import {GetActiveCustomerQuery, GetCompanyAccountQuery, GetMyCompaniesQuery, type CompanyUserCompany} from './queries';
3
- import {getActiveChannelCached} from './cached';
4
- import {cache} from "react";
5
- import {readFragment, ResultOf} from "@/graphql";
1
+ import { readFragment, ResultOf } from '@/graphql';
6
2
  import {
7
3
  ActiveCustomerFragment,
8
4
  CompanyBusinessUnitFragment,
@@ -10,7 +6,16 @@ import {
10
6
  CompanyPermissionFragment,
11
7
  CompanyRoleFragment,
12
8
  CompanyUserFragment,
13
- } from "@/lib/vendure/fragments";
9
+ } from '@/lib/vendure/fragments';
10
+ import { cache } from 'react';
11
+ import { client } from './api';
12
+ import { getActiveChannelCached } from './cached';
13
+ import {
14
+ GetActiveCustomerQuery,
15
+ GetCompanyAccountQuery,
16
+ GetMyCompaniesQuery,
17
+ type CompanyUserCompany,
18
+ } from './queries';
14
19
 
15
20
  type CompanyRoleData = Omit<ResultOf<typeof CompanyRoleFragment>, 'permissions'> & {
16
21
  permissions: ResultOf<typeof CompanyPermissionFragment>[];
@@ -34,7 +39,7 @@ export const getActiveCustomer = cache(async () => {
34
39
  return null;
35
40
  }
36
41
  return readFragment(ActiveCustomerFragment, result.data.activeCustomer);
37
- })
42
+ });
38
43
 
39
44
  export const getCompanyAccount = cache(async (): Promise<CompanyAccount | null> => {
40
45
  const [result, error] = await client.query(GetCompanyAccountQuery);
@@ -52,14 +57,14 @@ export const getCompanyAccount = cache(async (): Promise<CompanyAccount | null>
52
57
 
53
58
  const companyUser: CompanyUserData = {
54
59
  ...rawUser,
55
- companyRoles: rawUser.companyRoles.map(r => {
60
+ companyRoles: rawUser.companyRoles.map((r) => {
56
61
  const role = readFragment(CompanyRoleFragment, r);
57
62
  return {
58
63
  ...role,
59
- permissions: role.permissions.map(p => readFragment(CompanyPermissionFragment, p)),
64
+ permissions: role.permissions.map((p) => readFragment(CompanyPermissionFragment, p)),
60
65
  };
61
66
  }),
62
- businessUnits: rawUser.businessUnits.map(bu => readFragment(CompanyBusinessUnitFragment, bu)),
67
+ businessUnits: rawUser.businessUnits.map((bu) => readFragment(CompanyBusinessUnitFragment, bu)),
63
68
  };
64
69
 
65
70
  return {
@@ -76,8 +81,8 @@ export const getMyCompanies = cache(async (): Promise<CompanyUserCompany[]> => {
76
81
  const customer = result.data.activeCustomer;
77
82
  if (!customer) return [];
78
83
  return customer.companyUsers
79
- .filter(cu => cu.state === 'Active')
80
- .map(cu => ({ id: cu.company.id, name: cu.company.name, state: cu.company.state }));
84
+ .filter((cu) => cu.state === 'Active')
85
+ .map((cu) => ({ id: cu.company.id, name: cu.company.name, state: cu.company.state }));
81
86
  });
82
87
 
83
88
  /**
@@ -86,10 +91,7 @@ export const getMyCompanies = cache(async (): Promise<CompanyUserCompany[]> => {
86
91
  * to getMyCompanies (which includes pending companies via CompanyUser state).
87
92
  */
88
93
  export const getHasCompany = cache(async (): Promise<boolean> => {
89
- const [companyAccount, companies] = await Promise.all([
90
- getCompanyAccount(),
91
- getMyCompanies(),
92
- ]);
94
+ const [companyAccount, companies] = await Promise.all([getCompanyAccount(), getMyCompanies()]);
93
95
  return !!companyAccount || companies.length > 0;
94
96
  });
95
97
 
@@ -1,5 +1,5 @@
1
- import {createClient} from '@vendure-platform/storefront-client';
2
- import type {RequestMiddleware} from '@vendure-platform/storefront-client';
1
+ import type { RequestMiddleware } from '@vendure-platform/storefront-client';
2
+ import { createClient } from '@vendure-platform/storefront-client';
3
3
 
4
4
  const DRAFT_MODE_SECRET = process.env.DRAFT_MODE_SECRET;
5
5
 
@@ -11,7 +11,7 @@ const DRAFT_MODE_SECRET = process.env.DRAFT_MODE_SECRET;
11
11
  const draftModeMiddleware: RequestMiddleware = async (req, next) => {
12
12
  if (DRAFT_MODE_SECRET) {
13
13
  try {
14
- const {draftMode} = await import('next/headers');
14
+ const { draftMode } = await import('next/headers');
15
15
  const draft = await draftMode();
16
16
  if (draft.isEnabled) {
17
17
  const url = new URL(req.url);
@@ -26,35 +26,44 @@ const draftModeMiddleware: RequestMiddleware = async (req, next) => {
26
26
  };
27
27
 
28
28
  const VENDURE_API_URL = process.env.VENDURE_SHOP_API_URL || process.env.NEXT_PUBLIC_VENDURE_SHOP_API_URL;
29
- const VENDURE_CHANNEL_TOKEN = process.env.VENDURE_CHANNEL_TOKEN || process.env.NEXT_PUBLIC_VENDURE_CHANNEL_TOKEN;
29
+ const VENDURE_CHANNEL_TOKEN =
30
+ process.env.VENDURE_CHANNEL_TOKEN || process.env.NEXT_PUBLIC_VENDURE_CHANNEL_TOKEN;
30
31
  const VENDURE_AUTH_TOKEN_HEADER = process.env.VENDURE_AUTH_TOKEN_HEADER || 'vendure-auth-token';
31
32
  const VENDURE_CHANNEL_TOKEN_HEADER = process.env.VENDURE_CHANNEL_TOKEN_HEADER || 'vendure-token';
32
33
 
33
34
  if (!VENDURE_API_URL) {
34
- throw new Error('VENDURE_SHOP_API_URL or NEXT_PUBLIC_VENDURE_SHOP_API_URL environment variable is not set');
35
+ throw new Error(
36
+ 'VENDURE_SHOP_API_URL or NEXT_PUBLIC_VENDURE_SHOP_API_URL environment variable is not set',
37
+ );
35
38
  }
36
39
 
37
40
  // Dynamic imports to avoid Next.js static analysis marking this module as dynamic.
38
41
  // cookies() is only available in request context — providers gracefully return undefined otherwise.
39
42
  async function safeGetAuthToken(): Promise<string | undefined> {
40
43
  try {
41
- const {getAuthToken} = await import('@/lib/auth');
44
+ const { getAuthToken } = await import('@/lib/auth');
42
45
  return await getAuthToken();
43
- } catch { return undefined; }
46
+ } catch {
47
+ return undefined;
48
+ }
44
49
  }
45
50
 
46
51
  async function safeGetCompanyId(): Promise<string | undefined> {
47
52
  try {
48
- const {getCompanyId} = await import('@/lib/company-context');
53
+ const { getCompanyId } = await import('@/lib/company-context');
49
54
  return await getCompanyId();
50
- } catch { return undefined; }
55
+ } catch {
56
+ return undefined;
57
+ }
51
58
  }
52
59
 
53
60
  async function safeGetBusinessUnitId(): Promise<string | undefined> {
54
61
  try {
55
- const {getBusinessUnitId} = await import('@/lib/company-context');
62
+ const { getBusinessUnitId } = await import('@/lib/company-context');
56
63
  return await getBusinessUnitId();
57
- } catch { return undefined; }
64
+ } catch {
65
+ return undefined;
66
+ }
58
67
  }
59
68
 
60
69
  /**
@@ -65,16 +74,20 @@ async function safeGetBusinessUnitId(): Promise<string | undefined> {
65
74
  */
66
75
  async function safeGetChannelToken(): Promise<string | undefined> {
67
76
  try {
68
- const {getActiveChannelToken} = await import('@/lib/channel-server');
77
+ const { getActiveChannelToken } = await import('@/lib/channel-server');
69
78
  return await getActiveChannelToken();
70
- } catch { return undefined; }
79
+ } catch {
80
+ return undefined;
81
+ }
71
82
  }
72
83
 
73
84
  async function safeGetLanguageCode(): Promise<string | undefined> {
74
85
  try {
75
- const {getLocale} = await import('next-intl/server');
86
+ const { getLocale } = await import('next-intl/server');
76
87
  return await getLocale();
77
- } catch { return undefined; }
88
+ } catch {
89
+ return undefined;
90
+ }
78
91
  }
79
92
 
80
93
  const sharedConfig = {
@@ -84,6 +97,9 @@ const sharedConfig = {
84
97
  authToken: VENDURE_AUTH_TOKEN_HEADER,
85
98
  channelToken: VENDURE_CHANNEL_TOKEN_HEADER,
86
99
  },
100
+ // Dev-only guard: these operations return wrong-language results when no
101
+ // languageCode reaches the request (silent fallback to channel default).
102
+ warnOnMissingLanguageCode: ['search', 'searchCollections', 'quickOrderSearch'],
87
103
  } as const;
88
104
 
89
105
  /**
@@ -92,7 +108,7 @@ const sharedConfig = {
92
108
  */
93
109
  const currencyMiddleware: RequestMiddleware = async (req, next) => {
94
110
  try {
95
- const {getActiveCurrencyCode} = await import('@/lib/currency-server');
111
+ const { getActiveCurrencyCode } = await import('@/lib/currency-server');
96
112
  const currency = await getActiveCurrencyCode();
97
113
  const url = new URL(req.url);
98
114
  url.searchParams.set('currencyCode', currency);
@@ -113,10 +129,11 @@ export const client = createClient({
113
129
  channelToken: safeGetChannelToken,
114
130
  companyId: safeGetCompanyId,
115
131
  businessUnitId: safeGetBusinessUnitId,
116
- // languageCode is NOT included here because with cacheComponents: true,
117
- // every server component is an implicit cache scope where getLocale()
118
- // triggers headers() which is forbidden. Instead, languageCode is passed
119
- // explicitly via VendureContext or query options.
132
+ // Resolves the route locale via next-intl's getLocale(); fails soft
133
+ // (undefined) outside request scope. Not available on publicClient —
134
+ // 'use cache' scopes must receive languageCode as an explicit argument
135
+ // since it is part of the cache key.
136
+ languageCode: safeGetLanguageCode,
120
137
  },
121
138
  });
122
139
 
@@ -126,7 +143,7 @@ export const client = createClient({
126
143
  * access cookies, headers, or draftMode. Pass languageCode and currencyCode explicitly
127
144
  * as query options from the calling function.
128
145
  */
129
- export const publicClient = createClient({...sharedConfig});
146
+ export const publicClient = createClient({ ...sharedConfig });
130
147
 
131
148
  /**
132
149
  * Pre-resolved context for use at cache boundaries where cookies() is not available.
@@ -145,20 +162,20 @@ export interface VendureContext {
145
162
  * Use this at cache boundaries ('use cache') where providers can't access cookies().
146
163
  */
147
164
  export async function getVendureContext(): Promise<VendureContext> {
148
- const {getAuthToken} = await import('@/lib/auth');
165
+ const { getAuthToken } = await import('@/lib/auth');
149
166
  const authToken = await getAuthToken();
150
167
  let companyId: string | undefined;
151
168
  let businessUnitId: string | undefined;
152
169
  try {
153
- const {getCompanyId, getBusinessUnitId} = await import('@/lib/company-context');
170
+ const { getCompanyId, getBusinessUnitId } = await import('@/lib/company-context');
154
171
  companyId = await getCompanyId();
155
172
  businessUnitId = await getBusinessUnitId();
156
173
  } catch {}
157
- const {getActiveChannelToken} = await import('@/lib/channel-server');
174
+ const { getActiveChannelToken } = await import('@/lib/channel-server');
158
175
  const channelToken = await getActiveChannelToken();
159
- const {getRouteLocale} = await import('@/i18n/server');
176
+ const { getRouteLocale } = await import('@/i18n/server');
160
177
  const locale = await getRouteLocale();
161
- const {getActiveCurrencyCode} = await import('@/lib/currency-server');
178
+ const { getActiveCurrencyCode } = await import('@/lib/currency-server');
162
179
  const currencyCode = await getActiveCurrencyCode();
163
- return {authToken, channelToken, companyId, businessUnitId, locale, currencyCode};
180
+ return { authToken, channelToken, companyId, businessUnitId, locale, currencyCode };
164
181
  }
@@ -1,21 +1,22 @@
1
- import {client} from '@/lib/vendure/api';
2
- import type {VendureContext} from '@/lib/vendure/api';
3
- import {GetApprovalHistoryForEntityQuery} from '@/lib/vendure/queries';
1
+ import type { VendureContext } from '@/lib/vendure/api';
2
+ import { client } from '@/lib/vendure/api';
3
+ import { GetApprovalHistoryForEntityQuery } from '@/lib/vendure/queries';
4
4
 
5
5
  export async function getLatestApprovalForOrder(orderId: string, ctx?: VendureContext) {
6
6
  const queryArgs = { entityType: 'Order', entityId: orderId } as const;
7
7
  const [result] = ctx
8
8
  ? await client.query(GetApprovalHistoryForEntityQuery, queryArgs, ctx)
9
9
  : await client.query(GetApprovalHistoryForEntityQuery, queryArgs);
10
- const history = [...(result?.data?.approvalHistoryForEntity ?? [])]
11
- .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
10
+ const history = [...(result?.data?.approvalHistoryForEntity ?? [])].sort(
11
+ (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
12
+ );
12
13
  const latestApproval = history[0] ?? null;
13
14
  const changesRequested = latestApproval?.status === 'CHANGES_REQUESTED';
14
15
  const changesComment = changesRequested
15
16
  ? latestApproval.decisions
16
- ?.filter((d: any) => d.decision === 'CHANGES_REQUESTED' && d.comment)
17
- .map((d: any) => d.comment)
18
- .at(-1) ?? null
17
+ ?.filter((d: any) => d.decision === 'CHANGES_REQUESTED' && d.comment)
18
+ .map((d: any) => d.comment)
19
+ .at(-1) ?? null
19
20
  : null;
20
21
  return { latestApproval, changesRequested, changesComment };
21
22
  }