@shopify/hydrogen 2026.10.0-preview.4 → 2026.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (437) hide show
  1. package/dist/cli/index.mjs +23 -12
  2. package/dist/client/client.d.mts +18 -15
  3. package/dist/client/client.mjs +8 -3
  4. package/dist/client/client.mjs.map +1 -1
  5. package/dist/client/errors.d.mts +35 -13
  6. package/dist/client/errors.mjs +23 -13
  7. package/dist/client/errors.mjs.map +1 -1
  8. package/dist/client/types.d.mts +140 -90
  9. package/dist/core/analytics/cart-tracker.d.mts +19 -10
  10. package/dist/core/analytics/cart-tracker.mjs +18 -10
  11. package/dist/core/analytics/cart-tracker.mjs.map +1 -1
  12. package/dist/core/analytics/events.d.mts +17 -11
  13. package/dist/core/analytics/events.mjs +13 -4
  14. package/dist/core/analytics/events.mjs.map +1 -1
  15. package/dist/core/analytics/types.d.mts +207 -118
  16. package/dist/core/analytics/utils/flatten-connection.d.mts +11 -9
  17. package/dist/core/analytics/utils/flatten-connection.mjs +7 -6
  18. package/dist/core/analytics/utils/flatten-connection.mjs.map +1 -1
  19. package/dist/core/cache/fetch-with-cache.d.mts +24 -4
  20. package/dist/core/cache/fetch-with-cache.mjs +17 -2
  21. package/dist/core/cache/fetch-with-cache.mjs.map +1 -1
  22. package/dist/core/cache/key.d.mts +2 -0
  23. package/dist/core/cache/key.mjs.map +1 -1
  24. package/dist/core/cache/run-with-cache.d.mts +56 -8
  25. package/dist/core/cache/run-with-cache.mjs +17 -6
  26. package/dist/core/cache/run-with-cache.mjs.map +1 -1
  27. package/dist/core/cache/store.d.mts +8 -6
  28. package/dist/core/cache/store.mjs.map +1 -1
  29. package/dist/core/cache/strategies.d.mts +27 -2
  30. package/dist/core/cache/strategies.mjs +6 -0
  31. package/dist/core/cache/strategies.mjs.map +1 -1
  32. package/dist/core/cart/actions.d.mts +37 -30
  33. package/dist/core/cart/actions.mjs +21 -9
  34. package/dist/core/cart/actions.mjs.map +1 -1
  35. package/dist/core/cart/attach-quantity-input.d.mts +8 -7
  36. package/dist/core/cart/attach-quantity-input.mjs +8 -7
  37. package/dist/core/cart/attach-quantity-input.mjs.map +1 -1
  38. package/dist/core/cart/buyer-identity-sync.d.mts +7 -6
  39. package/dist/core/cart/buyer-identity-sync.mjs.map +1 -1
  40. package/dist/core/cart/cart.d.mts +59 -46
  41. package/dist/core/cart/cart.mjs +46 -29
  42. package/dist/core/cart/cart.mjs.map +1 -1
  43. package/dist/core/cart/cookie.d.mts +8 -4
  44. package/dist/core/cart/cookie.mjs +8 -4
  45. package/dist/core/cart/cookie.mjs.map +1 -1
  46. package/dist/core/cart/form.d.mts +34 -20
  47. package/dist/core/cart/form.mjs +6 -4
  48. package/dist/core/cart/form.mjs.map +1 -1
  49. package/dist/core/cart/get-cart.d.mts +27 -15
  50. package/dist/core/cart/get-cart.mjs +13 -8
  51. package/dist/core/cart/get-cart.mjs.map +1 -1
  52. package/dist/core/cart/quantity.d.mts +16 -5
  53. package/dist/core/cart/quantity.mjs +16 -5
  54. package/dist/core/cart/quantity.mjs.map +1 -1
  55. package/dist/core/cart/queries.d.mts +25 -19
  56. package/dist/core/cart/queries.mjs +15 -1
  57. package/dist/core/cart/queries.mjs.map +1 -1
  58. package/dist/core/cart/server-handlers.d.mts +82 -45
  59. package/dist/core/cart/server-handlers.mjs +4 -0
  60. package/dist/core/cart/server-handlers.mjs.map +1 -1
  61. package/dist/core/cart/state.d.mts +110 -64
  62. package/dist/core/cart/state.mjs +24 -6
  63. package/dist/core/cart/state.mjs.map +1 -1
  64. package/dist/core/collection/collection.d.mts +52 -53
  65. package/dist/core/collection/collection.mjs +5 -3
  66. package/dist/core/collection/collection.mjs.map +1 -1
  67. package/dist/core/collection/reconciler.d.mts +23 -16
  68. package/dist/core/collection/reconciler.mjs +8 -4
  69. package/dist/core/collection/reconciler.mjs.map +1 -1
  70. package/dist/core/collection/state.d.mts +31 -26
  71. package/dist/core/collection/state.mjs +4 -3
  72. package/dist/core/collection/state.mjs.map +1 -1
  73. package/dist/core/collection/url.d.mts +70 -29
  74. package/dist/core/collection/url.mjs +63 -25
  75. package/dist/core/collection/url.mjs.map +1 -1
  76. package/dist/core/constants.d.mts +1 -0
  77. package/dist/core/constants.mjs +1 -0
  78. package/dist/core/constants.mjs.map +1 -1
  79. package/dist/core/logging/logging.d.mts +14 -8
  80. package/dist/core/logging/logging.mjs +15 -10
  81. package/dist/core/logging/logging.mjs.map +1 -1
  82. package/dist/core/logging/types.d.mts +28 -11
  83. package/dist/core/logging/types.mjs.map +1 -1
  84. package/dist/core/money/format.d.mts +6 -4
  85. package/dist/core/money/format.mjs +19 -9
  86. package/dist/core/money/format.mjs.map +1 -1
  87. package/dist/core/money/types.d.mts +41 -25
  88. package/dist/core/predictive-search/form.d.mts +37 -7
  89. package/dist/core/predictive-search/form.mjs +21 -3
  90. package/dist/core/predictive-search/form.mjs.map +1 -1
  91. package/dist/core/predictive-search/queries.d.mts +18 -30
  92. package/dist/core/predictive-search/queries.mjs +7 -3
  93. package/dist/core/predictive-search/queries.mjs.map +1 -1
  94. package/dist/core/predictive-search/search.d.mts +25 -27
  95. package/dist/core/predictive-search/search.mjs +20 -19
  96. package/dist/core/predictive-search/search.mjs.map +1 -1
  97. package/dist/core/predictive-search/server-handlers.d.mts +25 -26
  98. package/dist/core/predictive-search/server-handlers.mjs +4 -0
  99. package/dist/core/predictive-search/server-handlers.mjs.map +1 -1
  100. package/dist/core/predictive-search/store.d.mts +65 -24
  101. package/dist/core/predictive-search/store.mjs +12 -1
  102. package/dist/core/predictive-search/store.mjs.map +1 -1
  103. package/dist/core/predictive-search/url.d.mts +36 -37
  104. package/dist/core/predictive-search/url.mjs +14 -6
  105. package/dist/core/predictive-search/url.mjs.map +1 -1
  106. package/dist/core/product/form.d.mts +63 -16
  107. package/dist/core/product/form.mjs +8 -2
  108. package/dist/core/product/form.mjs.map +1 -1
  109. package/dist/core/product/options.d.mts +8 -10
  110. package/dist/core/product/options.mjs +8 -10
  111. package/dist/core/product/options.mjs.map +1 -1
  112. package/dist/core/product/product-form.d.mts +77 -29
  113. package/dist/core/product/product-form.mjs +32 -10
  114. package/dist/core/product/product-form.mjs.map +1 -1
  115. package/dist/core/product/state.d.mts +55 -32
  116. package/dist/core/product/url.d.mts +19 -13
  117. package/dist/core/product/url.mjs +10 -10
  118. package/dist/core/product/url.mjs.map +1 -1
  119. package/dist/core/request-context.d.mts +77 -19
  120. package/dist/core/request-context.mjs +5 -1
  121. package/dist/core/request-context.mjs.map +1 -1
  122. package/dist/core/request-routing/handle-shopify-redirects.d.mts +12 -4
  123. package/dist/core/request-routing/handle-shopify-redirects.mjs +9 -2
  124. package/dist/core/request-routing/handle-shopify-redirects.mjs.map +1 -1
  125. package/dist/core/request-routing/handle-shopify-routes.d.mts +5 -5
  126. package/dist/core/request-routing/handle-shopify-routes.mjs +7 -5
  127. package/dist/core/request-routing/handle-shopify-routes.mjs.map +1 -1
  128. package/dist/core/request-routing/interceptors/proxy.mjs +79 -43
  129. package/dist/core/request-routing/interceptors/proxy.mjs.map +1 -1
  130. package/dist/core/request-routing/interceptors/ucp-profile-proxy.mjs +69 -0
  131. package/dist/core/request-routing/interceptors/ucp-profile-proxy.mjs.map +1 -0
  132. package/dist/core/request-routing/interceptors/url-redirects.mjs +6 -1
  133. package/dist/core/request-routing/interceptors/url-redirects.mjs.map +1 -1
  134. package/dist/core/request-routing/interceptors/well-known.mjs +1 -1
  135. package/dist/core/request-routing/interceptors/well-known.mjs.map +1 -1
  136. package/dist/core/request-routing/registered-routes.d.mts +12 -0
  137. package/dist/core/request-routing/registered-routes.mjs +12 -0
  138. package/dist/core/request-routing/registered-routes.mjs.map +1 -1
  139. package/dist/core/request-routing/route-types.d.mts +43 -18
  140. package/dist/core/shop-pay/shop-pay.d.mts +71 -35
  141. package/dist/core/shop-pay/shop-pay.mjs +36 -10
  142. package/dist/core/shop-pay/shop-pay.mjs.map +1 -1
  143. package/dist/core/shopify-scripts/index.d.mts +15 -5
  144. package/dist/core/shopify-scripts/index.mjs +15 -5
  145. package/dist/core/shopify-scripts/index.mjs.map +1 -1
  146. package/dist/core/shopify-scripts/initialize.d.mts +12 -4
  147. package/dist/core/shopify-scripts/initialize.mjs +12 -4
  148. package/dist/core/shopify-scripts/initialize.mjs.map +1 -1
  149. package/dist/core/shopify-scripts/types.d.mts +58 -25
  150. package/dist/core/standard-routes/build.d.mts +11 -12
  151. package/dist/core/standard-routes/build.mjs +11 -12
  152. package/dist/core/standard-routes/build.mjs.map +1 -1
  153. package/dist/core/standard-routes/types.d.mts +30 -24
  154. package/dist/core/url.mjs +2 -1
  155. package/dist/core/url.mjs.map +1 -1
  156. package/dist/customer-account/client.d.mts +36 -69
  157. package/dist/customer-account/client.mjs +7 -8
  158. package/dist/customer-account/client.mjs.map +1 -1
  159. package/dist/customer-account/errors.d.mts +45 -36
  160. package/dist/customer-account/errors.mjs +21 -36
  161. package/dist/customer-account/errors.mjs.map +1 -1
  162. package/dist/customer-account/graphql.d.mts +11 -23
  163. package/dist/customer-account/graphql.mjs +3 -9
  164. package/dist/customer-account/graphql.mjs.map +1 -1
  165. package/dist/customer-account/session.d.mts +130 -100
  166. package/dist/customer-account/session.mjs +32 -10
  167. package/dist/customer-account/session.mjs.map +1 -1
  168. package/dist/customer-account/type-resolver.d.mts +7 -8
  169. package/dist/development/client/client.d.mts +18 -15
  170. package/dist/development/client/client.mjs +8 -3
  171. package/dist/development/client/client.mjs.map +1 -1
  172. package/dist/development/client/errors.d.mts +35 -13
  173. package/dist/development/client/errors.mjs +23 -13
  174. package/dist/development/client/errors.mjs.map +1 -1
  175. package/dist/development/client/types.d.mts +140 -90
  176. package/dist/development/core/analytics/cart-tracker.d.mts +19 -10
  177. package/dist/development/core/analytics/cart-tracker.mjs +18 -10
  178. package/dist/development/core/analytics/cart-tracker.mjs.map +1 -1
  179. package/dist/development/core/analytics/events.d.mts +17 -11
  180. package/dist/development/core/analytics/events.mjs +13 -4
  181. package/dist/development/core/analytics/events.mjs.map +1 -1
  182. package/dist/development/core/analytics/types.d.mts +207 -118
  183. package/dist/development/core/analytics/utils/flatten-connection.d.mts +11 -9
  184. package/dist/development/core/analytics/utils/flatten-connection.mjs +7 -6
  185. package/dist/development/core/analytics/utils/flatten-connection.mjs.map +1 -1
  186. package/dist/development/core/cache/fetch-with-cache.d.mts +24 -4
  187. package/dist/development/core/cache/fetch-with-cache.mjs +17 -2
  188. package/dist/development/core/cache/fetch-with-cache.mjs.map +1 -1
  189. package/dist/development/core/cache/key.d.mts +2 -0
  190. package/dist/development/core/cache/key.mjs.map +1 -1
  191. package/dist/development/core/cache/run-with-cache.d.mts +56 -8
  192. package/dist/development/core/cache/run-with-cache.mjs +17 -6
  193. package/dist/development/core/cache/run-with-cache.mjs.map +1 -1
  194. package/dist/development/core/cache/store.d.mts +8 -6
  195. package/dist/development/core/cache/store.mjs.map +1 -1
  196. package/dist/development/core/cache/strategies.d.mts +27 -2
  197. package/dist/development/core/cache/strategies.mjs +6 -0
  198. package/dist/development/core/cache/strategies.mjs.map +1 -1
  199. package/dist/development/core/cart/actions.d.mts +37 -30
  200. package/dist/development/core/cart/actions.mjs +21 -9
  201. package/dist/development/core/cart/actions.mjs.map +1 -1
  202. package/dist/development/core/cart/attach-quantity-input.d.mts +8 -7
  203. package/dist/development/core/cart/attach-quantity-input.mjs +8 -7
  204. package/dist/development/core/cart/attach-quantity-input.mjs.map +1 -1
  205. package/dist/development/core/cart/buyer-identity-sync.d.mts +6 -5
  206. package/dist/development/core/cart/buyer-identity-sync.mjs.map +1 -1
  207. package/dist/development/core/cart/cart.d.mts +59 -46
  208. package/dist/development/core/cart/cart.mjs +46 -29
  209. package/dist/development/core/cart/cart.mjs.map +1 -1
  210. package/dist/development/core/cart/cookie.d.mts +8 -4
  211. package/dist/development/core/cart/cookie.mjs +8 -4
  212. package/dist/development/core/cart/cookie.mjs.map +1 -1
  213. package/dist/development/core/cart/form.d.mts +34 -20
  214. package/dist/development/core/cart/form.mjs +6 -4
  215. package/dist/development/core/cart/form.mjs.map +1 -1
  216. package/dist/development/core/cart/get-cart.d.mts +27 -15
  217. package/dist/development/core/cart/get-cart.mjs +13 -8
  218. package/dist/development/core/cart/get-cart.mjs.map +1 -1
  219. package/dist/development/core/cart/quantity.d.mts +16 -5
  220. package/dist/development/core/cart/quantity.mjs +16 -5
  221. package/dist/development/core/cart/quantity.mjs.map +1 -1
  222. package/dist/development/core/cart/queries.d.mts +25 -19
  223. package/dist/development/core/cart/queries.mjs +15 -1
  224. package/dist/development/core/cart/queries.mjs.map +1 -1
  225. package/dist/development/core/cart/server-handlers.d.mts +82 -45
  226. package/dist/development/core/cart/server-handlers.mjs +4 -0
  227. package/dist/development/core/cart/server-handlers.mjs.map +1 -1
  228. package/dist/development/core/cart/state.d.mts +110 -64
  229. package/dist/development/core/cart/state.mjs +24 -6
  230. package/dist/development/core/cart/state.mjs.map +1 -1
  231. package/dist/development/core/collection/collection.d.mts +52 -53
  232. package/dist/development/core/collection/collection.mjs +5 -3
  233. package/dist/development/core/collection/collection.mjs.map +1 -1
  234. package/dist/development/core/collection/reconciler.d.mts +23 -16
  235. package/dist/development/core/collection/reconciler.mjs +8 -4
  236. package/dist/development/core/collection/reconciler.mjs.map +1 -1
  237. package/dist/development/core/collection/state.d.mts +31 -26
  238. package/dist/development/core/collection/state.mjs +4 -3
  239. package/dist/development/core/collection/state.mjs.map +1 -1
  240. package/dist/development/core/collection/url.d.mts +70 -29
  241. package/dist/development/core/collection/url.mjs +63 -25
  242. package/dist/development/core/collection/url.mjs.map +1 -1
  243. package/dist/development/core/constants.mjs.map +1 -1
  244. package/dist/development/core/logging/logging.d.mts +14 -8
  245. package/dist/development/core/logging/logging.mjs +15 -10
  246. package/dist/development/core/logging/logging.mjs.map +1 -1
  247. package/dist/development/core/logging/types.d.mts +28 -11
  248. package/dist/development/core/logging/types.mjs.map +1 -1
  249. package/dist/development/core/money/format.d.mts +6 -4
  250. package/dist/development/core/money/format.mjs +19 -9
  251. package/dist/development/core/money/format.mjs.map +1 -1
  252. package/dist/development/core/money/types.d.mts +41 -25
  253. package/dist/development/core/predictive-search/form.d.mts +37 -7
  254. package/dist/development/core/predictive-search/form.mjs +21 -3
  255. package/dist/development/core/predictive-search/form.mjs.map +1 -1
  256. package/dist/development/core/predictive-search/queries.d.mts +18 -30
  257. package/dist/development/core/predictive-search/queries.mjs +7 -3
  258. package/dist/development/core/predictive-search/queries.mjs.map +1 -1
  259. package/dist/development/core/predictive-search/search.d.mts +25 -27
  260. package/dist/development/core/predictive-search/search.mjs +20 -19
  261. package/dist/development/core/predictive-search/search.mjs.map +1 -1
  262. package/dist/development/core/predictive-search/server-handlers.d.mts +25 -26
  263. package/dist/development/core/predictive-search/server-handlers.mjs +4 -0
  264. package/dist/development/core/predictive-search/server-handlers.mjs.map +1 -1
  265. package/dist/development/core/predictive-search/store.d.mts +65 -24
  266. package/dist/development/core/predictive-search/store.mjs +12 -1
  267. package/dist/development/core/predictive-search/store.mjs.map +1 -1
  268. package/dist/development/core/predictive-search/url.d.mts +36 -37
  269. package/dist/development/core/predictive-search/url.mjs +14 -6
  270. package/dist/development/core/predictive-search/url.mjs.map +1 -1
  271. package/dist/development/core/product/form.d.mts +63 -16
  272. package/dist/development/core/product/form.mjs +8 -2
  273. package/dist/development/core/product/form.mjs.map +1 -1
  274. package/dist/development/core/product/options.d.mts +8 -10
  275. package/dist/development/core/product/options.mjs +8 -10
  276. package/dist/development/core/product/options.mjs.map +1 -1
  277. package/dist/development/core/product/product-form.d.mts +77 -29
  278. package/dist/development/core/product/product-form.mjs +32 -10
  279. package/dist/development/core/product/product-form.mjs.map +1 -1
  280. package/dist/development/core/product/state.d.mts +55 -32
  281. package/dist/development/core/product/url.d.mts +19 -13
  282. package/dist/development/core/product/url.mjs +10 -10
  283. package/dist/development/core/product/url.mjs.map +1 -1
  284. package/dist/development/core/request-context.d.mts +77 -19
  285. package/dist/development/core/request-context.mjs +5 -1
  286. package/dist/development/core/request-context.mjs.map +1 -1
  287. package/dist/development/core/request-routing/handle-shopify-redirects.d.mts +12 -4
  288. package/dist/development/core/request-routing/handle-shopify-redirects.mjs +9 -2
  289. package/dist/development/core/request-routing/handle-shopify-redirects.mjs.map +1 -1
  290. package/dist/development/core/request-routing/handle-shopify-routes.development.d.mts +9 -1
  291. package/dist/development/core/request-routing/handle-shopify-routes.development.mjs +7 -0
  292. package/dist/development/core/request-routing/handle-shopify-routes.development.mjs.map +1 -1
  293. package/dist/development/core/request-routing/handle-shopify-routes.mjs +7 -5
  294. package/dist/development/core/request-routing/handle-shopify-routes.mjs.map +1 -1
  295. package/dist/development/core/request-routing/interceptors/proxy.mjs +79 -43
  296. package/dist/development/core/request-routing/interceptors/proxy.mjs.map +1 -1
  297. package/dist/development/core/request-routing/interceptors/ucp-profile-proxy.mjs +69 -0
  298. package/dist/development/core/request-routing/interceptors/ucp-profile-proxy.mjs.map +1 -0
  299. package/dist/development/core/request-routing/interceptors/url-redirects.mjs +6 -1
  300. package/dist/development/core/request-routing/interceptors/url-redirects.mjs.map +1 -1
  301. package/dist/development/core/request-routing/interceptors/well-known.mjs +1 -1
  302. package/dist/development/core/request-routing/interceptors/well-known.mjs.map +1 -1
  303. package/dist/development/core/request-routing/registered-routes.d.mts +12 -0
  304. package/dist/development/core/request-routing/registered-routes.mjs +12 -0
  305. package/dist/development/core/request-routing/registered-routes.mjs.map +1 -1
  306. package/dist/development/core/request-routing/route-types.d.mts +43 -18
  307. package/dist/development/core/shop-pay/shop-pay.d.mts +71 -35
  308. package/dist/development/core/shop-pay/shop-pay.mjs +36 -10
  309. package/dist/development/core/shop-pay/shop-pay.mjs.map +1 -1
  310. package/dist/development/core/shopify-scripts/index.d.mts +15 -5
  311. package/dist/development/core/shopify-scripts/index.mjs +15 -5
  312. package/dist/development/core/shopify-scripts/index.mjs.map +1 -1
  313. package/dist/development/core/shopify-scripts/initialize.d.mts +12 -4
  314. package/dist/development/core/shopify-scripts/initialize.mjs +12 -4
  315. package/dist/development/core/shopify-scripts/initialize.mjs.map +1 -1
  316. package/dist/development/core/shopify-scripts/types.d.mts +58 -25
  317. package/dist/development/core/standard-routes/build.d.mts +11 -12
  318. package/dist/development/core/standard-routes/build.mjs +11 -12
  319. package/dist/development/core/standard-routes/build.mjs.map +1 -1
  320. package/dist/development/core/standard-routes/types.d.mts +30 -24
  321. package/dist/development/core/url.mjs +2 -1
  322. package/dist/development/core/url.mjs.map +1 -1
  323. package/dist/development/customer-account/session.d.mts +45 -54
  324. package/dist/development/customer-account/session.mjs +20 -4
  325. package/dist/development/customer-account/session.mjs.map +1 -1
  326. package/dist/development/globals.d.mts +20 -11
  327. package/dist/development/graphql/generated/storefront-api-types.d.mts +127 -1
  328. package/dist/development/graphql/graphql.d.mts +17 -16
  329. package/dist/development/graphql/graphql.mjs +7 -8
  330. package/dist/development/graphql/graphql.mjs.map +1 -1
  331. package/dist/development/graphql/type-resolver.d.mts +15 -8
  332. package/dist/development/react/cart.d.mts +78 -32
  333. package/dist/development/react/cart.mjs +56 -29
  334. package/dist/development/react/cart.mjs.map +1 -1
  335. package/dist/development/react/collection.d.mts +40 -22
  336. package/dist/development/react/collection.mjs +27 -7
  337. package/dist/development/react/collection.mjs.map +1 -1
  338. package/dist/development/react/predictive-search.d.mts +65 -50
  339. package/dist/development/react/predictive-search.mjs +23 -21
  340. package/dist/development/react/predictive-search.mjs.map +1 -1
  341. package/dist/development/react/product.d.mts +45 -16
  342. package/dist/development/react/product.mjs +13 -11
  343. package/dist/development/react/product.mjs.map +1 -1
  344. package/dist/development/react/shop-pay.d.mts +15 -0
  345. package/dist/development/react/shop-pay.mjs +9 -0
  346. package/dist/development/react/shop-pay.mjs.map +1 -1
  347. package/dist/development/react/shopify-scripts.d.mts +23 -2
  348. package/dist/development/react/shopify-scripts.mjs +9 -0
  349. package/dist/development/react/shopify-scripts.mjs.map +1 -1
  350. package/dist/development/vue/cart.d.mts +28 -23
  351. package/dist/development/vue/cart.mjs +42 -25
  352. package/dist/development/vue/cart.mjs.map +1 -1
  353. package/dist/development/vue/collection.d.mts +20 -12
  354. package/dist/development/vue/collection.mjs +15 -7
  355. package/dist/development/vue/collection.mjs.map +1 -1
  356. package/dist/development/vue/index.d.mts +2 -2
  357. package/dist/development/vue/index.mjs +2 -2
  358. package/dist/development/vue/predictive-search.d.mts +31 -36
  359. package/dist/development/vue/predictive-search.mjs +16 -22
  360. package/dist/development/vue/predictive-search.mjs.map +1 -1
  361. package/dist/development/vue/product.d.mts +16 -15
  362. package/dist/development/vue/product.mjs +11 -11
  363. package/dist/development/vue/product.mjs.map +1 -1
  364. package/dist/development/vue/shop-pay.d.mts +14 -17
  365. package/dist/development/vue/shop-pay.mjs +8 -0
  366. package/dist/development/vue/shop-pay.mjs.map +1 -1
  367. package/dist/development/vue/shopify-scripts.d.mts +11 -0
  368. package/dist/development/vue/shopify-scripts.mjs +6 -0
  369. package/dist/development/vue/shopify-scripts.mjs.map +1 -1
  370. package/dist/globals.d.mts +20 -11
  371. package/dist/graphql/generated/storefront-api-types.d.mts +127 -1
  372. package/dist/graphql/graphql.d.mts +17 -16
  373. package/dist/graphql/graphql.mjs +7 -8
  374. package/dist/graphql/graphql.mjs.map +1 -1
  375. package/dist/graphql/type-resolver.d.mts +15 -8
  376. package/dist/react/cart.d.mts +78 -32
  377. package/dist/react/cart.mjs +56 -29
  378. package/dist/react/cart.mjs.map +1 -1
  379. package/dist/react/collection.d.mts +40 -22
  380. package/dist/react/collection.mjs +27 -7
  381. package/dist/react/collection.mjs.map +1 -1
  382. package/dist/react/predictive-search.d.mts +65 -50
  383. package/dist/react/predictive-search.mjs +23 -21
  384. package/dist/react/predictive-search.mjs.map +1 -1
  385. package/dist/react/product.d.mts +45 -16
  386. package/dist/react/product.mjs +13 -11
  387. package/dist/react/product.mjs.map +1 -1
  388. package/dist/react/shop-pay.d.mts +15 -0
  389. package/dist/react/shop-pay.mjs +9 -0
  390. package/dist/react/shop-pay.mjs.map +1 -1
  391. package/dist/react/shopify-scripts.d.mts +23 -2
  392. package/dist/react/shopify-scripts.mjs +9 -0
  393. package/dist/react/shopify-scripts.mjs.map +1 -1
  394. package/dist/ts-plugin/index.cjs +6 -0
  395. package/dist/ts-plugin/index.cjs.map +1 -1
  396. package/dist/ts-plugin/index.d.cts +6 -0
  397. package/dist/vite/local-https.d.mts +51 -17
  398. package/dist/vite/local-https.mjs +26 -5
  399. package/dist/vite/local-https.mjs.map +1 -1
  400. package/dist/vue/cart.d.mts +28 -23
  401. package/dist/vue/cart.mjs +42 -25
  402. package/dist/vue/cart.mjs.map +1 -1
  403. package/dist/vue/collection.d.mts +20 -12
  404. package/dist/vue/collection.mjs +15 -7
  405. package/dist/vue/collection.mjs.map +1 -1
  406. package/dist/vue/index.d.mts +2 -2
  407. package/dist/vue/index.mjs +2 -2
  408. package/dist/vue/predictive-search.d.mts +31 -36
  409. package/dist/vue/predictive-search.mjs +16 -22
  410. package/dist/vue/predictive-search.mjs.map +1 -1
  411. package/dist/vue/product.d.mts +16 -15
  412. package/dist/vue/product.mjs +11 -11
  413. package/dist/vue/product.mjs.map +1 -1
  414. package/dist/vue/shop-pay.d.mts +14 -17
  415. package/dist/vue/shop-pay.mjs +8 -0
  416. package/dist/vue/shop-pay.mjs.map +1 -1
  417. package/dist/vue/shopify-scripts.d.mts +11 -0
  418. package/dist/vue/shopify-scripts.mjs +6 -0
  419. package/dist/vue/shopify-scripts.mjs.map +1 -1
  420. package/package.json +3 -1
  421. package/skills/hydrogen-analytics/SKILL.md +1 -1
  422. package/skills/hydrogen-cart-ui/SKILL.md +28 -2
  423. package/skills/hydrogen-collection-browser/SKILL.md +9 -1
  424. package/skills/hydrogen-collection-browser/references/nextjs.md +1 -1
  425. package/skills/hydrogen-collection-browser/references/nuxt.md +1 -1
  426. package/skills/hydrogen-collection-browser/references/react.md +151 -32
  427. package/skills/hydrogen-customer-account/SKILL.md +2 -0
  428. package/skills/hydrogen-request-handlers/SKILL.md +21 -11
  429. package/skills/hydrogen-setup/references/analytics.md +14 -8
  430. package/skills/hydrogen-setup/steps/1-inspect-app.md +2 -2
  431. package/skills/hydrogen-setup/steps/6-product-detail-page.md +21 -11
  432. package/skills/hydrogen-storefront-client/SKILL.md +1 -1
  433. package/skills/hydrogen-storefront-client/references/caching.md +2 -0
  434. package/skills/hydrogen-variant-form/SKILL.md +25 -7
  435. package/skills/hydrogen-variant-form/references/nextjs.md +39 -4
  436. package/skills/hydrogen-variant-form/references/nuxt.md +83 -42
  437. package/skills/hydrogen-variant-form/references/react.md +45 -9
