@shopify/hydrogen 2026.10.0-preview.2 → 2026.10.0-preview.4

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 (404) hide show
  1. package/README.md +34 -3
  2. package/dist/cli/index.mjs +578 -85
  3. package/dist/client/client.mjs +2 -2
  4. package/dist/client/errors.d.mts +19 -19
  5. package/dist/client/errors.mjs +19 -16
  6. package/dist/client/errors.mjs.map +1 -1
  7. package/dist/client/types.d.mts +91 -10
  8. package/dist/core/analytics/cart-tracker.d.mts +14 -0
  9. package/dist/core/analytics/cart-tracker.mjs +15 -1
  10. package/dist/core/analytics/cart-tracker.mjs.map +1 -1
  11. package/dist/core/analytics/custom-consent.mjs +12 -0
  12. package/dist/core/analytics/custom-consent.mjs.map +1 -0
  13. package/dist/core/analytics/events.d.mts +7 -0
  14. package/dist/core/analytics/events.mjs +7 -0
  15. package/dist/core/analytics/events.mjs.map +1 -1
  16. package/dist/core/analytics/index.d.mts +1 -1
  17. package/dist/core/analytics/types.d.mts +152 -16
  18. package/dist/core/cart/actions.d.mts +47 -3
  19. package/dist/core/cart/actions.mjs +29 -0
  20. package/dist/core/cart/actions.mjs.map +1 -1
  21. package/dist/core/cart/attach-quantity-input.d.mts +26 -0
  22. package/dist/core/cart/attach-quantity-input.mjs +26 -0
  23. package/dist/core/cart/attach-quantity-input.mjs.map +1 -1
  24. package/dist/core/cart/cart.d.mts +106 -6
  25. package/dist/core/cart/cart.mjs +57 -6
  26. package/dist/core/cart/cart.mjs.map +1 -1
  27. package/dist/core/cart/cookie.d.mts +15 -0
  28. package/dist/core/cart/cookie.mjs +15 -0
  29. package/dist/core/cart/cookie.mjs.map +1 -1
  30. package/dist/core/cart/form.d.mts +61 -0
  31. package/dist/core/cart/form.mjs +18 -0
  32. package/dist/core/cart/form.mjs.map +1 -1
  33. package/dist/core/cart/get-cart.d.mts +43 -2
  34. package/dist/core/cart/get-cart.mjs +33 -0
  35. package/dist/core/cart/get-cart.mjs.map +1 -1
  36. package/dist/core/cart/index.d.mts +1 -1
  37. package/dist/core/cart/quantity.d.mts +17 -0
  38. package/dist/core/cart/quantity.mjs +17 -0
  39. package/dist/core/cart/quantity.mjs.map +1 -1
  40. package/dist/core/cart/queries.d.mts +402 -369
  41. package/dist/core/cart/queries.mjs +2 -1
  42. package/dist/core/cart/queries.mjs.map +1 -1
  43. package/dist/core/cart/server-handlers.d.mts +69 -0
  44. package/dist/core/cart/server-handlers.mjs +2 -10
  45. package/dist/core/cart/server-handlers.mjs.map +1 -1
  46. package/dist/core/cart/state.d.mts +133 -0
  47. package/dist/core/cart/state.mjs +8 -0
  48. package/dist/core/cart/state.mjs.map +1 -1
  49. package/dist/core/collection/collection.d.mts +18 -2
  50. package/dist/core/collection/collection.mjs +11 -0
  51. package/dist/core/collection/collection.mjs.map +1 -1
  52. package/dist/core/collection/index.d.mts +1 -1
  53. package/dist/core/collection/reconciler.d.mts +13 -4
  54. package/dist/core/collection/reconciler.mjs.map +1 -1
  55. package/dist/core/collection/state.d.mts +7 -2
  56. package/dist/core/collection/state.mjs.map +1 -1
  57. package/dist/core/collection/url.d.mts +3 -0
  58. package/dist/core/collection/url.mjs.map +1 -1
  59. package/dist/core/constants.d.mts +1 -1
  60. package/dist/core/constants.mjs +2 -2
  61. package/dist/core/constants.mjs.map +1 -1
  62. package/dist/core/headers.mjs +2 -2
  63. package/dist/core/headers.mjs.map +1 -1
  64. package/dist/core/index.d.mts +5 -5
  65. package/dist/core/logging/logging.mjs.map +1 -1
  66. package/dist/core/money/format.mjs +6 -3
  67. package/dist/core/money/format.mjs.map +1 -1
  68. package/dist/core/observable.mjs +0 -3
  69. package/dist/core/observable.mjs.map +1 -1
  70. package/dist/core/predictive-search/form.d.mts +1 -0
  71. package/dist/core/predictive-search/form.mjs +1 -0
  72. package/dist/core/predictive-search/form.mjs.map +1 -1
  73. package/dist/core/predictive-search/index.d.mts +1 -1
  74. package/dist/core/predictive-search/queries.d.mts +40 -4
  75. package/dist/core/predictive-search/queries.mjs +7 -1
  76. package/dist/core/predictive-search/queries.mjs.map +1 -1
  77. package/dist/core/predictive-search/search.d.mts +43 -10
  78. package/dist/core/predictive-search/search.mjs +34 -0
  79. package/dist/core/predictive-search/search.mjs.map +1 -1
  80. package/dist/core/predictive-search/server-handlers.d.mts +31 -5
  81. package/dist/core/predictive-search/server-handlers.mjs +5 -3
  82. package/dist/core/predictive-search/server-handlers.mjs.map +1 -1
  83. package/dist/core/predictive-search/store.d.mts +3 -1
  84. package/dist/core/predictive-search/store.mjs.map +1 -1
  85. package/dist/core/predictive-search/url.d.mts +50 -8
  86. package/dist/core/predictive-search/url.mjs +9 -0
  87. package/dist/core/predictive-search/url.mjs.map +1 -1
  88. package/dist/core/product/form.d.mts +21 -2
  89. package/dist/core/product/form.mjs +13 -0
  90. package/dist/core/product/form.mjs.map +1 -1
  91. package/dist/core/product/index.d.mts +1 -1
  92. package/dist/core/product/options.d.mts +2 -2
  93. package/dist/core/product/options.mjs +2 -2
  94. package/dist/core/product/options.mjs.map +1 -1
  95. package/dist/core/product/product-form.d.mts +33 -1
  96. package/dist/core/product/product-form.mjs +30 -0
  97. package/dist/core/product/product-form.mjs.map +1 -1
  98. package/dist/core/product/state.d.mts +41 -0
  99. package/dist/core/product/url.d.mts +6 -0
  100. package/dist/core/product/url.mjs.map +1 -1
  101. package/dist/core/request-context.d.mts +8 -5
  102. package/dist/core/request-context.mjs +17 -39
  103. package/dist/core/request-context.mjs.map +1 -1
  104. package/dist/core/request-routing/handle-shopify-routes.mjs +4 -1
  105. package/dist/core/request-routing/handle-shopify-routes.mjs.map +1 -1
  106. package/dist/core/request-routing/interceptors/ajax-api.mjs +1 -1
  107. package/dist/core/request-routing/interceptors/api-proxy.mjs +1 -1
  108. package/dist/core/request-routing/interceptors/checkout.mjs +22 -6
  109. package/dist/core/request-routing/interceptors/checkout.mjs.map +1 -1
  110. package/dist/core/request-routing/interceptors/mcp-proxy.mjs +1 -1
  111. package/dist/core/request-routing/interceptors/proxy.mjs +36 -10
  112. package/dist/core/request-routing/interceptors/proxy.mjs.map +1 -1
  113. package/dist/core/request-routing/interceptors/query-param-redirect.mjs +5 -11
  114. package/dist/core/request-routing/interceptors/query-param-redirect.mjs.map +1 -1
  115. package/dist/core/request-routing/interceptors/sfapi-proxy.mjs +19 -1
  116. package/dist/core/request-routing/interceptors/sfapi-proxy.mjs.map +1 -1
  117. package/dist/core/request-routing/interceptors/ucp-mcp-proxy.mjs +35 -0
  118. package/dist/core/request-routing/interceptors/ucp-mcp-proxy.mjs.map +1 -0
  119. package/dist/core/request-routing/interceptors/well-known.mjs +1 -1
  120. package/dist/core/shopify-scripts/analytics.mjs +2 -2
  121. package/dist/core/shopify-scripts/analytics.mjs.map +1 -1
  122. package/dist/core/shopify-scripts/constants.mjs +4 -2
  123. package/dist/core/shopify-scripts/constants.mjs.map +1 -1
  124. package/dist/core/shopify-scripts/global.mjs +9 -4
  125. package/dist/core/shopify-scripts/global.mjs.map +1 -1
  126. package/dist/core/shopify-scripts/index.d.mts +1 -0
  127. package/dist/core/shopify-scripts/index.mjs +14 -12
  128. package/dist/core/shopify-scripts/index.mjs.map +1 -1
  129. package/dist/core/shopify-scripts/initialize.d.mts +1 -0
  130. package/dist/core/shopify-scripts/initialize.mjs +10 -3
  131. package/dist/core/shopify-scripts/initialize.mjs.map +1 -1
  132. package/dist/core/shopify-scripts/types.d.mts +6 -0
  133. package/dist/core/url.mjs +21 -2
  134. package/dist/core/url.mjs.map +1 -1
  135. package/dist/customer-account/client.d.mts +128 -4
  136. package/dist/customer-account/client.mjs +27 -1
  137. package/dist/customer-account/client.mjs.map +1 -1
  138. package/dist/customer-account/errors.d.mts +46 -0
  139. package/dist/customer-account/errors.mjs +46 -0
  140. package/dist/customer-account/errors.mjs.map +1 -1
  141. package/dist/customer-account/graphql.d.mts +68 -0
  142. package/dist/customer-account/graphql.mjs +47 -0
  143. package/dist/customer-account/graphql.mjs.map +1 -1
  144. package/dist/customer-account/session.d.mts +114 -23
  145. package/dist/customer-account/session.mjs +27 -12
  146. package/dist/customer-account/session.mjs.map +1 -1
  147. package/dist/customer-account/type-resolver.d.mts +23 -0
  148. package/dist/customer-account-api-types.d.ts +570 -374
  149. package/dist/customer-account.schema.json +2981 -1527
  150. package/dist/development/client/client.mjs +2 -2
  151. package/dist/development/client/errors.d.mts +19 -19
  152. package/dist/development/client/errors.mjs +20 -20
  153. package/dist/development/client/errors.mjs.map +1 -1
  154. package/dist/development/client/types.d.mts +91 -10
  155. package/dist/development/core/analytics/cart-tracker.d.mts +14 -0
  156. package/dist/development/core/analytics/cart-tracker.mjs +15 -1
  157. package/dist/development/core/analytics/cart-tracker.mjs.map +1 -1
  158. package/dist/development/core/analytics/custom-consent.mjs +12 -0
  159. package/dist/development/core/analytics/custom-consent.mjs.map +1 -0
  160. package/dist/development/core/analytics/events.d.mts +7 -0
  161. package/dist/development/core/analytics/events.mjs +7 -0
  162. package/dist/development/core/analytics/events.mjs.map +1 -1
  163. package/dist/development/core/analytics/index.d.mts +1 -1
  164. package/dist/development/core/analytics/types.d.mts +152 -16
  165. package/dist/development/core/cart/actions.d.mts +47 -3
  166. package/dist/development/core/cart/actions.mjs +29 -0
  167. package/dist/development/core/cart/actions.mjs.map +1 -1
  168. package/dist/development/core/cart/attach-quantity-input.d.mts +26 -0
  169. package/dist/development/core/cart/attach-quantity-input.mjs +26 -0
  170. package/dist/development/core/cart/attach-quantity-input.mjs.map +1 -1
  171. package/dist/development/core/cart/cart.d.mts +106 -6
  172. package/dist/development/core/cart/cart.mjs +57 -6
  173. package/dist/development/core/cart/cart.mjs.map +1 -1
  174. package/dist/development/core/cart/cookie.d.mts +15 -0
  175. package/dist/development/core/cart/cookie.mjs +15 -0
  176. package/dist/development/core/cart/cookie.mjs.map +1 -1
  177. package/dist/development/core/cart/form.d.mts +61 -0
  178. package/dist/development/core/cart/form.mjs +18 -0
  179. package/dist/development/core/cart/form.mjs.map +1 -1
  180. package/dist/development/core/cart/get-cart.d.mts +43 -2
  181. package/dist/development/core/cart/get-cart.mjs +33 -0
  182. package/dist/development/core/cart/get-cart.mjs.map +1 -1
  183. package/dist/development/core/cart/index.d.mts +1 -1
  184. package/dist/development/core/cart/quantity.d.mts +17 -0
  185. package/dist/development/core/cart/quantity.mjs +17 -0
  186. package/dist/development/core/cart/quantity.mjs.map +1 -1
  187. package/dist/development/core/cart/queries.d.mts +345 -312
  188. package/dist/development/core/cart/queries.mjs +2 -1
  189. package/dist/development/core/cart/queries.mjs.map +1 -1
  190. package/dist/development/core/cart/server-handlers.d.mts +69 -0
  191. package/dist/development/core/cart/server-handlers.mjs +2 -10
  192. package/dist/development/core/cart/server-handlers.mjs.map +1 -1
  193. package/dist/development/core/cart/state.d.mts +133 -0
  194. package/dist/development/core/cart/state.mjs +8 -0
  195. package/dist/development/core/cart/state.mjs.map +1 -1
  196. package/dist/development/core/collection/collection.d.mts +18 -2
  197. package/dist/development/core/collection/collection.mjs +11 -0
  198. package/dist/development/core/collection/collection.mjs.map +1 -1
  199. package/dist/development/core/collection/index.d.mts +1 -1
  200. package/dist/development/core/collection/reconciler.d.mts +13 -4
  201. package/dist/development/core/collection/reconciler.mjs.map +1 -1
  202. package/dist/development/core/collection/state.d.mts +7 -2
  203. package/dist/development/core/collection/state.mjs.map +1 -1
  204. package/dist/development/core/collection/url.d.mts +3 -0
  205. package/dist/development/core/collection/url.mjs.map +1 -1
  206. package/dist/development/core/constants.mjs +1 -1
  207. package/dist/development/core/constants.mjs.map +1 -1
  208. package/dist/development/core/development.d.mts +5 -5
  209. package/dist/development/core/headers.mjs +2 -2
  210. package/dist/development/core/headers.mjs.map +1 -1
  211. package/dist/development/core/index.d.mts +4 -4
  212. package/dist/development/core/logging/logging.mjs.map +1 -1
  213. package/dist/development/core/money/format.mjs +6 -3
  214. package/dist/development/core/money/format.mjs.map +1 -1
  215. package/dist/development/core/observable.mjs +0 -3
  216. package/dist/development/core/observable.mjs.map +1 -1
  217. package/dist/development/core/predictive-search/form.d.mts +1 -0
  218. package/dist/development/core/predictive-search/form.mjs +1 -0
  219. package/dist/development/core/predictive-search/form.mjs.map +1 -1
  220. package/dist/development/core/predictive-search/index.d.mts +1 -1
  221. package/dist/development/core/predictive-search/queries.d.mts +38 -2
  222. package/dist/development/core/predictive-search/queries.mjs +7 -1
  223. package/dist/development/core/predictive-search/queries.mjs.map +1 -1
  224. package/dist/development/core/predictive-search/search.d.mts +43 -10
  225. package/dist/development/core/predictive-search/search.mjs +34 -0
  226. package/dist/development/core/predictive-search/search.mjs.map +1 -1
  227. package/dist/development/core/predictive-search/server-handlers.d.mts +31 -5
  228. package/dist/development/core/predictive-search/server-handlers.mjs +5 -3
  229. package/dist/development/core/predictive-search/server-handlers.mjs.map +1 -1
  230. package/dist/development/core/predictive-search/store.d.mts +3 -1
  231. package/dist/development/core/predictive-search/store.mjs.map +1 -1
  232. package/dist/development/core/predictive-search/url.d.mts +50 -8
  233. package/dist/development/core/predictive-search/url.mjs +9 -0
  234. package/dist/development/core/predictive-search/url.mjs.map +1 -1
  235. package/dist/development/core/product/form.d.mts +21 -2
  236. package/dist/development/core/product/form.mjs +13 -0
  237. package/dist/development/core/product/form.mjs.map +1 -1
  238. package/dist/development/core/product/index.d.mts +1 -1
  239. package/dist/development/core/product/options.d.mts +2 -2
  240. package/dist/development/core/product/options.mjs +2 -2
  241. package/dist/development/core/product/options.mjs.map +1 -1
  242. package/dist/development/core/product/product-form.d.mts +33 -1
  243. package/dist/development/core/product/product-form.mjs +30 -0
  244. package/dist/development/core/product/product-form.mjs.map +1 -1
  245. package/dist/development/core/product/state.d.mts +41 -0
  246. package/dist/development/core/product/url.d.mts +6 -0
  247. package/dist/development/core/product/url.mjs.map +1 -1
  248. package/dist/development/core/request-context.d.mts +8 -5
  249. package/dist/development/core/request-context.mjs +17 -39
  250. package/dist/development/core/request-context.mjs.map +1 -1
  251. package/dist/development/core/request-routing/handle-shopify-routes.mjs +4 -1
  252. package/dist/development/core/request-routing/handle-shopify-routes.mjs.map +1 -1
  253. package/dist/development/core/request-routing/interceptors/ajax-api.mjs +1 -1
  254. package/dist/development/core/request-routing/interceptors/api-proxy.mjs +1 -1
  255. package/dist/development/core/request-routing/interceptors/checkout.mjs +22 -6
  256. package/dist/development/core/request-routing/interceptors/checkout.mjs.map +1 -1
  257. package/dist/development/core/request-routing/interceptors/mcp-proxy.mjs +1 -1
  258. package/dist/development/core/request-routing/interceptors/proxy.mjs +36 -10
  259. package/dist/development/core/request-routing/interceptors/proxy.mjs.map +1 -1
  260. package/dist/development/core/request-routing/interceptors/query-param-redirect.mjs +5 -11
  261. package/dist/development/core/request-routing/interceptors/query-param-redirect.mjs.map +1 -1
  262. package/dist/development/core/request-routing/interceptors/sfapi-proxy.mjs +19 -1
  263. package/dist/development/core/request-routing/interceptors/sfapi-proxy.mjs.map +1 -1
  264. package/dist/development/core/request-routing/interceptors/ucp-mcp-proxy.mjs +35 -0
  265. package/dist/development/core/request-routing/interceptors/ucp-mcp-proxy.mjs.map +1 -0
  266. package/dist/development/core/request-routing/interceptors/well-known.mjs +1 -1
  267. package/dist/development/core/shopify-scripts/analytics.mjs +2 -2
  268. package/dist/development/core/shopify-scripts/analytics.mjs.map +1 -1
  269. package/dist/development/core/shopify-scripts/constants.mjs +4 -2
  270. package/dist/development/core/shopify-scripts/constants.mjs.map +1 -1
  271. package/dist/development/core/shopify-scripts/global.mjs +9 -4
  272. package/dist/development/core/shopify-scripts/global.mjs.map +1 -1
  273. package/dist/development/core/shopify-scripts/index.d.mts +1 -0
  274. package/dist/development/core/shopify-scripts/index.mjs +14 -12
  275. package/dist/development/core/shopify-scripts/index.mjs.map +1 -1
  276. package/dist/development/core/shopify-scripts/initialize.d.mts +1 -0
  277. package/dist/development/core/shopify-scripts/initialize.mjs +10 -3
  278. package/dist/development/core/shopify-scripts/initialize.mjs.map +1 -1
  279. package/dist/development/core/shopify-scripts/types.d.mts +6 -0
  280. package/dist/development/core/url.mjs +21 -2
  281. package/dist/development/core/url.mjs.map +1 -1
  282. package/dist/development/customer-account/session.d.mts +69 -13
  283. package/dist/development/customer-account/session.mjs +4 -0
  284. package/dist/development/customer-account/session.mjs.map +1 -1
  285. package/dist/development/globals.d.mts +6 -5
  286. package/dist/development/graphql/generated/graphql-env.d.mts +459 -16
  287. package/dist/development/graphql/generated/storefront-api-types.d.mts +1 -1
  288. package/dist/development/graphql/graphql.d.mts +33 -0
  289. package/dist/development/graphql/graphql.mjs +30 -0
  290. package/dist/development/graphql/graphql.mjs.map +1 -1
  291. package/dist/development/graphql/type-resolver.d.mts +14 -0
  292. package/dist/development/react/cart.d.mts +85 -14
  293. package/dist/development/react/cart.mjs +123 -3
  294. package/dist/development/react/cart.mjs.map +1 -1
  295. package/dist/development/react/collection.d.mts +2 -4
  296. package/dist/development/react/collection.mjs.map +1 -1
  297. package/dist/development/react/index.d.mts +8 -6
  298. package/dist/development/react/index.mjs +2 -2
  299. package/dist/development/react/predictive-search.d.mts +68 -7
  300. package/dist/development/react/predictive-search.mjs +54 -12
  301. package/dist/development/react/predictive-search.mjs.map +1 -1
  302. package/dist/development/react/product.d.mts +1 -0
  303. package/dist/development/react/product.mjs +5 -2
  304. package/dist/development/react/product.mjs.map +1 -1
  305. package/dist/development/react/shopify-scripts.mjs +1 -0
  306. package/dist/development/react/shopify-scripts.mjs.map +1 -1
  307. package/dist/development/vue/cart.d.mts +85 -6
  308. package/dist/development/vue/cart.mjs +95 -0
  309. package/dist/development/vue/cart.mjs.map +1 -1
  310. package/dist/development/vue/collection.d.mts +83 -5
  311. package/dist/development/vue/collection.mjs +52 -0
  312. package/dist/development/vue/collection.mjs.map +1 -1
  313. package/dist/development/vue/index.d.mts +6 -4
  314. package/dist/development/vue/predictive-search.d.mts +53 -6
  315. package/dist/development/vue/predictive-search.mjs +33 -0
  316. package/dist/development/vue/predictive-search.mjs.map +1 -1
  317. package/dist/development/vue/product.d.mts +6 -2
  318. package/dist/development/vue/product.mjs.map +1 -1
  319. package/dist/development/vue/shopify-scripts.d.mts +30 -3
  320. package/dist/development/vue/shopify-scripts.mjs +6 -0
  321. package/dist/development/vue/shopify-scripts.mjs.map +1 -1
  322. package/dist/globals.d.mts +6 -5
  323. package/dist/graphql/generated/customer-account-graphql-env.d.mts +1717 -1090
  324. package/dist/graphql/generated/graphql-env.d.mts +459 -16
  325. package/dist/graphql/generated/storefront-api-types.d.mts +1 -1
  326. package/dist/graphql/graphql.d.mts +33 -0
  327. package/dist/graphql/graphql.mjs +30 -0
  328. package/dist/graphql/graphql.mjs.map +1 -1
  329. package/dist/graphql/type-resolver.d.mts +14 -0
  330. package/dist/react/cart.d.mts +85 -14
  331. package/dist/react/cart.mjs +123 -3
  332. package/dist/react/cart.mjs.map +1 -1
  333. package/dist/react/collection.d.mts +2 -4
  334. package/dist/react/collection.mjs.map +1 -1
  335. package/dist/react/index.d.mts +8 -6
  336. package/dist/react/index.mjs +2 -2
  337. package/dist/react/predictive-search.d.mts +68 -7
  338. package/dist/react/predictive-search.mjs +54 -12
  339. package/dist/react/predictive-search.mjs.map +1 -1
  340. package/dist/react/product.d.mts +1 -0
  341. package/dist/react/product.mjs +5 -2
  342. package/dist/react/product.mjs.map +1 -1
  343. package/dist/react/shopify-scripts.mjs +1 -0
  344. package/dist/react/shopify-scripts.mjs.map +1 -1
  345. package/dist/storefront-api-types.d.ts +165 -20
  346. package/dist/storefront.schema.json +782 -57
  347. package/dist/vite/customer-account.mjs +191 -0
  348. package/dist/vite/customer-account.mjs.map +1 -0
  349. package/dist/vite/local-https.mjs +13 -29
  350. package/dist/vite/local-https.mjs.map +1 -1
  351. package/dist/vite/mkcert.mjs +1 -1
  352. package/dist/vue/cart.d.mts +85 -6
  353. package/dist/vue/cart.mjs +95 -0
  354. package/dist/vue/cart.mjs.map +1 -1
  355. package/dist/vue/collection.d.mts +83 -5
  356. package/dist/vue/collection.mjs +52 -0
  357. package/dist/vue/collection.mjs.map +1 -1
  358. package/dist/vue/index.d.mts +6 -4
  359. package/dist/vue/predictive-search.d.mts +53 -6
  360. package/dist/vue/predictive-search.mjs +33 -0
  361. package/dist/vue/predictive-search.mjs.map +1 -1
  362. package/dist/vue/product.d.mts +6 -2
  363. package/dist/vue/product.mjs.map +1 -1
  364. package/dist/vue/shopify-scripts.d.mts +31 -4
  365. package/dist/vue/shopify-scripts.mjs +6 -0
  366. package/dist/vue/shopify-scripts.mjs.map +1 -1
  367. package/package.json +5 -2
  368. package/skills/hydrogen-analytics/SKILL.md +6 -5
  369. package/skills/hydrogen-analytics/references/custom-consent.md +52 -0
  370. package/skills/hydrogen-analytics/references/react.md +1 -1
  371. package/skills/hydrogen-cart-metafields/SKILL.md +133 -0
  372. package/skills/hydrogen-cart-ui/SKILL.md +2 -1
  373. package/skills/hydrogen-customer-account/SKILL.md +3 -3
  374. package/skills/hydrogen-local-https/SKILL.md +22 -7
  375. package/skills/hydrogen-request-handlers/SKILL.md +5 -5
  376. package/skills/hydrogen-request-handlers/references/nuxt.md +0 -6
  377. package/skills/hydrogen-setup/references/analytics.md +24 -23
  378. package/skills/hydrogen-setup/steps/1-inspect-app.md +1 -1
  379. package/skills/hydrogen-setup/steps/11-verify.md +1 -0
  380. package/skills/hydrogen-setup/steps/2-scaffold.md +22 -1
  381. package/skills/hydrogen-smoke-test/SKILL.md +2 -2
  382. package/skills/hydrogen-storefront-client/SKILL.md +4 -2
  383. package/skills/hydrogen-variant-form/SKILL.md +10 -4
  384. package/ts-plugin/package.json +5 -0
  385. package/dist/core/shopify-scripts/consent.mjs +0 -17
  386. package/dist/core/shopify-scripts/consent.mjs.map +0 -1
  387. package/dist/core/shopify-scripts/deprecated-cookies.mjs +0 -97
  388. package/dist/core/shopify-scripts/deprecated-cookies.mjs.map +0 -1
  389. package/dist/core/shopify-scripts/utils/cookie-domain.mjs +0 -43
  390. package/dist/core/shopify-scripts/utils/cookie-domain.mjs.map +0 -1
  391. package/dist/core/shopify-scripts/utils/tracking-values.mjs +0 -65
  392. package/dist/core/shopify-scripts/utils/tracking-values.mjs.map +0 -1
  393. package/dist/core/shopify-scripts/utils/uuid.mjs +0 -17
  394. package/dist/core/shopify-scripts/utils/uuid.mjs.map +0 -1
  395. package/dist/development/core/shopify-scripts/consent.mjs +0 -17
  396. package/dist/development/core/shopify-scripts/consent.mjs.map +0 -1
  397. package/dist/development/core/shopify-scripts/deprecated-cookies.mjs +0 -97
  398. package/dist/development/core/shopify-scripts/deprecated-cookies.mjs.map +0 -1
  399. package/dist/development/core/shopify-scripts/utils/cookie-domain.mjs +0 -43
  400. package/dist/development/core/shopify-scripts/utils/cookie-domain.mjs.map +0 -1
  401. package/dist/development/core/shopify-scripts/utils/tracking-values.mjs +0 -65
  402. package/dist/development/core/shopify-scripts/utils/tracking-values.mjs.map +0 -1
  403. package/dist/development/core/shopify-scripts/utils/uuid.mjs +0 -17
  404. package/dist/development/core/shopify-scripts/utils/uuid.mjs.map +0 -1
