@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
@@ -15,16 +15,12 @@ const LOCAL_ORIGIN_HOSTS = new Set([
15
15
  "::1",
16
16
  "[::1]"
17
17
  ]);
18
- const USER_AGENT = `Hydrogen 2026.10.0-preview.4`;
18
+ const USER_AGENT = `Hydrogen 2026.10.0`;
19
19
  const CUSTOMER_ACCOUNT_GRAPHQL_PERSONALIZATION_REASON = "customer-account-graphql";
20
20
  /**
21
- * Creates a server-only {@link CustomerAccountClient} for the Shopify Customer
22
- * Account API.
21
+ * Creates a client that sends Customer Account API requests from your server. Create the client with the current request's context.
23
22
  *
24
- * Validates `shopId`, `customerApiVersion`, and `defaultTimeoutInMs` at
25
- * construction time. The returned client auto-injects the `language` variable
26
- * from `requestContext.i18n.language` when applicable, composes abort signals,
27
- * and marks responses as personalized (sets `private, no-store` cache headers).
23
+ * The function throws when the shop ID, API version, or timeout is invalid, when the request context has no HTTPS URL, when no fetch implementation is available, and when the function runs in a browser.
28
24
  *
29
25
  * @example
30
26
  * ```ts
@@ -41,7 +37,10 @@ const CUSTOMER_ACCOUNT_GRAPHQL_PERSONALIZATION_REASON = "customer-account-graphq
41
37
  * );
42
38
  * ```
43
39
  *
44
- * @throws {Error} When called in a browser context, when `shopId`, `customerApiVersion`, or `defaultTimeoutInMs` is invalid, when no `fetch` is available, or when `requestContext.url` is missing or not HTTPS.
40
+ * @param options - The shop ID, the API version, the request context, a custom fetch, and the request timeout.
41
+ * @returns A client with the GraphQL endpoint URL and a `graphql()` method for Customer Account API requests.
42
+ * @throws {Error} When called in a browser, when the shop ID, API version, or timeout is invalid, when no fetch is available, or when the request context URL is missing or not HTTPS.
43
+ * @publicDocs
45
44
  */