@@ -1 +1 @@
1
- {"version":3,"file":"queries.mjs","names":[],"sources":["../../../../src/core/predictive-search/queries.ts"],"sourcesContent":["import {\n gql,\n type AnyStorefrontQueryString,\n type ComposedSource,\n type SourceOf,\n type StorefrontQueryString,\n} from \"../../graphql\";\nimport type { InferResult, InferVariables } from \"../../graphql\";\n\nconst PRODUCT_FRAGMENT_NAME = \"PredictiveSearchProductFragment\";\nconst COLLECTION_FRAGMENT_NAME = \"PredictiveSearchCollectionFragment\";\nconst PAGE_FRAGMENT_NAME = \"PredictiveSearchPageFragment\";\nconst ARTICLE_FRAGMENT_NAME = \"PredictiveSearchArticleFragment\";\nconst QUERY_FRAGMENT_NAME = \"PredictiveSearchQueryFragment\";\n\nconst PRODUCT_TYPE_NAME = \"Product\";\nconst COLLECTION_TYPE_NAME = \"Collection\";\nconst PAGE_TYPE_NAME = \"Page\";\nconst ARTICLE_TYPE_NAME = \"Article\";\nconst QUERY_TYPE_NAME = \"SearchQuerySuggestion\";\n\ntype FragmentContract = {\n readonly label: string;\n readonly name: string;\n readonly typeName: string;\n};\n\nconst PRODUCT_CONTRACT = {\n label: \"product\",\n name: PRODUCT_FRAGMENT_NAME,\n typeName: PRODUCT_TYPE_NAME,\n} as const satisfies FragmentContract;\n\nconst COLLECTION_CONTRACT = {\n label: \"collection\",\n name: COLLECTION_FRAGMENT_NAME,\n typeName: COLLECTION_TYPE_NAME,\n} as const satisfies FragmentContract;\n\nconst PAGE_CONTRACT = {\n label: \"page\",\n name: PAGE_FRAGMENT_NAME,\n typeName: PAGE_TYPE_NAME,\n} as const satisfies FragmentContract;\n\nconst ARTICLE_CONTRACT = {\n label: \"article\",\n name: ARTICLE_FRAGMENT_NAME,\n typeName: ARTICLE_TYPE_NAME,\n} as const satisfies FragmentContract;\n\nconst QUERY_CONTRACT = {\n label: \"query\",\n name: QUERY_FRAGMENT_NAME,\n typeName: QUERY_TYPE_NAME,\n} as const satisfies FragmentContract;\n\nconst HYDROGEN_PRODUCT_FRAGMENT = gql(`\n fragment HydrogenPredictiveSearchProductFragment on Product {\n __typename\n id\n title\n handle\n trackingParameters\n selectedOrFirstAvailableVariant(\n selectedOptions: []\n ignoreUnknownOptions: true\n caseInsensitiveMatch: true\n ) {\n id\n image {\n url\n altText\n width\n height\n }\n price {\n amount\n currencyCode\n }\n }\n }\n`);\n\nconst HYDROGEN_COLLECTION_FRAGMENT = gql(`\n fragment HydrogenPredictiveSearchCollectionFragment on Collection {\n __typename\n id\n title\n handle\n image {\n url\n altText\n width\n height\n }\n trackingParameters\n }\n`);\n\nconst HYDROGEN_PAGE_FRAGMENT = gql(`\n fragment HydrogenPredictiveSearchPageFragment on Page {\n __typename\n id\n title\n handle\n trackingParameters\n }\n`);\n\nconst HYDROGEN_ARTICLE_FRAGMENT = gql(`\n fragment HydrogenPredictiveSearchArticleFragment on Article {\n __typename\n id\n title\n handle\n blog {\n handle\n }\n image {\n url\n altText\n width\n height\n }\n trackingParameters\n }\n`);\n\nconst HYDROGEN_QUERY_FRAGMENT = gql(`\n fragment HydrogenPredictiveSearchQueryFragment on SearchQuerySuggestion {\n __typename\n text\n styledText\n trackingParameters\n }\n`);\n\n// The consumer-overridable fragment spreads (e.g. PredictiveSearchProductFragment)\n// are interpolated on purpose: those fragments only exist at runtime, and the\n// gql.tada plugin skips documents containing interpolations instead of flagging\n// unknown fragments, while TypeScript still resolves the full literal source type.\n// The resolved fragments are composed in at runtime by `makePredictiveSearchQueries`.\nconst PREDICTIVE_SEARCH_QUERY = gql(\n `query PredictiveSearch(\n $country: CountryCode\n $language: LanguageCode\n $limit: Int\n $limitScope: PredictiveSearchLimitScope\n $term: String!\n $types: [PredictiveSearchType!]\n $searchableFields: [SearchableField!]\n $unavailableProducts: SearchUnavailableProductsType\n ) @inContext(country: $country, language: $language) {\n predictiveSearch(\n limit: $limit\n limitScope: $limitScope\n query: $term\n types: $types\n searchableFields: $searchableFields\n unavailableProducts: $unavailableProducts\n ) {\n articles {\n ...HydrogenPredictiveSearchArticleFragment\n ...${ARTICLE_FRAGMENT_NAME}\n }\n collections {\n ...HydrogenPredictiveSearchCollectionFragment\n ...${COLLECTION_FRAGMENT_NAME}\n }\n pages {\n ...HydrogenPredictiveSearchPageFragment\n ...${PAGE_FRAGMENT_NAME}\n }\n products {\n ...HydrogenPredictiveSearchProductFragment\n ...${PRODUCT_FRAGMENT_NAME}\n }\n queries {\n ...HydrogenPredictiveSearchQueryFragment\n ...${QUERY_FRAGMENT_NAME}\n }\n }\n }`,\n [\n HYDROGEN_PRODUCT_FRAGMENT,\n HYDROGEN_COLLECTION_FRAGMENT,\n HYDROGEN_PAGE_FRAGMENT,\n HYDROGEN_ARTICLE_FRAGMENT,\n HYDROGEN_QUERY_FRAGMENT,\n ],\n);\n\nconst DEFAULT_PRODUCT_FRAGMENT = gql(`\n fragment PredictiveSearchProductFragment on Product {\n id\n }\n`);\n\nconst DEFAULT_COLLECTION_FRAGMENT = gql(`\n fragment PredictiveSearchCollectionFragment on Collection {\n id\n }\n`);\n\nconst DEFAULT_PAGE_FRAGMENT = gql(`\n fragment PredictiveSearchPageFragment on Page {\n id\n }\n`);\n\nconst DEFAULT_ARTICLE_FRAGMENT = gql(`\n fragment PredictiveSearchArticleFragment on Article {\n id\n }\n`);\n\nconst DEFAULT_QUERY_FRAGMENT = gql(`\n fragment PredictiveSearchQueryFragment on SearchQuerySuggestion {\n text\n }\n`);\n\n/**\n * Additional GraphQL fragments that select extra fields on each predictive search result type.\n *\n * Each fragment must be named and typed as follows, or\n * `makePredictiveSearchQueries` throws:\n *\n * - `product`: `fragment PredictiveSearchProductFragment on Product`\n * - `collection`: `fragment PredictiveSearchCollectionFragment on Collection`\n * - `page`: `fragment PredictiveSearchPageFragment on Page`\n * - `article`: `fragment PredictiveSearchArticleFragment on Article`\n * - `query`: `fragment PredictiveSearchQueryFragment on SearchQuerySuggestion`\n *\n * Hydrogen's own fields (used for URL generation, tracking, and display) are\n * always selected; custom fragments are merged alongside them.\n */\nexport type PredictiveSearchFragments = {\n readonly product?: AnyStorefrontQueryString;\n readonly collection?: AnyStorefrontQueryString;\n readonly page?: AnyStorefrontQueryString;\n readonly article?: AnyStorefrontQueryString;\n readonly query?: AnyStorefrontQueryString;\n};\n\n/** Options for {@link makePredictiveSearchQueries}. */\nexport type CreatePredictiveSearchQueriesOptions<\n TFragments extends PredictiveSearchFragments = PredictiveSearchFragments,\n> = {\n /** Extra fields to select per result type. Hydrogen's built-in fields are always included. */\n readonly fragments?: TFragments;\n};\n\ntype FragmentForOptions<\n TOptions,\n TKey extends keyof PredictiveSearchFragments,\n TDefault extends AnyStorefrontQueryString,\n> = TOptions extends { readonly fragments: infer TFragments }\n ? TFragments extends Record<TKey, infer TFragment extends AnyStorefrontQueryString>\n ? TFragment\n : TDefault\n : TDefault;\n\ntype PredictiveSearchQueryFragmentsForOptions<TOptions> = [\n FragmentForOptions<TOptions, \"product\", typeof DEFAULT_PRODUCT_FRAGMENT>,\n FragmentForOptions<TOptions, \"collection\", typeof DEFAULT_COLLECTION_FRAGMENT>,\n FragmentForOptions<TOptions, \"page\", typeof DEFAULT_PAGE_FRAGMENT>,\n FragmentForOptions<TOptions, \"article\", typeof DEFAULT_ARTICLE_FRAGMENT>,\n FragmentForOptions<TOptions, \"query\", typeof DEFAULT_QUERY_FRAGMENT>,\n];\n\ntype PredictiveSearchQuerySourceForOptions<TOptions> = ComposedSource<\n SourceOf<typeof PREDICTIVE_SEARCH_QUERY>,\n PredictiveSearchQueryFragmentsForOptions<TOptions>\n>;\n\ntype PredictiveSearchQueryForOptions<TOptions> = StorefrontQueryString<\n InferResult<PredictiveSearchQuerySourceForOptions<TOptions>>,\n InferVariables<PredictiveSearchQuerySourceForOptions<TOptions>>,\n PredictiveSearchQuerySourceForOptions<TOptions>\n>;\n\n/** Resolves the query map shape from {@link CreatePredictiveSearchQueriesOptions}, preserving full type inference from custom fragments. */\nexport type PredictiveSearchQueriesForOptions<TOptions> = {\n readonly predictiveSearch: PredictiveSearchQueryForOptions<TOptions>;\n};\n\nfunction assertFragmentContract(fragment: string, contract: FragmentContract): void {\n const pattern = new RegExp(`fragment\\\\s+${contract.name}\\\\s+on\\\\s+${contract.typeName}\\\\b`);\n if (pattern.test(fragment)) return;\n\n throw new Error(\n `Predictive search ${contract.label} fragment must be named ${contract.name} and target ${contract.typeName}`,\n );\n}\n\nfunction resolveFragments(fragments: PredictiveSearchFragments | undefined) {\n if (fragments?.product) assertFragmentContract(fragments.product, PRODUCT_CONTRACT);\n if (fragments?.collection) assertFragmentContract(fragments.collection, COLLECTION_CONTRACT);\n if (fragments?.page) assertFragmentContract(fragments.page, PAGE_CONTRACT);\n if (fragments?.article) assertFragmentContract(fragments.article, ARTICLE_CONTRACT);\n if (fragments?.query) assertFragmentContract(fragments.query, QUERY_CONTRACT);\n\n return [\n fragments?.product ?? DEFAULT_PRODUCT_FRAGMENT,\n fragments?.collection ?? DEFAULT_COLLECTION_FRAGMENT,\n fragments?.page ?? DEFAULT_PAGE_FRAGMENT,\n fragments?.article ?? DEFAULT_ARTICLE_FRAGMENT,\n fragments?.query ?? DEFAULT_QUERY_FRAGMENT,\n ] as const;\n}\n\n/**\n * Composes the predictive search GraphQL query document from the built-in\n * base query and either custom or default fragments.\n *\n * Custom fragments are validated at runtime against their expected names\n * and target GraphQL types. See {@link PredictiveSearchFragments} for the\n * naming contract.\n *\n * The returned object's `predictiveSearch` key carries the composed query\n * with full type inference from the provided fragments.\n *\n * @throws {Error} When a custom fragment does not match its required name or target type.\n */\nexport function makePredictiveSearchQueries<\n const TOptions extends CreatePredictiveSearchQueriesOptions,\n>(options: TOptions): PredictiveSearchQueriesForOptions<TOptions>;\nexport function makePredictiveSearchQueries(): PredictiveSearchQueriesForOptions<undefined>;\nexport function makePredictiveSearchQueries(options?: CreatePredictiveSearchQueriesOptions) {\n return {\n predictiveSearch: gql(PREDICTIVE_SEARCH_QUERY, resolveFragments(options?.fragments)),\n } as PredictiveSearchQueriesForOptions<typeof options>;\n}\n\n/**\n * Internal default query object built from Hydrogen's default fragments;\n * used when `query` is omitted.\n *\n * Build custom query documents with {@link makePredictiveSearchQueries}.\n */\nexport const predictiveSearchQueries = makePredictiveSearchQueries();\n"],"mappings":";;;AASA,MAAA,wBAAA;AACA,MAAA,2BAAA;AACA,MAAA,qBAAA;AACA,MAAA,wBAAA;AACA,MAAA,sBAAA;AAEA,MAAA,oBAAA;AACA,MAAA,uBAAA;AACA,MAAA,iBAAA;AACA,MAAA,oBAAA;AACA,MAAA,kBAAA;AAQA,MAAA,mBAAA;CACA,OAAA;CACA,MAAA;CACA,UAAA;CACA;AAEA,MAAA,sBAAA;CACA,OAAA;CACA,MAAA;CACA,UAAA;CACA;AAEA,MAAA,gBAAA;CACA,OAAA;CACA,MAAA;CACA,UAAA;CACA;AAEA,MAAA,mBAAA;CACA,OAAA;CACA,MAAA;CACA,UAAA;CACA;AAEA,MAAA,iBAAA;CACA,OAAA;CACA,MAAA;CACA,UAAA;CACA;AAEA,MAAA,4BAAA,IAAA,kRAyBA;AAEA,MAAA,+BAAA,IAAA,kJAcA;AAEA,MAAA,yBAAA,IAAA,uGAQA;AAEA,MAAA,4BAAA,IAAA,wJAiBA;AAEA,MAAA,0BAAA,IAAA,yHAOA;AAOA,MAAA,0BAAA,IACA,wfAoBW,sBAAwB,gEAIxB,yBAA2B,oDAI3B,mBAAqB,0DAIrB,sBAAwB,uDAIxB,oBAAsB,MAIjC;CACA;CACA;CACA;CACA;CACA;CACA,CACA;AAEA,MAAA,2BAAA,IAAA,0DAIA;AAEA,MAAA,8BAAA,IAAA,gEAIA;AAEA,MAAA,wBAAA,IAAA,oDAIA;AAEA,MAAA,2BAAA,IAAA,0DAIA;AAEA,MAAA,yBAAA,IAAA,wEAIA;AAmEA,SAAA,uBAAA,UAAA,UAAA;AAEA,KAAA,IADA,OAAA,eAAA,SAAA,KAAA,YAAA,SAAA,SAAA,KACA,CAAA,KAAA,SAAA,CAAA;AAEA,OAAA,IAAA,MACA,qBAAA,SAAA,MAAA,0BAAA,SAAA,KAAA,cAAA,SAAA,WACA;;AAGA,SAAA,iBAAA,WAAA;AACA,KAAA,WAAA,QAAA,wBAAA,UAAA,SAAA,iBAAA;AACA,KAAA,WAAA,WAAA,wBAAA,UAAA,YAAA,oBAAA;AACA,KAAA,WAAA,KAAA,wBAAA,UAAA,MAAA,cAAA;AACA,KAAA,WAAA,QAAA,wBAAA,UAAA,SAAA,iBAAA;AACA,KAAA,WAAA,MAAA,wBAAA,UAAA,OAAA,eAAA;AAEA,QAAA;EACA,WAAA,WAAA;EACA,WAAA,cAAA;EACA,WAAA,QAAA;EACA,WAAA,WAAA;EACA,WAAA,SAAA;EACA;;AAoBA,SAAA,4BAAA,SAAA;AACA,QAAA,EACA,kBAAA,IAAA,yBAAA,iBAAA,SAAA,UAAA,CAAA,EACA;;;;;;;;AASA,MAAA,0BAAA,6BAAA"}
1
+ {"version":3,"file":"queries.mjs","names":[],"sources":["../../../../src/core/predictive-search/queries.ts"],"sourcesContent":["import {\n gql,\n type AnyStorefrontQueryString,\n type ComposedSource,\n type SourceOf,\n type StorefrontQueryString,\n} from \"../../graphql\";\nimport type { InferResult, InferVariables } from \"../../graphql\";\n\nconst PRODUCT_FRAGMENT_NAME = \"PredictiveSearchProductFragment\";\nconst COLLECTION_FRAGMENT_NAME = \"PredictiveSearchCollectionFragment\";\nconst PAGE_FRAGMENT_NAME = \"PredictiveSearchPageFragment\";\nconst ARTICLE_FRAGMENT_NAME = \"PredictiveSearchArticleFragment\";\nconst QUERY_FRAGMENT_NAME = \"PredictiveSearchQueryFragment\";\n\nconst PRODUCT_TYPE_NAME = \"Product\";\nconst COLLECTION_TYPE_NAME = \"Collection\";\nconst PAGE_TYPE_NAME = \"Page\";\nconst ARTICLE_TYPE_NAME = \"Article\";\nconst QUERY_TYPE_NAME = \"SearchQuerySuggestion\";\n\ntype FragmentContract = {\n readonly label: string;\n readonly name: string;\n readonly typeName: string;\n};\n\nconst PRODUCT_CONTRACT = {\n label: \"product\",\n name: PRODUCT_FRAGMENT_NAME,\n typeName: PRODUCT_TYPE_NAME,\n} as const satisfies FragmentContract;\n\nconst COLLECTION_CONTRACT = {\n label: \"collection\",\n name: COLLECTION_FRAGMENT_NAME,\n typeName: COLLECTION_TYPE_NAME,\n} as const satisfies FragmentContract;\n\nconst PAGE_CONTRACT = {\n label: \"page\",\n name: PAGE_FRAGMENT_NAME,\n typeName: PAGE_TYPE_NAME,\n} as const satisfies FragmentContract;\n\nconst ARTICLE_CONTRACT = {\n label: \"article\",\n name: ARTICLE_FRAGMENT_NAME,\n typeName: ARTICLE_TYPE_NAME,\n} as const satisfies FragmentContract;\n\nconst QUERY_CONTRACT = {\n label: \"query\",\n name: QUERY_FRAGMENT_NAME,\n typeName: QUERY_TYPE_NAME,\n} as const satisfies FragmentContract;\n\nconst HYDROGEN_PRODUCT_FRAGMENT = gql(`\n fragment HydrogenPredictiveSearchProductFragment on Product {\n __typename\n id\n title\n handle\n trackingParameters\n selectedOrFirstAvailableVariant(\n selectedOptions: []\n ignoreUnknownOptions: true\n caseInsensitiveMatch: true\n ) {\n id\n image {\n url\n altText\n width\n height\n }\n price {\n amount\n currencyCode\n }\n }\n }\n`);\n\nconst HYDROGEN_COLLECTION_FRAGMENT = gql(`\n fragment HydrogenPredictiveSearchCollectionFragment on Collection {\n __typename\n id\n title\n handle\n image {\n url\n altText\n width\n height\n }\n trackingParameters\n }\n`);\n\nconst HYDROGEN_PAGE_FRAGMENT = gql(`\n fragment HydrogenPredictiveSearchPageFragment on Page {\n __typename\n id\n title\n handle\n trackingParameters\n }\n`);\n\nconst HYDROGEN_ARTICLE_FRAGMENT = gql(`\n fragment HydrogenPredictiveSearchArticleFragment on Article {\n __typename\n id\n title\n handle\n blog {\n handle\n }\n image {\n url\n altText\n width\n height\n }\n trackingParameters\n }\n`);\n\nconst HYDROGEN_QUERY_FRAGMENT = gql(`\n fragment HydrogenPredictiveSearchQueryFragment on SearchQuerySuggestion {\n __typename\n text\n styledText\n trackingParameters\n }\n`);\n\n// The consumer-overridable fragment spreads (e.g. PredictiveSearchProductFragment)\n// are interpolated on purpose: those fragments only exist at runtime, and the\n// gql.tada plugin skips documents containing interpolations instead of flagging\n// unknown fragments, while TypeScript still resolves the full literal source type.\n// The resolved fragments are composed in at runtime by `makePredictiveSearchQueries`.\nconst PREDICTIVE_SEARCH_QUERY = gql(\n `query PredictiveSearch(\n $country: CountryCode\n $language: LanguageCode\n $limit: Int\n $limitScope: PredictiveSearchLimitScope\n $term: String!\n $types: [PredictiveSearchType!]\n $searchableFields: [SearchableField!]\n $unavailableProducts: SearchUnavailableProductsType\n ) @inContext(country: $country, language: $language) {\n predictiveSearch(\n limit: $limit\n limitScope: $limitScope\n query: $term\n types: $types\n searchableFields: $searchableFields\n unavailableProducts: $unavailableProducts\n ) {\n articles {\n ...HydrogenPredictiveSearchArticleFragment\n ...${ARTICLE_FRAGMENT_NAME}\n }\n collections {\n ...HydrogenPredictiveSearchCollectionFragment\n ...${COLLECTION_FRAGMENT_NAME}\n }\n pages {\n ...HydrogenPredictiveSearchPageFragment\n ...${PAGE_FRAGMENT_NAME}\n }\n products {\n ...HydrogenPredictiveSearchProductFragment\n ...${PRODUCT_FRAGMENT_NAME}\n }\n queries {\n ...HydrogenPredictiveSearchQueryFragment\n ...${QUERY_FRAGMENT_NAME}\n }\n }\n }`,\n [\n HYDROGEN_PRODUCT_FRAGMENT,\n HYDROGEN_COLLECTION_FRAGMENT,\n HYDROGEN_PAGE_FRAGMENT,\n HYDROGEN_ARTICLE_FRAGMENT,\n HYDROGEN_QUERY_FRAGMENT,\n ],\n);\n\nconst DEFAULT_PRODUCT_FRAGMENT = gql(`\n fragment PredictiveSearchProductFragment on Product {\n id\n }\n`);\n\nconst DEFAULT_COLLECTION_FRAGMENT = gql(`\n fragment PredictiveSearchCollectionFragment on Collection {\n id\n }\n`);\n\nconst DEFAULT_PAGE_FRAGMENT = gql(`\n fragment PredictiveSearchPageFragment on Page {\n id\n }\n`);\n\nconst DEFAULT_ARTICLE_FRAGMENT = gql(`\n fragment PredictiveSearchArticleFragment on Article {\n id\n }\n`);\n\nconst DEFAULT_QUERY_FRAGMENT = gql(`\n fragment PredictiveSearchQueryFragment on SearchQuerySuggestion {\n text\n }\n`);\n\n/**\n * GraphQL fragments that add fields to each type of predictive search result.\n *\n * Each fragment needs the name and type that its option lists, or `makePredictiveSearchQueries` throws an error.\n * Results keep Hydrogen's built-in fields for links, tracking, and display.\n */\nexport type PredictiveSearchFragments = {\n /** Adds fields to product results. Start the fragment with `fragment PredictiveSearchProductFragment on Product`. */\n readonly product?: AnyStorefrontQueryString;\n /** Adds fields to collection results. Start the fragment with `fragment PredictiveSearchCollectionFragment on Collection`. */\n readonly collection?: AnyStorefrontQueryString;\n /** Adds fields to page results. Start the fragment with `fragment PredictiveSearchPageFragment on Page`. */\n readonly page?: AnyStorefrontQueryString;\n /** Adds fields to article results. Start the fragment with `fragment PredictiveSearchArticleFragment on Article`. */\n readonly article?: AnyStorefrontQueryString;\n /** Adds fields to query suggestions. Start the fragment with `fragment PredictiveSearchQueryFragment on SearchQuerySuggestion`. */\n readonly query?: AnyStorefrontQueryString;\n};\n\n/** Options for a custom predictive search query. */\nexport type CreatePredictiveSearchQueriesOptions<\n TFragments extends PredictiveSearchFragments = PredictiveSearchFragments,\n> = {\n /** Fragments that add fields to each result type. Results keep Hydrogen's built-in fields. */\n readonly fragments?: TFragments;\n};\n\ntype FragmentForOptions<\n TOptions,\n TKey extends keyof PredictiveSearchFragments,\n TDefault extends AnyStorefrontQueryString,\n> = TOptions extends { readonly fragments: infer TFragments }\n ? TFragments extends Record<TKey, infer TFragment extends AnyStorefrontQueryString>\n ? TFragment\n : TDefault\n : TDefault;\n\ntype PredictiveSearchQueryFragmentsForOptions<TOptions> = [\n FragmentForOptions<TOptions, \"product\", typeof DEFAULT_PRODUCT_FRAGMENT>,\n FragmentForOptions<TOptions, \"collection\", typeof DEFAULT_COLLECTION_FRAGMENT>,\n FragmentForOptions<TOptions, \"page\", typeof DEFAULT_PAGE_FRAGMENT>,\n FragmentForOptions<TOptions, \"article\", typeof DEFAULT_ARTICLE_FRAGMENT>,\n FragmentForOptions<TOptions, \"query\", typeof DEFAULT_QUERY_FRAGMENT>,\n];\n\ntype PredictiveSearchQuerySourceForOptions<TOptions> = ComposedSource<\n SourceOf<typeof PREDICTIVE_SEARCH_QUERY>,\n PredictiveSearchQueryFragmentsForOptions<TOptions>\n>;\n\n/** Type of a custom predictive search query, with result types from your fragments. */\ntype PredictiveSearchQueryForOptions<TOptions> = StorefrontQueryString<\n InferResult<PredictiveSearchQuerySourceForOptions<TOptions>>,\n InferVariables<PredictiveSearchQuerySourceForOptions<TOptions>>,\n PredictiveSearchQuerySourceForOptions<TOptions>\n>;\n\n/** Type of the object that makePredictiveSearchQueries returns, with result types from your fragments. */\nexport type PredictiveSearchQueriesForOptions<TOptions> = {\n readonly predictiveSearch: PredictiveSearchQueryForOptions<TOptions>;\n};\n\nfunction assertFragmentContract(fragment: string, contract: FragmentContract): void {\n const pattern = new RegExp(`fragment\\\\s+${contract.name}\\\\s+on\\\\s+${contract.typeName}\\\\b`);\n if (pattern.test(fragment)) return;\n\n throw new Error(\n `Predictive search ${contract.label} fragment must be named ${contract.name} and target ${contract.typeName}`,\n );\n}\n\nfunction resolveFragments(fragments: PredictiveSearchFragments | undefined) {\n if (fragments?.product) assertFragmentContract(fragments.product, PRODUCT_CONTRACT);\n if (fragments?.collection) assertFragmentContract(fragments.collection, COLLECTION_CONTRACT);\n if (fragments?.page) assertFragmentContract(fragments.page, PAGE_CONTRACT);\n if (fragments?.article) assertFragmentContract(fragments.article, ARTICLE_CONTRACT);\n if (fragments?.query) assertFragmentContract(fragments.query, QUERY_CONTRACT);\n\n return [\n fragments?.product ?? DEFAULT_PRODUCT_FRAGMENT,\n fragments?.collection ?? DEFAULT_COLLECTION_FRAGMENT,\n fragments?.page ?? DEFAULT_PAGE_FRAGMENT,\n fragments?.article ?? DEFAULT_ARTICLE_FRAGMENT,\n fragments?.query ?? DEFAULT_QUERY_FRAGMENT,\n ] as const;\n}\n\n/**\n * Builds a predictive search query that adds the fields from your fragments to the results.\n *\n * Pass the query to `queryPredictiveSearch`, or pass the same fragments to `createPredictiveSearchServerHandlers`. TypeScript types the results from your fragments.\n * The function throws an error when a fragment doesn't use its required name and type.\n *\n * @throws {Error} When a custom fragment does not match its required name or target type.\n * @publicDocs\n */\nexport function makePredictiveSearchQueries<\n const TOptions extends CreatePredictiveSearchQueriesOptions,\n>(options: TOptions): PredictiveSearchQueriesForOptions<TOptions>;\nexport function makePredictiveSearchQueries(): PredictiveSearchQueriesForOptions<undefined>;\n/**\n * @param options Fragments that add fields to each result type.\n * @returns An object with the query under `predictiveSearch`.\n */\nexport function makePredictiveSearchQueries(options?: CreatePredictiveSearchQueriesOptions) {\n return {\n predictiveSearch: gql(PREDICTIVE_SEARCH_QUERY, resolveFragments(options?.fragments)),\n } as PredictiveSearchQueriesForOptions<typeof options>;\n}\n\n/**\n * Hydrogen's built-in predictive search query, under `predictiveSearch`.\n * queryPredictiveSearch uses the query when you omit the `query` option.\n *\n * To add fields to the results, use makePredictiveSearchQueries.\n */\nexport const predictiveSearchQueries = makePredictiveSearchQueries();\n"],"mappings":";;;AASA,MAAA,wBAAA;AACA,MAAA,2BAAA;AACA,MAAA,qBAAA;AACA,MAAA,wBAAA;AACA,MAAA,sBAAA;AAEA,MAAA,oBAAA;AACA,MAAA,uBAAA;AACA,MAAA,iBAAA;AACA,MAAA,oBAAA;AACA,MAAA,kBAAA;AAQA,MAAA,mBAAA;CACA,OAAA;CACA,MAAA;CACA,UAAA;CACA;AAEA,MAAA,sBAAA;CACA,OAAA;CACA,MAAA;CACA,UAAA;CACA;AAEA,MAAA,gBAAA;CACA,OAAA;CACA,MAAA;CACA,UAAA;CACA;AAEA,MAAA,mBAAA;CACA,OAAA;CACA,MAAA;CACA,UAAA;CACA;AAEA,MAAA,iBAAA;CACA,OAAA;CACA,MAAA;CACA,UAAA;CACA;AAEA,MAAA,4BAAA,IAAA,kRAyBA;AAEA,MAAA,+BAAA,IAAA,kJAcA;AAEA,MAAA,yBAAA,IAAA,uGAQA;AAEA,MAAA,4BAAA,IAAA,wJAiBA;AAEA,MAAA,0BAAA,IAAA,yHAOA;AAOA,MAAA,0BAAA,IACA,wfAoBW,sBAAwB,gEAIxB,yBAA2B,oDAI3B,mBAAqB,0DAIrB,sBAAwB,uDAIxB,oBAAsB,MAIjC;CACA;CACA;CACA;CACA;CACA;CACA,CACA;AAEA,MAAA,2BAAA,IAAA,0DAIA;AAEA,MAAA,8BAAA,IAAA,gEAIA;AAEA,MAAA,wBAAA,IAAA,oDAIA;AAEA,MAAA,2BAAA,IAAA,0DAIA;AAEA,MAAA,yBAAA,IAAA,wEAIA;AAgEA,SAAA,uBAAA,UAAA,UAAA;AAEA,KAAA,IADA,OAAA,eAAA,SAAA,KAAA,YAAA,SAAA,SAAA,KACA,CAAA,KAAA,SAAA,CAAA;AAEA,OAAA,IAAA,MACA,qBAAA,SAAA,MAAA,0BAAA,SAAA,KAAA,cAAA,SAAA,WACA;;AAGA,SAAA,iBAAA,WAAA;AACA,KAAA,WAAA,QAAA,wBAAA,UAAA,SAAA,iBAAA;AACA,KAAA,WAAA,WAAA,wBAAA,UAAA,YAAA,oBAAA;AACA,KAAA,WAAA,KAAA,wBAAA,UAAA,MAAA,cAAA;AACA,KAAA,WAAA,QAAA,wBAAA,UAAA,SAAA,iBAAA;AACA,KAAA,WAAA,MAAA,wBAAA,UAAA,OAAA,eAAA;AAEA,QAAA;EACA,WAAA,WAAA;EACA,WAAA,cAAA;EACA,WAAA,QAAA;EACA,WAAA,WAAA;EACA,WAAA,SAAA;EACA;;;;;;AAoBA,SAAA,4BAAA,SAAA;AACA,QAAA,EACA,kBAAA,IAAA,yBAAA,iBAAA,SAAA,UAAA,CAAA,EACA;;;;;;;;AASA,MAAA,0BAAA,6BAAA"}
@@ -9,11 +9,11 @@ type PredictiveSearchItemsForQuery<TQuery extends AnyStorefrontQueryString> = No
9
9
  predictiveSearch?: (infer TItems) | null;