@@ -1,4 +1,19 @@
1
1
  //#region src/core/cart/cookie.d.ts
2
+ /**
3
+ * Serializes a cart GID into a `Set-Cookie` header value.
4
+ *
5
+ * Strips the `gid://shopify/Cart/` prefix before encoding — the cookie stores
6
+ * only the opaque suffix to keep the header compact. The cookie is set with
7
+ * `Path=/; SameSite=Lax` and a 14-day `Max-Age`.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const cookie = createCartCookie("gid://shopify/Cart/abc123");
12
+ * // "cart=abc123; Path=/; SameSite=Lax; Max-Age=1209600"
13
+ *
14
+ * headers.append("Set-Cookie", cookie);
15
+ * ```
16
+ */
2
17
  declare function createCartCookie(cartId: string): string;
3
18
  //#endregion
4
19
  export { createCartCookie };
@@ -15,6 +15,21 @@ function getCartIdFromCookie(input) {
15
15
  if (!token) return null;
16
16
  return normalizeCartId(token);
17
17
  }
18
+ /**
19
+ * Serializes a cart GID into a `Set-Cookie` header value.
20
+ *
21
+ * Strips the `gid://shopify/Cart/` prefix before encoding — the cookie stores
22
+ * only the opaque suffix to keep the header compact. The cookie is set with
23
+ * `Path=/; SameSite=Lax` and a 14-day `Max-Age`.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const cookie = createCartCookie("gid://shopify/Cart/abc123");
28
+ * // "cart=abc123; Path=/; SameSite=Lax; Max-Age=1209600"
29
+ *
30
+ * headers.append("Set-Cookie", cookie);
31
+ * ```
32
+ */
18
33
  function createCartCookie(cartId) {
19
34
  const token = cartId.startsWith(CART_GID_PREFIX) ? cartId.slice(19) : cartId;
20
35
  return `${COOKIE_NAME}=${encodeURIComponent(token)}; Path=/; SameSite=Lax; Max-Age=${MAX_AGE_IN_SECONDS}`;
@@ -1 +1 @@
1
- {"version":3,"file":"cookie.mjs","names":[],"sources":["../../../src/core/cart/cookie.ts"],"sourcesContent":["const COOKIE_NAME = \"cart\";\nconst MAX_AGE_IN_SECONDS = 1209600; // 14 days\nconst CART_GID_PREFIX = \"gid://shopify/Cart/\";\n\ntype CartCookieSource = Request | { cookie?: string };\n\nexport function normalizeCartId(cartId: string | null | undefined): string | null {\n if (!cartId) return null;\n return cartId.startsWith(CART_GID_PREFIX) ? cartId : CART_GID_PREFIX + cartId;\n}\n\nexport function getCartIdFromCookie(input: CartCookieSource): string | null {\n const header = input instanceof Request ? input.headers.get(\"cookie\") : input.cookie;\n if (!header) return null;\n\n const match = header.match(new RegExp(`(?:^|;\\\\s*)${COOKIE_NAME}=([^;]*)`));\n if (!match || !match[1]) return null;\n\n const token = decodeURIComponent(match[1]);\n if (!token) return null;\n\n return normalizeCartId(token);\n}\n\nexport function createCartCookie(cartId: string): string {\n const token = cartId.startsWith(CART_GID_PREFIX) ? cartId.slice(CART_GID_PREFIX.length) : cartId;\n const encoded = encodeURIComponent(token);\n return `${COOKIE_NAME}=${encoded}; Path=/; SameSite=Lax; Max-Age=${MAX_AGE_IN_SECONDS}`;\n}\n\nexport function createExpiredCartCookie(): string {\n return `${COOKIE_NAME}=; Path=/; SameSite=Lax; Max-Age=0`;\n}\n"],"mappings":";AAAA,MAAM,cAAc;AACpB,MAAM,qBAAqB;AAC3B,MAAM,kBAAkB;AAIxB,SAAgB,gBAAgB,QAAkD;AAChF,KAAI,CAAC,OAAQ,QAAO;AACpB,QAAO,OAAO,WAAW,gBAAgB,GAAG,SAAS,kBAAkB;;AAGzE,SAAgB,oBAAoB,OAAwC;CAC1E,MAAM,SAAS,iBAAiB,UAAU,MAAM,QAAQ,IAAI,SAAS,GAAG,MAAM;AAC9E,KAAI,CAAC,OAAQ,QAAO;CAEpB,MAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,cAAc,YAAY,UAAU,CAAC;AAC3E,KAAI,CAAC,SAAS,CAAC,MAAM,GAAI,QAAO;CAEhC,MAAM,QAAQ,mBAAmB,MAAM,GAAG;AAC1C,KAAI,CAAC,MAAO,QAAO;AAEnB,QAAO,gBAAgB,MAAM;;AAG/B,SAAgB,iBAAiB,QAAwB;CACvD,MAAM,QAAQ,OAAO,WAAW,gBAAgB,GAAG,OAAO,MAAM,GAAuB,GAAG;AAE1F,QAAO,GAAG,YAAY,GADN,mBAAmB,MACH,CAAC,kCAAkC;;AAGrE,SAAgB,0BAAkC;AAChD,QAAO,GAAG,YAAY"}
1
+ {"version":3,"file":"cookie.mjs","names":[],"sources":["../../../src/core/cart/cookie.ts"],"sourcesContent":["const COOKIE_NAME = \"cart\";\nconst MAX_AGE_IN_SECONDS = 1209600; // 14 days\nconst CART_GID_PREFIX = \"gid://shopify/Cart/\";\n\ntype CartCookieSource = Request | { cookie?: string };\n\nexport function normalizeCartId(cartId: string | null | undefined): string | null {\n if (!cartId) return null;\n return cartId.startsWith(CART_GID_PREFIX) ? cartId : CART_GID_PREFIX + cartId;\n}\n\nexport function getCartIdFromCookie(input: CartCookieSource): string | null {\n const header = input instanceof Request ? input.headers.get(\"cookie\") : input.cookie;\n if (!header) return null;\n\n const match = header.match(new RegExp(`(?:^|;\\\\s*)${COOKIE_NAME}=([^;]*)`));\n if (!match || !match[1]) return null;\n\n const token = decodeURIComponent(match[1]);\n if (!token) return null;\n\n return normalizeCartId(token);\n}\n\n/**\n * Serializes a cart GID into a `Set-Cookie` header value.\n *\n * Strips the `gid://shopify/Cart/` prefix before encoding — the cookie stores\n * only the opaque suffix to keep the header compact. The cookie is set with\n * `Path=/; SameSite=Lax` and a 14-day `Max-Age`.\n *\n * @example\n * ```ts\n * const cookie = createCartCookie(\"gid://shopify/Cart/abc123\");\n * // \"cart=abc123; Path=/; SameSite=Lax; Max-Age=1209600\"\n *\n * headers.append(\"Set-Cookie\", cookie);\n * ```\n */\nexport function createCartCookie(cartId: string): string {\n const token = cartId.startsWith(CART_GID_PREFIX) ? cartId.slice(CART_GID_PREFIX.length) : cartId;\n const encoded = encodeURIComponent(token);\n return `${COOKIE_NAME}=${encoded}; Path=/; SameSite=Lax; Max-Age=${MAX_AGE_IN_SECONDS}`;\n}\n\nexport function createExpiredCartCookie(): string {\n return `${COOKIE_NAME}=; Path=/; SameSite=Lax; Max-Age=0`;\n}\n"],"mappings":";AAAA,MAAM,cAAc;AACpB,MAAM,qBAAqB;AAC3B,MAAM,kBAAkB;AAIxB,SAAgB,gBAAgB,QAAkD;AAChF,KAAI,CAAC,OAAQ,QAAO;AACpB,QAAO,OAAO,WAAW,gBAAgB,GAAG,SAAS,kBAAkB;;AAGzE,SAAgB,oBAAoB,OAAwC;CAC1E,MAAM,SAAS,iBAAiB,UAAU,MAAM,QAAQ,IAAI,SAAS,GAAG,MAAM;AAC9E,KAAI,CAAC,OAAQ,QAAO;CAEpB,MAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,cAAc,YAAY,UAAU,CAAC;AAC3E,KAAI,CAAC,SAAS,CAAC,MAAM,GAAI,QAAO;CAEhC,MAAM,QAAQ,mBAAmB,MAAM,GAAG;AAC1C,KAAI,CAAC,MAAO,QAAO;AAEnB,QAAO,gBAAgB,MAAM;;;;;;;;;;;;;;;;;AAkB/B,SAAgB,iBAAiB,QAAwB;CACvD,MAAM,QAAQ,OAAO,WAAW,gBAAgB,GAAG,OAAO,MAAM,GAAuB,GAAG;AAE1F,QAAO,GAAG,YAAY,GADN,mBAAmB,MACH,CAAC,kCAAkC;;AAGrE,SAAgB,0BAAkC;AAChD,QAAO,GAAG,YAAY"}
@@ -1,10 +1,24 @@
1
1
  //#region src/core/cart/form.d.ts
2
+ /**
3
+ * HTML attributes for a hidden submit button that triggers the `"set"` intent.
4
+ *
5
+ * Used by {@link CartFormRegister} when `register("set")` is called. The button
6
+ * must be the first submit button in the form for `attachQuantityInput`
7
+ * to auto-submit on quantity changes.
8
+ */
2
9
  interface SetButtonAttributes {
3
10
  name: "intent";
4
11
  value: "set";
5
12
  type: "submit";
6
13
  hidden: true;
7
14
  }
15
+ /**
16
+ * HTML attributes for a quantity `<input>` in interactive mode.
17
+ *
18
+ * Returned by `register("quantity", { value, interactive: true })`. Uses
19
+ * `type: "text"` with `inputMode: "numeric"` for mobile number keyboards
20
+ * without the native spinner arrows.
21
+ */
8
22
  interface QuantityInputAttributes {
9
23
  name: "quantity";
10
24
  value: string;
@@ -15,6 +29,35 @@ interface QuantityInputAttributes {
15
29
  autoCorrect: "off";
16
30
  }
17
31
  type AttributeValueName = `attributes.${string}`;
32
+ /**
33
+ * Overloaded function that produces the correct HTML attributes for any cart
34
+ * form field or action button.
35
+ *
36
+ * Call with a **field name** (`"lineId"`, `"quantity"`, `"merchandiseId"`,
37
+ * `"discountCode"`, `"note"`, `"attributeValue"`, `"sellingPlanId"`) to get
38
+ * input attributes, or with an **action name** (`"add"`, `"increase"`,
39
+ * `"decrease"`, `"remove"`, `"set"`, `"discount-apply"`, `"discount-remove"`,
40
+ * `"note-update"`, `"attributes-update"`) to get submit button attributes.
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * const register = createCartFormRegister();
45
+ *
46
+ * // Line ID field (register returns readOnly; add type="hidden" to hide it)
47
+ * <input {...register("lineId", { value: line.id })} />
48
+ *
49
+ * // Interactive quantity input (pair with attachQuantityInput to auto-submit on change)
50
+ * <input {...register("quantity", { value: line.quantity, interactive: true })} />
51
+ *
52
+ * // Hidden submit button for the "set" intent
53
+ * <button {...register("set")} />
54
+ *
55
+ * // Increase quantity button
56
+ * <button {...register("increase")}>+</button>
57
+ * ```
58
+ *
59
+ * @throws `TypeError` when called with `"attributeValue"` and no non-empty `key`.
60
+ */
18
61
  type CartFormRegister = {
19
62
  (field: "lineId", opts: {
20
63
  value: string;
@@ -124,6 +167,24 @@ type CartFormRegister = {
124
167
  value: "attributes-update";
125
168
  };
126
169
  };
170
+ /**
171
+ * Creates a {@link CartFormRegister} function for generating cart form field attributes.
172
+ *
173
+ * The returned `register` function is stateless — it can be called multiple times
174
+ * and shared across components. Framework hooks (`useCartForm`) wrap this with
175
+ * additional conveniences like `formProps()` and interactive `ref` wiring.
176
+ *
177
+ * @example
178
+ * ```ts
179
+ * const register = createCartFormRegister();
180
+ *
181
+ * const lineIdAttrs = register("lineId", { value: "gid://shopify/CartLine/123" });
182
+ * // → { name: "lineId", value: "gid://shopify/CartLine/123", readOnly: true }
183
+ *
184
+ * const addAttrs = register("add");
185
+ * // → { name: "intent", value: "add" }
186
+ * ```
187
+ */
127
188
  declare function createCartFormRegister(): CartFormRegister;
128
189
  //#endregion
129
190
  export { CartFormRegister, QuantityInputAttributes, SetButtonAttributes, createCartFormRegister };
@@ -53,6 +53,24 @@ function createFieldAttributes(name, opts) {
53
53
  if (name === "lineId") attrs.readOnly = true;
54
54
  return attrs;
55
55
  }
56
+ /**
57
+ * Creates a {@link CartFormRegister} function for generating cart form field attributes.
58
+ *
59
+ * The returned `register` function is stateless — it can be called multiple times
60
+ * and shared across components. Framework hooks (`useCartForm`) wrap this with
61
+ * additional conveniences like `formProps()` and interactive `ref` wiring.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const register = createCartFormRegister();
66
+ *
67
+ * const lineIdAttrs = register("lineId", { value: "gid://shopify/CartLine/123" });
68
+ * // → { name: "lineId", value: "gid://shopify/CartLine/123", readOnly: true }
69
+ *
70
+ * const addAttrs = register("add");
71
+ * // → { name: "intent", value: "add" }
72
+ * ```
73
+ */
56
74
  function createCartFormRegister() {
57
75
  return ((nameOrAction, opts) => {
58
76
  if (nameOrAction === "attributeValue") return createAttributeValueAttributes(opts);
@@ -1 +1 @@
1
- {"version":3,"file":"form.mjs","names":[],"sources":["../../../src/core/cart/form.ts"],"sourcesContent":["export interface SetButtonAttributes {\n name: \"intent\";\n value: \"set\";\n type: \"submit\";\n hidden: true;\n}\n\nexport interface QuantityInputAttributes {\n name: \"quantity\";\n value: string;\n type: \"text\";\n inputMode: \"numeric\";\n pattern: string;\n autoComplete: \"off\";\n autoCorrect: \"off\";\n}\n\ntype AttributeValueName = `attributes.${string}`;\n\nexport type CartFormRegister = {\n (field: \"lineId\", opts: { value: string }): { name: \"lineId\"; value: string; readOnly: true };\n (field: \"quantity\", opts: { value: number | string; interactive: true }): QuantityInputAttributes;\n (\n field: \"quantity\",\n opts: { value: number | string; interactive?: false },\n ): { name: \"quantity\"; value: string };\n (field: \"quantity\", opts: { defaultValue: number }): { name: \"quantity\"; defaultValue: string };\n (field: \"discountCode\", opts: { value: string }): { name: \"discountCode\"; value: string };\n (\n field: \"discountCode\",\n opts: { defaultValue: string },\n ): { name: \"discountCode\"; defaultValue: string };\n (field: \"merchandiseId\", opts: { value: string }): { name: \"merchandiseId\"; value: string };\n (field: \"note\", opts: { value: string }): { name: \"note\"; value: string };\n (field: \"note\", opts: { defaultValue: string }): { name: \"note\"; defaultValue: string };\n (\n field: \"attributeValue\",\n opts: { key: string; value: string },\n ): { name: AttributeValueName; value: string };\n (\n field: \"attributeValue\",\n opts: { key: string; defaultValue: string },\n ): { name: AttributeValueName; defaultValue: string };\n (field: \"sellingPlanId\", opts: { value: string }): { name: \"sellingPlanId\"; value: string };\n (action: \"add\"): { name: \"intent\"; value: \"add\" };\n (action: \"increase\"): { name: \"intent\"; value: \"increase\" };\n (action: \"decrease\"): { name: \"intent\"; value: \"decrease\" };\n (action: \"remove\"): { name: \"intent\"; value: \"remove\" };\n (action: \"set\"): SetButtonAttributes;\n (action: \"discount-apply\"): { name: \"intent\"; value: \"discount-apply\" };\n (action: \"discount-remove\"): { name: \"intent\"; value: \"discount-remove\" };\n (action: \"note-update\"): { name: \"intent\"; value: \"note-update\" };\n (action: \"attributes-update\"): { name: \"intent\"; value: \"attributes-update\" };\n};\n\nconst FIELD_REGISTERS = new Set([\n \"lineId\",\n \"quantity\",\n \"discountCode\",\n \"merchandiseId\",\n \"note\",\n \"sellingPlanId\",\n]);\n\nconst ATTRIBUTE_VALUE_NAME_PREFIX = \"attributes.\";\n\ntype RegisterOptions = {\n key?: string;\n value?: string | number;\n defaultValue?: string;\n interactive?: boolean;\n};\n\nexport function getCartAttributeFormEntries(\n formData: FormData,\n): Array<{ key: string; value: FormDataEntryValue }> {\n const attributes: Array<{ key: string; value: FormDataEntryValue }> = [];\n for (const [name, value] of formData.entries()) {\n if (!name.startsWith(ATTRIBUTE_VALUE_NAME_PREFIX)) continue;\n attributes.push({ key: name.slice(ATTRIBUTE_VALUE_NAME_PREFIX.length), value });\n }\n return attributes;\n}\n\nfunction createAttributeValueAttributes(opts?: RegisterOptions) {\n if (!opts?.key) throw new TypeError('Cart attribute values require a non-empty \"key\".');\n const name = `${ATTRIBUTE_VALUE_NAME_PREFIX}${opts.key}` as AttributeValueName;\n if (\"defaultValue\" in opts) {\n return { name, defaultValue: String(opts.defaultValue) };\n }\n return { name, value: String(opts.value ?? \"\") };\n}\n\nfunction createFieldAttributes(name: string, opts?: RegisterOptions) {\n if (opts && \"defaultValue\" in opts) {\n return { name, defaultValue: String(opts.defaultValue) };\n }\n\n const value = String(opts?.value ?? \"\");\n\n if (name === \"quantity\" && opts?.interactive) {\n return {\n name: \"quantity\",\n value,\n type: \"text\",\n inputMode: \"numeric\",\n pattern: \"\\\\d+\",\n autoComplete: \"off\",\n autoCorrect: \"off\",\n } satisfies QuantityInputAttributes;\n }\n\n const attrs: Record<string, string | boolean> = { name, value };\n if (name === \"lineId\") attrs.readOnly = true;\n return attrs;\n}\n\nexport function createCartFormRegister(): CartFormRegister {\n return ((nameOrAction: string, opts?: RegisterOptions) => {\n if (nameOrAction === \"attributeValue\") {\n return createAttributeValueAttributes(opts);\n }\n\n if (FIELD_REGISTERS.has(nameOrAction)) {\n return createFieldAttributes(nameOrAction, opts);\n }\n\n if (nameOrAction === \"set\") {\n return {\n name: \"intent\",\n value: \"set\",\n type: \"submit\",\n hidden: true,\n } satisfies SetButtonAttributes;\n }\n\n return { name: \"intent\", value: nameOrAction };\n }) as CartFormRegister;\n}\n"],"mappings":";AAuDA,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,8BAA8B;AASpC,SAAgB,4BACd,UACmD;CACnD,MAAM,aAAgE,EAAE;AACxE,MAAK,MAAM,CAAC,MAAM,UAAU,SAAS,SAAS,EAAE;AAC9C,MAAI,CAAC,KAAK,WAAW,4BAA4B,CAAE;AACnD,aAAW,KAAK;GAAE,KAAK,KAAK,MAAM,GAAmC;GAAE;GAAO,CAAC;;AAEjF,QAAO;;AAGT,SAAS,+BAA+B,MAAwB;AAC9D,KAAI,CAAC,MAAM,IAAK,OAAM,IAAI,UAAU,qDAAmD;CACvF,MAAM,OAAO,GAAG,8BAA8B,KAAK;AACnD,KAAI,kBAAkB,KACpB,QAAO;EAAE;EAAM,cAAc,OAAO,KAAK,aAAa;EAAE;AAE1D,QAAO;EAAE;EAAM,OAAO,OAAO,KAAK,SAAS,GAAG;EAAE;;AAGlD,SAAS,sBAAsB,MAAc,MAAwB;AACnE,KAAI,QAAQ,kBAAkB,KAC5B,QAAO;EAAE;EAAM,cAAc,OAAO,KAAK,aAAa;EAAE;CAG1D,MAAM,QAAQ,OAAO,MAAM,SAAS,GAAG;AAEvC,KAAI,SAAS,cAAc,MAAM,YAC/B,QAAO;EACL,MAAM;EACN;EACA,MAAM;EACN,WAAW;EACX,SAAS;EACT,cAAc;EACd,aAAa;EACd;CAGH,MAAM,QAA0C;EAAE;EAAM;EAAO;AAC/D,KAAI,SAAS,SAAU,OAAM,WAAW;AACxC,QAAO;;AAGT,SAAgB,yBAA2C;AACzD,UAAS,cAAsB,SAA2B;AACxD,MAAI,iBAAiB,iBACnB,QAAO,+BAA+B,KAAK;AAG7C,MAAI,gBAAgB,IAAI,aAAa,CACnC,QAAO,sBAAsB,cAAc,KAAK;AAGlD,MAAI,iBAAiB,MACnB,QAAO;GACL,MAAM;GACN,OAAO;GACP,MAAM;GACN,QAAQ;GACT;AAGH,SAAO;GAAE,MAAM;GAAU,OAAO;GAAc"}
1
+ {"version":3,"file":"form.mjs","names":[],"sources":["../../../src/core/cart/form.ts"],"sourcesContent":["/**\n * HTML attributes for a hidden submit button that triggers the `\"set\"` intent.\n *\n * Used by {@link CartFormRegister} when `register(\"set\")` is called. The button\n * must be the first submit button in the form for `attachQuantityInput`\n * to auto-submit on quantity changes.\n */\nexport interface SetButtonAttributes {\n name: \"intent\";\n value: \"set\";\n type: \"submit\";\n hidden: true;\n}\n\n/**\n * HTML attributes for a quantity `<input>` in interactive mode.\n *\n * Returned by `register(\"quantity\", { value, interactive: true })`. Uses\n * `type: \"text\"` with `inputMode: \"numeric\"` for mobile number keyboards\n * without the native spinner arrows.\n */\nexport interface QuantityInputAttributes {\n name: \"quantity\";\n value: string;\n type: \"text\";\n inputMode: \"numeric\";\n pattern: string;\n autoComplete: \"off\";\n autoCorrect: \"off\";\n}\n\ntype AttributeValueName = `attributes.${string}`;\n\n/**\n * Overloaded function that produces the correct HTML attributes for any cart\n * form field or action button.\n *\n * Call with a **field name** (`\"lineId\"`, `\"quantity\"`, `\"merchandiseId\"`,\n * `\"discountCode\"`, `\"note\"`, `\"attributeValue\"`, `\"sellingPlanId\"`) to get\n * input attributes, or with an **action name** (`\"add\"`, `\"increase\"`,\n * `\"decrease\"`, `\"remove\"`, `\"set\"`, `\"discount-apply\"`, `\"discount-remove\"`,\n * `\"note-update\"`, `\"attributes-update\"`) to get submit button attributes.\n *\n * @example\n * ```tsx\n * const register = createCartFormRegister();\n *\n * // Line ID field (register returns readOnly; add type=\"hidden\" to hide it)\n * <input {...register(\"lineId\", { value: line.id })} />\n *\n * // Interactive quantity input (pair with attachQuantityInput to auto-submit on change)\n * <input {...register(\"quantity\", { value: line.quantity, interactive: true })} />\n *\n * // Hidden submit button for the \"set\" intent\n * <button {...register(\"set\")} />\n *\n * // Increase quantity button\n * <button {...register(\"increase\")}>+</button>\n * ```\n *\n * @throws `TypeError` when called with `\"attributeValue\"` and no non-empty `key`.\n */\nexport type CartFormRegister = {\n (field: \"lineId\", opts: { value: string }): { name: \"lineId\"; value: string; readOnly: true };\n (field: \"quantity\", opts: { value: number | string; interactive: true }): QuantityInputAttributes;\n (\n field: \"quantity\",\n opts: { value: number | string; interactive?: false },\n ): { name: \"quantity\"; value: string };\n (field: \"quantity\", opts: { defaultValue: number }): { name: \"quantity\"; defaultValue: string };\n (field: \"discountCode\", opts: { value: string }): { name: \"discountCode\"; value: string };\n (\n field: \"discountCode\",\n opts: { defaultValue: string },\n ): { name: \"discountCode\"; defaultValue: string };\n (field: \"merchandiseId\", opts: { value: string }): { name: \"merchandiseId\"; value: string };\n (field: \"note\", opts: { value: string }): { name: \"note\"; value: string };\n (field: \"note\", opts: { defaultValue: string }): { name: \"note\"; defaultValue: string };\n (\n field: \"attributeValue\",\n opts: { key: string; value: string },\n ): { name: AttributeValueName; value: string };\n (\n field: \"attributeValue\",\n opts: { key: string; defaultValue: string },\n ): { name: AttributeValueName; defaultValue: string };\n (field: \"sellingPlanId\", opts: { value: string }): { name: \"sellingPlanId\"; value: string };\n (action: \"add\"): { name: \"intent\"; value: \"add\" };\n (action: \"increase\"): { name: \"intent\"; value: \"increase\" };\n (action: \"decrease\"): { name: \"intent\"; value: \"decrease\" };\n (action: \"remove\"): { name: \"intent\"; value: \"remove\" };\n (action: \"set\"): SetButtonAttributes;\n (action: \"discount-apply\"): { name: \"intent\"; value: \"discount-apply\" };\n (action: \"discount-remove\"): { name: \"intent\"; value: \"discount-remove\" };\n (action: \"note-update\"): { name: \"intent\"; value: \"note-update\" };\n (action: \"attributes-update\"): { name: \"intent\"; value: \"attributes-update\" };\n};\n\nconst FIELD_REGISTERS = new Set([\n \"lineId\",\n \"quantity\",\n \"discountCode\",\n \"merchandiseId\",\n \"note\",\n \"sellingPlanId\",\n]);\n\nconst ATTRIBUTE_VALUE_NAME_PREFIX = \"attributes.\";\n\ntype RegisterOptions = {\n key?: string;\n value?: string | number;\n defaultValue?: string;\n interactive?: boolean;\n};\n\nexport function getCartAttributeFormEntries(\n formData: FormData,\n): Array<{ key: string; value: FormDataEntryValue }> {\n const attributes: Array<{ key: string; value: FormDataEntryValue }> = [];\n for (const [name, value] of formData.entries()) {\n if (!name.startsWith(ATTRIBUTE_VALUE_NAME_PREFIX)) continue;\n attributes.push({ key: name.slice(ATTRIBUTE_VALUE_NAME_PREFIX.length), value });\n }\n return attributes;\n}\n\nfunction createAttributeValueAttributes(opts?: RegisterOptions) {\n if (!opts?.key) throw new TypeError('Cart attribute values require a non-empty \"key\".');\n const name = `${ATTRIBUTE_VALUE_NAME_PREFIX}${opts.key}` as AttributeValueName;\n if (\"defaultValue\" in opts) {\n return { name, defaultValue: String(opts.defaultValue) };\n }\n return { name, value: String(opts.value ?? \"\") };\n}\n\nfunction createFieldAttributes(name: string, opts?: RegisterOptions) {\n if (opts && \"defaultValue\" in opts) {\n return { name, defaultValue: String(opts.defaultValue) };\n }\n\n const value = String(opts?.value ?? \"\");\n\n if (name === \"quantity\" && opts?.interactive) {\n return {\n name: \"quantity\",\n value,\n type: \"text\",\n inputMode: \"numeric\",\n pattern: \"\\\\d+\",\n autoComplete: \"off\",\n autoCorrect: \"off\",\n } satisfies QuantityInputAttributes;\n }\n\n const attrs: Record<string, string | boolean> = { name, value };\n if (name === \"lineId\") attrs.readOnly = true;\n return attrs;\n}\n\n/**\n * Creates a {@link CartFormRegister} function for generating cart form field attributes.\n *\n * The returned `register` function is stateless — it can be called multiple times\n * and shared across components. Framework hooks (`useCartForm`) wrap this with\n * additional conveniences like `formProps()` and interactive `ref` wiring.\n *\n * @example\n * ```ts\n * const register = createCartFormRegister();\n *\n * const lineIdAttrs = register(\"lineId\", { value: \"gid://shopify/CartLine/123\" });\n * // → { name: \"lineId\", value: \"gid://shopify/CartLine/123\", readOnly: true }\n *\n * const addAttrs = register(\"add\");\n * // → { name: \"intent\", value: \"add\" }\n * ```\n */\nexport function createCartFormRegister(): CartFormRegister {\n return ((nameOrAction: string, opts?: RegisterOptions) => {\n if (nameOrAction === \"attributeValue\") {\n return createAttributeValueAttributes(opts);\n }\n\n if (FIELD_REGISTERS.has(nameOrAction)) {\n return createFieldAttributes(nameOrAction, opts);\n }\n\n if (nameOrAction === \"set\") {\n return {\n name: \"intent\",\n value: \"set\",\n type: \"submit\",\n hidden: true,\n } satisfies SetButtonAttributes;\n }\n\n return { name: \"intent\", value: nameOrAction };\n }) as CartFormRegister;\n}\n"],"mappings":";AAkGA,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,8BAA8B;AASpC,SAAgB,4BACd,UACmD;CACnD,MAAM,aAAgE,EAAE;AACxE,MAAK,MAAM,CAAC,MAAM,UAAU,SAAS,SAAS,EAAE;AAC9C,MAAI,CAAC,KAAK,WAAW,4BAA4B,CAAE;AACnD,aAAW,KAAK;GAAE,KAAK,KAAK,MAAM,GAAmC;GAAE;GAAO,CAAC;;AAEjF,QAAO;;AAGT,SAAS,+BAA+B,MAAwB;AAC9D,KAAI,CAAC,MAAM,IAAK,OAAM,IAAI,UAAU,qDAAmD;CACvF,MAAM,OAAO,GAAG,8BAA8B,KAAK;AACnD,KAAI,kBAAkB,KACpB,QAAO;EAAE;EAAM,cAAc,OAAO,KAAK,aAAa;EAAE;AAE1D,QAAO;EAAE;EAAM,OAAO,OAAO,KAAK,SAAS,GAAG;EAAE;;AAGlD,SAAS,sBAAsB,MAAc,MAAwB;AACnE,KAAI,QAAQ,kBAAkB,KAC5B,QAAO;EAAE;EAAM,cAAc,OAAO,KAAK,aAAa;EAAE;CAG1D,MAAM,QAAQ,OAAO,MAAM,SAAS,GAAG;AAEvC,KAAI,SAAS,cAAc,MAAM,YAC/B,QAAO;EACL,MAAM;EACN;EACA,MAAM;EACN,WAAW;EACX,SAAS;EACT,cAAc;EACd,aAAa;EACd;CAGH,MAAM,QAA0C;EAAE;EAAM;EAAO;AAC/D,KAAI,SAAS,SAAU,OAAM,WAAW;AACxC,QAAO;;;;;;;;;;;;;;;;;;;;AAqBT,SAAgB,yBAA2C;AACzD,UAAS,cAAsB,SAA2B;AACxD,MAAI,iBAAiB,iBACnB,QAAO,+BAA+B,KAAK;AAG7C,MAAI,gBAAgB,IAAI,aAAa,CACnC,QAAO,sBAAsB,cAAc,KAAK;AAGlD,MAAI,iBAAiB,MACnB,QAAO;GACL,MAAM;GACN,OAAO;GACP,MAAM;GACN,QAAQ;GACT;AAGH,SAAO;GAAE,MAAM;GAAU,OAAO;GAAc"}
@@ -6,19 +6,60 @@ import { cartQueries } from "./queries.mjs";
6
6
 
7
7
  //#region src/core/cart/get-cart.d.ts
8
8
  type MergeCartData<TCart> = Omit<CartData, keyof TCart> & TCart;
9
+ /**
10
+ * Infers the {@link CartData} shape from a custom Storefront API cart query string.
11
+ *
12
+ * When you pass a custom cart query to {@link getCart}, this type extracts the
13
+ * `cart` field from the query's result type and merges it with the base
14
+ * {@link CartData} interface, so the returned data is fully typed to your query.
15
+ */
9
16
  type CartDataFromQuery<TQuery extends AnyStorefrontQueryString> = TQuery extends StorefrontQueryString<infer Result, infer _Variables, string> ? Result extends {
10
17
  cart?: (infer Cart) | null;
11
18
  } ? MergeCartData<NonNullable<Cart>> : CartData : CartData;
19
+ /** Result of a {@link getCart} call — the cart data (or `null`), any errors, and response headers. */
12
20
  type CartResult<TCart extends CartData = CartData> = {
13
- cart: TCart | null;
21
+ /** The cart, or `null` when no cart exists or the query failed. */cart: TCart | null;
14
22
  errors?: Array<{
15
23
  message: string;
16
- }>;
24
+ }>; /** Response headers from the Storefront API (e.g. cache directives). */
17
25
  headers: Headers;
18
26
  };
19
27
  type StorefrontCartClient = Pick<StorefrontClient, "graphql">;
20
28
  type CartIdSource = Request | Pick<ShopifyRequestContext, "cookie" | "url">;
29
+ /**
30
+ * Extracts the cart GID from a request.
31
+ *
32
+ * Checks the `cartId` search parameter first (for explicit linking), then
33
+ * falls back to the `cart` cookie. Returns `null` when neither source
34
+ * contains a cart identifier.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * // In a framework loader
39
+ * const cartId = getCartId(request);
40
+ * if (cartId) {
41
+ * const { cart } = await getCart(cartId, storefront);
42
+ * }
43
+ * ```
44
+ */
21
45
  declare function getCartId(input: CartIdSource): string | null;
46
+ /**
47
+ * Fetches a cart by ID from the Storefront API.
48
+ *
49
+ * Accepts an optional custom cart query document — the result type is inferred
50
+ * via {@link CartDataFromQuery} so the returned `cart` is fully typed to your
51
+ * query's fields. When `cartId` is `null`, returns `{ cart: null }` immediately
52
+ * without making a network request.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * const cartId = getCartId(request);
57
+ * const { cart, errors, headers } = await getCart(cartId, storefront);
58
+ *
59
+ * // With a custom query
60
+ * const { cart } = await getCart(cartId, storefront, CUSTOM_CART_QUERY);
61
+ * ```
62
+ */
22
63
  declare function getCart<TQuery extends AnyStorefrontQueryString = typeof cartQueries.cart>(cartId: string | null, storefront: StorefrontCartClient, cartQuery?: TQuery): Promise<CartResult<CartDataFromQuery<TQuery>>>;
23
64
  //#endregion
24
65
  export { CartDataFromQuery, CartResult, getCart, getCartId };
@@ -2,6 +2,22 @@ import { getCartIdFromCookie } from "./cookie.mjs";
2
2
  import { cartQueries } from "./queries.mjs";
3
3
 
4
4
  //#region src/core/cart/get-cart.ts
5
+ /**
6
+ * Extracts the cart GID from a request.
7
+ *
8
+ * Checks the `cartId` search parameter first (for explicit linking), then
9
+ * falls back to the `cart` cookie. Returns `null` when neither source
10
+ * contains a cart identifier.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * // In a framework loader
15
+ * const cartId = getCartId(request);
16
+ * if (cartId) {
17
+ * const { cart } = await getCart(cartId, storefront);
18
+ * }
19
+ * ```
20
+ */
5
21
  function getCartId(input) {
6
22
  if (input.url) {
7
23
  const cartId = new URL(input.url, "https://hydrogen.local").searchParams.get("cartId");
@@ -9,6 +25,23 @@ function getCartId(input) {
9
25
  }
10
26
  return getCartIdFromCookie(input);
11
27
  }
28
+ /**
29
+ * Fetches a cart by ID from the Storefront API.
30
+ *
31
+ * Accepts an optional custom cart query document — the result type is inferred
32
+ * via {@link CartDataFromQuery} so the returned `cart` is fully typed to your
33
+ * query's fields. When `cartId` is `null`, returns `{ cart: null }` immediately
34
+ * without making a network request.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const cartId = getCartId(request);
39
+ * const { cart, errors, headers } = await getCart(cartId, storefront);
40
+ *
41
+ * // With a custom query
42
+ * const { cart } = await getCart(cartId, storefront, CUSTOM_CART_QUERY);
43
+ * ```
44
+ */
12
45
  async function getCart(cartId, storefront, cartQuery = cartQueries.cart) {
13
46
  if (!cartId) return {
14
47
  cart: null,
@@ -1 +1 @@
1
- {"version":3,"file":"get-cart.mjs","names":[],"sources":["../../../src/core/cart/get-cart.ts"],"sourcesContent":["import type { StorefrontClient } from \"../../client\";\nimport type { AnyStorefrontQueryString, StorefrontQueryString } from \"../../graphql\";\nimport type { ShopifyRequestContext } from \"../request-context\";\nimport { getCartIdFromCookie } from \"./cookie\";\nimport { cartQueries } from \"./queries\";\nimport type { CartData } from \"./state\";\n\ntype MergeCartData<TCart> = Omit<CartData, keyof TCart> & TCart;\n\nexport type CartDataFromQuery<TQuery extends AnyStorefrontQueryString> =\n TQuery extends StorefrontQueryString<infer Result, infer _Variables, string>\n ? Result extends { cart?: (infer Cart) | null }\n ? MergeCartData<NonNullable<Cart>>\n : CartData\n : CartData;\n\nexport type CartResult<TCart extends CartData = CartData> = {\n cart: TCart | null;\n errors?: Array<{ message: string }>;\n headers: Headers;\n};\n\ntype CartQueryResult = {\n data: { cart?: unknown } | null;\n errors?: Array<{ message: string }>;\n headers: Headers;\n};\n\ntype StorefrontCartClient = Pick<StorefrontClient, \"graphql\">;\n\ntype CartQueryDocument = AnyStorefrontQueryString;\n\ntype CartQueryGraphql = (\n query: CartQueryDocument,\n options: { variables: { id: string } },\n) => Promise<CartQueryResult>;\n\ntype CartIdSource = Request | Pick<ShopifyRequestContext, \"cookie\" | \"url\">;\n\nexport function getCartId(input: CartIdSource): string | null {\n if (input.url) {\n const parsedUrl = new URL(input.url, \"https://hydrogen.local\");\n const cartId = parsedUrl.searchParams.get(\"cartId\");\n if (cartId) return cartId;\n }\n\n return getCartIdFromCookie(input);\n}\n\nexport async function getCart<TQuery extends AnyStorefrontQueryString = typeof cartQueries.cart>(\n cartId: string | null,\n storefront: StorefrontCartClient,\n cartQuery: TQuery = cartQueries.cart as TQuery,\n): Promise<CartResult<CartDataFromQuery<TQuery>>> {\n if (!cartId) {\n return {\n cart: null,\n headers: new Headers(),\n };\n }\n\n const queryCart = storefront.graphql as CartQueryGraphql;\n const result = await queryCart(cartQuery, { variables: { id: cartId } });\n\n if (result.errors || !result.data?.cart) {\n return {\n cart: null,\n errors: result.errors,\n headers: result.headers,\n };\n }\n\n return { cart: result.data.cart as CartDataFromQuery<TQuery>, headers: result.headers };\n}\n"],"mappings":";;;;AAuCA,SAAgB,UAAU,OAAoC;AAC5D,KAAI,MAAM,KAAK;EAEb,MAAM,SAAS,IADO,IAAI,MAAM,KAAK,yBACb,CAAC,aAAa,IAAI,SAAS;AACnD,MAAI,OAAQ,QAAO;;AAGrB,QAAO,oBAAoB,MAAM;;AAGnC,eAAsB,QACpB,QACA,YACA,YAAoB,YAAY,MACgB;AAChD,KAAI,CAAC,OACH,QAAO;EACL,MAAM;EACN,SAAS,IAAI,SAAS;EACvB;CAGH,MAAM,YAAY,WAAW;CAC7B,MAAM,SAAS,MAAM,UAAU,WAAW,EAAE,WAAW,EAAE,IAAI,QAAQ,EAAE,CAAC;AAExE,KAAI,OAAO,UAAU,CAAC,OAAO,MAAM,KACjC,QAAO;EACL,MAAM;EACN,QAAQ,OAAO;EACf,SAAS,OAAO;EACjB;AAGH,QAAO;EAAE,MAAM,OAAO,KAAK;EAAmC,SAAS,OAAO;EAAS"}
1
+ {"version":3,"file":"get-cart.mjs","names":[],"sources":["../../../src/core/cart/get-cart.ts"],"sourcesContent":["import type { StorefrontClient } from \"../../client\";\nimport type { AnyStorefrontQueryString, StorefrontQueryString } from \"../../graphql\";\nimport type { ShopifyRequestContext } from \"../request-context\";\nimport { getCartIdFromCookie } from \"./cookie\";\nimport { cartQueries } from \"./queries\";\nimport type { CartData } from \"./state\";\n\ntype MergeCartData<TCart> = Omit<CartData, keyof TCart> & TCart;\n\n/**\n * Infers the {@link CartData} shape from a custom Storefront API cart query string.\n *\n * When you pass a custom cart query to {@link getCart}, this type extracts the\n * `cart` field from the query's result type and merges it with the base\n * {@link CartData} interface, so the returned data is fully typed to your query.\n */\nexport type CartDataFromQuery<TQuery extends AnyStorefrontQueryString> =\n TQuery extends StorefrontQueryString<infer Result, infer _Variables, string>\n ? Result extends { cart?: (infer Cart) | null }\n ? MergeCartData<NonNullable<Cart>>\n : CartData\n : CartData;\n\n/** Result of a {@link getCart} call — the cart data (or `null`), any errors, and response headers. */\nexport type CartResult<TCart extends CartData = CartData> = {\n /** The cart, or `null` when no cart exists or the query failed. */\n cart: TCart | null;\n errors?: Array<{ message: string }>;\n /** Response headers from the Storefront API (e.g. cache directives). */\n headers: Headers;\n};\n\ntype CartQueryResult = {\n data: { cart?: unknown } | null;\n errors?: Array<{ message: string }>;\n headers: Headers;\n};\n\ntype StorefrontCartClient = Pick<StorefrontClient, \"graphql\">;\n\ntype CartQueryDocument = AnyStorefrontQueryString;\n\ntype CartQueryGraphql = (\n query: CartQueryDocument,\n options: { variables: { id: string } },\n) => Promise<CartQueryResult>;\n\ntype CartIdSource = Request | Pick<ShopifyRequestContext, \"cookie\" | \"url\">;\n\n/**\n * Extracts the cart GID from a request.\n *\n * Checks the `cartId` search parameter first (for explicit linking), then\n * falls back to the `cart` cookie. Returns `null` when neither source\n * contains a cart identifier.\n *\n * @example\n * ```ts\n * // In a framework loader\n * const cartId = getCartId(request);\n * if (cartId) {\n * const { cart } = await getCart(cartId, storefront);\n * }\n * ```\n */\nexport function getCartId(input: CartIdSource): string | null {\n if (input.url) {\n const parsedUrl = new URL(input.url, \"https://hydrogen.local\");\n const cartId = parsedUrl.searchParams.get(\"cartId\");\n if (cartId) return cartId;\n }\n\n return getCartIdFromCookie(input);\n}\n\n/**\n * Fetches a cart by ID from the Storefront API.\n *\n * Accepts an optional custom cart query document — the result type is inferred\n * via {@link CartDataFromQuery} so the returned `cart` is fully typed to your\n * query's fields. When `cartId` is `null`, returns `{ cart: null }` immediately\n * without making a network request.\n *\n * @example\n * ```ts\n * const cartId = getCartId(request);\n * const { cart, errors, headers } = await getCart(cartId, storefront);\n *\n * // With a custom query\n * const { cart } = await getCart(cartId, storefront, CUSTOM_CART_QUERY);\n * ```\n */\nexport async function getCart<TQuery extends AnyStorefrontQueryString = typeof cartQueries.cart>(\n cartId: string | null,\n storefront: StorefrontCartClient,\n cartQuery: TQuery = cartQueries.cart as TQuery,\n): Promise<CartResult<CartDataFromQuery<TQuery>>> {\n if (!cartId) {\n return {\n cart: null,\n headers: new Headers(),\n };\n }\n\n const queryCart = storefront.graphql as CartQueryGraphql;\n const result = await queryCart(cartQuery, { variables: { id: cartId } });\n\n if (result.errors || !result.data?.cart) {\n return {\n cart: null,\n errors: result.errors,\n headers: result.headers,\n };\n }\n\n return { cart: result.data.cart as CartDataFromQuery<TQuery>, headers: result.headers };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAiEA,SAAgB,UAAU,OAAoC;AAC5D,KAAI,MAAM,KAAK;EAEb,MAAM,SAAS,IADO,IAAI,MAAM,KAAK,yBACb,CAAC,aAAa,IAAI,SAAS;AACnD,MAAI,OAAQ,QAAO;;AAGrB,QAAO,oBAAoB,MAAM;;;;;;;;;;;;;;;;;;;AAoBnC,eAAsB,QACpB,QACA,YACA,YAAoB,YAAY,MACgB;AAChD,KAAI,CAAC,OACH,QAAO;EACL,MAAM;EACN,SAAS,IAAI,SAAS;EACvB;CAGH,MAAM,YAAY,WAAW;CAC7B,MAAM,SAAS,MAAM,UAAU,WAAW,EAAE,WAAW,EAAE,IAAI,QAAQ,EAAE,CAAC;AAExE,KAAI,OAAO,UAAU,CAAC,OAAO,MAAM,KACjC,QAAO;EACL,MAAM;EACN,QAAQ,OAAO;EACf,SAAS,OAAO;EACjB;AAGH,QAAO;EAAE,MAAM,OAAO,KAAK;EAAmC,SAAS,OAAO;EAAS"}
@@ -1,5 +1,5 @@
1
1
  import { Attribute, CartCost, CartData, CartErrorGroup, CartErrorState, CartLine, CartLineConnection, CartLineCost, CartLineMerchandise, CartNetworkEntry, CartPending, CartState, CartUserError, CartWarning, DiscountCode, EMPTY_CART_DATA, EMPTY_CART_STATE, createEmptyCartErrors, createEmptyErrorGroup } from "./state.mjs";
2
- import { CartNetworkError, CartStore, CreateCartStoreOptions, STANDARD_ACTION_TIMEOUT_IN_MS, configureCartEndpoint, createCartStore } from "./cart.mjs";
2
+ import { CartActions, CartNetworkError, CartStore, CreateCartStoreOptions, STANDARD_ACTION_TIMEOUT_IN_MS, configureCartEndpoint, createCartStore } from "./cart.mjs";
3
3
  import { CartFormRegister, QuantityInputAttributes, SetButtonAttributes, createCartFormRegister } from "./form.mjs";
4
4
  import { attachQuantityInput } from "./attach-quantity-input.mjs";
5
5
  import { CartAction, CartAttributeInput, CartLineAddInput, CartLineUpdateInput, parseCartRequest } from "./actions.mjs";
@@ -1,6 +1,23 @@
1
1
  //#region src/core/cart/quantity.d.ts
2
+ /** Default lower bound for {@link sanitizeQuantity} when no `min` is given. */
2
3
  declare const DEFAULT_MINIMUM_QUANTITY = 1;
4
+ /** Sentinel upper bound for {@link sanitizeQuantity} meaning "no maximum". */
3
5
  declare const NO_QUANTITY_LIMIT: number;
6
+ /**
7
+ * Clamps a raw value to a valid integer quantity within `min`/`max` bounds.
8
+ *
9
+ * Parses strings, rounds floats, and falls back to `min` for unparseable input.
10
+ * Used internally by the cart form system to sanitize user-typed quantities.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * sanitizeQuantity("3") // → 3
15
+ * sanitizeQuantity("2.7") // → 3
16
+ * sanitizeQuantity("abc") // → 1 (falls back to min)
17
+ * sanitizeQuantity(5, { max: 3 }) // → 3
18
+ * sanitizeQuantity(0, { min: 1 }) // → 1
19
+ * ```
20
+ */
4
21
  declare function sanitizeQuantity(raw: unknown, options?: {
5
22
  min?: number;
6
23
  max?: number;
@@ -1,6 +1,23 @@
1
1
  //#region src/core/cart/quantity.ts
2
+ /** Default lower bound for {@link sanitizeQuantity} when no `min` is given. */
2
3
  const DEFAULT_MINIMUM_QUANTITY = 1;
4
+ /** Sentinel upper bound for {@link sanitizeQuantity} meaning "no maximum". */
3
5
  const NO_QUANTITY_LIMIT = Infinity;
6
+ /**
7
+ * Clamps a raw value to a valid integer quantity within `min`/`max` bounds.
8
+ *
9
+ * Parses strings, rounds floats, and falls back to `min` for unparseable input.
10
+ * Used internally by the cart form system to sanitize user-typed quantities.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * sanitizeQuantity("3") // → 3
15
+ * sanitizeQuantity("2.7") // → 3
16
+ * sanitizeQuantity("abc") // → 1 (falls back to min)
17
+ * sanitizeQuantity(5, { max: 3 }) // → 3
18
+ * sanitizeQuantity(0, { min: 1 }) // → 1
19
+ * ```
20
+ */
4
21
  function sanitizeQuantity(raw, options) {
5
22
  const min = options?.min ?? 1;
6
23
  const max = options?.max ?? Infinity;
@@ -1 +1 @@
1
- {"version":3,"file":"quantity.mjs","names":[],"sources":["../../../src/core/cart/quantity.ts"],"sourcesContent":["export const DEFAULT_MINIMUM_QUANTITY = 1;\nexport const NO_QUANTITY_LIMIT = Infinity;\n\nexport function sanitizeQuantity(raw: unknown, options?: { min?: number; max?: number }): number {\n const min = options?.min ?? DEFAULT_MINIMUM_QUANTITY;\n const max = options?.max ?? NO_QUANTITY_LIMIT;\n\n const parsed = Number(String(raw).trim());\n if (Number.isNaN(parsed)) return min;\n\n const rounded = Math.round(parsed);\n return Math.min(Math.max(rounded, min), max);\n}\n"],"mappings":";AAAA,MAAa,2BAA2B;AACxC,MAAa,oBAAoB;AAEjC,SAAgB,iBAAiB,KAAc,SAAkD;CAC/F,MAAM,MAAM,SAAS;CACrB,MAAM,MAAM,SAAS;CAErB,MAAM,SAAS,OAAO,OAAO,IAAI,CAAC,MAAM,CAAC;AACzC,KAAI,OAAO,MAAM,OAAO,CAAE,QAAO;AAGjC,QAAO,KAAK,IAAI,KAAK,IADL,KAAK,MAAM,OACK,EAAE,IAAI,EAAE,IAAI"}
1
+ {"version":3,"file":"quantity.mjs","names":[],"sources":["../../../src/core/cart/quantity.ts"],"sourcesContent":["/** Default lower bound for {@link sanitizeQuantity} when no `min` is given. */\nexport const DEFAULT_MINIMUM_QUANTITY = 1;\n\n/** Sentinel upper bound for {@link sanitizeQuantity} meaning \"no maximum\". */\nexport const NO_QUANTITY_LIMIT = Infinity;\n\n/**\n * Clamps a raw value to a valid integer quantity within `min`/`max` bounds.\n *\n * Parses strings, rounds floats, and falls back to `min` for unparseable input.\n * Used internally by the cart form system to sanitize user-typed quantities.\n *\n * @example\n * ```ts\n * sanitizeQuantity(\"3\") // → 3\n * sanitizeQuantity(\"2.7\") // → 3\n * sanitizeQuantity(\"abc\") // → 1 (falls back to min)\n * sanitizeQuantity(5, { max: 3 }) // → 3\n * sanitizeQuantity(0, { min: 1 }) // → 1\n * ```\n */\nexport function sanitizeQuantity(raw: unknown, options?: { min?: number; max?: number }): number {\n const min = options?.min ?? DEFAULT_MINIMUM_QUANTITY;\n const max = options?.max ?? NO_QUANTITY_LIMIT;\n\n const parsed = Number(String(raw).trim());\n if (Number.isNaN(parsed)) return min;\n\n const rounded = Math.round(parsed);\n return Math.min(Math.max(rounded, min), max);\n}\n"],"mappings":";;AACA,MAAa,2BAA2B;;AAGxC,MAAa,oBAAoB;;;;;;;;;;;;;;;;AAiBjC,SAAgB,iBAAiB,KAAc,SAAkD;CAC/F,MAAM,MAAM,SAAS;CACrB,MAAM,MAAM,SAAS;CAErB,MAAM,SAAS,OAAO,OAAO,IAAI,CAAC,MAAM,CAAC;AACzC,KAAI,OAAO,MAAM,OAAO,CAAE,QAAO;AAGjC,QAAO,KAAK,IAAI,KAAK,IADL,KAAK,MAAM,OACK,EAAE,IAAI,EAAE,IAAI"}