46
45
  function createCustomerAccountClient({ shopId, customerApiVersion = CUSTOMER_ACCOUNT_API_VERSION, requestContext, fetch: customFetch, defaultTimeoutInMs = DEFAULT_TIMEOUT_IN_MS }) {
47
46
  if (typeof document !== "undefined") throw new Error("Customer Account API tokens cannot be used in a browser context. Use this client from server or edge routes only.");
@@ -1 +1 @@
1
- {"version":3,"file":"client.mjs","names":[],"sources":["../../src/customer-account/client.ts"],"sourcesContent":["import type { GraphQLFormattedError } from \"../client/types\";\nimport { CUSTOMER_ACCOUNT_API_VERSION, DEFAULT_TIMEOUT_IN_MS } from \"../core/constants\";\nimport type { ShopifyRequestContext } from \"../core/request-context\";\nimport { isObjectRecord } from \"../core/utils/record\";\nimport {\n CustomerAccountApiError,\n CustomerAccountAuthenticationError,\n CustomerAccountTimeoutError,\n} from \"./errors\";\nimport {\n assertCustomerAccountDocument,\n type AnyCustomerAccountDocument,\n type CustomerAccountDocument,\n} from \"./graphql\";\n\nconst SHOP_ID_RE = /^\\d+$/;\nconst CUSTOMER_API_VERSION_RE = /^\\d{4}-\\d{2}$/;\nconst MAX_ASCII_CONTROL_CODE_POINT = 31;\nconst ASCII_DELETE_CODE_POINT = 127;\nconst MAX_SET_TIMEOUT_IN_MS = 2_147_483_647;\nconst LOCAL_ORIGIN_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\", \"[::1]\"]);\nconst USER_AGENT = `Hydrogen ${__HYDROGEN_VERSION__}`;\nconst CUSTOMER_ACCOUNT_GRAPHQL_PERSONALIZATION_REASON = \"customer-account-graphql\";\n\ntype AccessToken = string | null | undefined;\ntype FetchCustomerAccountGraphqlParams = {\n fetch: typeof globalThis.fetch;\n apiUrl: string;\n accessToken: string;\n origin: string;\n query: string;\n variables: Record<string, unknown>;\n signal: AbortSignal;\n timeoutSignal: AbortSignal;\n timeoutInMs: number;\n};\n\n/**\n * Options for {@link createCustomerAccountClient}.\n *\n * The client validates `shopId`, `customerApiVersion`, and `defaultTimeoutInMs`\n * at construction time and throws synchronously on invalid values.\n */\nexport type CreateCustomerAccountClientOptions = {\n /** Numeric Shopify shop ID as a string (e.g. `\"12345\"`). Validated against `/^\\d+$/`. */\n shopId: string;\n /**\n * Customer Account API version in `YYYY-MM` format.\n * Defaults to {@link CUSTOMER_ACCOUNT_API_VERSION}.\n */\n customerApiVersion?: string;\n /**\n * Request-scoped context created by `createShopifyRequestContext`. Must\n * have a `url` property (throws at construction when missing or non-HTTPS;\n * `http://localhost`, `127.0.0.1` and `::1` are accepted and sent as\n * HTTPS). Supplies the i18n language for automatic `$language` variable\n * injection, an abort signal that propagates request cancellation, and a\n * personalization marker (sets `private, no-store` and removes CDN cache\n * headers).\n */\n requestContext: ShopifyRequestContext;\n /** Custom `fetch` implementation. Falls back to `globalThis.fetch`. */\n fetch?: typeof globalThis.fetch;\n /**\n * Per-request timeout in milliseconds. Must be a positive safe integer no\n * greater than 2,147,483,647. Defaults to 30,000 ms.\n */\n defaultTimeoutInMs?: number;\n};\n\n/**\n * Per-call options passed to {@link CustomerAccountClient.graphql}.\n * See `variables` for automatic `$language` injection.\n */\nexport type CustomerAccountGraphqlOptions<Variables = Record<string, unknown>> = {\n /** Customer Account API access token, e.g. from `CustomerSession.getAccessToken()` or `getOrRefreshAccessToken()`. */\n accessToken: string;\n /**\n * Query variables. When the GraphQL document declares a `$language` variable\n * and you omit it here, the client injects it automatically from\n * `requestContext.i18n.language`.\n */\n variables?: Variables;\n /**\n * Optional abort signal. Combined with the request context signal and the\n * per-request timeout signal via `AbortSignal.any`, so cancellation from any\n * source stops the request.\n */\n signal?: AbortSignal;\n};\n\ntype ResultOfDoc<Doc> =\n Doc extends CustomerAccountDocument<infer Result, never, string> ? Result : never;\ntype VariablesOfDoc<Doc> =\n Doc extends CustomerAccountDocument<unknown, infer Variables, string> ? Variables : never;\ntype OptionalAutoVariables<Variables> = \"language\" extends keyof Variables\n ? { language?: Variables[\"language\"] }\n : {};\ntype UserVariables<Doc> = Omit<VariablesOfDoc<Doc>, \"language\"> &\n OptionalAutoVariables<VariablesOfDoc<Doc>>;\ntype HasNoRequiredKeys<T> = Record<string, never> extends T ? true : false;\n\n/**\n * Discriminated union returned by {@link CustomerAccountClient.graphql}.\n *\n * Discriminate on the presence of `errors`, not via `Partial`:\n *\n * - **Success:** `data` is always present, `errors` is `undefined`.\n * - **Partial or error:** `errors` is a non-empty array of\n * {@link GraphQLFormattedError}, and `data` may be `null`.\n *\n * Both arms expose the raw response `headers` for inspecting\n * `x-request-id` or rate-limit metadata.\n */\nexport type CustomerAccountGraphqlResult<Result = unknown> =\n | { data: Result; errors?: undefined; headers: Headers }\n | { data: Result | null; errors: GraphQLFormattedError[]; headers: Headers };\n\n/**\n * Conditional rest parameter for {@link CustomerAccountClient.graphql}.\n *\n * When the document has no required user variables (after `language` is\n * excluded from the requirement), `options.variables` is optional. When the\n * document declares required variables, the type forces the caller to supply\n * them, turning a missing-variables bug into a compile error.\n */\nexport type CustomerAccountGqlRestParam<Doc extends AnyCustomerAccountDocument> =\n HasNoRequiredKeys<UserVariables<Doc>> extends true\n ? [options: CustomerAccountGraphqlOptions<UserVariables<Doc>>]\n : [\n options: CustomerAccountGraphqlOptions<UserVariables<Doc>> & {\n variables: UserVariables<Doc>;\n },\n ];\n\n/**\n * A server-side GraphQL client for the Shopify Customer Account API.\n *\n * Created by {@link createCustomerAccountClient}. Each call to `graphql()`\n * validates that the document was produced by `gql()` (runtime branded with a\n * private Symbol), validates the access token, auto-injects the `language`\n * variable from i18n context when applicable, and marks the response as\n * personalized so the app response is sent with private, no-store cache headers.\n */\nexport type CustomerAccountClient = {\n /** Constructed endpoint: `https://shopify.com/{shopId}/account/customer/api/{version}/graphql`. */\n readonly apiUrl: string;\n /**\n * Send a GraphQL request to the Customer Account API.\n *\n * The document must be created by `gql()`. At call time the client:\n * 1. Validates the document brand and options object.\n * 2. Marks the response as personalized (sets `private, no-store`).\n * 3. Validates the access token.\n * 4. Throws if a signal is already aborted.\n * 5. Combines the request context signal, the caller's signal, and a timeout\n * signal via `AbortSignal.any`.\n * 6. Auto-injects the `language` variable from `requestContext.i18n.language`\n * when the document declares `$language` and the caller omits it.\n *\n * @throws {TypeError} When the document is not a branded `gql()` result.\n * @throws {CustomerAccountAuthenticationError} When the access token fails pre-flight validation.\n * @throws {CustomerAccountTimeoutError} When the request exceeds `defaultTimeoutInMs`.\n * @throws {CustomerAccountApiError} On non-OK HTTP status, unparseable JSON, or missing `data`.\n *\n * @example\n * ```ts\n * const result = await client.graphql(\n * gql(`query { customer { firstName lastName } }`),\n * { accessToken },\n * );\n *\n * if (result.errors) {\n * console.error(result.errors);\n * } else {\n * console.log(result.data.customer.firstName);\n * }\n * ```\n */\n graphql: <const Doc extends AnyCustomerAccountDocument>(\n document: Doc,\n ...options: CustomerAccountGqlRestParam<Doc>\n ) => Promise<CustomerAccountGraphqlResult<ResultOfDoc<Doc>>>;\n};\n\n/**\n * Creates a server-only {@link CustomerAccountClient} for the Shopify Customer\n * Account API.\n *\n * Validates `shopId`, `customerApiVersion`, and `defaultTimeoutInMs` at\n * construction time. The returned client auto-injects the `language` variable\n * from `requestContext.i18n.language` when applicable, composes abort signals,\n * and marks responses as personalized (sets `private, no-store` cache headers).\n *\n * @example\n * ```ts\n * import { createCustomerAccountClient, gql } from \"@shopify/hydrogen/customer-account\";\n *\n * const customerAccount = createCustomerAccountClient({\n * shopId: \"12345\",\n * requestContext,\n * });\n *\n * const { data } = await customerAccount.graphql(\n * gql(`query { customer { firstName } }`),\n * { accessToken },\n * );\n * ```\n *\n * @throws {Error} When called in a browser context, when `shopId`, `customerApiVersion`, or `defaultTimeoutInMs` is invalid, when no `fetch` is available, or when `requestContext.url` is missing or not HTTPS.\n */\nexport function createCustomerAccountClient({\n shopId,\n customerApiVersion = CUSTOMER_ACCOUNT_API_VERSION,\n requestContext,\n fetch: customFetch,\n defaultTimeoutInMs = DEFAULT_TIMEOUT_IN_MS,\n}: CreateCustomerAccountClientOptions): CustomerAccountClient {\n if (typeof document !== \"undefined\") {\n throw new Error(\n \"Customer Account API tokens cannot be used in a browser context. Use this client from server or edge routes only.\",\n );\n }\n\n validateShopId(shopId);\n validateCustomerApiVersion(customerApiVersion);\n validateTimeout(defaultTimeoutInMs);\n\n const resolvedFetch = customFetch ?? globalThis.fetch;\n if (typeof resolvedFetch !== \"function\") {\n throw new Error(\n \"No fetch function available. Pass a fetch option or ensure globalThis.fetch exists.\",\n );\n }\n\n const origin = getOrigin(requestContext.url);\n const apiUrl = `https://shopify.com/${shopId}/account/customer/api/${customerApiVersion}/graphql`;\n\n async function graphql<const Doc extends AnyCustomerAccountDocument>(\n document: Doc,\n ...rest: CustomerAccountGqlRestParam<Doc>\n ): Promise<CustomerAccountGraphqlResult<ResultOfDoc<Doc>>>;\n async function graphql(\n document: AnyCustomerAccountDocument,\n ...rest: [options?: CustomerAccountGraphqlOptions<unknown>]\n ): Promise<CustomerAccountGraphqlResult<unknown>> {\n assertCustomerAccountDocument(document);\n const options = validateGraphqlOptions(rest[0]);\n requestContext.markResponseAsPersonalized(CUSTOMER_ACCOUNT_GRAPHQL_PERSONALIZATION_REASON);\n const accessToken = validateAccessToken(options.accessToken);\n const externalSignals = [requestContext.signal, options.signal].filter(\n (signal): signal is AbortSignal => Boolean(signal),\n );\n throwIfAlreadyAborted(externalSignals);\n\n const { signal: timeoutSignal, cleanup: cleanupTimeout } =\n createCustomerAccountTimeoutSignal(defaultTimeoutInMs);\n externalSignals.push(timeoutSignal);\n const signal = AbortSignal.any(externalSignals);\n\n try {\n const variables = getVariables(\n document,\n getOptionalVariables(options.variables),\n requestContext.i18n.language,\n );\n const response = await fetchCustomerAccountGraphql({\n fetch: resolvedFetch,\n apiUrl,\n accessToken,\n origin,\n query: document.source,\n variables,\n signal,\n timeoutSignal,\n timeoutInMs: defaultTimeoutInMs,\n });\n\n return await readCustomerAccountGraphqlResponse(\n response,\n signal,\n timeoutSignal,\n defaultTimeoutInMs,\n );\n } finally {\n cleanupTimeout();\n }\n }\n\n return { apiUrl, graphql };\n}\n\nasync function fetchCustomerAccountGraphql({\n fetch,\n apiUrl,\n accessToken,\n origin,\n query,\n variables,\n signal,\n timeoutSignal,\n timeoutInMs,\n}: FetchCustomerAccountGraphqlParams): Promise<Response> {\n try {\n return await withAbort(\n fetch(apiUrl, {\n method: \"POST\",\n headers: new Headers({\n Authorization: accessToken,\n \"Content-Type\": \"application/json\",\n Origin: origin,\n \"User-Agent\": USER_AGENT,\n }),\n body: JSON.stringify({ query, variables }),\n cache: \"no-store\",\n redirect: \"manual\",\n signal,\n }),\n signal,\n );\n } catch (cause) {\n throwIfCustomerAccountSignalAborted(signal, timeoutSignal, timeoutInMs);\n if (isAbortError(cause)) throw cause;\n throw new CustomerAccountApiError(\"Customer Account API request failed\", { cause });\n }\n}\n\nasync function readCustomerAccountGraphqlResponse(\n response: Response,\n signal: AbortSignal,\n timeoutSignal: AbortSignal,\n timeoutInMs: number,\n): Promise<CustomerAccountGraphqlResult<unknown>> {\n const requestId = response.headers.get(\"x-request-id\") ?? undefined;\n if (!response.ok) {\n cancelResponseBody(response);\n throw new CustomerAccountApiError(`Customer Account API responded with ${response.status}`, {\n status: response.status,\n requestId,\n retryAfter: response.headers.get(\"retry-after\") ?? undefined,\n });\n }\n\n let body: { data?: unknown; errors?: GraphQLFormattedError[] };\n try {\n body = parseGraphqlResponse(await withAbort(response.json(), signal));\n } catch (cause) {\n cancelResponseBody(response);\n\n throwIfCustomerAccountSignalAborted(signal, timeoutSignal, timeoutInMs);\n if (isAbortError(cause)) throw cause;\n throw new CustomerAccountApiError(\"Failed to parse Customer Account API response as JSON\", {\n status: response.status,\n requestId,\n cause,\n });\n }\n\n if (body.errors) {\n return { data: body.data ?? null, errors: body.errors, headers: response.headers };\n }\n\n if (body.data == null) {\n throw new CustomerAccountApiError(\"Customer Account API response did not include data\", {\n status: response.status,\n requestId,\n });\n }\n\n return { data: body.data, headers: response.headers };\n}\n\nfunction cancelResponseBody(response: Response): void {\n try {\n void response.body?.cancel().catch(() => undefined);\n } catch {}\n}\n\nfunction validateTimeout(timeoutInMs: number): void {\n if (\n !Number.isSafeInteger(timeoutInMs) ||\n timeoutInMs <= 0 ||\n timeoutInMs > MAX_SET_TIMEOUT_IN_MS\n ) {\n throw new Error(\n `defaultTimeoutInMs must be a positive safe integer no greater than ${MAX_SET_TIMEOUT_IN_MS}`,\n );\n }\n}\n\nfunction createCustomerAccountTimeoutSignal(timeoutInMs: number): {\n signal: AbortSignal;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort(new CustomerAccountTimeoutError(timeoutInMs));\n }, timeoutInMs);\n\n return { signal: controller.signal, cleanup: () => clearTimeout(timeoutId) };\n}\n\nfunction withAbort<T>(promise: T | Promise<T>, signal: AbortSignal | undefined): Promise<T> {\n if (!signal) return Promise.resolve(promise);\n if (signal.aborted) {\n return Promise.reject(\n signal.reason ?? new DOMException(\"signal is aborted without reason\", \"AbortError\"),\n );\n }\n\n return new Promise<T>((resolve, reject) => {\n const abort = () => {\n signal.removeEventListener(\"abort\", abort);\n const reason =\n signal.reason ?? new DOMException(\"signal is aborted without reason\", \"AbortError\");\n reject(reason);\n };\n signal.addEventListener(\"abort\", abort, { once: true });\n Promise.resolve(promise).then(\n (value) => {\n signal.removeEventListener(\"abort\", abort);\n resolve(value);\n },\n (error) => {\n signal.removeEventListener(\"abort\", abort);\n reject(error);\n },\n );\n });\n}\n\nfunction getVariables(\n document: { variableNames: ReadonlySet<string> },\n variables: Record<string, unknown>,\n language: ShopifyRequestContext[\"i18n\"][\"language\"],\n): Record<string, unknown> {\n if (!document.variableNames.has(\"language\")) return variables;\n if (\"language\" in variables) return variables;\n return { ...variables, language };\n}\n\nfunction throwIfAlreadyAborted(signals: AbortSignal[]): void {\n const abortedSignal = signals.find((signal) => signal.aborted);\n if (!abortedSignal) return;\n throw abortedSignal.reason ?? new DOMException(\"signal is aborted without reason\", \"AbortError\");\n}\n\nfunction throwIfCustomerAccountSignalAborted(\n signal: AbortSignal,\n timeoutSignal: AbortSignal,\n timeoutInMs: number,\n): void {\n if (!signal.aborted) return;\n if (timeoutSignal.aborted && signal.reason === timeoutSignal.reason) {\n const reason = timeoutSignal.reason;\n throw reason instanceof CustomerAccountTimeoutError\n ? reason\n : new CustomerAccountTimeoutError(timeoutInMs);\n }\n throw signal.reason ?? new DOMException(\"signal is aborted without reason\", \"AbortError\");\n}\n\nfunction isAbortError(cause: unknown): cause is DOMException {\n return cause instanceof DOMException && cause.name === \"AbortError\";\n}\n\nfunction parseGraphqlResponse(json: unknown): {\n data?: unknown;\n errors?: GraphQLFormattedError[];\n} {\n if (!isObjectRecord(json)) {\n throw new Error(\"Customer Account API returned unexpected JSON type\");\n }\n\n if (!(\"data\" in json) && !(\"errors\" in json)) {\n throw new Error(\"Customer Account API response must include data or errors\");\n }\n const errors = json.errors;\n if (errors !== undefined && !isGraphqlErrorArray(errors)) {\n throw new Error(\"Customer Account API returned invalid GraphQL errors\");\n }\n return { data: json.data, errors };\n}\n\nfunction isGraphqlErrorArray(value: unknown): value is GraphQLFormattedError[] {\n if (!Array.isArray(value)) return false;\n return value.every((error) => {\n return typeof error === \"object\" && error !== null && typeof error.message === \"string\";\n });\n}\n\nfunction validateShopId(shopId: string): void {\n if (!SHOP_ID_RE.test(shopId)) {\n throw new Error(\"shopId must be a numeric Shopify shop ID string\");\n }\n}\n\nfunction validateCustomerApiVersion(customerApiVersion: string): void {\n if (!CUSTOMER_API_VERSION_RE.test(customerApiVersion)) {\n throw new Error(\"customerApiVersion must use YYYY-MM format\");\n }\n}\n\nfunction validateAccessToken(accessToken: AccessToken): string {\n if (\n typeof accessToken !== \"string\" ||\n accessToken === \"\" ||\n accessToken.trim() !== accessToken ||\n hasAsciiControlCharacter(accessToken)\n ) {\n throw new CustomerAccountAuthenticationError();\n }\n return accessToken;\n}\n\nfunction validateGraphqlOptions(\n options: CustomerAccountGraphqlOptions<unknown> | undefined,\n): CustomerAccountGraphqlOptions<unknown> {\n if (typeof options !== \"object\" || options === null) {\n throw new CustomerAccountAuthenticationError();\n }\n return options;\n}\n\nfunction getOptionalVariables(variables: unknown): Record<string, unknown> {\n if (variables === undefined) return {};\n if (!isObjectRecord(variables)) {\n throw new TypeError(\"Customer Account API variables must be an object\");\n }\n return variables;\n}\n\nfunction hasAsciiControlCharacter(value: string): boolean {\n for (let index = 0; index < value.length; index++) {\n const codePoint = value.charCodeAt(index);\n if (codePoint <= MAX_ASCII_CONTROL_CODE_POINT || codePoint === ASCII_DELETE_CODE_POINT) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Customer Account API requires an HTTPS Origin, but local dev frameworks often\n * receive `http://localhost` requests. Keep that local-only exception without\n * weakening origin validation for non-local requests.\n */\nfunction getOrigin(requestUrl: string | undefined): string {\n if (!requestUrl) {\n throw new Error(\"requestContext.url is required for Customer Account API requests\");\n }\n\n const url = new URL(requestUrl);\n if (url.protocol === \"https:\") return url.origin;\n if (url.protocol === \"http:\" && LOCAL_ORIGIN_HOSTS.has(url.hostname)) {\n return `https://${url.host}`;\n }\n throw new Error(`Customer Account API origin must use HTTPS. Received: ${requestUrl}`);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.mjs","names":[],"sources":["../../src/customer-account/client.ts"],"sourcesContent":["import type { GraphQLFormattedError } from \"../client/types\";\nimport { CUSTOMER_ACCOUNT_API_VERSION, DEFAULT_TIMEOUT_IN_MS } from \"../core/constants\";\nimport type { ShopifyRequestContext } from \"../core/request-context\";\nimport { isObjectRecord } from \"../core/utils/record\";\nimport {\n CustomerAccountApiError,\n CustomerAccountAuthenticationError,\n CustomerAccountTimeoutError,\n} from \"./errors\";\nimport {\n assertCustomerAccountDocument,\n type AnyCustomerAccountDocument,\n type CustomerAccountDocument,\n} from \"./graphql\";\n\nconst SHOP_ID_RE = /^\\d+$/;\nconst CUSTOMER_API_VERSION_RE = /^\\d{4}-\\d{2}$/;\nconst MAX_ASCII_CONTROL_CODE_POINT = 31;\nconst ASCII_DELETE_CODE_POINT = 127;\nconst MAX_SET_TIMEOUT_IN_MS = 2_147_483_647;\nconst LOCAL_ORIGIN_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\", \"[::1]\"]);\nconst USER_AGENT = `Hydrogen ${__HYDROGEN_VERSION__}`;\nconst CUSTOMER_ACCOUNT_GRAPHQL_PERSONALIZATION_REASON = \"customer-account-graphql\";\n\n/** A Customer Account API access token, or `null` or `undefined` when the customer has none. */\ntype AccessToken = string | null | undefined;\ntype FetchCustomerAccountGraphqlParams = {\n fetch: typeof globalThis.fetch;\n apiUrl: string;\n accessToken: string;\n origin: string;\n query: string;\n variables: Record<string, unknown>;\n signal: AbortSignal;\n timeoutSignal: AbortSignal;\n timeoutInMs: number;\n};\n\n/**\n * Options for creating a Customer Account API client.\n */\nexport type CreateCustomerAccountClientOptions = {\n /** Numeric Shopify shop ID as a string of digits, such as `12345`. */\n shopId: string;\n /**\n * Customer Account API version in `YYYY-MM` format. Defaults to `2026-10`.\n */\n customerApiVersion?: string;\n /**\n * The context for the current request, from `createShopifyRequestContext`.\n *\n * The context's URL must use HTTPS, or creating the client throws. Local `http://` URLs on localhost, 127.0.0.1, and ::1 also work for development.\n *\n * The client fills `$language` from the context's language and stops requests when the context's signal aborts.\n */\n requestContext: ShopifyRequestContext;\n /** Custom fetch implementation. Defaults to the global fetch. */\n fetch?: typeof globalThis.fetch;\n /**\n * Timeout for each request in milliseconds. Must be a positive integer no greater than 2,147,483,647. Defaults to `30000`.\n */\n defaultTimeoutInMs?: number;\n};\n\n/**\n * Options for a single Customer Account API request.\n */\nexport type CustomerAccountGraphqlOptions<Variables = Record<string, unknown>> = {\n /** The customer's access token, such as one from the customer session's `getOrRefreshAccessToken()` method. */\n accessToken: string;\n /**\n * The document's variables. When the document declares `$language` and you omit it, the client fills the variable from the request context's language.\n */\n variables?: Variables;\n /**\n * Stops this request when the signal aborts. The request also stops when the request context's signal aborts or the timeout passes.\n */\n signal?: AbortSignal;\n};\n\ntype ResultOfDoc<Doc> =\n Doc extends CustomerAccountDocument<infer Result, never, string> ? Result : never;\n/** The variables that a Customer Account document declares. */\ntype VariablesOfDoc<Doc> =\n Doc extends CustomerAccountDocument<unknown, infer Variables, string> ? Variables : never;\n/** An optional `language` variable for a document that declares `$language`. The client fills a missing value from the request context. */\ntype OptionalAutoVariables<Variables> = \"language\" extends keyof Variables\n ? { language?: Variables[\"language\"] }\n : {};\ntype UserVariables<Doc> = Omit<VariablesOfDoc<Doc>, \"language\"> &\n OptionalAutoVariables<VariablesOfDoc<Doc>>;\ntype HasNoRequiredKeys<T> = Record<string, never> extends T ? true : false;\n\n/**\n * Result of a Customer Account API request. Check `errors` to tell the outcomes apart.\n *\n * On success, `data` holds the result and `errors` is `undefined`. When the response has GraphQL errors, `errors` holds them and `data` can be `null`. Every result includes the raw response headers.\n */\nexport type CustomerAccountGraphqlResult<Result = unknown> =\n | { data: Result; errors?: undefined; headers: Headers }\n | { data: Result | null; errors: GraphQLFormattedError[]; headers: Headers };\n\n/**\n * The options argument for a Customer Account API request.\n *\n * Pass `variables` when the document declares a required variable other than `language`. TypeScript reports an error when a required variable is missing.\n */\nexport type CustomerAccountGqlRestParam<Doc extends AnyCustomerAccountDocument> =\n HasNoRequiredKeys<UserVariables<Doc>> extends true\n ? [options: CustomerAccountGraphqlOptions<UserVariables<Doc>>]\n : [\n options: CustomerAccountGraphqlOptions<UserVariables<Doc>> & {\n variables: UserVariables<Doc>;\n },\n ];\n\n/**\n * A client that sends Customer Account API requests from your server for the current request.\n */\nexport type CustomerAccountClient = {\n /** The GraphQL endpoint, `https://shopify.com/{shopId}/account/customer/api/{version}/graphql`. */\n readonly apiUrl: string;\n /**\n * Sends a Customer Account API query or mutation with the customer's access token, and returns the data, any GraphQL errors, and the response headers. Pass a document from the Customer Account `gql` function.\n *\n * The request makes the final response private and uncacheable when you call `applyResponseHeaders()`. When the document declares `$language` and you omit it, the client fills the variable from the request context's language.\n *\n * The method throws a `TypeError` for a document from any other `gql` function, including the Storefront API `gql` function, and for variables that aren't an object. When a signal aborts, the method throws the signal's reason. A missing or malformed access token throws `CustomerAccountAuthenticationError`, a timeout throws `CustomerAccountTimeoutError`, and other request failures throw `CustomerAccountApiError`.\n *\n * @throws {TypeError} When another gql function created the document, or when the variables aren't an object.\n * @throws {CustomerAccountAuthenticationError} When the options object is missing or the access token fails validation.\n * @throws {CustomerAccountTimeoutError} When the request exceeds the client's timeout.\n * @throws {CustomerAccountApiError} On a non-OK HTTP status, unparseable JSON, a response without data, or a network failure.\n *\n * @example\n * ```ts\n * const result = await client.graphql(\n * gql(`query { customer { firstName lastName } }`),\n * { accessToken },\n * );\n *\n * if (result.errors) {\n * console.error(result.errors);\n * } else {\n * console.log(result.data.customer.firstName);\n * }\n * ```\n */\n graphql: <const Doc extends AnyCustomerAccountDocument>(\n document: Doc,\n ...options: CustomerAccountGqlRestParam<Doc>\n ) => Promise<CustomerAccountGraphqlResult<ResultOfDoc<Doc>>>;\n};\n\n/**\n * Creates a client that sends Customer Account API requests from your server. Create the client with the current request's context.\n *\n * The function throws when the shop ID, API version, or timeout is invalid, when the request context has no HTTPS URL, when no fetch implementation is available, and when the function runs in a browser.\n *\n * @example\n * ```ts\n * import { createCustomerAccountClient, gql } from \"@shopify/hydrogen/customer-account\";\n *\n * const customerAccount = createCustomerAccountClient({\n * shopId: \"12345\",\n * requestContext,\n * });\n *\n * const { data } = await customerAccount.graphql(\n * gql(`query { customer { firstName } }`),\n * { accessToken },\n * );\n * ```\n *\n * @param options - The shop ID, the API version, the request context, a custom fetch, and the request timeout.\n * @returns A client with the GraphQL endpoint URL and a `graphql()` method for Customer Account API requests.\n * @throws {Error} When called in a browser, when the shop ID, API version, or timeout is invalid, when no fetch is available, or when the request context URL is missing or not HTTPS.\n * @publicDocs\n */\nexport function createCustomerAccountClient({\n shopId,\n customerApiVersion = CUSTOMER_ACCOUNT_API_VERSION,\n requestContext,\n fetch: customFetch,\n defaultTimeoutInMs = DEFAULT_TIMEOUT_IN_MS,\n}: CreateCustomerAccountClientOptions): CustomerAccountClient {\n if (typeof document !== \"undefined\") {\n throw new Error(\n \"Customer Account API tokens cannot be used in a browser context. Use this client from server or edge routes only.\",\n );\n }\n\n validateShopId(shopId);\n validateCustomerApiVersion(customerApiVersion);\n validateTimeout(defaultTimeoutInMs);\n\n const resolvedFetch = customFetch ?? globalThis.fetch;\n if (typeof resolvedFetch !== \"function\") {\n throw new Error(\n \"No fetch function available. Pass a fetch option or ensure globalThis.fetch exists.\",\n );\n }\n\n const origin = getOrigin(requestContext.url);\n const apiUrl = `https://shopify.com/${shopId}/account/customer/api/${customerApiVersion}/graphql`;\n\n async function graphql<const Doc extends AnyCustomerAccountDocument>(\n document: Doc,\n ...rest: CustomerAccountGqlRestParam<Doc>\n ): Promise<CustomerAccountGraphqlResult<ResultOfDoc<Doc>>>;\n async function graphql(\n document: AnyCustomerAccountDocument,\n ...rest: [options?: CustomerAccountGraphqlOptions<unknown>]\n ): Promise<CustomerAccountGraphqlResult<unknown>> {\n assertCustomerAccountDocument(document);\n const options = validateGraphqlOptions(rest[0]);\n requestContext.markResponseAsPersonalized(CUSTOMER_ACCOUNT_GRAPHQL_PERSONALIZATION_REASON);\n const accessToken = validateAccessToken(options.accessToken);\n const externalSignals = [requestContext.signal, options.signal].filter(\n (signal): signal is AbortSignal => Boolean(signal),\n );\n throwIfAlreadyAborted(externalSignals);\n\n const { signal: timeoutSignal, cleanup: cleanupTimeout } =\n createCustomerAccountTimeoutSignal(defaultTimeoutInMs);\n externalSignals.push(timeoutSignal);\n const signal = AbortSignal.any(externalSignals);\n\n try {\n const variables = getVariables(\n document,\n getOptionalVariables(options.variables),\n requestContext.i18n.language,\n );\n const response = await fetchCustomerAccountGraphql({\n fetch: resolvedFetch,\n apiUrl,\n accessToken,\n origin,\n query: document.source,\n variables,\n signal,\n timeoutSignal,\n timeoutInMs: defaultTimeoutInMs,\n });\n\n return await readCustomerAccountGraphqlResponse(\n response,\n signal,\n timeoutSignal,\n defaultTimeoutInMs,\n );\n } finally {\n cleanupTimeout();\n }\n }\n\n return { apiUrl, graphql };\n}\n\nasync function fetchCustomerAccountGraphql({\n fetch,\n apiUrl,\n accessToken,\n origin,\n query,\n variables,\n signal,\n timeoutSignal,\n timeoutInMs,\n}: FetchCustomerAccountGraphqlParams): Promise<Response> {\n try {\n return await withAbort(\n fetch(apiUrl, {\n method: \"POST\",\n headers: new Headers({\n Authorization: accessToken,\n \"Content-Type\": \"application/json\",\n Origin: origin,\n \"User-Agent\": USER_AGENT,\n }),\n body: JSON.stringify({ query, variables }),\n cache: \"no-store\",\n redirect: \"manual\",\n signal,\n }),\n signal,\n );\n } catch (cause) {\n throwIfCustomerAccountSignalAborted(signal, timeoutSignal, timeoutInMs);\n if (isAbortError(cause)) throw cause;\n throw new CustomerAccountApiError(\"Customer Account API request failed\", { cause });\n }\n}\n\nasync function readCustomerAccountGraphqlResponse(\n response: Response,\n signal: AbortSignal,\n timeoutSignal: AbortSignal,\n timeoutInMs: number,\n): Promise<CustomerAccountGraphqlResult<unknown>> {\n const requestId = response.headers.get(\"x-request-id\") ?? undefined;\n if (!response.ok) {\n cancelResponseBody(response);\n throw new CustomerAccountApiError(`Customer Account API responded with ${response.status}`, {\n status: response.status,\n requestId,\n retryAfter: response.headers.get(\"retry-after\") ?? undefined,\n });\n }\n\n let body: { data?: unknown; errors?: GraphQLFormattedError[] };\n try {\n body = parseGraphqlResponse(await withAbort(response.json(), signal));\n } catch (cause) {\n cancelResponseBody(response);\n\n throwIfCustomerAccountSignalAborted(signal, timeoutSignal, timeoutInMs);\n if (isAbortError(cause)) throw cause;\n throw new CustomerAccountApiError(\"Failed to parse Customer Account API response as JSON\", {\n status: response.status,\n requestId,\n cause,\n });\n }\n\n if (body.errors) {\n return { data: body.data ?? null, errors: body.errors, headers: response.headers };\n }\n\n if (body.data == null) {\n throw new CustomerAccountApiError(\"Customer Account API response did not include data\", {\n status: response.status,\n requestId,\n });\n }\n\n return { data: body.data, headers: response.headers };\n}\n\nfunction cancelResponseBody(response: Response): void {\n try {\n void response.body?.cancel().catch(() => undefined);\n } catch {}\n}\n\nfunction validateTimeout(timeoutInMs: number): void {\n if (\n !Number.isSafeInteger(timeoutInMs) ||\n timeoutInMs <= 0 ||\n timeoutInMs > MAX_SET_TIMEOUT_IN_MS\n ) {\n throw new Error(\n `defaultTimeoutInMs must be a positive safe integer no greater than ${MAX_SET_TIMEOUT_IN_MS}`,\n );\n }\n}\n\nfunction createCustomerAccountTimeoutSignal(timeoutInMs: number): {\n signal: AbortSignal;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort(new CustomerAccountTimeoutError(timeoutInMs));\n }, timeoutInMs);\n\n return { signal: controller.signal, cleanup: () => clearTimeout(timeoutId) };\n}\n\nfunction withAbort<T>(promise: T | Promise<T>, signal: AbortSignal | undefined): Promise<T> {\n if (!signal) return Promise.resolve(promise);\n if (signal.aborted) {\n return Promise.reject(\n signal.reason ?? new DOMException(\"signal is aborted without reason\", \"AbortError\"),\n );\n }\n\n return new Promise<T>((resolve, reject) => {\n const abort = () => {\n signal.removeEventListener(\"abort\", abort);\n const reason =\n signal.reason ?? new DOMException(\"signal is aborted without reason\", \"AbortError\");\n reject(reason);\n };\n signal.addEventListener(\"abort\", abort, { once: true });\n Promise.resolve(promise).then(\n (value) => {\n signal.removeEventListener(\"abort\", abort);\n resolve(value);\n },\n (error) => {\n signal.removeEventListener(\"abort\", abort);\n reject(error);\n },\n );\n });\n}\n\nfunction getVariables(\n document: { variableNames: ReadonlySet<string> },\n variables: Record<string, unknown>,\n language: ShopifyRequestContext[\"i18n\"][\"language\"],\n): Record<string, unknown> {\n if (!document.variableNames.has(\"language\")) return variables;\n if (\"language\" in variables) return variables;\n return { ...variables, language };\n}\n\nfunction throwIfAlreadyAborted(signals: AbortSignal[]): void {\n const abortedSignal = signals.find((signal) => signal.aborted);\n if (!abortedSignal) return;\n throw abortedSignal.reason ?? new DOMException(\"signal is aborted without reason\", \"AbortError\");\n}\n\nfunction throwIfCustomerAccountSignalAborted(\n signal: AbortSignal,\n timeoutSignal: AbortSignal,\n timeoutInMs: number,\n): void {\n if (!signal.aborted) return;\n if (timeoutSignal.aborted && signal.reason === timeoutSignal.reason) {\n const reason = timeoutSignal.reason;\n throw reason instanceof CustomerAccountTimeoutError\n ? reason\n : new CustomerAccountTimeoutError(timeoutInMs);\n }\n throw signal.reason ?? new DOMException(\"signal is aborted without reason\", \"AbortError\");\n}\n\nfunction isAbortError(cause: unknown): cause is DOMException {\n return cause instanceof DOMException && cause.name === \"AbortError\";\n}\n\nfunction parseGraphqlResponse(json: unknown): {\n data?: unknown;\n errors?: GraphQLFormattedError[];\n} {\n if (!isObjectRecord(json)) {\n throw new Error(\"Customer Account API returned unexpected JSON type\");\n }\n\n if (!(\"data\" in json) && !(\"errors\" in json)) {\n throw new Error(\"Customer Account API response must include data or errors\");\n }\n const errors = json.errors;\n if (errors !== undefined && !isGraphqlErrorArray(errors)) {\n throw new Error(\"Customer Account API returned invalid GraphQL errors\");\n }\n return { data: json.data, errors };\n}\n\nfunction isGraphqlErrorArray(value: unknown): value is GraphQLFormattedError[] {\n if (!Array.isArray(value)) return false;\n return value.every((error) => {\n return typeof error === \"object\" && error !== null && typeof error.message === \"string\";\n });\n}\n\nfunction validateShopId(shopId: string): void {\n if (!SHOP_ID_RE.test(shopId)) {\n throw new Error(\"shopId must be a numeric Shopify shop ID string\");\n }\n}\n\nfunction validateCustomerApiVersion(customerApiVersion: string): void {\n if (!CUSTOMER_API_VERSION_RE.test(customerApiVersion)) {\n throw new Error(\"customerApiVersion must use YYYY-MM format\");\n }\n}\n\nfunction validateAccessToken(accessToken: AccessToken): string {\n if (\n typeof accessToken !== \"string\" ||\n accessToken === \"\" ||\n accessToken.trim() !== accessToken ||\n hasAsciiControlCharacter(accessToken)\n ) {\n throw new CustomerAccountAuthenticationError();\n }\n return accessToken;\n}\n\nfunction validateGraphqlOptions(\n options: CustomerAccountGraphqlOptions<unknown> | undefined,\n): CustomerAccountGraphqlOptions<unknown> {\n if (typeof options !== \"object\" || options === null) {\n throw new CustomerAccountAuthenticationError();\n }\n return options;\n}\n\nfunction getOptionalVariables(variables: unknown): Record<string, unknown> {\n if (variables === undefined) return {};\n if (!isObjectRecord(variables)) {\n throw new TypeError(\"Customer Account API variables must be an object\");\n }\n return variables;\n}\n\nfunction hasAsciiControlCharacter(value: string): boolean {\n for (let index = 0; index < value.length; index++) {\n const codePoint = value.charCodeAt(index);\n if (codePoint <= MAX_ASCII_CONTROL_CODE_POINT || codePoint === ASCII_DELETE_CODE_POINT) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Customer Account API requires an HTTPS Origin, but local dev frameworks often\n * receive `http://localhost` requests. Keep that local-only exception without\n * weakening origin validation for non-local requests.\n */\nfunction getOrigin(requestUrl: string | undefined): string {\n if (!requestUrl) {\n throw new Error(\"requestContext.url is required for Customer Account API requests\");\n }\n\n const url = new URL(requestUrl);\n if (url.protocol === \"https:\") return url.origin;\n if (url.protocol === \"http:\" && LOCAL_ORIGIN_HOSTS.has(url.hostname)) {\n return `https://${url.host}`;\n }\n throw new Error(`Customer Account API origin must use HTTPS. Received: ${requestUrl}`);\n}\n"],"mappings":"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"}
@@ -1,24 +1,24 @@
1
1
  //#region src/customer-account/errors.d.ts
2
2
  /**
3
- * Base error for Customer Account API failures. Thrown by
4
- * `CustomerAccountClient.graphql()` when the API responds with a non-OK
5
- * HTTP status, when the response body cannot be parsed as JSON, or when the
6
- * parsed response is missing `data`. Also thrown (without subclassing) for
7
- * OAuth token-request timeouts and network failures.
3
+ * The error that a Customer Account API request throws when the request fails. The client throws this error for a non-OK HTTP status, a response that isn't valid GraphQL, a response without data, or a network failure. The OAuth callback also throws this error when its token request times out.
8
4
  *
9
- * Not all fields are populated on every instance. `status` is present
10
- * whenever an HTTP response was received. `requestId` is set when the
11
- * `x-request-id` response header exists. Both are absent on network
12
- * failures where no response arrived. `retryAfter` is populated only on
13
- * non-OK responses.
5
+ * Catch this class to handle every Customer Account API failure, including authentication and timeout errors. Read `status`, `requestId`, and `retryAfter` to handle the failure. Network failures have no status or request ID, and only non-OK responses include a retry-after value.
6
+ *
7
+ * @publicDocs
14
8
  */
15
9
  declare class CustomerAccountApiError extends Error {
16
- /** HTTP status code from the API response. Present whenever an HTTP response was received (including parse failures), absent on network failures where no response arrived. */
10
+ /** The HTTP status of the response, including a response that Hydrogen can't parse. */
17
11
  readonly status?: number;
18
- /** Value of the `x-request-id` response header, when the API returned one. Useful for Shopify support requests. */
12
+ /** The response's `x-request-id` header. Include the ID in Shopify support requests. */
19
13
  readonly requestId?: string;
20
- /** Value of the `retry-after` response header, when present. Indicates when the client should retry a rate-limited request. */
14
+ /** The `retry-after` header on a non-OK response. Use the value to schedule a retry of a rate-limited request. */
21
15
  readonly retryAfter?: string;
16
+ /** `CustomerAccountApiError`. Each subclass sets its own class name. */
17
+ name: string;
18
+ /** Describes the failure, such as the HTTP status that the API returned. */
19
+ message: string;
20
+ /** The stack trace, when the JavaScript runtime records one. */
21
+ stack?: string;
22
22
  constructor(message: string, options?: {
23
23
  status?: number;
24
24
  requestId?: string;
@@ -27,44 +27,53 @@ declare class CustomerAccountApiError extends Error {
27
27
  });
28
28
  }
29
29
  /**
30
- * Client-side pre-flight check. Thrown when the access token is missing,
31
- * empty, has leading or trailing whitespace, or contains ASCII control
32
- * characters (including DEL). Also thrown when the options object is
33
- * missing. A token the server rejects (e.g. expired or revoked) produces
34
- * the base {@link CustomerAccountApiError} with `status: 401` instead.
30
+ * The error that a Customer Account API request throws when the access token is missing or malformed. The client throws this error before it sends the request when the token is empty, has leading or trailing whitespace, or contains control characters. The client also throws this error when you omit the options argument.
31
+ *
32
+ * When the API rejects a token, the client throws `CustomerAccountApiError` with the response status.
33
+ *
34
+ * @publicDocs
35
35
  */
36
36
  declare class CustomerAccountAuthenticationError extends CustomerAccountApiError {
37
+ /** Always `CustomerAccountAuthenticationError`. */
38
+ name: string;
39
+ /** Always `"Customer Account API access token is required"`. */
40
+ message: string;
41
+ /** The stack trace, when the JavaScript runtime records one. */
42
+ stack?: string;
37
43
  constructor(message?: string);
38
44
  }
39
45
  /**
40
- * Thrown when a `CustomerAccountClient.graphql()` request exceeds
41
- * `defaultTimeoutInMs`. (OAuth token-request timeouts throw the base
42
- * {@link CustomerAccountApiError} instead.) Extends
43
- * {@link CustomerAccountApiError}.
46
+ * The error that a Customer Account API request throws when the request takes longer than the client's timeout. The timeout covers the whole request, including reading the response body.
47
+ *
48
+ * @publicDocs
44
49
  */
45
50
  declare class CustomerAccountTimeoutError extends CustomerAccountApiError {
46
- /** The timeout threshold (in milliseconds) that was exceeded. */
51
+ /** The timeout that the request exceeded, in milliseconds. */
47
52
  readonly timeoutInMs: number;
53
+ /** Always `CustomerAccountTimeoutError`. */
54
+ name: string;
55
+ /** States the timeout, such as `"Customer Account API request timed out after 30000ms"`. */
56
+ message: string;
57
+ /** The stack trace, when the JavaScript runtime records one. */
58
+ stack?: string;
48
59
  constructor(timeoutInMs: number);
49
60
  }
50
61
  /**
51
- * Thrown during the Customer Account OAuth authorization code exchange
52
- * or id_token validation in `handleOAuthCallback`. Refresh failures never
53
- * surface this error (they are caught internally and returned as
54
- * `undefined`). Extends `Error` directly, **not**
55
- * {@link CustomerAccountApiError}. A `catch` block for
56
- * `CustomerAccountApiError` will not catch this error.
62
+ * The error that the OAuth callback throws when customer sign-in fails. Sign-in fails when the callback doesn't match the sign-in that `prepareLoginUrl()` started, when that sign-in started more than 10 minutes earlier, when the code exchange fails, or when Shopify's tokens fail validation. The authorize route catches this error and redirects the customer to the failed-login path. Token refreshes never throw this error, and a failed refresh returns `undefined`.
63
+ *
64
+ * Read `code` to handle each failure. The codes are `missing_callback_params`, `state_mismatch`, `missing_pending_login`, `token_exchange_rejected`, `token_exchange_failed`, `invalid_token_response`, `nonce_mismatch`, `issuer_mismatch`, `audience_mismatch`, `expired_id_token`, and `invalid_id_token`.
57
65
  *
58
- * Use the `code` field for programmatic handling. Known codes:
59
- * `"missing_callback_params"`, `"state_mismatch"`,
60
- * `"token_exchange_rejected"`, `"token_exchange_failed"`,
61
- * `"invalid_token_response"`, `"nonce_mismatch"`, `"issuer_mismatch"`,
62
- * `"audience_mismatch"`, `"expired_id_token"`, `"invalid_id_token"`,
63
- * `"missing_pending_login"`.
66
+ * @publicDocs
64
67
  */
65
68
  declare class CustomerAccountOAuthError extends Error {
66
- /** Machine-readable error identifier for programmatic handling. */
69
+ /** The failure code, one of the codes in the class description. */
67
70
  readonly code: string;
71
+ /** Always `CustomerAccountOAuthError`. */
72
+ name: string;
73
+ /** Describes the sign-in failure. Read `code` to handle the failure. */
74
+ message: string;
75
+ /** The stack trace, when the JavaScript runtime records one. */
76
+ stack?: string;
68
77
  constructor(code: string, message: string, options?: {
69
78
  cause?: unknown;
70
79
  });
@@ -1,23 +1,17 @@
1
1
  //#region src/customer-account/errors.ts
2
2
  /**
3
- * Base error for Customer Account API failures. Thrown by
4
- * `CustomerAccountClient.graphql()` when the API responds with a non-OK
5
- * HTTP status, when the response body cannot be parsed as JSON, or when the
6
- * parsed response is missing `data`. Also thrown (without subclassing) for
7
- * OAuth token-request timeouts and network failures.
3
+ * The error that a Customer Account API request throws when the request fails. The client throws this error for a non-OK HTTP status, a response that isn't valid GraphQL, a response without data, or a network failure. The OAuth callback also throws this error when its token request times out.
8
4
  *
9
- * Not all fields are populated on every instance. `status` is present
10
- * whenever an HTTP response was received. `requestId` is set when the
11
- * `x-request-id` response header exists. Both are absent on network
12
- * failures where no response arrived. `retryAfter` is populated only on
13
- * non-OK responses.
5
+ * Catch this class to handle every Customer Account API failure, including authentication and timeout errors. Read `status`, `requestId`, and `retryAfter` to handle the failure. Network failures have no status or request ID, and only non-OK responses include a retry-after value.
6
+ *
7
+ * @publicDocs
14
8
  */
15
9
  var CustomerAccountApiError = class extends Error {
16
- /** HTTP status code from the API response. Present whenever an HTTP response was received (including parse failures), absent on network failures where no response arrived. */
10
+ /** The HTTP status of the response, including a response that Hydrogen can't parse. */
17
11
  status;
18
- /** Value of the `x-request-id` response header, when the API returned one. Useful for Shopify support requests. */
12
+ /** The response's `x-request-id` header. Include the ID in Shopify support requests. */
19
13
  requestId;
20
- /** Value of the `retry-after` response header, when present. Indicates when the client should retry a rate-limited request. */
14
+ /** The `retry-after` header on a non-OK response. Use the value to schedule a retry of a rate-limited request. */
21
15
  retryAfter;
22
16
  constructor(message, options) {
23
17
  super(message, options?.cause ? { cause: options.cause } : void 0);
@@ -28,11 +22,11 @@ var CustomerAccountApiError = class extends Error {
28
22
  }
29
23
  };
30
24
  /**
31
- * Client-side pre-flight check. Thrown when the access token is missing,
32
- * empty, has leading or trailing whitespace, or contains ASCII control
33
- * characters (including DEL). Also thrown when the options object is
34
- * missing. A token the server rejects (e.g. expired or revoked) produces
35
- * the base {@link CustomerAccountApiError} with `status: 401` instead.
25
+ * The error that a Customer Account API request throws when the access token is missing or malformed. The client throws this error before it sends the request when the token is empty, has leading or trailing whitespace, or contains control characters. The client also throws this error when you omit the options argument.
26
+ *
27
+ * When the API rejects a token, the client throws `CustomerAccountApiError` with the response status.
28
+ *
29
+ * @publicDocs
36
30
  */
37
31
  var CustomerAccountAuthenticationError = class extends CustomerAccountApiError {
38
32
  constructor(message = "Customer Account API access token is required") {
@@ -41,13 +35,12 @@ var CustomerAccountAuthenticationError = class extends CustomerAccountApiError {
41
35
  }
42
36
  };
43
37
  /**
44
- * Thrown when a `CustomerAccountClient.graphql()` request exceeds
45
- * `defaultTimeoutInMs`. (OAuth token-request timeouts throw the base
46
- * {@link CustomerAccountApiError} instead.) Extends
47
- * {@link CustomerAccountApiError}.
38
+ * The error that a Customer Account API request throws when the request takes longer than the client's timeout. The timeout covers the whole request, including reading the response body.
39
+ *
40
+ * @publicDocs
48
41
  */
49
42
  var CustomerAccountTimeoutError = class extends CustomerAccountApiError {
50
- /** The timeout threshold (in milliseconds) that was exceeded. */
43
+ /** The timeout that the request exceeded, in milliseconds. */
51
44
  timeoutInMs;
52
45
  constructor(timeoutInMs) {
53
46
  super(`Customer Account API request timed out after ${timeoutInMs}ms`);
@@ -56,22 +49,14 @@ var CustomerAccountTimeoutError = class extends CustomerAccountApiError {
56
49
  }
57
50
  };
58
51
  /**
59
- * Thrown during the Customer Account OAuth authorization code exchange
60
- * or id_token validation in `handleOAuthCallback`. Refresh failures never
61
- * surface this error (they are caught internally and returned as
62
- * `undefined`). Extends `Error` directly, **not**
63
- * {@link CustomerAccountApiError}. A `catch` block for
64
- * `CustomerAccountApiError` will not catch this error.
52
+ * The error that the OAuth callback throws when customer sign-in fails. Sign-in fails when the callback doesn't match the sign-in that `prepareLoginUrl()` started, when that sign-in started more than 10 minutes earlier, when the code exchange fails, or when Shopify's tokens fail validation. The authorize route catches this error and redirects the customer to the failed-login path. Token refreshes never throw this error, and a failed refresh returns `undefined`.
53
+ *
54
+ * Read `code` to handle each failure. The codes are `missing_callback_params`, `state_mismatch`, `missing_pending_login`, `token_exchange_rejected`, `token_exchange_failed`, `invalid_token_response`, `nonce_mismatch`, `issuer_mismatch`, `audience_mismatch`, `expired_id_token`, and `invalid_id_token`.
65
55
  *
66
- * Use the `code` field for programmatic handling. Known codes:
67
- * `"missing_callback_params"`, `"state_mismatch"`,
68
- * `"token_exchange_rejected"`, `"token_exchange_failed"`,
69
- * `"invalid_token_response"`, `"nonce_mismatch"`, `"issuer_mismatch"`,
70
- * `"audience_mismatch"`, `"expired_id_token"`, `"invalid_id_token"`,
71
- * `"missing_pending_login"`.
56
+ * @publicDocs
72
57
  */
73
58
  var CustomerAccountOAuthError = class extends Error {
74
- /** Machine-readable error identifier for programmatic handling. */
59
+ /** The failure code, one of the codes in the class description. */
75
60
  code;
76
61
  constructor(code, message, options) {
77
62
  super(message, options?.cause ? { cause: options.cause } : void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.mjs","names":[],"sources":["../../src/customer-account/errors.ts"],"sourcesContent":["/**\n * Base error for Customer Account API failures. Thrown by\n * `CustomerAccountClient.graphql()` when the API responds with a non-OK\n * HTTP status, when the response body cannot be parsed as JSON, or when the\n * parsed response is missing `data`. Also thrown (without subclassing) for\n * OAuth token-request timeouts and network failures.\n *\n * Not all fields are populated on every instance. `status` is present\n * whenever an HTTP response was received. `requestId` is set when the\n * `x-request-id` response header exists. Both are absent on network\n * failures where no response arrived. `retryAfter` is populated only on\n * non-OK responses.\n */\nexport class CustomerAccountApiError extends Error {\n /** HTTP status code from the API response. Present whenever an HTTP response was received (including parse failures), absent on network failures where no response arrived. */\n readonly status?: number;\n /** Value of the `x-request-id` response header, when the API returned one. Useful for Shopify support requests. */\n readonly requestId?: string;\n /** Value of the `retry-after` response header, when present. Indicates when the client should retry a rate-limited request. */\n readonly retryAfter?: string;\n\n constructor(\n message: string,\n options?: { status?: number; requestId?: string; retryAfter?: string; cause?: unknown },\n ) {\n super(message, options?.cause ? { cause: options.cause } : undefined);\n this.name = \"CustomerAccountApiError\";\n this.status = options?.status;\n this.requestId = options?.requestId;\n this.retryAfter = options?.retryAfter;\n }\n}\n\n/**\n * Client-side pre-flight check. Thrown when the access token is missing,\n * empty, has leading or trailing whitespace, or contains ASCII control\n * characters (including DEL). Also thrown when the options object is\n * missing. A token the server rejects (e.g. expired or revoked) produces\n * the base {@link CustomerAccountApiError} with `status: 401` instead.\n */\nexport class CustomerAccountAuthenticationError extends CustomerAccountApiError {\n constructor(message = \"Customer Account API access token is required\") {\n super(message);\n this.name = \"CustomerAccountAuthenticationError\";\n }\n}\n\n/**\n * Thrown when a `CustomerAccountClient.graphql()` request exceeds\n * `defaultTimeoutInMs`. (OAuth token-request timeouts throw the base\n * {@link CustomerAccountApiError} instead.) Extends\n * {@link CustomerAccountApiError}.\n */\nexport class CustomerAccountTimeoutError extends CustomerAccountApiError {\n /** The timeout threshold (in milliseconds) that was exceeded. */\n readonly timeoutInMs: number;\n\n constructor(timeoutInMs: number) {\n super(`Customer Account API request timed out after ${timeoutInMs}ms`);\n this.name = \"CustomerAccountTimeoutError\";\n this.timeoutInMs = timeoutInMs;\n }\n}\n\n/**\n * Thrown during the Customer Account OAuth authorization code exchange\n * or id_token validation in `handleOAuthCallback`. Refresh failures never\n * surface this error (they are caught internally and returned as\n * `undefined`). Extends `Error` directly, **not**\n * {@link CustomerAccountApiError}. A `catch` block for\n * `CustomerAccountApiError` will not catch this error.\n *\n * Use the `code` field for programmatic handling. Known codes:\n * `\"missing_callback_params\"`, `\"state_mismatch\"`,\n * `\"token_exchange_rejected\"`, `\"token_exchange_failed\"`,\n * `\"invalid_token_response\"`, `\"nonce_mismatch\"`, `\"issuer_mismatch\"`,\n * `\"audience_mismatch\"`, `\"expired_id_token\"`, `\"invalid_id_token\"`,\n * `\"missing_pending_login\"`.\n */\nexport class CustomerAccountOAuthError extends Error {\n /** Machine-readable error identifier for programmatic handling. */\n readonly code: string;\n\n constructor(code: string, message: string, options?: { cause?: unknown }) {\n super(message, options?.cause ? { cause: options.cause } : undefined);\n this.name = \"CustomerAccountOAuthError\";\n this.code = code;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,IAAa,0BAAb,cAA6C,MAAM;;CAEjD,AAAS;;CAET,AAAS;;CAET,AAAS;CAET,YACE,SACA,SACA;AACA,QAAM,SAAS,SAAS,QAAQ,EAAE,OAAO,QAAQ,OAAO,GAAG,OAAU;AACrE,OAAK,OAAO;AACZ,OAAK,SAAS,SAAS;AACvB,OAAK,YAAY,SAAS;AAC1B,OAAK,aAAa,SAAS;;;;;;;;;;AAW/B,IAAa,qCAAb,cAAwD,wBAAwB;CAC9E,YAAY,UAAU,iDAAiD;AACrE,QAAM,QAAQ;AACd,OAAK,OAAO;;;;;;;;;AAUhB,IAAa,8BAAb,cAAiD,wBAAwB;;CAEvE,AAAS;CAET,YAAY,aAAqB;AAC/B,QAAM,gDAAgD,YAAY,IAAI;AACtE,OAAK,OAAO;AACZ,OAAK,cAAc;;;;;;;;;;;;;;;;;;AAmBvB,IAAa,4BAAb,cAA+C,MAAM;;CAEnD,AAAS;CAET,YAAY,MAAc,SAAiB,SAA+B;AACxE,QAAM,SAAS,SAAS,QAAQ,EAAE,OAAO,QAAQ,OAAO,GAAG,OAAU;AACrE,OAAK,OAAO;AACZ,OAAK,OAAO"}
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../../src/customer-account/errors.ts"],"sourcesContent":["/**\n * The error that a Customer Account API request throws when the request fails. The client throws this error for a non-OK HTTP status, a response that isn't valid GraphQL, a response without data, or a network failure. The OAuth callback also throws this error when its token request times out.\n *\n * Catch this class to handle every Customer Account API failure, including authentication and timeout errors. Read `status`, `requestId`, and `retryAfter` to handle the failure. Network failures have no status or request ID, and only non-OK responses include a retry-after value.\n *\n * @publicDocs\n */\nexport class CustomerAccountApiError extends Error {\n /** The HTTP status of the response, including a response that Hydrogen can't parse. */\n readonly status?: number;\n /** The response's `x-request-id` header. Include the ID in Shopify support requests. */\n readonly requestId?: string;\n /** The `retry-after` header on a non-OK response. Use the value to schedule a retry of a rate-limited request. */\n readonly retryAfter?: string;\n\n /** `CustomerAccountApiError`. Each subclass sets its own class name. */\n declare name: string;\n /** Describes the failure, such as the HTTP status that the API returned. */\n declare message: string;\n /** The stack trace, when the JavaScript runtime records one. */\n declare stack?: string;\n\n constructor(\n message: string,\n options?: { status?: number; requestId?: string; retryAfter?: string; cause?: unknown },\n ) {\n super(message, options?.cause ? { cause: options.cause } : undefined);\n this.name = \"CustomerAccountApiError\";\n this.status = options?.status;\n this.requestId = options?.requestId;\n this.retryAfter = options?.retryAfter;\n }\n}\n\n/**\n * The error that a Customer Account API request throws when the access token is missing or malformed. The client throws this error before it sends the request when the token is empty, has leading or trailing whitespace, or contains control characters. The client also throws this error when you omit the options argument.\n *\n * When the API rejects a token, the client throws `CustomerAccountApiError` with the response status.\n *\n * @publicDocs\n */\nexport class CustomerAccountAuthenticationError extends CustomerAccountApiError {\n /** Always `CustomerAccountAuthenticationError`. */\n declare name: string;\n /** Always `\"Customer Account API access token is required\"`. */\n declare message: string;\n /** The stack trace, when the JavaScript runtime records one. */\n declare stack?: string;\n\n constructor(message = \"Customer Account API access token is required\") {\n super(message);\n this.name = \"CustomerAccountAuthenticationError\";\n }\n}\n\n/**\n * The error that a Customer Account API request throws when the request takes longer than the client's timeout. The timeout covers the whole request, including reading the response body.\n *\n * @publicDocs\n */\nexport class CustomerAccountTimeoutError extends CustomerAccountApiError {\n /** The timeout that the request exceeded, in milliseconds. */\n readonly timeoutInMs: number;\n\n /** Always `CustomerAccountTimeoutError`. */\n declare name: string;\n /** States the timeout, such as `\"Customer Account API request timed out after 30000ms\"`. */\n declare message: string;\n /** The stack trace, when the JavaScript runtime records one. */\n declare stack?: string;\n\n constructor(timeoutInMs: number) {\n super(`Customer Account API request timed out after ${timeoutInMs}ms`);\n this.name = \"CustomerAccountTimeoutError\";\n this.timeoutInMs = timeoutInMs;\n }\n}\n\n/**\n * The error that the OAuth callback throws when customer sign-in fails. Sign-in fails when the callback doesn't match the sign-in that `prepareLoginUrl()` started, when that sign-in started more than 10 minutes earlier, when the code exchange fails, or when Shopify's tokens fail validation. The authorize route catches this error and redirects the customer to the failed-login path. Token refreshes never throw this error, and a failed refresh returns `undefined`.\n *\n * Read `code` to handle each failure. The codes are `missing_callback_params`, `state_mismatch`, `missing_pending_login`, `token_exchange_rejected`, `token_exchange_failed`, `invalid_token_response`, `nonce_mismatch`, `issuer_mismatch`, `audience_mismatch`, `expired_id_token`, and `invalid_id_token`.\n *\n * @publicDocs\n */\nexport class CustomerAccountOAuthError extends Error {\n /** The failure code, one of the codes in the class description. */\n readonly code: string;\n\n /** Always `CustomerAccountOAuthError`. */\n declare name: string;\n /** Describes the sign-in failure. Read `code` to handle the failure. */\n declare message: string;\n /** The stack trace, when the JavaScript runtime records one. */\n declare stack?: string;\n\n constructor(code: string, message: string, options?: { cause?: unknown }) {\n super(message, options?.cause ? { cause: options.cause } : undefined);\n this.name = \"CustomerAccountOAuthError\";\n this.code = code;\n }\n}\n"],"mappings":";;;;;;;;AAOA,IAAa,0BAAb,cAA6C,MAAM;;CAEjD,AAAS;;CAET,AAAS;;CAET,AAAS;CAST,YACE,SACA,SACA;AACA,QAAM,SAAS,SAAS,QAAQ,EAAE,OAAO,QAAQ,OAAO,GAAG,OAAU;AACrE,OAAK,OAAO;AACZ,OAAK,SAAS,SAAS;AACvB,OAAK,YAAY,SAAS;AAC1B,OAAK,aAAa,SAAS;;;;;;;;;;AAW/B,IAAa,qCAAb,cAAwD,wBAAwB;CAQ9E,YAAY,UAAU,iDAAiD;AACrE,QAAM,QAAQ;AACd,OAAK,OAAO;;;;;;;;AAShB,IAAa,8BAAb,cAAiD,wBAAwB;;CAEvE,AAAS;CAST,YAAY,aAAqB;AAC/B,QAAM,gDAAgD,YAAY,IAAI;AACtE,OAAK,OAAO;AACZ,OAAK,cAAc;;;;;;;;;;AAWvB,IAAa,4BAAb,cAA+C,MAAM;;CAEnD,AAAS;CAST,YAAY,MAAc,SAAiB,SAA+B;AACxE,QAAM,SAAS,SAAS,QAAQ,EAAE,OAAO,QAAQ,OAAO,GAAG,OAAU;AACrE,OAAK,OAAO;AACZ,OAAK,OAAO"}
@@ -10,34 +10,28 @@ type CustomerAccountTadaGql = initGraphQLTada<{
10
10
  }>;
11
11
  declare const CUSTOMER_ACCOUNT_DOCUMENT: unique symbol;
12
12
  /**
13
- * Branded document type returned by {@link gql}.
13
+ * A Customer Account API query or mutation that `gql` from `@shopify/hydrogen/customer-account` returns. TypeScript infers the result and variables types from the document's GraphQL source.
14
14
  *
15
- * Carries the GraphQL source as a type-level string literal so that
16
- * `InferResult` and `InferVariables` can derive typed responses. The
17
- * `[CUSTOMER_ACCOUNT_DOCUMENT]` brand is private and cannot be constructed
18
- * externally — only `gql()` produces valid instances. Passing a plain object
19
- * with a `source` property to `CustomerAccountClient.graphql()` will throw
20
- * a `TypeError` at runtime.
15
+ * Create documents only with the Customer Account `gql` function. The client throws a `TypeError` for any other object.
21
16
  */
22
17
  type CustomerAccountDocument<Result = unknown, Variables = never, Source extends string = string> = DocumentDecoration<Result, Variables> & {
23
18
  readonly [CUSTOMER_ACCOUNT_DOCUMENT]: true;
24
19
  readonly source: Source;
25
20
  };
26
- /** Widened alias for {@link CustomerAccountDocument}. Use as a constraint when accepting any Customer Account document. */
21
+ /** Any Customer Account API document. Use the type as a constraint when a function accepts any document. */
27
22
  type AnyCustomerAccountDocument = CustomerAccountDocument<unknown, never, string>;
28
- /** Extracts the source string literal type from a {@link CustomerAccountDocument}. */
23
+ /** Extracts the source string literal type from a Customer Account document. */
29
24
  type SourceOf<Doc> = Doc extends {
30
25
  readonly source: infer Source extends string;
31
26
  } ? Source : never;
32
27
  /**
33
- * Recursively concatenates the source strings of an array of fragment
34
- * documents at the type level, joining each with a newline. An empty
35
- * tuple produces `""`.
28
+ * Joins the source strings of a tuple of fragment documents with newlines at the type level. An empty tuple produces `""`.
36
29
  */
37
30
  type FragmentSources<Fragments extends readonly AnyCustomerAccountDocument[]> = Fragments extends readonly [] ? "" : Fragments extends readonly [infer Only extends AnyCustomerAccountDocument] ? SourceOf<Only> : Fragments extends readonly [infer First extends AnyCustomerAccountDocument, ...infer Rest extends readonly AnyCustomerAccountDocument[]] ? `${SourceOf<First>}\n${FragmentSources<Rest>}` : string;
38
31
  /**
39
- * Combines an operation source with its {@link FragmentSources} at the type
40
- * level. When `Fragments` is empty the result is just `Source`.
32
+ * Combines an operation source with the sources of its fragments at the type level. With no fragments, the result is the operation source.
33
+ *
34
+ * @publicDocs
41
35
  */
42
36
  type ComposedSource<Source extends string, Fragments extends readonly AnyCustomerAccountDocument[]> = FragmentSources<Fragments> extends "" ? Source : `${Source}\n${FragmentSources<Fragments>}`;
43
37
  type CustomerAccountGql = {
@@ -45,16 +39,9 @@ type CustomerAccountGql = {
45
39
  <const Source extends string, const Fragments extends readonly AnyCustomerAccountDocument[], const DocumentSource extends string = ComposedSource<Source, Fragments>>(source: Source, fragments: Fragments): CustomerAccountDocument<InferResult<DocumentSource>, InferVariables<DocumentSource>, DocumentSource>;
46
40
  } & CustomerAccountTadaGql;
47
41
  /**
48
- * Creates a branded {@link CustomerAccountDocument} from a GraphQL source
49
- * string. This is a regular function call, not a tagged template literal.
50
- *
51
- * The returned document is branded with a private Symbol that
52
- * `CustomerAccountClient.graphql()` validates at runtime — passing a plain
53
- * object with a `source` property will throw a `TypeError`.
42
+ * Creates a typed Customer Account API query or mutation from a GraphQL source string. Pass the document to the Customer Account API client. Call `gql` as a regular function. Tagged template syntax doesn't work.
54
43
  *
55
- * An optional second argument accepts an array of fragment documents. Fragments
56
- * are deduplicated by source string identity (`Set` check, not by fragment
57
- * name) and appended to the operation source.
44
+ * Pass an array of fragment documents as the second argument to append the fragments to the operation. Each fragment must come from this `gql` function, or the call throws a `TypeError`.
58
45
  *
59
46
  * @example
60
47
  * ```ts
@@ -90,6 +77,7 @@ type CustomerAccountGql = {
90
77
  * }
91
78
  * `, [ORDER_FIELDS]);
92
79
  * ```
80
+ * @publicDocs
93
81
  */
94
82
  declare const gql: CustomerAccountGql;
95
83
  //#endregion
@@ -4,16 +4,9 @@ import { isObjectRecord } from "../core/utils/record.mjs";
4
4
  const CUSTOMER_ACCOUNT_DOCUMENT = Symbol("CustomerAccountDocument");
5
5
  const VARIABLE_DEFINITION_RE = /\$([_A-Za-z][_0-9A-Za-z]*)\s*:/g;
6
6
  /**
7
- * Creates a branded {@link CustomerAccountDocument} from a GraphQL source
8
- * string. This is a regular function call, not a tagged template literal.
7
+ * Creates a typed Customer Account API query or mutation from a GraphQL source string. Pass the document to the Customer Account API client. Call `gql` as a regular function. Tagged template syntax doesn't work.
9
8
  *
10
- * The returned document is branded with a private Symbol that
11
- * `CustomerAccountClient.graphql()` validates at runtime — passing a plain
12
- * object with a `source` property will throw a `TypeError`.
13
- *
14
- * An optional second argument accepts an array of fragment documents. Fragments
15
- * are deduplicated by source string identity (`Set` check, not by fragment
16
- * name) and appended to the operation source.
9
+ * Pass an array of fragment documents as the second argument to append the fragments to the operation. Each fragment must come from this `gql` function, or the call throws a `TypeError`.
17
10
  *
18
11
  * @example
19
12
  * ```ts
@@ -49,6 +42,7 @@ const VARIABLE_DEFINITION_RE = /\$([_A-Za-z][_0-9A-Za-z]*)\s*:/g;
49
42
  * }
50
43
  * `, [ORDER_FIELDS]);
51
44
  * ```
45
+ * @publicDocs
52
46
  */
53
47
  const gql = ((source, fragments) => {
54
48
  let query = source;
@@ -1 +1 @@
1
- {"version":3,"file":"graphql.mjs","names":[],"sources":["../../src/customer-account/graphql.ts"],"sourcesContent":["import type { DocumentDecoration, initGraphQLTada as InitGraphQLTada } from \"gql.tada\";\n\nimport { isObjectRecord } from \"../core/utils/record\";\nimport type { introspection } from \"../graphql/generated/customer-account-graphql-env\";\nimport type { CustomerAccountScalars } from \"../graphql/scalars\";\nimport type { InferResult, InferVariables } from \"./type-resolver\";\n\ntype CustomerAccountTadaGql = InitGraphQLTada<{\n introspection: introspection;\n scalars: CustomerAccountScalars;\n}>;\n\nconst CUSTOMER_ACCOUNT_DOCUMENT = Symbol(\"CustomerAccountDocument\");\nconst VARIABLE_DEFINITION_RE = /\\$([_A-Za-z][_0-9A-Za-z]*)\\s*:/g;\n\n/**\n * Branded document type returned by {@link gql}.\n *\n * Carries the GraphQL source as a type-level string literal so that\n * `InferResult` and `InferVariables` can derive typed responses. The\n * `[CUSTOMER_ACCOUNT_DOCUMENT]` brand is private and cannot be constructed\n * externally — only `gql()` produces valid instances. Passing a plain object\n * with a `source` property to `CustomerAccountClient.graphql()` will throw\n * a `TypeError` at runtime.\n */\nexport type CustomerAccountDocument<\n Result = unknown,\n Variables = never,\n Source extends string = string,\n> = DocumentDecoration<Result, Variables> & {\n readonly [CUSTOMER_ACCOUNT_DOCUMENT]: true;\n readonly source: Source;\n};\n\n/** Widened alias for {@link CustomerAccountDocument}. Use as a constraint when accepting any Customer Account document. */\nexport type AnyCustomerAccountDocument = CustomerAccountDocument<unknown, never, string>;\n\n/** Extracts the source string literal type from a {@link CustomerAccountDocument}. */\nexport type SourceOf<Doc> = Doc extends { readonly source: infer Source extends string }\n ? Source\n : never;\n\n/**\n * Recursively concatenates the source strings of an array of fragment\n * documents at the type level, joining each with a newline. An empty\n * tuple produces `\"\"`.\n */\nexport type FragmentSources<Fragments extends readonly AnyCustomerAccountDocument[]> =\n Fragments extends readonly []\n ? \"\"\n : Fragments extends readonly [infer Only extends AnyCustomerAccountDocument]\n ? SourceOf<Only>\n : Fragments extends readonly [\n infer First extends AnyCustomerAccountDocument,\n ...infer Rest extends readonly AnyCustomerAccountDocument[],\n ]\n ? `${SourceOf<First>}\\n${FragmentSources<Rest>}`\n : string;\n\n/**\n * Combines an operation source with its {@link FragmentSources} at the type\n * level. When `Fragments` is empty the result is just `Source`.\n */\nexport type ComposedSource<\n Source extends string,\n Fragments extends readonly AnyCustomerAccountDocument[],\n> = FragmentSources<Fragments> extends \"\" ? Source : `${Source}\\n${FragmentSources<Fragments>}`;\n\ntype CustomerAccountDocumentValue = AnyCustomerAccountDocument & {\n readonly variableNames: ReadonlySet<string>;\n};\n\ntype CustomerAccountGql = {\n <const Source extends string>(\n source: Source,\n ): CustomerAccountDocument<InferResult<Source>, InferVariables<Source>, Source>;\n <\n const Source extends string,\n const Fragments extends readonly AnyCustomerAccountDocument[],\n const DocumentSource extends string = ComposedSource<Source, Fragments>,\n >(\n source: Source,\n fragments: Fragments,\n ): CustomerAccountDocument<\n InferResult<DocumentSource>,\n InferVariables<DocumentSource>,\n DocumentSource\n >;\n} & CustomerAccountTadaGql;\n\n/**\n * Creates a branded {@link CustomerAccountDocument} from a GraphQL source\n * string. This is a regular function call, not a tagged template literal.\n *\n * The returned document is branded with a private Symbol that\n * `CustomerAccountClient.graphql()` validates at runtime — passing a plain\n * object with a `source` property will throw a `TypeError`.\n *\n * An optional second argument accepts an array of fragment documents. Fragments\n * are deduplicated by source string identity (`Set` check, not by fragment\n * name) and appended to the operation source.\n *\n * @example\n * ```ts\n * import { gql } from \"@shopify/hydrogen/customer-account\";\n *\n * const CUSTOMER_QUERY = gql(`\n * query CustomerDetails {\n * customer {\n * firstName\n * lastName\n * emailAddress { emailAddress }\n * }\n * }\n * `);\n * ```\n *\n * @example\n * ```ts\n * const ORDER_FIELDS = gql(`\n * fragment OrderFields on Order {\n * id\n * totalPrice { amount currencyCode }\n * }\n * `);\n *\n * const ORDERS_QUERY = gql(`\n * query CustomerOrders {\n * customer {\n * orders(first: 10) {\n * nodes { ...OrderFields }\n * }\n * }\n * }\n * `, [ORDER_FIELDS]);\n * ```\n */\n// oxlint-disable-next-line typescript-eslint/consistent-type-assertions -- gql.tada adds phantom helper properties to the function type that are not used at runtime.\nexport const gql = ((source: string, fragments?: readonly CustomerAccountDocument[]) => {\n let query = source;\n\n if (fragments) {\n const seen = new Set<string>();\n for (const fragment of fragments) {\n assertCustomerAccountDocument(fragment);\n if (!seen.has(fragment.source)) {\n seen.add(fragment.source);\n query += \"\\n\" + fragment.source;\n }\n }\n }\n\n const document = {\n [CUSTOMER_ACCOUNT_DOCUMENT]: true,\n source: query,\n variableNames: getVariableNames(query),\n } satisfies CustomerAccountDocumentValue;\n return document;\n}) as unknown as CustomerAccountGql;\n\nexport function isCustomerAccountDocument(value: unknown): value is CustomerAccountDocumentValue {\n if (!isObjectRecord(value)) return false;\n return value[CUSTOMER_ACCOUNT_DOCUMENT] === true && typeof value.source === \"string\";\n}\n\nexport function assertCustomerAccountDocument(\n value: unknown,\n): asserts value is CustomerAccountDocumentValue {\n if (!isCustomerAccountDocument(value)) {\n throw new TypeError(\"Expected a Customer Account API document returned by CAAPI.gql().\");\n }\n}\n\nfunction getVariableNames(source: string): ReadonlySet<string> {\n const names = new Set<string>();\n for (const match of source.matchAll(VARIABLE_DEFINITION_RE)) {\n names.add(match[1]);\n }\n return names;\n}\n"],"mappings":";;;AAYA,MAAM,4BAA4B,OAAO,0BAA0B;AACnE,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6H/B,MAAa,QAAQ,QAAgB,cAAmD;CACtF,IAAI,QAAQ;AAEZ,KAAI,WAAW;EACb,MAAM,uBAAO,IAAI,KAAa;AAC9B,OAAK,MAAM,YAAY,WAAW;AAChC,iCAA8B,SAAS;AACvC,OAAI,CAAC,KAAK,IAAI,SAAS,OAAO,EAAE;AAC9B,SAAK,IAAI,SAAS,OAAO;AACzB,aAAS,OAAO,SAAS;;;;AAU/B,QAAO;GAJJ,4BAA4B;EAC7B,QAAQ;EACR,eAAe,iBAAiB,MAAM;EAEzB;;AAGjB,SAAgB,0BAA0B,OAAuD;AAC/F,KAAI,CAAC,eAAe,MAAM,CAAE,QAAO;AACnC,QAAO,MAAM,+BAA+B,QAAQ,OAAO,MAAM,WAAW;;AAG9E,SAAgB,8BACd,OAC+C;AAC/C,KAAI,CAAC,0BAA0B,MAAM,CACnC,OAAM,IAAI,UAAU,oEAAoE;;AAI5F,SAAS,iBAAiB,QAAqC;CAC7D,MAAM,wBAAQ,IAAI,KAAa;AAC/B,MAAK,MAAM,SAAS,OAAO,SAAS,uBAAuB,CACzD,OAAM,IAAI,MAAM,GAAG;AAErB,QAAO"}
1
+ {"version":3,"file":"graphql.mjs","names":[],"sources":["../../src/customer-account/graphql.ts"],"sourcesContent":["import type { DocumentDecoration, initGraphQLTada as InitGraphQLTada } from \"gql.tada\";\n\nimport { isObjectRecord } from \"../core/utils/record\";\nimport type { introspection } from \"../graphql/generated/customer-account-graphql-env\";\nimport type { CustomerAccountScalars } from \"../graphql/scalars\";\nimport type { InferResult, InferVariables } from \"./type-resolver\";\n\ntype CustomerAccountTadaGql = InitGraphQLTada<{\n introspection: introspection;\n scalars: CustomerAccountScalars;\n}>;\n\nconst CUSTOMER_ACCOUNT_DOCUMENT = Symbol(\"CustomerAccountDocument\");\nconst VARIABLE_DEFINITION_RE = /\\$([_A-Za-z][_0-9A-Za-z]*)\\s*:/g;\n\n/**\n * A Customer Account API query or mutation that `gql` from `@shopify/hydrogen/customer-account` returns. TypeScript infers the result and variables types from the document's GraphQL source.\n *\n * Create documents only with the Customer Account `gql` function. The client throws a `TypeError` for any other object.\n */\nexport type CustomerAccountDocument<\n Result = unknown,\n Variables = never,\n Source extends string = string,\n> = DocumentDecoration<Result, Variables> & {\n readonly [CUSTOMER_ACCOUNT_DOCUMENT]: true;\n readonly source: Source;\n};\n\n/** Any Customer Account API document. Use the type as a constraint when a function accepts any document. */\nexport type AnyCustomerAccountDocument = CustomerAccountDocument<unknown, never, string>;\n\n/** Extracts the source string literal type from a Customer Account document. */\nexport type SourceOf<Doc> = Doc extends { readonly source: infer Source extends string }\n ? Source\n : never;\n\n/**\n * Joins the source strings of a tuple of fragment documents with newlines at the type level. An empty tuple produces `\"\"`.\n */\nexport type FragmentSources<Fragments extends readonly AnyCustomerAccountDocument[]> =\n Fragments extends readonly []\n ? \"\"\n : Fragments extends readonly [infer Only extends AnyCustomerAccountDocument]\n ? SourceOf<Only>\n : Fragments extends readonly [\n infer First extends AnyCustomerAccountDocument,\n ...infer Rest extends readonly AnyCustomerAccountDocument[],\n ]\n ? `${SourceOf<First>}\\n${FragmentSources<Rest>}`\n : string;\n\n/**\n * Combines an operation source with the sources of its fragments at the type level. With no fragments, the result is the operation source.\n *\n * @publicDocs\n */\nexport type ComposedSource<\n Source extends string,\n Fragments extends readonly AnyCustomerAccountDocument[],\n> = FragmentSources<Fragments> extends \"\" ? Source : `${Source}\\n${FragmentSources<Fragments>}`;\n\ntype CustomerAccountDocumentValue = AnyCustomerAccountDocument & {\n readonly variableNames: ReadonlySet<string>;\n};\n\ntype CustomerAccountGql = {\n <const Source extends string>(\n source: Source,\n ): CustomerAccountDocument<InferResult<Source>, InferVariables<Source>, Source>;\n <\n const Source extends string,\n const Fragments extends readonly AnyCustomerAccountDocument[],\n const DocumentSource extends string = ComposedSource<Source, Fragments>,\n >(\n source: Source,\n fragments: Fragments,\n ): CustomerAccountDocument<\n InferResult<DocumentSource>,\n InferVariables<DocumentSource>,\n DocumentSource\n >;\n} & CustomerAccountTadaGql;\n\n/**\n * Creates a typed Customer Account API query or mutation from a GraphQL source string. Pass the document to the Customer Account API client. Call `gql` as a regular function. Tagged template syntax doesn't work.\n *\n * Pass an array of fragment documents as the second argument to append the fragments to the operation. Each fragment must come from this `gql` function, or the call throws a `TypeError`.\n *\n * @example\n * ```ts\n * import { gql } from \"@shopify/hydrogen/customer-account\";\n *\n * const CUSTOMER_QUERY = gql(`\n * query CustomerDetails {\n * customer {\n * firstName\n * lastName\n * emailAddress { emailAddress }\n * }\n * }\n * `);\n * ```\n *\n * @example\n * ```ts\n * const ORDER_FIELDS = gql(`\n * fragment OrderFields on Order {\n * id\n * totalPrice { amount currencyCode }\n * }\n * `);\n *\n * const ORDERS_QUERY = gql(`\n * query CustomerOrders {\n * customer {\n * orders(first: 10) {\n * nodes { ...OrderFields }\n * }\n * }\n * }\n * `, [ORDER_FIELDS]);\n * ```\n * @publicDocs\n */\n// oxlint-disable-next-line typescript-eslint/consistent-type-assertions -- gql.tada adds phantom helper properties to the function type that are not used at runtime.\nexport const gql = ((source: string, fragments?: readonly CustomerAccountDocument[]) => {\n let query = source;\n\n if (fragments) {\n const seen = new Set<string>();\n for (const fragment of fragments) {\n assertCustomerAccountDocument(fragment);\n if (!seen.has(fragment.source)) {\n seen.add(fragment.source);\n query += \"\\n\" + fragment.source;\n }\n }\n }\n\n const document = {\n [CUSTOMER_ACCOUNT_DOCUMENT]: true,\n source: query,\n variableNames: getVariableNames(query),\n } satisfies CustomerAccountDocumentValue;\n return document;\n}) as unknown as CustomerAccountGql;\n\nexport function isCustomerAccountDocument(value: unknown): value is CustomerAccountDocumentValue {\n if (!isObjectRecord(value)) return false;\n return value[CUSTOMER_ACCOUNT_DOCUMENT] === true && typeof value.source === \"string\";\n}\n\nexport function assertCustomerAccountDocument(\n value: unknown,\n): asserts value is CustomerAccountDocumentValue {\n if (!isCustomerAccountDocument(value)) {\n throw new TypeError(\"Expected a Customer Account API document returned by CAAPI.gql().\");\n }\n}\n\nfunction getVariableNames(source: string): ReadonlySet<string> {\n const names = new Set<string>();\n for (const match of source.matchAll(VARIABLE_DEFINITION_RE)) {\n names.add(match[1]);\n }\n return names;\n}\n\n/**\n * Creates a typed Customer Account API query or mutation from a GraphQL source string. Pass the document to the Customer Account API client. Call `gql` as a regular function.\n *\n * Pass an array of fragment documents as the second argument to append the fragments to the operation. Each fragment must come from this `gql` function, or the call throws a `TypeError`.\n *\n * To validate documents, run `hydrogen gql check` in your `typecheck` script with the `@shopify/hydrogen/ts-plugin` setup. Framework typecheck commands don't validate the documents.\n *\n * @publicDocs\n */\nexport type CustomerAccountGqlForDocs =\n /**\n * @param source - The GraphQL source of an operation or a fragment.\n * @param fragments - The fragment documents that the operation uses.\n * @returns A typed document to pass to the Customer Account API client.\n */\n (source: string, fragments?: readonly AnyCustomerAccountDocument[]) => AnyCustomerAccountDocument;\n"],"mappings":";;;AAYA,MAAM,4BAA4B,OAAO,0BAA0B;AACnE,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiH/B,MAAa,QAAQ,QAAgB,cAAmD;CACtF,IAAI,QAAQ;AAEZ,KAAI,WAAW;EACb,MAAM,uBAAO,IAAI,KAAa;AAC9B,OAAK,MAAM,YAAY,WAAW;AAChC,iCAA8B,SAAS;AACvC,OAAI,CAAC,KAAK,IAAI,SAAS,OAAO,EAAE;AAC9B,SAAK,IAAI,SAAS,OAAO;AACzB,aAAS,OAAO,SAAS;;;;AAU/B,QAAO;GAJJ,4BAA4B;EAC7B,QAAQ;EACR,eAAe,iBAAiB,MAAM;EAEzB;;AAGjB,SAAgB,0BAA0B,OAAuD;AAC/F,KAAI,CAAC,eAAe,MAAM,CAAE,QAAO;AACnC,QAAO,MAAM,+BAA+B,QAAQ,OAAO,MAAM,WAAW;;AAG9E,SAAgB,8BACd,OAC+C;AAC/C,KAAI,CAAC,0BAA0B,MAAM,CACnC,OAAM,IAAI,UAAU,oEAAoE;;AAI5F,SAAS,iBAAiB,QAAqC;CAC7D,MAAM,wBAAQ,IAAI,KAAa;AAC/B,MAAK,MAAM,SAAS,OAAO,SAAS,uBAAuB,CACzD,OAAM,IAAI,MAAM,GAAG;AAErB,QAAO"}