10
10
  } ? TItems : never>;
11
11
  /**
12
- * Predictive search result payload returned by {@link queryPredictiveSearch}.
12
+ * Predictive search results, with the search term and the result count.
13
13
  *
14
- * The generic parameter is the shape of `items` and defaults to the
15
- * built-in query's items. For custom fragments, infer the full payload from
16
- * `queryPredictiveSearch` and your query document:
14
+ * The type parameter sets the shape of the results and defaults to the
15
+ * results of Hydrogen's built-in query. For a custom query, use the awaited
16
+ * return type of `queryPredictiveSearch` for that query.
17
17
  *
18
18
  * @example
19
19
  * ```ts
@@ -23,41 +23,39 @@ type PredictiveSearchItemsForQuery<TQuery extends AnyStorefrontQueryString> = No
23
23
  * ```
24
24
  */
25
25
  type PredictiveSearchData<TItems = PredictiveSearchItemsForQuery<typeof predictiveSearchQueries.predictiveSearch>> = {
26
- /** Trimmed search term that produced this result. */term: string; /** Number of items returned, summed across every array in `items` (including query suggestions). Not a total match count. */
27
- total: number; /** Predictive search items grouped by resource type. */
26
+ /** Search term for the results, without surrounding whitespace. */term: string; /** Number of results in the response across every result type, including query suggestions. The count leaves out matches beyond the limit. */
27
+ total: number; /** Results grouped by type. */
28
28
  items: TItems;
29
29
  };
30
- /** Resolves {@link PredictiveSearchData} from a custom query document type, inferring the items shape from the query's result type. */
30
+ /** Predictive search results typed from a custom query. The results take their shape from the query's fields. */
31
31
  type PredictiveSearchDataForQuery<TQuery extends AnyStorefrontQueryString> = PredictiveSearchData<PredictiveSearchItemsForQuery<TQuery>>;
32
- /** Resolves {@link PredictiveSearchData} from {@link CreatePredictiveSearchQueriesOptions}, reflecting the items shape produced by custom fragments. */
32
+ /** Predictive search results typed from query options. The results include the fields from your custom fragments. */
33
33
  type PredictiveSearchDataForOptions<TOptions extends CreatePredictiveSearchQueriesOptions> = PredictiveSearchDataForQuery<PredictiveSearchQueriesForOptions<TOptions>["predictiveSearch"]>;
34
- /**
35
- * Options for {@link queryPredictiveSearch}.
36
- *
37
- * The generic parameter accepts a custom query document type and defaults to
38
- * the built-in predictive search query.
39
- */
34
+ /** Storefront client, search term, custom query, and search settings for `queryPredictiveSearch`. */
40
35
  type QueryPredictiveSearchOptions<TQuery extends AnyStorefrontQueryString = typeof predictiveSearchQueries.predictiveSearch> = {
41
- /** Storefront client instance. Only the `graphql` method is used. */storefrontClient: Pick<StorefrontClient, "graphql">; /** Search term. Trimmed before use; empty or whitespace-only terms return an empty result without a network request. */
42
- term: string; /** Custom GraphQL query document, usually created with `makePredictiveSearchQueries`. Must declare the same variables as the built-in query (`$term`, `$limit`, `$limitScope`, `$types`, `$searchableFields`, `$unavailableProducts`). */
43
- query?: TQuery; /** Maximum result count. Truncated to an integer, then clamped to the Storefront API's accepted range (1-10). Omitted or non-finite values use Hydrogen's default of 5 (the Storefront API's own default is 10). */
44
- limit?: number; /** Whether the limit applies to each resource type independently or to all types combined. Defaults to `"EACH"` (the Storefront API's own default is `"ALL"`). */
45
- limitScope?: PredictiveSearchLimitScope; /** Resource types to include. When omitted, the Storefront API uses the shop's predictive search type settings, which exclude articles by default. Pass `types` explicitly to control which result arrays are populated. */
46
- types?: PredictiveSearchType[]; /** Fields to search within. When omitted, the Storefront API searches its default field set (title, product type, variant title, and vendor), not every field. */
47
- searchableFields?: SearchableField[]; /** How to handle unavailable products. Defaults to `"HIDE"` rather than the Storefront API's shop-specific setting (which defaults to `"LAST"`). */
48
- unavailableProducts?: SearchUnavailableProductsType; /** Signal to abort the in-flight request. */
36
+ /** Storefront client that sends the query. Any object with a `graphql()` method works. */storefrontClient: Pick<StorefrontClient, "graphql">; /** Search term. A blank term returns empty results without a Storefront API request. */
37
+ term: string; /** Custom query, usually from `makePredictiveSearchQueries`. Defaults to Hydrogen's built-in query. A hand-written query receives the term, limit, limit scope, types, searchable fields, and unavailable products as variables. */
38
+ query?: TQuery; /** Maximum number of results, from 1 to 10. Predictive search clamps other values to that range. Defaults to `5`, which differs from the Storefront API default of 10. */
39
+ limit?: number; /** Whether the limit applies to each result type or to all result types combined. Defaults to `EACH`. */
40
+ limitScope?: PredictiveSearchLimitScope; /** Result types to include. */
41
+ types?: PredictiveSearchType[]; /** Fields to search for page, article, and collection results. Defaults to the title. Product results always search every product field. */
42
+ searchableFields?: SearchableField[]; /** Whether results hide unavailable products, show them, or list them last. Defaults to `HIDE`, which differs from the Storefront API default of `LAST`. */
43
+ unavailableProducts?: SearchUnavailableProductsType; /** Cancels the request when the signal aborts. */
49
44
  signal?: AbortSignal;
50
45
  };
51
46
  /**
52
- * Executes a predictive search query against the Storefront API and returns
53
- * the data payload.
47
+ * Queries the Storefront API for predictive search results. Use the function in server code, such as a route loader. Pass the Storefront client and the search term.
48
+ *
49
+ * The function throws an error when the Storefront API returns GraphQL errors or no predictive search data. Network failures and aborts from the Storefront client also throw.
54
50
  *
55
- * To serve results with the Storefront API response headers (e.g. cache
56
- * headers), use the `get` handler from `createPredictiveSearchServerHandlers()`.
51
+ * To serve results to the browser with the Storefront API response headers, use `createPredictiveSearchServerHandlers`.
57
52
  *
53
+ * @param options - The Storefront client, the search term, a custom query, and search settings.
54
+ * @returns The search term, the result count, and the results grouped by type.
58
55
  * @throws {Error} When the Storefront API returns GraphQL errors.
59
56
  * @throws {Error} When the response contains no predictive search data.
60
- * @throws Errors from `storefrontClient.graphql` (e.g. network failures or an `AbortError` when `signal` aborts).
57
+ * @throws Errors from the Storefront client, such as network failures or an abort error when the signal aborts.
58
+ * @publicDocs
61
59
  */
62
60
  declare function queryPredictiveSearch<const TQuery extends AnyStorefrontQueryString = typeof predictiveSearchQueries.predictiveSearch>(options: QueryPredictiveSearchOptions<TQuery>): Promise<PredictiveSearchDataForQuery<TQuery>>;
63
61
  //#endregion
@@ -1,22 +1,22 @@
1
1
  import { predictiveSearchQueries } from "./queries.mjs";
2
2
 
3
3
  //#region src/core/predictive-search/search.ts
4
- /** Minimum result count accepted by the Storefront API predictive search query. Values below this are clamped up. */
4
+ /** Smallest result limit. Predictive search raises lower limits to this value. */
5
5
  const MIN_PREDICTIVE_SEARCH_LIMIT = 1;
6
- /** Maximum result count accepted by the Storefront API predictive search query. Values above this are clamped down. */
6
+ /** Largest result limit. Predictive search lowers higher limits to this value. */
7
7
  const MAX_PREDICTIVE_SEARCH_LIMIT = 10;
8
- /** Default result count used when no limit is specified. */
8
+ /** Result limit that predictive search uses when you don't set one. */
9
9
  const DEFAULT_PREDICTIVE_SEARCH_LIMIT = 5;
10
- /** Default limit scope, applying the limit to each resource type independently. */
10
+ /** Default limit scope, which applies the limit to each result type separately. */
11
11
  const DEFAULT_PREDICTIVE_SEARCH_LIMIT_SCOPE = "EACH";
12
- /** Default unavailable-product behavior, hiding them from results. */
12
+ /** Default unavailable product behavior, which hides unavailable products. */
13
13
  const DEFAULT_PREDICTIVE_SEARCH_UNAVAILABLE_PRODUCTS = "HIDE";
14
14
  /**
15
- * Returns a zero-result `PredictiveSearchData` payload with empty arrays
16
- * for every resource type.
15
+ * Returns an empty predictive search result with an empty array for every
16
+ * resource type.
17
17
  *
18
- * Used internally for blank terms and for the client store's initial and
19
- * reset state. Typed with the default items shape.
18
+ * The query function returns the empty result for blank terms. The client
19
+ * store uses the empty result for its initial and reset state.
20
20
  */
21
21
  function getEmptyPredictiveSearchResult(term = "") {
22
22
  return {
@@ -32,29 +32,30 @@ function getEmptyPredictiveSearchResult(term = "") {
32
32
  };
33
33
  }
34
34
  /**
35
- * Executes a predictive search query against the Storefront API and returns
36
- * the data payload.
35
+ * Queries the Storefront API for predictive search results. Use the function in server code, such as a route loader. Pass the Storefront client and the search term.
37
36
  *
38
- * To serve results with the Storefront API response headers (e.g. cache
39
- * headers), use the `get` handler from `createPredictiveSearchServerHandlers()`.
37
+ * The function throws an error when the Storefront API returns GraphQL errors or no predictive search data. Network failures and aborts from the Storefront client also throw.
40
38
  *
39
+ * To serve results to the browser with the Storefront API response headers, use `createPredictiveSearchServerHandlers`.
40
+ *
41
+ * @param options - The Storefront client, the search term, a custom query, and search settings.
42
+ * @returns The search term, the result count, and the results grouped by type.
41
43
  * @throws {Error} When the Storefront API returns GraphQL errors.
42
44
  * @throws {Error} When the response contains no predictive search data.
43
- * @throws Errors from `storefrontClient.graphql` (e.g. network failures or an `AbortError` when `signal` aborts).
45
+ * @throws Errors from the Storefront client, such as network failures or an abort error when the signal aborts.
46
+ * @publicDocs
44
47
  */
45
48
  async function queryPredictiveSearch(options) {
46
49
  return (await fetchPredictiveSearch(options)).data;
47
50
  }
48
51
  /**
49
- * Executes a predictive search query against the Storefront API and returns
50
- * both the data payload and response headers.
52
+ * Queries the Storefront API for predictive search results and returns the results with the Storefront API response headers.
51
53
  *
52
- * See `QueryPredictiveSearchOptions` for option defaults and
53
- * `PredictiveSearchData` for the shape of the returned data.
54
+ * The function takes the same options as queryPredictiveSearch.
54
55
  *
55
56
  * @throws {Error} When the Storefront API returns GraphQL errors.
56
57
  * @throws {Error} When the response contains no predictive search data.
57
- * @throws Errors from `storefrontClient.graphql` (e.g. network failures or an `AbortError` when `signal` aborts).
58
+ * @throws Errors from the Storefront client, such as network failures or an abort error when the signal aborts.
58
59
  */
59
60
  async function fetchPredictiveSearch({ storefrontClient, term, query, limit, limitScope = DEFAULT_PREDICTIVE_SEARCH_LIMIT_SCOPE, types, searchableFields, unavailableProducts = DEFAULT_PREDICTIVE_SEARCH_UNAVAILABLE_PRODUCTS, signal }) {
60
61
  const trimmedTerm = term.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"search.mjs","names":[],"sources":["../../../../src/core/predictive-search/search.ts"],"sourcesContent":["import type { GraphQLFormattedError, StorefrontClient } from \"../../client\";\nimport type { AnyStorefrontQueryString, StorefrontQueryString } from \"../../graphql\";\nimport type {\n PredictiveSearchLimitScope,\n PredictiveSearchType,\n SearchUnavailableProductsType,\n SearchableField,\n} from \"../../graphql/generated/storefront-api-types\";\nimport {\n predictiveSearchQueries,\n type CreatePredictiveSearchQueriesOptions,\n type PredictiveSearchQueriesForOptions,\n} from \"./queries\";\n\n/** Minimum result count accepted by the Storefront API predictive search query. Values below this are clamped up. */\nexport const MIN_PREDICTIVE_SEARCH_LIMIT = 1;\n/** Maximum result count accepted by the Storefront API predictive search query. Values above this are clamped down. */\nexport const MAX_PREDICTIVE_SEARCH_LIMIT = 10;\n/** Default result count used when no limit is specified. */\nexport const DEFAULT_PREDICTIVE_SEARCH_LIMIT = 5;\n/** Default limit scope, applying the limit to each resource type independently. */\nexport const DEFAULT_PREDICTIVE_SEARCH_LIMIT_SCOPE = \"EACH\" satisfies PredictiveSearchLimitScope;\n/** Default unavailable-product behavior, hiding them from results. */\nexport const DEFAULT_PREDICTIVE_SEARCH_UNAVAILABLE_PRODUCTS =\n \"HIDE\" satisfies SearchUnavailableProductsType;\n\ntype PredictiveSearchGraphqlResult<TQuery extends AnyStorefrontQueryString> =\n TQuery extends StorefrontQueryString<infer TResult, infer _Variables, string> ? TResult : never;\n\ntype PredictiveSearchItemsForQuery<TQuery extends AnyStorefrontQueryString> = NonNullable<\n PredictiveSearchGraphqlResult<TQuery> extends { predictiveSearch?: (infer TItems) | null }\n ? TItems\n : never\n>;\n\n/**\n * Predictive search result payload returned by {@link queryPredictiveSearch}.\n *\n * The generic parameter is the shape of `items` and defaults to the\n * built-in query's items. For custom fragments, infer the full payload from\n * `queryPredictiveSearch` and your query document:\n *\n * @example\n * ```ts\n * type CustomSearchData = Awaited<\n * ReturnType<typeof queryPredictiveSearch<typeof queries.predictiveSearch>>\n * >;\n * ```\n */\nexport type PredictiveSearchData<\n TItems = PredictiveSearchItemsForQuery<typeof predictiveSearchQueries.predictiveSearch>,\n> = {\n /** Trimmed search term that produced this result. */\n term: string;\n /** Number of items returned, summed across every array in `items` (including query suggestions). Not a total match count. */\n total: number;\n /** Predictive search items grouped by resource type. */\n items: TItems;\n};\n\n/** Resolves {@link PredictiveSearchData} from a custom query document type, inferring the items shape from the query's result type. */\nexport type PredictiveSearchDataForQuery<TQuery extends AnyStorefrontQueryString> =\n PredictiveSearchData<PredictiveSearchItemsForQuery<TQuery>>;\n\n/** Resolves {@link PredictiveSearchData} from {@link CreatePredictiveSearchQueriesOptions}, reflecting the items shape produced by custom fragments. */\nexport type PredictiveSearchDataForOptions<TOptions extends CreatePredictiveSearchQueriesOptions> =\n PredictiveSearchDataForQuery<PredictiveSearchQueriesForOptions<TOptions>[\"predictiveSearch\"]>;\n\n/**\n * Options for {@link queryPredictiveSearch}.\n *\n * The generic parameter accepts a custom query document type and defaults to\n * the built-in predictive search query.\n */\nexport type QueryPredictiveSearchOptions<\n TQuery extends AnyStorefrontQueryString = typeof predictiveSearchQueries.predictiveSearch,\n> = {\n /** Storefront client instance. Only the `graphql` method is used. */\n storefrontClient: Pick<StorefrontClient, \"graphql\">;\n /** Search term. Trimmed before use; empty or whitespace-only terms return an empty result without a network request. */\n term: string;\n /** Custom GraphQL query document, usually created with `makePredictiveSearchQueries`. Must declare the same variables as the built-in query (`$term`, `$limit`, `$limitScope`, `$types`, `$searchableFields`, `$unavailableProducts`). */\n query?: TQuery;\n /** Maximum result count. Truncated to an integer, then clamped to the Storefront API's accepted range (1-10). Omitted or non-finite values use Hydrogen's default of 5 (the Storefront API's own default is 10). */\n limit?: number;\n /** Whether the limit applies to each resource type independently or to all types combined. Defaults to `\"EACH\"` (the Storefront API's own default is `\"ALL\"`). */\n limitScope?: PredictiveSearchLimitScope;\n /** Resource types to include. When omitted, the Storefront API uses the shop's predictive search type settings, which exclude articles by default. Pass `types` explicitly to control which result arrays are populated. */\n types?: PredictiveSearchType[];\n /** Fields to search within. When omitted, the Storefront API searches its default field set (title, product type, variant title, and vendor), not every field. */\n searchableFields?: SearchableField[];\n /** How to handle unavailable products. Defaults to `\"HIDE\"` rather than the Storefront API's shop-specific setting (which defaults to `\"LAST\"`). */\n unavailableProducts?: SearchUnavailableProductsType;\n /** Signal to abort the in-flight request. */\n signal?: AbortSignal;\n};\n\ntype FetchPredictiveSearchResult<TQuery extends AnyStorefrontQueryString> = {\n data: PredictiveSearchDataForQuery<TQuery>;\n headers: Headers;\n};\n\ntype PredictiveSearchQueryDocument = AnyStorefrontQueryString;\n\ntype PredictiveSearchVariables = {\n term: string;\n limit: number;\n limitScope: PredictiveSearchLimitScope;\n types: PredictiveSearchType[] | undefined;\n searchableFields: SearchableField[] | undefined;\n unavailableProducts: SearchUnavailableProductsType;\n};\n\ntype PredictiveSearchQueryResult<TItems> = {\n data: { predictiveSearch?: TItems | null } | null;\n errors?: GraphQLFormattedError[];\n headers: Headers;\n};\n\ntype PredictiveSearchGraphql<TItems> = (\n query: PredictiveSearchQueryDocument,\n options: { variables: PredictiveSearchVariables; signal?: AbortSignal },\n) => Promise<PredictiveSearchQueryResult<TItems>>;\n\n/**\n * Returns a zero-result `PredictiveSearchData` payload with empty arrays\n * for every resource type.\n *\n * Used internally for blank terms and for the client store's initial and\n * reset state. Typed with the default items shape.\n */\nexport function getEmptyPredictiveSearchResult(term = \"\"): PredictiveSearchData {\n return {\n term,\n total: 0,\n items: {\n products: [],\n collections: [],\n pages: [],\n articles: [],\n queries: [],\n },\n };\n}\n\n/**\n * Executes a predictive search query against the Storefront API and returns\n * the data payload.\n *\n * To serve results with the Storefront API response headers (e.g. cache\n * headers), use the `get` handler from `createPredictiveSearchServerHandlers()`.\n *\n * @throws {Error} When the Storefront API returns GraphQL errors.\n * @throws {Error} When the response contains no predictive search data.\n * @throws Errors from `storefrontClient.graphql` (e.g. network failures or an `AbortError` when `signal` aborts).\n */\nexport async function queryPredictiveSearch<\n const TQuery extends AnyStorefrontQueryString = typeof predictiveSearchQueries.predictiveSearch,\n>(options: QueryPredictiveSearchOptions<TQuery>): Promise<PredictiveSearchDataForQuery<TQuery>> {\n const result = await fetchPredictiveSearch(options);\n return result.data;\n}\n\n/**\n * Executes a predictive search query against the Storefront API and returns\n * both the data payload and response headers.\n *\n * See `QueryPredictiveSearchOptions` for option defaults and\n * `PredictiveSearchData` for the shape of the returned data.\n *\n * @throws {Error} When the Storefront API returns GraphQL errors.\n * @throws {Error} When the response contains no predictive search data.\n * @throws Errors from `storefrontClient.graphql` (e.g. network failures or an `AbortError` when `signal` aborts).\n */\nexport async function fetchPredictiveSearch<\n const TQuery extends AnyStorefrontQueryString = typeof predictiveSearchQueries.predictiveSearch,\n>({\n storefrontClient,\n term,\n query,\n limit,\n limitScope = DEFAULT_PREDICTIVE_SEARCH_LIMIT_SCOPE,\n types,\n searchableFields,\n unavailableProducts = DEFAULT_PREDICTIVE_SEARCH_UNAVAILABLE_PRODUCTS,\n signal,\n}: QueryPredictiveSearchOptions<TQuery>): Promise<FetchPredictiveSearchResult<TQuery>> {\n const trimmedTerm = term.trim();\n if (!trimmedTerm) {\n return {\n data: getEmptyPredictiveSearchResult(\n trimmedTerm,\n ) as unknown as PredictiveSearchDataForQuery<TQuery>,\n headers: new Headers(),\n };\n }\n\n const document = query ?? predictiveSearchQueries.predictiveSearch;\n const graphql = storefrontClient.graphql as PredictiveSearchGraphql<\n PredictiveSearchItemsForQuery<TQuery>\n >;\n const result = await graphql(document, {\n variables: {\n limit: clampPredictiveSearchLimit(limit),\n limitScope,\n term: trimmedTerm,\n types,\n searchableFields,\n unavailableProducts,\n },\n ...(signal ? { signal } : {}),\n });\n\n if (result.errors) {\n throw new Error(`Shopify API errors: ${formatGraphQLErrors(result.errors)}`);\n }\n\n const items = result.data?.predictiveSearch;\n if (!items) {\n throw new Error(\"No predictive search data returned from Shopify API\");\n }\n\n return {\n data: {\n term: trimmedTerm,\n total: countPredictiveSearchItems(items),\n items,\n } as PredictiveSearchDataForQuery<TQuery>,\n headers: result.headers,\n };\n}\n\nfunction clampPredictiveSearchLimit(limit: number | undefined): number {\n if (typeof limit !== \"number\") return DEFAULT_PREDICTIVE_SEARCH_LIMIT;\n if (!Number.isFinite(limit)) return DEFAULT_PREDICTIVE_SEARCH_LIMIT;\n\n const integerLimit = Math.trunc(limit);\n return Math.min(MAX_PREDICTIVE_SEARCH_LIMIT, Math.max(MIN_PREDICTIVE_SEARCH_LIMIT, integerLimit));\n}\n\nfunction countPredictiveSearchItems(items: unknown): number {\n if (!items || typeof items !== \"object\") return 0;\n\n return Object.values(items).reduce((total, value) => {\n if (!Array.isArray(value)) return total;\n return total + value.length;\n }, 0);\n}\n\nfunction formatGraphQLErrors(errors: GraphQLFormattedError[]): string {\n return errors.map(({ message }) => message).join(\", \");\n}\n"],"mappings":";;;;AAeA,MAAa,8BAA8B;;AAE3C,MAAa,8BAA8B;;AAE3C,MAAa,kCAAkC;;AAE/C,MAAa,wCAAwC;;AAErD,MAAa,iDACX;;;;;;;;AA2GF,SAAgB,+BAA+B,OAAO,IAA0B;AAC9E,QAAO;EACL;EACA,OAAO;EACP,OAAO;GACL,UAAU,EAAE;GACZ,aAAa,EAAE;GACf,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,SAAS,EAAE;GACZ;EACF;;;;;;;;;;;;;AAcH,eAAsB,sBAEpB,SAA8F;AAE9F,SAAO,MADc,sBAAsB,QAAQ,EACrC;;;;;;;;;;;;;AAchB,eAAsB,sBAEpB,EACA,kBACA,MACA,OACA,OACA,aAAa,uCACb,OACA,kBACA,sBAAsB,gDACtB,UACqF;CACrF,MAAM,cAAc,KAAK,MAAM;AAC/B,KAAI,CAAC,YACH,QAAO;EACL,MAAM,+BACJ,YACD;EACD,SAAS,IAAI,SAAS;EACvB;CAGH,MAAM,WAAW,SAAS,wBAAwB;CAClD,MAAM,UAAU,iBAAiB;CAGjC,MAAM,SAAS,MAAM,QAAQ,UAAU;EACrC,WAAW;GACT,OAAO,2BAA2B,MAAM;GACxC;GACA,MAAM;GACN;GACA;GACA;GACD;EACD,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;EAC7B,CAAC;AAEF,KAAI,OAAO,OACT,OAAM,IAAI,MAAM,uBAAuB,oBAAoB,OAAO,OAAO,GAAG;CAG9E,MAAM,QAAQ,OAAO,MAAM;AAC3B,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,sDAAsD;AAGxE,QAAO;EACL,MAAM;GACJ,MAAM;GACN,OAAO,2BAA2B,MAAM;GACxC;GACD;EACD,SAAS,OAAO;EACjB;;AAGH,SAAS,2BAA2B,OAAmC;AACrE,KAAI,OAAO,UAAU,SAAU;AAC/B,KAAI,CAAC,OAAO,SAAS,MAAM,CAAE;AAG7B,QAAO,KAAK,QAAiC,KAAK,OAD7B,KAAK,MAAM,MAC+D,CAAC,CAAC;;AAGnG,SAAS,2BAA2B,OAAwB;AAC1D,KAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAEhD,QAAO,OAAO,OAAO,MAAM,CAAC,QAAQ,OAAO,UAAU;AACnD,MAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO;AAClC,SAAO,QAAQ,MAAM;IACpB,EAAE;;AAGP,SAAS,oBAAoB,QAAyC;AACpE,QAAO,OAAO,KAAK,EAAE,cAAc,QAAQ,CAAC,KAAK,KAAK"}
1
+ {"version":3,"file":"search.mjs","names":[],"sources":["../../../../src/core/predictive-search/search.ts"],"sourcesContent":["import type { GraphQLFormattedError, StorefrontClient } from \"../../client\";\nimport type { AnyStorefrontQueryString, StorefrontQueryString } from \"../../graphql\";\nimport type {\n PredictiveSearchLimitScope,\n PredictiveSearchType,\n SearchUnavailableProductsType,\n SearchableField,\n} from \"../../graphql/generated/storefront-api-types\";\nimport {\n predictiveSearchQueries,\n type CreatePredictiveSearchQueriesOptions,\n type PredictiveSearchQueriesForOptions,\n} from \"./queries\";\n\n/** Smallest result limit. Predictive search raises lower limits to this value. */\nexport const MIN_PREDICTIVE_SEARCH_LIMIT = 1;\n/** Largest result limit. Predictive search lowers higher limits to this value. */\nexport const MAX_PREDICTIVE_SEARCH_LIMIT = 10;\n/** Result limit that predictive search uses when you don't set one. */\nexport const DEFAULT_PREDICTIVE_SEARCH_LIMIT = 5;\n/** Default limit scope, which applies the limit to each result type separately. */\nexport const DEFAULT_PREDICTIVE_SEARCH_LIMIT_SCOPE = \"EACH\" satisfies PredictiveSearchLimitScope;\n/** Default unavailable product behavior, which hides unavailable products. */\nexport const DEFAULT_PREDICTIVE_SEARCH_UNAVAILABLE_PRODUCTS =\n \"HIDE\" satisfies SearchUnavailableProductsType;\n\ntype PredictiveSearchGraphqlResult<TQuery extends AnyStorefrontQueryString> =\n TQuery extends StorefrontQueryString<infer TResult, infer _Variables, string> ? TResult : never;\n\ntype PredictiveSearchItemsForQuery<TQuery extends AnyStorefrontQueryString> = NonNullable<\n PredictiveSearchGraphqlResult<TQuery> extends { predictiveSearch?: (infer TItems) | null }\n ? TItems\n : never\n>;\n\n/**\n * Predictive search results, with the search term and the result count.\n *\n * The type parameter sets the shape of the results and defaults to the\n * results of Hydrogen's built-in query. For a custom query, use the awaited\n * return type of `queryPredictiveSearch` for that query.\n *\n * @example\n * ```ts\n * type CustomSearchData = Awaited<\n * ReturnType<typeof queryPredictiveSearch<typeof queries.predictiveSearch>>\n * >;\n * ```\n */\nexport type PredictiveSearchData<\n TItems = PredictiveSearchItemsForQuery<typeof predictiveSearchQueries.predictiveSearch>,\n> = {\n /** Search term for the results, without surrounding whitespace. */\n term: string;\n /** Number of results in the response across every result type, including query suggestions. The count leaves out matches beyond the limit. */\n total: number;\n /** Results grouped by type. */\n items: TItems;\n};\n\n/** Predictive search results typed from a custom query. The results take their shape from the query's fields. */\nexport type PredictiveSearchDataForQuery<TQuery extends AnyStorefrontQueryString> =\n PredictiveSearchData<PredictiveSearchItemsForQuery<TQuery>>;\n\n/** Predictive search results typed from query options. The results include the fields from your custom fragments. */\nexport type PredictiveSearchDataForOptions<TOptions extends CreatePredictiveSearchQueriesOptions> =\n PredictiveSearchDataForQuery<PredictiveSearchQueriesForOptions<TOptions>[\"predictiveSearch\"]>;\n\n/** Storefront client, search term, custom query, and search settings for `queryPredictiveSearch`. */\nexport type QueryPredictiveSearchOptions<\n TQuery extends AnyStorefrontQueryString = typeof predictiveSearchQueries.predictiveSearch,\n> = {\n /** Storefront client that sends the query. Any object with a `graphql()` method works. */\n storefrontClient: Pick<StorefrontClient, \"graphql\">;\n /** Search term. A blank term returns empty results without a Storefront API request. */\n term: string;\n /** Custom query, usually from `makePredictiveSearchQueries`. Defaults to Hydrogen's built-in query. A hand-written query receives the term, limit, limit scope, types, searchable fields, and unavailable products as variables. */\n query?: TQuery;\n /** Maximum number of results, from 1 to 10. Predictive search clamps other values to that range. Defaults to `5`, which differs from the Storefront API default of 10. */\n limit?: number;\n /** Whether the limit applies to each result type or to all result types combined. Defaults to `EACH`. */\n limitScope?: PredictiveSearchLimitScope;\n /** Result types to include. */\n types?: PredictiveSearchType[];\n /** Fields to search for page, article, and collection results. Defaults to the title. Product results always search every product field. */\n searchableFields?: SearchableField[];\n /** Whether results hide unavailable products, show them, or list them last. Defaults to `HIDE`, which differs from the Storefront API default of `LAST`. */\n unavailableProducts?: SearchUnavailableProductsType;\n /** Cancels the request when the signal aborts. */\n signal?: AbortSignal;\n};\n\ntype FetchPredictiveSearchResult<TQuery extends AnyStorefrontQueryString> = {\n data: PredictiveSearchDataForQuery<TQuery>;\n headers: Headers;\n};\n\ntype PredictiveSearchQueryDocument = AnyStorefrontQueryString;\n\ntype PredictiveSearchVariables = {\n term: string;\n limit: number;\n limitScope: PredictiveSearchLimitScope;\n types: PredictiveSearchType[] | undefined;\n searchableFields: SearchableField[] | undefined;\n unavailableProducts: SearchUnavailableProductsType;\n};\n\ntype PredictiveSearchQueryResult<TItems> = {\n data: { predictiveSearch?: TItems | null } | null;\n errors?: GraphQLFormattedError[];\n headers: Headers;\n};\n\ntype PredictiveSearchGraphql<TItems> = (\n query: PredictiveSearchQueryDocument,\n options: { variables: PredictiveSearchVariables; signal?: AbortSignal },\n) => Promise<PredictiveSearchQueryResult<TItems>>;\n\n/**\n * Returns an empty predictive search result with an empty array for every\n * resource type.\n *\n * The query function returns the empty result for blank terms. The client\n * store uses the empty result for its initial and reset state.\n */\nexport function getEmptyPredictiveSearchResult(term = \"\"): PredictiveSearchData {\n return {\n term,\n total: 0,\n items: {\n products: [],\n collections: [],\n pages: [],\n articles: [],\n queries: [],\n },\n };\n}\n\n/**\n * Queries the Storefront API for predictive search results. Use the function in server code, such as a route loader. Pass the Storefront client and the search term.\n *\n * The function throws an error when the Storefront API returns GraphQL errors or no predictive search data. Network failures and aborts from the Storefront client also throw.\n *\n * To serve results to the browser with the Storefront API response headers, use `createPredictiveSearchServerHandlers`.\n *\n * @param options - The Storefront client, the search term, a custom query, and search settings.\n * @returns The search term, the result count, and the results grouped by type.\n * @throws {Error} When the Storefront API returns GraphQL errors.\n * @throws {Error} When the response contains no predictive search data.\n * @throws Errors from the Storefront client, such as network failures or an abort error when the signal aborts.\n * @publicDocs\n */\nexport async function queryPredictiveSearch<\n const TQuery extends AnyStorefrontQueryString = typeof predictiveSearchQueries.predictiveSearch,\n>(options: QueryPredictiveSearchOptions<TQuery>): Promise<PredictiveSearchDataForQuery<TQuery>> {\n const result = await fetchPredictiveSearch(options);\n return result.data;\n}\n\n/**\n * Queries the Storefront API for predictive search results and returns the results with the Storefront API response headers.\n *\n * The function takes the same options as queryPredictiveSearch.\n *\n * @throws {Error} When the Storefront API returns GraphQL errors.\n * @throws {Error} When the response contains no predictive search data.\n * @throws Errors from the Storefront client, such as network failures or an abort error when the signal aborts.\n */\nexport async function fetchPredictiveSearch<\n const TQuery extends AnyStorefrontQueryString = typeof predictiveSearchQueries.predictiveSearch,\n>({\n storefrontClient,\n term,\n query,\n limit,\n limitScope = DEFAULT_PREDICTIVE_SEARCH_LIMIT_SCOPE,\n types,\n searchableFields,\n unavailableProducts = DEFAULT_PREDICTIVE_SEARCH_UNAVAILABLE_PRODUCTS,\n signal,\n}: QueryPredictiveSearchOptions<TQuery>): Promise<FetchPredictiveSearchResult<TQuery>> {\n const trimmedTerm = term.trim();\n if (!trimmedTerm) {\n return {\n data: getEmptyPredictiveSearchResult(\n trimmedTerm,\n ) as unknown as PredictiveSearchDataForQuery<TQuery>,\n headers: new Headers(),\n };\n }\n\n const document = query ?? predictiveSearchQueries.predictiveSearch;\n const graphql = storefrontClient.graphql as PredictiveSearchGraphql<\n PredictiveSearchItemsForQuery<TQuery>\n >;\n const result = await graphql(document, {\n variables: {\n limit: clampPredictiveSearchLimit(limit),\n limitScope,\n term: trimmedTerm,\n types,\n searchableFields,\n unavailableProducts,\n },\n ...(signal ? { signal } : {}),\n });\n\n if (result.errors) {\n throw new Error(`Shopify API errors: ${formatGraphQLErrors(result.errors)}`);\n }\n\n const items = result.data?.predictiveSearch;\n if (!items) {\n throw new Error(\"No predictive search data returned from Shopify API\");\n }\n\n return {\n data: {\n term: trimmedTerm,\n total: countPredictiveSearchItems(items),\n items,\n } as PredictiveSearchDataForQuery<TQuery>,\n headers: result.headers,\n };\n}\n\nfunction clampPredictiveSearchLimit(limit: number | undefined): number {\n if (typeof limit !== \"number\") return DEFAULT_PREDICTIVE_SEARCH_LIMIT;\n if (!Number.isFinite(limit)) return DEFAULT_PREDICTIVE_SEARCH_LIMIT;\n\n const integerLimit = Math.trunc(limit);\n return Math.min(MAX_PREDICTIVE_SEARCH_LIMIT, Math.max(MIN_PREDICTIVE_SEARCH_LIMIT, integerLimit));\n}\n\nfunction countPredictiveSearchItems(items: unknown): number {\n if (!items || typeof items !== \"object\") return 0;\n\n return Object.values(items).reduce((total, value) => {\n if (!Array.isArray(value)) return total;\n return total + value.length;\n }, 0);\n}\n\nfunction formatGraphQLErrors(errors: GraphQLFormattedError[]): string {\n return errors.map(({ message }) => message).join(\", \");\n}\n\n/**\n * Queries the Storefront API for predictive search results. Use the function in server code, such as a route loader. Pass the Storefront client and the search term.\n *\n * The function throws an error when the Storefront API returns GraphQL errors or no predictive search data. Network failures and aborts from the Storefront client also throw.\n *\n * To serve results to the browser with the Storefront API response headers, use `createPredictiveSearchServerHandlers`.\n *\n * @throws {Error} When the Storefront API returns GraphQL errors.\n * @throws {Error} When the response contains no predictive search data.\n * @throws Errors from the Storefront client, such as network failures or an abort error when the signal aborts.\n * @publicDocs\n */\nexport type QueryPredictiveSearchForDocs =\n /**\n * @param options - The Storefront client, the search term, a custom query, and search settings.\n * @returns The search term, the result count, and the results grouped by type.\n */\n (options: QueryPredictiveSearchOptions) => Promise<PredictiveSearchData>;\n"],"mappings":";;;;AAeA,MAAa,8BAA8B;;AAE3C,MAAa,8BAA8B;;AAE3C,MAAa,kCAAkC;;AAE/C,MAAa,wCAAwC;;AAErD,MAAa,iDACX;;;;;;;;AAsGF,SAAgB,+BAA+B,OAAO,IAA0B;AAC9E,QAAO;EACL;EACA,OAAO;EACP,OAAO;GACL,UAAU,EAAE;GACZ,aAAa,EAAE;GACf,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,SAAS,EAAE;GACZ;EACF;;;;;;;;;;;;;;;;AAiBH,eAAsB,sBAEpB,SAA8F;AAE9F,SAAO,MADc,sBAAsB,QAAQ,EACrC;;;;;;;;;;;AAYhB,eAAsB,sBAEpB,EACA,kBACA,MACA,OACA,OACA,aAAa,uCACb,OACA,kBACA,sBAAsB,gDACtB,UACqF;CACrF,MAAM,cAAc,KAAK,MAAM;AAC/B,KAAI,CAAC,YACH,QAAO;EACL,MAAM,+BACJ,YACD;EACD,SAAS,IAAI,SAAS;EACvB;CAGH,MAAM,WAAW,SAAS,wBAAwB;CAClD,MAAM,UAAU,iBAAiB;CAGjC,MAAM,SAAS,MAAM,QAAQ,UAAU;EACrC,WAAW;GACT,OAAO,2BAA2B,MAAM;GACxC;GACA,MAAM;GACN;GACA;GACA;GACD;EACD,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;EAC7B,CAAC;AAEF,KAAI,OAAO,OACT,OAAM,IAAI,MAAM,uBAAuB,oBAAoB,OAAO,OAAO,GAAG;CAG9E,MAAM,QAAQ,OAAO,MAAM;AAC3B,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,sDAAsD;AAGxE,QAAO;EACL,MAAM;GACJ,MAAM;GACN,OAAO,2BAA2B,MAAM;GACxC;GACD;EACD,SAAS,OAAO;EACjB;;AAGH,SAAS,2BAA2B,OAAmC;AACrE,KAAI,OAAO,UAAU,SAAU;AAC/B,KAAI,CAAC,OAAO,SAAS,MAAM,CAAE;AAG7B,QAAO,KAAK,QAAiC,KAAK,OAD7B,KAAK,MAAM,MAC+D,CAAC,CAAC;;AAGnG,SAAS,2BAA2B,OAAwB;AAC1D,KAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAEhD,QAAO,OAAO,OAAO,MAAM,CAAC,QAAQ,OAAO,UAAU;AACnD,MAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO;AAClC,SAAO,QAAQ,MAAM;IACpB,EAAE;;AAGP,SAAS,oBAAoB,QAAyC;AACpE,QAAO,OAAO,KAAK,EAAE,cAAc,QAAQ,CAAC,KAAK,KAAK"}
@@ -16,44 +16,43 @@ type PredictiveSearchErrorCode = "invalid_predictive_search_request";
16
16
  type PredictiveSearchError = ShopifyRouteError & {
17
17
  code: PredictiveSearchErrorCode;
18
18
  };
19
+ /** GET route handler that returns predictive search results or an error. */
19
20
  type PredictiveSearchGetHandler<TData = PredictiveSearchDataForOptions<{}>> = CallableRouteHandler<PredictiveSearchHandlerContext, PredictiveSearchGetResult<TData>, string, typeof PREDICTIVE_SEARCH_GET_METHOD>;
21
+ /** Predictive search route handlers to pass to `handleShopifyRoutes`. */
20
22
  type PredictiveSearchServerHandlers<TOptions extends CreatePredictiveSearchServerHandlersOptions = {}, TData = PredictiveSearchDataForOptions<TOptions>> = {
21
- readonly [predictiveSearchServerHandlersQuery]: PredictiveSearchQueriesForOptions<TOptions>["predictiveSearch"];
23
+ /** Query that the handlers run, with any custom fragments. */readonly [predictiveSearchServerHandlersQuery]: PredictiveSearchQueriesForOptions<TOptions>["predictiveSearch"]; /** Answers GET requests with predictive search results as JSON. */
22
24
  get: PredictiveSearchGetHandler<TData>;
23
25
  };
24
26
  /**
25
- * Options for {@link createPredictiveSearchServerHandlers}.
27
+ * Route path, custom fragments, and default search settings for the predictive search route.
26
28
  *
27
- * Extends {@link CreatePredictiveSearchQueriesOptions} with server-specific
28
- * defaults. Each search option sets a default that individual requests can
29
- * override via query parameters. These are defaults, not restrictions: any
30
- * client can override them.
29
+ * A request overrides a default search setting with a URL parameter of the same name.
31
30
  */
32
- type CreatePredictiveSearchServerHandlersOptions = CreatePredictiveSearchQueriesOptions & {
33
- /** Route path the handler is registered at. Defaults to `"/api/predictive-search"`. */path?: string; /** Default result count. Requests can override it with the `limit` query parameter; empty or unparseable values fall back to this default. See {@link QueryPredictiveSearchOptions.limit} for normalization and the default when omitted. */
34
- limit?: number; /** Default limit scope. Individual requests override via the `limitScope` query parameter. */
35
- limitScope?: PredictiveSearchLimitScope; /** Default resource types to search. Individual requests override via the `types` query parameter (comma-separated). */
36
- types?: PredictiveSearchType[]; /** Default fields to search. Individual requests override via the `searchableFields` query parameter (comma-separated). */
37
- searchableFields?: SearchableField[]; /** Default unavailable-product behavior. Individual requests override via the `unavailableProducts` query parameter. */
31
+ interface CreatePredictiveSearchServerHandlersOptions extends CreatePredictiveSearchQueriesOptions {
32
+ /** Route path that the GET handler serves. Defaults to `/api/predictive-search`. */
33
+ path?: string;
34
+ /** Default maximum number of results, from 1 to 10. Applies when a request has no numeric `limit` parameter. Predictive search clamps other values to that range. Defaults to `5`. */
35
+ limit?: number;
36
+ /** Default limit scope. Defaults to `EACH`. */
37
+ limitScope?: PredictiveSearchLimitScope;
38
+ /** Default result types. A request can set `types` to a comma-separated list. */
39
+ types?: PredictiveSearchType[];
40
+ /** Default fields to search. A request can set `searchableFields` to a comma-separated list. */
41
+ searchableFields?: SearchableField[];
42
+ /** Default handling of unavailable products. Defaults to `HIDE`. */
38
43
  unavailableProducts?: SearchUnavailableProductsType;
39
- };
44
+ }
40
45
  /**
41
- * Creates a GET request handler that serves predictive search results from
42
- * the Storefront API.
43
- *
44
- * The handler parses search parameters from the request URL:
46
+ * Creates the route that answers predictive search requests from the browser.
47
+ * Register the handlers with `handleShopifyRoutes`. The default route path matches
48
+ * the default endpoint of `createPredictiveSearchStore` and `PredictiveSearchProvider`.
45
49
  *
46
- * - `q` for the search term
47
- * - Each search option in {@link CreatePredictiveSearchServerHandlersOptions}
48
- * can be overridden by a query parameter of the same name
50
+ * The route reads the search term from the `q` URL parameter. A URL parameter with the same name as a search setting overrides the setting's default.
49
51
  *
50
- * The `types` and `searchableFields` parameters accept comma-separated values. Invalid enum
51
- * values, and any Storefront API failure, produce an error result with code
52
- * `"invalid_predictive_search_request"`.
52
+ * An invalid setting value or a failed Storefront API query returns HTTP status `400` with a JSON body of `{error: {code, message}}`. The `code` value is `invalid_predictive_search_request`.
53
+ * A successful response forwards the Storefront API response headers except the content encoding, content length, and server timing headers.
53
54
  *
54
- * The returned handlers object has a `get` method that can be registered
55
- * as a route handler. Successful results include the Storefront API response
56
- * headers, excluding `content-encoding`, `content-length`, and `server-timing`.
55
+ * @publicDocs
57
56
  */
58
57
  declare function createPredictiveSearchServerHandlers(): PredictiveSearchServerHandlers;
59
58
  declare function createPredictiveSearchServerHandlers<const TOptions extends CreatePredictiveSearchServerHandlersOptions>(options: TOptions): PredictiveSearchServerHandlers<TOptions>;
@@ -30,6 +30,10 @@ const VALID_UNAVAILABLE_PRODUCTS = [
30
30
  "LAST",
31
31
  "SHOW"
32
32
  ];
33
+ /**
34
+ * @param options Route path, custom fragments, and default search settings for the route.
35
+ * @returns Route handlers to pass to `handleShopifyRoutes`.
36
+ */
33
37
  function createPredictiveSearchServerHandlers(options = {}) {
34
38
  const queries = options.fragments ? makePredictiveSearchQueries(options) : predictiveSearchQueries;
35
39
  const handlers = { get: createCallableRouteHandler(options.path ?? "/api/predictive-search", "GET", (context) => handleGet(context, options, queries)) };
@@ -1 +1 @@
1
- {"version":3,"file":"server-handlers.mjs","names":[],"sources":["../../../../src/core/predictive-search/server-handlers.ts"],"sourcesContent":["import type {\n PredictiveSearchLimitScope,\n PredictiveSearchType,\n SearchUnavailableProductsType,\n SearchableField,\n} from \"../../graphql/generated/storefront-api-types\";\nimport { createProxyResponseHeaders } from \"../request-routing/interceptors/proxy\";\nimport type {\n CallableRouteHandler,\n ShopifyRouteError,\n ShopifyRouteErrorResult,\n ShopifyRouteJsonResult,\n} from \"../request-routing/registered-routes\";\nimport { createCallableRouteHandler } from \"../request-routing/registered-routes\";\nimport { PREDICTIVE_SEARCH_API_PATH, PREDICTIVE_SEARCH_GET_METHOD } from \"./constants\";\nimport {\n makePredictiveSearchQueries,\n predictiveSearchQueries,\n type CreatePredictiveSearchQueriesOptions,\n type PredictiveSearchQueriesForOptions,\n} from \"./queries\";\nimport {\n DEFAULT_PREDICTIVE_SEARCH_LIMIT,\n DEFAULT_PREDICTIVE_SEARCH_LIMIT_SCOPE,\n DEFAULT_PREDICTIVE_SEARCH_UNAVAILABLE_PRODUCTS,\n fetchPredictiveSearch,\n type PredictiveSearchDataForOptions,\n type QueryPredictiveSearchOptions,\n} from \"./search\";\n\nconst predictiveSearchServerHandlersQuery: unique symbol = Symbol(\"hydrogen.predictiveSearchQuery\");\n\nconst VALID_LIMIT_SCOPES: readonly PredictiveSearchLimitScope[] = [\"ALL\", \"EACH\"];\nconst VALID_PREDICTIVE_SEARCH_TYPES: readonly PredictiveSearchType[] = [\n \"ARTICLE\",\n \"COLLECTION\",\n \"PAGE\",\n \"PRODUCT\",\n \"QUERY\",\n];\nconst VALID_SEARCHABLE_FIELDS: readonly SearchableField[] = [\n \"AUTHOR\",\n \"BODY\",\n \"PRODUCT_TYPE\",\n \"TAG\",\n \"TITLE\",\n \"VARIANTS_BARCODE\",\n \"VARIANTS_SKU\",\n \"VARIANTS_TITLE\",\n \"VENDOR\",\n];\nconst VALID_UNAVAILABLE_PRODUCTS: readonly SearchUnavailableProductsType[] = [\n \"HIDE\",\n \"LAST\",\n \"SHOW\",\n];\n\ntype PredictiveSearchHandlerContext = {\n request: Request;\n storefrontClient: QueryPredictiveSearchOptions[\"storefrontClient\"];\n};\n\ntype PredictiveSearchGetData<TData = PredictiveSearchDataForOptions<{}>> = TData;\ntype PredictiveSearchGetResult<TData = PredictiveSearchDataForOptions<{}>> =\n | ShopifyRouteJsonResult<PredictiveSearchGetData<TData>>\n | ShopifyRouteErrorResult<PredictiveSearchError>;\n\ntype PredictiveSearchErrorCode = \"invalid_predictive_search_request\";\ntype PredictiveSearchError = ShopifyRouteError & {\n code: PredictiveSearchErrorCode;\n};\n\ntype PredictiveSearchGetHandler<TData = PredictiveSearchDataForOptions<{}>> = CallableRouteHandler<\n PredictiveSearchHandlerContext,\n PredictiveSearchGetResult<TData>,\n string,\n typeof PREDICTIVE_SEARCH_GET_METHOD\n>;\n\ntype PredictiveSearchServerHandlers<\n TOptions extends CreatePredictiveSearchServerHandlersOptions = {},\n TData = PredictiveSearchDataForOptions<TOptions>,\n> = {\n readonly [predictiveSearchServerHandlersQuery]: PredictiveSearchQueriesForOptions<TOptions>[\"predictiveSearch\"];\n get: PredictiveSearchGetHandler<TData>;\n};\n\n/**\n * Options for {@link createPredictiveSearchServerHandlers}.\n *\n * Extends {@link CreatePredictiveSearchQueriesOptions} with server-specific\n * defaults. Each search option sets a default that individual requests can\n * override via query parameters. These are defaults, not restrictions: any\n * client can override them.\n */\nexport type CreatePredictiveSearchServerHandlersOptions = CreatePredictiveSearchQueriesOptions & {\n /** Route path the handler is registered at. Defaults to `\"/api/predictive-search\"`. */\n path?: string;\n /** Default result count. Requests can override it with the `limit` query parameter; empty or unparseable values fall back to this default. See {@link QueryPredictiveSearchOptions.limit} for normalization and the default when omitted. */\n limit?: number;\n /** Default limit scope. Individual requests override via the `limitScope` query parameter. */\n limitScope?: PredictiveSearchLimitScope;\n /** Default resource types to search. Individual requests override via the `types` query parameter (comma-separated). */\n types?: PredictiveSearchType[];\n /** Default fields to search. Individual requests override via the `searchableFields` query parameter (comma-separated). */\n searchableFields?: SearchableField[];\n /** Default unavailable-product behavior. Individual requests override via the `unavailableProducts` query parameter. */\n unavailableProducts?: SearchUnavailableProductsType;\n};\n\n/**\n * Creates a GET request handler that serves predictive search results from\n * the Storefront API.\n *\n * The handler parses search parameters from the request URL:\n *\n * - `q` for the search term\n * - Each search option in {@link CreatePredictiveSearchServerHandlersOptions}\n * can be overridden by a query parameter of the same name\n *\n * The `types` and `searchableFields` parameters accept comma-separated values. Invalid enum\n * values, and any Storefront API failure, produce an error result with code\n * `\"invalid_predictive_search_request\"`.\n *\n * The returned handlers object has a `get` method that can be registered\n * as a route handler. Successful results include the Storefront API response\n * headers, excluding `content-encoding`, `content-length`, and `server-timing`.\n */\nexport function createPredictiveSearchServerHandlers(): PredictiveSearchServerHandlers;\nexport function createPredictiveSearchServerHandlers<\n const TOptions extends CreatePredictiveSearchServerHandlersOptions,\n>(options: TOptions): PredictiveSearchServerHandlers<TOptions>;\nexport function createPredictiveSearchServerHandlers(\n options: CreatePredictiveSearchServerHandlersOptions = {},\n): PredictiveSearchServerHandlers<CreatePredictiveSearchServerHandlersOptions> {\n const queries = options.fragments\n ? makePredictiveSearchQueries(options)\n : predictiveSearchQueries;\n const handler = createCallableRouteHandler(\n options.path ?? PREDICTIVE_SEARCH_API_PATH,\n PREDICTIVE_SEARCH_GET_METHOD,\n (context: PredictiveSearchHandlerContext) => handleGet(context, options, queries),\n );\n const handlers = {\n get: handler,\n } as PredictiveSearchServerHandlers<CreatePredictiveSearchServerHandlersOptions>;\n\n Object.defineProperty(handlers, predictiveSearchServerHandlersQuery, {\n value: queries.predictiveSearch,\n });\n return handlers;\n}\n\nasync function handleGet(\n { request, storefrontClient }: PredictiveSearchHandlerContext,\n options: CreatePredictiveSearchServerHandlersOptions,\n queries: PredictiveSearchQueriesForOptions<CreatePredictiveSearchServerHandlersOptions>,\n): Promise<PredictiveSearchGetResult> {\n let searchOptions: ParsedPredictiveSearchRequest;\n try {\n searchOptions = parsePredictiveSearchRequest(request, options);\n } catch (error) {\n return errorResult(getErrorMessage(error, \"Invalid predictive search request\"));\n }\n\n try {\n const result = await fetchPredictiveSearch({\n storefrontClient,\n query: queries.predictiveSearch,\n ...searchOptions,\n });\n return {\n type: \"json\",\n data: result.data,\n headers: createProxyResponseHeaders(result.headers),\n };\n } catch (error) {\n return errorResult(getErrorMessage(error, \"Predictive search request failed\"));\n }\n}\n\ntype ParsedPredictiveSearchRequest = Omit<\n QueryPredictiveSearchOptions,\n \"storefrontClient\" | \"query\" | \"signal\"\n>;\n\nfunction parsePredictiveSearchRequest(\n request: Request,\n options: CreatePredictiveSearchServerHandlersOptions,\n): ParsedPredictiveSearchRequest {\n const searchParams = new URL(request.url).searchParams;\n return {\n term: searchParams.get(\"q\") ?? \"\",\n limit: parseLimit(searchParams, options),\n limitScope:\n parseOne(searchParams, \"limitScope\", VALID_LIMIT_SCOPES) ??\n options.limitScope ??\n DEFAULT_PREDICTIVE_SEARCH_LIMIT_SCOPE,\n types: parseMany(searchParams, \"types\", VALID_PREDICTIVE_SEARCH_TYPES) ?? options.types,\n searchableFields:\n parseMany(searchParams, \"searchableFields\", VALID_SEARCHABLE_FIELDS) ??\n options.searchableFields,\n unavailableProducts:\n parseOne(searchParams, \"unavailableProducts\", VALID_UNAVAILABLE_PRODUCTS) ??\n options.unavailableProducts ??\n DEFAULT_PREDICTIVE_SEARCH_UNAVAILABLE_PRODUCTS,\n };\n}\n\n// Invalid enum params return a typed error, but an unparseable limit falls back to the configured default.\nfunction parseLimit(\n searchParams: URLSearchParams,\n options: CreatePredictiveSearchServerHandlersOptions,\n): number {\n const defaultLimit = options.limit ?? DEFAULT_PREDICTIVE_SEARCH_LIMIT;\n const rawLimit = searchParams.get(\"limit\")?.trim() ?? \"\";\n if (rawLimit === \"\") return defaultLimit;\n\n const limit = Number(rawLimit);\n return Number.isFinite(limit) ? limit : defaultLimit;\n}\n\nfunction parseOne<TValue extends string>(\n searchParams: URLSearchParams,\n name: string,\n allowedValues: readonly TValue[],\n): TValue | undefined {\n const value = searchParams.get(name);\n if (value === null || value === \"\") return undefined;\n if (isAllowedValue(value, allowedValues)) return value;\n throw new Error(`Invalid ${name} value \"${value}\".`);\n}\n\nfunction parseMany<TValue extends string>(\n searchParams: URLSearchParams,\n name: string,\n allowedValues: readonly TValue[],\n): TValue[] | undefined {\n const values = splitParamValues(searchParams, name);\n if (values.length === 0) return undefined;\n return values.map((value) => parseAllowedValue(name, value, allowedValues));\n}\n\nfunction splitParamValues(searchParams: URLSearchParams, name: string): string[] {\n return searchParams\n .getAll(name)\n .flatMap((value) => value.split(\",\"))\n .map((value) => value.trim())\n .filter(Boolean);\n}\n\nfunction parseAllowedValue<TValue extends string>(\n name: string,\n value: string,\n allowedValues: readonly TValue[],\n): TValue {\n if (isAllowedValue(value, allowedValues)) return value;\n throw new Error(`Invalid ${name} value \"${value}\".`);\n}\n\nfunction isAllowedValue<TValue extends string>(\n value: string,\n allowedValues: readonly TValue[],\n): value is TValue {\n return allowedValues.some((allowedValue) => allowedValue === value);\n}\n\nfunction errorResult(message: string): ShopifyRouteErrorResult<PredictiveSearchError> {\n return {\n type: \"error\",\n error: {\n code: \"invalid_predictive_search_request\",\n message,\n },\n };\n}\n\nfunction getErrorMessage(error: unknown, fallback: string): string {\n return error instanceof Error ? error.message : fallback;\n}\n"],"mappings":";;;;;;;AA8BA,MAAM,sCAAqD,OAAO,iCAAiC;AAEnG,MAAM,qBAA4D,CAAC,OAAO,OAAO;AACjF,MAAM,gCAAiE;CACrE;CACA;CACA;CACA;CACA;CACD;AACD,MAAM,0BAAsD;CAC1D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AACD,MAAM,6BAAuE;CAC3E;CACA;CACA;CACD;AA6ED,SAAgB,qCACd,UAAuD,EAAE,EACoB;CAC7E,MAAM,UAAU,QAAQ,YACpB,4BAA4B,QAAQ,GACpC;CAMJ,MAAM,WAAW,EACf,KANc,2BACd,QAAQ,0CAEP,YAA4C,UAAU,SAAS,SAAS,QAAQ,CAGrE,EACb;AAED,QAAO,eAAe,UAAU,qCAAqC,EACnE,OAAO,QAAQ,kBAChB,CAAC;AACF,QAAO;;AAGT,eAAe,UACb,EAAE,SAAS,oBACX,SACA,SACoC;CACpC,IAAI;AACJ,KAAI;AACF,kBAAgB,6BAA6B,SAAS,QAAQ;UACvD,OAAO;AACd,SAAO,YAAY,gBAAgB,OAAO,oCAAoC,CAAC;;AAGjF,KAAI;EACF,MAAM,SAAS,MAAM,sBAAsB;GACzC;GACA,OAAO,QAAQ;GACf,GAAG;GACJ,CAAC;AACF,SAAO;GACL,MAAM;GACN,MAAM,OAAO;GACb,SAAS,2BAA2B,OAAO,QAAQ;GACpD;UACM,OAAO;AACd,SAAO,YAAY,gBAAgB,OAAO,mCAAmC,CAAC;;;AASlF,SAAS,6BACP,SACA,SAC+B;CAC/B,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,CAAC;AAC1C,QAAO;EACL,MAAM,aAAa,IAAI,IAAI,IAAI;EAC/B,OAAO,WAAW,cAAc,QAAQ;EACxC,YACE,SAAS,cAAc,cAAc,mBAAmB,IACxD,QAAQ;EAEV,OAAO,UAAU,cAAc,SAAS,8BAA8B,IAAI,QAAQ;EAClF,kBACE,UAAU,cAAc,oBAAoB,wBAAwB,IACpE,QAAQ;EACV,qBACE,SAAS,cAAc,uBAAuB,2BAA2B,IACzE,QAAQ;EAEX;;AAIH,SAAS,WACP,cACA,SACQ;CACR,MAAM,eAAe,QAAQ;CAC7B,MAAM,WAAW,aAAa,IAAI,QAAQ,EAAE,MAAM,IAAI;AACtD,KAAI,aAAa,GAAI,QAAO;CAE5B,MAAM,QAAQ,OAAO,SAAS;AAC9B,QAAO,OAAO,SAAS,MAAM,GAAG,QAAQ;;AAG1C,SAAS,SACP,cACA,MACA,eACoB;CACpB,MAAM,QAAQ,aAAa,IAAI,KAAK;AACpC,KAAI,UAAU,QAAQ,UAAU,GAAI,QAAO;AAC3C,KAAI,eAAe,OAAO,cAAc,CAAE,QAAO;AACjD,OAAM,IAAI,MAAM,WAAW,KAAK,UAAU,MAAM,IAAI;;AAGtD,SAAS,UACP,cACA,MACA,eACsB;CACtB,MAAM,SAAS,iBAAiB,cAAc,KAAK;AACnD,KAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAO,OAAO,KAAK,UAAU,kBAAkB,MAAM,OAAO,cAAc,CAAC;;AAG7E,SAAS,iBAAiB,cAA+B,MAAwB;AAC/E,QAAO,aACJ,OAAO,KAAK,CACZ,SAAS,UAAU,MAAM,MAAM,IAAI,CAAC,CACpC,KAAK,UAAU,MAAM,MAAM,CAAC,CAC5B,OAAO,QAAQ;;AAGpB,SAAS,kBACP,MACA,OACA,eACQ;AACR,KAAI,eAAe,OAAO,cAAc,CAAE,QAAO;AACjD,OAAM,IAAI,MAAM,WAAW,KAAK,UAAU,MAAM,IAAI;;AAGtD,SAAS,eACP,OACA,eACiB;AACjB,QAAO,cAAc,MAAM,iBAAiB,iBAAiB,MAAM;;AAGrE,SAAS,YAAY,SAAiE;AACpF,QAAO;EACL,MAAM;EACN,OAAO;GACL,MAAM;GACN;GACD;EACF;;AAGH,SAAS,gBAAgB,OAAgB,UAA0B;AACjE,QAAO,iBAAiB,QAAQ,MAAM,UAAU"}
1
+ {"version":3,"file":"server-handlers.mjs","names":[],"sources":["../../../../src/core/predictive-search/server-handlers.ts"],"sourcesContent":["import type {\n PredictiveSearchLimitScope,\n PredictiveSearchType,\n SearchUnavailableProductsType,\n SearchableField,\n} from \"../../graphql/generated/storefront-api-types\";\nimport { createProxyResponseHeaders } from \"../request-routing/interceptors/proxy\";\nimport type {\n CallableRouteHandler,\n ShopifyRouteError,\n ShopifyRouteErrorResult,\n ShopifyRouteJsonResult,\n} from \"../request-routing/registered-routes\";\nimport { createCallableRouteHandler } from \"../request-routing/registered-routes\";\nimport { PREDICTIVE_SEARCH_API_PATH, PREDICTIVE_SEARCH_GET_METHOD } from \"./constants\";\nimport {\n makePredictiveSearchQueries,\n predictiveSearchQueries,\n type CreatePredictiveSearchQueriesOptions,\n type PredictiveSearchQueriesForOptions,\n} from \"./queries\";\nimport {\n DEFAULT_PREDICTIVE_SEARCH_LIMIT,\n DEFAULT_PREDICTIVE_SEARCH_LIMIT_SCOPE,\n DEFAULT_PREDICTIVE_SEARCH_UNAVAILABLE_PRODUCTS,\n fetchPredictiveSearch,\n type PredictiveSearchDataForOptions,\n type QueryPredictiveSearchOptions,\n} from \"./search\";\n\nconst predictiveSearchServerHandlersQuery: unique symbol = Symbol(\"hydrogen.predictiveSearchQuery\");\n\nconst VALID_LIMIT_SCOPES: readonly PredictiveSearchLimitScope[] = [\"ALL\", \"EACH\"];\nconst VALID_PREDICTIVE_SEARCH_TYPES: readonly PredictiveSearchType[] = [\n \"ARTICLE\",\n \"COLLECTION\",\n \"PAGE\",\n \"PRODUCT\",\n \"QUERY\",\n];\nconst VALID_SEARCHABLE_FIELDS: readonly SearchableField[] = [\n \"AUTHOR\",\n \"BODY\",\n \"PRODUCT_TYPE\",\n \"TAG\",\n \"TITLE\",\n \"VARIANTS_BARCODE\",\n \"VARIANTS_SKU\",\n \"VARIANTS_TITLE\",\n \"VENDOR\",\n];\nconst VALID_UNAVAILABLE_PRODUCTS: readonly SearchUnavailableProductsType[] = [\n \"HIDE\",\n \"LAST\",\n \"SHOW\",\n];\n\ntype PredictiveSearchHandlerContext = {\n request: Request;\n storefrontClient: QueryPredictiveSearchOptions[\"storefrontClient\"];\n};\n\ntype PredictiveSearchGetData<TData = PredictiveSearchDataForOptions<{}>> = TData;\ntype PredictiveSearchGetResult<TData = PredictiveSearchDataForOptions<{}>> =\n | ShopifyRouteJsonResult<PredictiveSearchGetData<TData>>\n | ShopifyRouteErrorResult<PredictiveSearchError>;\n\ntype PredictiveSearchErrorCode = \"invalid_predictive_search_request\";\ntype PredictiveSearchError = ShopifyRouteError & {\n code: PredictiveSearchErrorCode;\n};\n\n/** GET route handler that returns predictive search results or an error. */\ntype PredictiveSearchGetHandler<TData = PredictiveSearchDataForOptions<{}>> = CallableRouteHandler<\n PredictiveSearchHandlerContext,\n PredictiveSearchGetResult<TData>,\n string,\n typeof PREDICTIVE_SEARCH_GET_METHOD\n>;\n\n/** Predictive search route handlers to pass to `handleShopifyRoutes`. */\ntype PredictiveSearchServerHandlers<\n TOptions extends CreatePredictiveSearchServerHandlersOptions = {},\n TData = PredictiveSearchDataForOptions<TOptions>,\n> = {\n /** Query that the handlers run, with any custom fragments. */\n readonly [predictiveSearchServerHandlersQuery]: PredictiveSearchQueriesForOptions<TOptions>[\"predictiveSearch\"];\n /** Answers GET requests with predictive search results as JSON. */\n get: PredictiveSearchGetHandler<TData>;\n};\n\n/**\n * Route path, custom fragments, and default search settings for the predictive search route.\n *\n * A request overrides a default search setting with a URL parameter of the same name.\n */\nexport interface CreatePredictiveSearchServerHandlersOptions extends CreatePredictiveSearchQueriesOptions {\n /** Route path that the GET handler serves. Defaults to `/api/predictive-search`. */\n path?: string;\n /** Default maximum number of results, from 1 to 10. Applies when a request has no numeric `limit` parameter. Predictive search clamps other values to that range. Defaults to `5`. */\n limit?: number;\n /** Default limit scope. Defaults to `EACH`. */\n limitScope?: PredictiveSearchLimitScope;\n /** Default result types. A request can set `types` to a comma-separated list. */\n types?: PredictiveSearchType[];\n /** Default fields to search. A request can set `searchableFields` to a comma-separated list. */\n searchableFields?: SearchableField[];\n /** Default handling of unavailable products. Defaults to `HIDE`. */\n unavailableProducts?: SearchUnavailableProductsType;\n}\n\n/**\n * Creates the route that answers predictive search requests from the browser.\n * Register the handlers with `handleShopifyRoutes`. The default route path matches\n * the default endpoint of `createPredictiveSearchStore` and `PredictiveSearchProvider`.\n *\n * The route reads the search term from the `q` URL parameter. A URL parameter with the same name as a search setting overrides the setting's default.\n *\n * An invalid setting value or a failed Storefront API query returns HTTP status `400` with a JSON body of `{error: {code, message}}`. The `code` value is `invalid_predictive_search_request`.\n * A successful response forwards the Storefront API response headers except the content encoding, content length, and server timing headers.\n *\n * @publicDocs\n */\nexport function createPredictiveSearchServerHandlers(): PredictiveSearchServerHandlers;\nexport function createPredictiveSearchServerHandlers<\n const TOptions extends CreatePredictiveSearchServerHandlersOptions,\n>(options: TOptions): PredictiveSearchServerHandlers<TOptions>;\n/**\n * @param options Route path, custom fragments, and default search settings for the route.\n * @returns Route handlers to pass to `handleShopifyRoutes`.\n */\nexport function createPredictiveSearchServerHandlers(\n options: CreatePredictiveSearchServerHandlersOptions = {},\n): PredictiveSearchServerHandlers<CreatePredictiveSearchServerHandlersOptions> {\n const queries = options.fragments\n ? makePredictiveSearchQueries(options)\n : predictiveSearchQueries;\n const handler = createCallableRouteHandler(\n options.path ?? PREDICTIVE_SEARCH_API_PATH,\n PREDICTIVE_SEARCH_GET_METHOD,\n (context: PredictiveSearchHandlerContext) => handleGet(context, options, queries),\n );\n const handlers = {\n get: handler,\n } as PredictiveSearchServerHandlers<CreatePredictiveSearchServerHandlersOptions>;\n\n Object.defineProperty(handlers, predictiveSearchServerHandlersQuery, {\n value: queries.predictiveSearch,\n });\n return handlers;\n}\n\nasync function handleGet(\n { request, storefrontClient }: PredictiveSearchHandlerContext,\n options: CreatePredictiveSearchServerHandlersOptions,\n queries: PredictiveSearchQueriesForOptions<CreatePredictiveSearchServerHandlersOptions>,\n): Promise<PredictiveSearchGetResult> {\n let searchOptions: ParsedPredictiveSearchRequest;\n try {\n searchOptions = parsePredictiveSearchRequest(request, options);\n } catch (error) {\n return errorResult(getErrorMessage(error, \"Invalid predictive search request\"));\n }\n\n try {\n const result = await fetchPredictiveSearch({\n storefrontClient,\n query: queries.predictiveSearch,\n ...searchOptions,\n });\n return {\n type: \"json\",\n data: result.data,\n headers: createProxyResponseHeaders(result.headers),\n };\n } catch (error) {\n return errorResult(getErrorMessage(error, \"Predictive search request failed\"));\n }\n}\n\ntype ParsedPredictiveSearchRequest = Omit<\n QueryPredictiveSearchOptions,\n \"storefrontClient\" | \"query\" | \"signal\"\n>;\n\nfunction parsePredictiveSearchRequest(\n request: Request,\n options: CreatePredictiveSearchServerHandlersOptions,\n): ParsedPredictiveSearchRequest {\n const searchParams = new URL(request.url).searchParams;\n return {\n term: searchParams.get(\"q\") ?? \"\",\n limit: parseLimit(searchParams, options),\n limitScope:\n parseOne(searchParams, \"limitScope\", VALID_LIMIT_SCOPES) ??\n options.limitScope ??\n DEFAULT_PREDICTIVE_SEARCH_LIMIT_SCOPE,\n types: parseMany(searchParams, \"types\", VALID_PREDICTIVE_SEARCH_TYPES) ?? options.types,\n searchableFields:\n parseMany(searchParams, \"searchableFields\", VALID_SEARCHABLE_FIELDS) ??\n options.searchableFields,\n unavailableProducts:\n parseOne(searchParams, \"unavailableProducts\", VALID_UNAVAILABLE_PRODUCTS) ??\n options.unavailableProducts ??\n DEFAULT_PREDICTIVE_SEARCH_UNAVAILABLE_PRODUCTS,\n };\n}\n\n// Invalid enum params return a typed error, but an unparseable limit falls back to the configured default.\nfunction parseLimit(\n searchParams: URLSearchParams,\n options: CreatePredictiveSearchServerHandlersOptions,\n): number {\n const defaultLimit = options.limit ?? DEFAULT_PREDICTIVE_SEARCH_LIMIT;\n const rawLimit = searchParams.get(\"limit\")?.trim() ?? \"\";\n if (rawLimit === \"\") return defaultLimit;\n\n const limit = Number(rawLimit);\n return Number.isFinite(limit) ? limit : defaultLimit;\n}\n\nfunction parseOne<TValue extends string>(\n searchParams: URLSearchParams,\n name: string,\n allowedValues: readonly TValue[],\n): TValue | undefined {\n const value = searchParams.get(name);\n if (value === null || value === \"\") return undefined;\n if (isAllowedValue(value, allowedValues)) return value;\n throw new Error(`Invalid ${name} value \"${value}\".`);\n}\n\nfunction parseMany<TValue extends string>(\n searchParams: URLSearchParams,\n name: string,\n allowedValues: readonly TValue[],\n): TValue[] | undefined {\n const values = splitParamValues(searchParams, name);\n if (values.length === 0) return undefined;\n return values.map((value) => parseAllowedValue(name, value, allowedValues));\n}\n\nfunction splitParamValues(searchParams: URLSearchParams, name: string): string[] {\n return searchParams\n .getAll(name)\n .flatMap((value) => value.split(\",\"))\n .map((value) => value.trim())\n .filter(Boolean);\n}\n\nfunction parseAllowedValue<TValue extends string>(\n name: string,\n value: string,\n allowedValues: readonly TValue[],\n): TValue {\n if (isAllowedValue(value, allowedValues)) return value;\n throw new Error(`Invalid ${name} value \"${value}\".`);\n}\n\nfunction isAllowedValue<TValue extends string>(\n value: string,\n allowedValues: readonly TValue[],\n): value is TValue {\n return allowedValues.some((allowedValue) => allowedValue === value);\n}\n\nfunction errorResult(message: string): ShopifyRouteErrorResult<PredictiveSearchError> {\n return {\n type: \"error\",\n error: {\n code: \"invalid_predictive_search_request\",\n message,\n },\n };\n}\n\nfunction getErrorMessage(error: unknown, fallback: string): string {\n return error instanceof Error ? error.message : fallback;\n}\n"],"mappings":";;;;;;;AA8BA,MAAM,sCAAqD,OAAO,iCAAiC;AAEnG,MAAM,qBAA4D,CAAC,OAAO,OAAO;AACjF,MAAM,gCAAiE;CACrE;CACA;CACA;CACA;CACA;CACD;AACD,MAAM,0BAAsD;CAC1D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AACD,MAAM,6BAAuE;CAC3E;CACA;CACA;CACD;;;;;AA4ED,SAAgB,qCACd,UAAuD,EAAE,EACoB;CAC7E,MAAM,UAAU,QAAQ,YACpB,4BAA4B,QAAQ,GACpC;CAMJ,MAAM,WAAW,EACf,KANc,2BACd,QAAQ,0CAEP,YAA4C,UAAU,SAAS,SAAS,QAAQ,CAGrE,EACb;AAED,QAAO,eAAe,UAAU,qCAAqC,EACnE,OAAO,QAAQ,kBAChB,CAAC;AACF,QAAO;;AAGT,eAAe,UACb,EAAE,SAAS,oBACX,SACA,SACoC;CACpC,IAAI;AACJ,KAAI;AACF,kBAAgB,6BAA6B,SAAS,QAAQ;UACvD,OAAO;AACd,SAAO,YAAY,gBAAgB,OAAO,oCAAoC,CAAC;;AAGjF,KAAI;EACF,MAAM,SAAS,MAAM,sBAAsB;GACzC;GACA,OAAO,QAAQ;GACf,GAAG;GACJ,CAAC;AACF,SAAO;GACL,MAAM;GACN,MAAM,OAAO;GACb,SAAS,2BAA2B,OAAO,QAAQ;GACpD;UACM,OAAO;AACd,SAAO,YAAY,gBAAgB,OAAO,mCAAmC,CAAC;;;AASlF,SAAS,6BACP,SACA,SAC+B;CAC/B,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,CAAC;AAC1C,QAAO;EACL,MAAM,aAAa,IAAI,IAAI,IAAI;EAC/B,OAAO,WAAW,cAAc,QAAQ;EACxC,YACE,SAAS,cAAc,cAAc,mBAAmB,IACxD,QAAQ;EAEV,OAAO,UAAU,cAAc,SAAS,8BAA8B,IAAI,QAAQ;EAClF,kBACE,UAAU,cAAc,oBAAoB,wBAAwB,IACpE,QAAQ;EACV,qBACE,SAAS,cAAc,uBAAuB,2BAA2B,IACzE,QAAQ;EAEX;;AAIH,SAAS,WACP,cACA,SACQ;CACR,MAAM,eAAe,QAAQ;CAC7B,MAAM,WAAW,aAAa,IAAI,QAAQ,EAAE,MAAM,IAAI;AACtD,KAAI,aAAa,GAAI,QAAO;CAE5B,MAAM,QAAQ,OAAO,SAAS;AAC9B,QAAO,OAAO,SAAS,MAAM,GAAG,QAAQ;;AAG1C,SAAS,SACP,cACA,MACA,eACoB;CACpB,MAAM,QAAQ,aAAa,IAAI,KAAK;AACpC,KAAI,UAAU,QAAQ,UAAU,GAAI,QAAO;AAC3C,KAAI,eAAe,OAAO,cAAc,CAAE,QAAO;AACjD,OAAM,IAAI,MAAM,WAAW,KAAK,UAAU,MAAM,IAAI;;AAGtD,SAAS,UACP,cACA,MACA,eACsB;CACtB,MAAM,SAAS,iBAAiB,cAAc,KAAK;AACnD,KAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAO,OAAO,KAAK,UAAU,kBAAkB,MAAM,OAAO,cAAc,CAAC;;AAG7E,SAAS,iBAAiB,cAA+B,MAAwB;AAC/E,QAAO,aACJ,OAAO,KAAK,CACZ,SAAS,UAAU,MAAM,MAAM,IAAI,CAAC,CACpC,KAAK,UAAU,MAAM,MAAM,CAAC,CAC5B,OAAO,QAAQ;;AAGpB,SAAS,kBACP,MACA,OACA,eACQ;AACR,KAAI,eAAe,OAAO,cAAc,CAAE,QAAO;AACjD,OAAM,IAAI,MAAM,WAAW,KAAK,UAAU,MAAM,IAAI;;AAGtD,SAAS,eACP,OACA,eACiB;AACjB,QAAO,cAAc,MAAM,iBAAiB,iBAAiB,MAAM;;AAGrE,SAAS,YAAY,SAAiE;AACpF,QAAO;EACL,MAAM;EACN,OAAO;GACL,MAAM;GACN;GACD;EACF;;AAGH,SAAS,gBAAgB,OAAgB,UAA0B;AACjE,QAAO,iBAAiB,QAAQ,MAAM,UAAU"}
@@ -2,44 +2,85 @@ import { PredictiveSearchLimitScope, PredictiveSearchType, SearchUnavailableProd
2
2
  import { PredictiveSearchData } from "./search.mjs";
3
3
 
4
4
  //#region src/core/predictive-search/store.d.ts
5
- /** Lifecycle state for the predictive search client store. */
5
+ /** Status of the current search. */
6
6
  type PredictiveSearchStatus = "idle" | "loading" | "success" | "error";
7
- /** Current predictive search snapshot exposed to UI bindings. */
7
+ /** Current search term, status, results, and error of a predictive search. */
8
8
  type PredictiveSearchState<TData extends PredictiveSearchData = PredictiveSearchData> = {
9
- /** Latest trimmed search term known to the store. */term: string; /** Request lifecycle state for the current term. */
10
- status: PredictiveSearchStatus; /** Predictive search data for the current term, or an empty result while idle. */
11
- result: TData; /** Error message for the latest failed request, or null when there is no active error. */
9
+ /** Latest search term, without surrounding whitespace. */term: string; /** Status of the search for the current term. */
10
+ status: PredictiveSearchStatus; /** Results of the latest successful search. Previous results stay in place while a new search loads and after a search fails. The idle state holds empty results. */
11
+ result: TData; /** Message from the latest failed search, or `null` when the current search hasn't failed. A custom endpoint sets the message with a JSON body of `{error: {message}}`. */
12
12
  error: string | null;
13
13
  };
14
- /** Options for creating a framework-neutral predictive search client store. */
14
+ /**
15
+ * Endpoint, timing, and search settings for a predictive search store.
16
+ *
17
+ * The store sends each search setting to the endpoint as a URL parameter of the same name. The server handlers apply their own defaults to omitted settings.
18
+ */
15
19
  type CreatePredictiveSearchStoreOptions = {
16
20
  /**
17
- * Same-origin JSON endpoint used for browser predictive-search requests.
21
+ * Route that returns predictive search results as JSON, in the shape that `createPredictiveSearchServerHandlers` returns.
18
22
  *
19
- * The endpoint must return JSON matching the data payload from
20
- * `await predictiveSearchHandlers.get(...)`.
23
+ * Defaults to `/api/predictive-search`.
21
24
  */
22
- predictiveSearchEndpoint?: string; /** Delay before sending a request after the term changes. */
23
- debounceInMs?: number; /** Minimum trimmed term length required before searching. */
24
- minTermLength?: number; /** Fetch implementation, injectable for tests and non-browser runtimes. */
25
- fetch?: typeof globalThis.fetch; /** Maximum result count requested from the Storefront API. */
26
- limit?: number; /** Whether `limit` applies to each result type or all result types combined. */
27
- limitScope?: PredictiveSearchLimitScope; /** Storefront API result types to include in predictive search. */
28
- types?: PredictiveSearchType[]; /** Storefront API fields to search. */
29
- searchableFields?: SearchableField[]; /** Storefront API unavailable-product behavior. */
25
+ predictiveSearchEndpoint?: string;
26
+ /**
27
+ * Milliseconds to wait after the latest term change before searching.
28
+ *
29
+ * Defaults to `150`. Pass `0` to search right away. Negative and non-finite values use the default.
30
+ */
31
+ debounceInMs?: number;
32
+ /**
33
+ * Number of characters a term needs, after trimming, before the store searches.
34
+ *
35
+ * Defaults to `1`. Negative and non-finite values use the default.
36
+ */
37
+ minTermLength?: number; /** Function that sends search requests. Defaults to the global `fetch`. Pass a function for tests or for runtimes without a global `fetch`. */
38
+ fetch?: typeof globalThis.fetch; /** Maximum number of results, from 1 to 10. The server handlers clamp other values to that range. */
39
+ limit?: number; /** Whether the limit applies to each result type or to all result types combined. */
40
+ limitScope?: PredictiveSearchLimitScope; /** Result types to include. */
41
+ types?: PredictiveSearchType[]; /** Fields to search for page, article, and collection results. */
42
+ searchableFields?: SearchableField[]; /** Whether results hide unavailable products, show them, or list them last. */
30
43
  unavailableProducts?: SearchUnavailableProductsType;
31
44
  };
32
- /** Framework-neutral predictive search store used by UI bindings. */
45
+ /** Holds the search term, status, and results, and runs searches as the customer types. */
33
46
  type PredictiveSearchStore<TData extends PredictiveSearchData = PredictiveSearchData> = {
34
- /** Reactivates store updates after destroy(). */connect(): void; /** Returns the current predictive search state snapshot. */
35
- getState(): PredictiveSearchState<TData>; /** Subscribes to state changes and returns an unsubscribe callback. */
36
- subscribe(listener: (state: PredictiveSearchState<TData>) => void): () => void; /** Searches for a term using the configured debounce and request lifecycle. */
37
- search(term: string): Promise<void>; /** Cancels pending work and resets the store to an empty state. */
38
- clear(): void; /** Cancels pending work and pauses store updates until reconnect. */
47
+ /** Restarts a store after `destroy()`. A new store doesn't need this call. */connect(): void; /** Returns the current search term, status, results, and error. */
48
+ getState(): PredictiveSearchState<TData>; /** Calls your function with the new state on every change. Returns a function that stops the calls. */
49
+ subscribe(listener: (state: PredictiveSearchState<TData>) => void): () => void;
50
+ /**
51
+ * Searches for a term after the debounce delay. Call the method on every keystroke.
52
+ *
53
+ * Each call cancels the previous pending search. A term shorter than the minimum length, after trimming, returns the store to `idle` with empty results. Otherwise, the status changes to `loading` until the search ends with `success` or `error`. Responses for earlier terms never replace newer results.
54
+ *
55
+ * The returned promise resolves when the search ends, or when a later search, `clear()`, or `destroy()` cancels the search.
56
+ */
57
+ search(term: string): Promise<void>;
58
+ /**
59
+ * Cancels any pending search and returns the store to the idle state with no term and empty results.
60
+ *
61
+ * Call `clear()` when the customer closes the search UI.
62
+ */
63
+ clear(): void;
64
+ /**
65
+ * Stops the store. Call `destroy()` when the search UI unmounts.
66
+ *
67
+ * The store cancels any pending search, keeps its current state, and ignores searches until you call `connect()`.
68
+ */
39
69
  destroy(): void;
40
70
  };
41
- /** Search methods exposed by the predictive search store. */
71
+ /** Methods that search for a term and clear the results. */
42
72
  type PredictiveSearchActions = Pick<PredictiveSearchStore, "search" | "clear">;
73
+ /**
74
+ * Creates a store that searches as the customer types and holds the latest predictive search results. Use the store in DOM code or in UI frameworks without Hydrogen bindings. In React and Vue, use `PredictiveSearchProvider`.
75
+ *
76
+ * Call `search()` with each new term, read results with `getState()` or `subscribe()`, and call `destroy()` when the search UI unmounts. By default, the store requests results from the route that `createPredictiveSearchServerHandlers` serves.
77
+ *
78
+ * The function throws an error when you omit the `fetch` option in a runtime without a global `fetch`.
79
+ *
80
+ * @param options Endpoint, timing, and search settings for the store.
81
+ * @returns A store with no term and empty results, ready to search.
82
+ * @publicDocs
83
+ */
43
84
  declare function createPredictiveSearchStore<TData extends PredictiveSearchData = PredictiveSearchData>(options?: CreatePredictiveSearchStoreOptions): PredictiveSearchStore<TData>;
44
85
  //#endregion
45
86
  export { CreatePredictiveSearchStoreOptions, PredictiveSearchActions, PredictiveSearchState, PredictiveSearchStatus, PredictiveSearchStore, createPredictiveSearchStore };
@@ -3,10 +3,21 @@ import { PREDICTIVE_SEARCH_API_PATH } from "./constants.mjs";
3
3
  import { getEmptyPredictiveSearchResult } from "./search.mjs";
4
4
 
5
5
  //#region src/core/predictive-search/store.ts
6
- /** Default delay before predictive search sends a request after a term changes. */
6
+ /** Default wait, in milliseconds, between the latest term change and the search request. */
7
7
  const DEFAULT_PREDICTIVE_SEARCH_DEBOUNCE_IN_MS = 150;
8
8
  /** Default minimum trimmed term length required before predictive search sends a request. */
9
9
  const DEFAULT_PREDICTIVE_SEARCH_MIN_TERM_LENGTH = 1;
10
+ /**
11
+ * Creates a store that searches as the customer types and holds the latest predictive search results. Use the store in DOM code or in UI frameworks without Hydrogen bindings. In React and Vue, use `PredictiveSearchProvider`.
12
+ *
13
+ * Call `search()` with each new term, read results with `getState()` or `subscribe()`, and call `destroy()` when the search UI unmounts. By default, the store requests results from the route that `createPredictiveSearchServerHandlers` serves.
14
+ *
15
+ * The function throws an error when you omit the `fetch` option in a runtime without a global `fetch`.
16
+ *
17
+ * @param options Endpoint, timing, and search settings for the store.
18
+ * @returns A store with no term and empty results, ready to search.
19
+ * @publicDocs
20
+ */
10
21
  function createPredictiveSearchStore(options = {}) {
11
22
  const resolvedFetch = options.fetch ?? resolveGlobalFetch();
12
23
  if (typeof resolvedFetch !== "function") throw new Error("No fetch function available. Pass a fetch option or ensure globalThis.fetch exists.");