@shopify/hydrogen 0.22.1 → 0.23.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 (468) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/dist/esnext/components/AddToCartButton/AddToCartButton.client.js +5 -5
  3. package/dist/esnext/components/CartLines/{CartLines.d.ts → CartLines.client.d.ts} +0 -0
  4. package/dist/esnext/components/CartLines/{CartLines.js → CartLines.client.js} +0 -0
  5. package/dist/esnext/components/CartLines/index.d.ts +1 -1
  6. package/dist/esnext/components/CartLines/index.js +1 -1
  7. package/dist/esnext/components/DevTools.client.js +1 -1
  8. package/dist/esnext/components/Image/Image.d.ts +8 -0
  9. package/dist/esnext/components/Image/Image.js +58 -10
  10. package/dist/esnext/components/Link/Link.client.d.ts +2 -0
  11. package/dist/esnext/components/Link/Link.client.js +7 -4
  12. package/dist/esnext/components/LocalizationProvider/LocalizationProvider.server.js +1 -1
  13. package/dist/esnext/components/ProductOptionsProvider/ProductOptionsProvider.client.d.ts +21 -0
  14. package/dist/esnext/components/ProductOptionsProvider/ProductOptionsProvider.client.js +140 -0
  15. package/dist/esnext/components/ProductOptionsProvider/context.d.ts +2 -0
  16. package/dist/esnext/components/{ProductProvider → ProductOptionsProvider}/context.js +0 -1
  17. package/dist/esnext/components/ProductOptionsProvider/index.d.ts +2 -0
  18. package/dist/esnext/components/ProductOptionsProvider/index.js +2 -0
  19. package/dist/esnext/components/ProductPrice/ProductPrice.client.d.ts +5 -2
  20. package/dist/esnext/components/ProductPrice/ProductPrice.client.js +10 -12
  21. package/dist/esnext/components/index.d.ts +1 -1
  22. package/dist/esnext/components/index.js +1 -1
  23. package/dist/esnext/entry-client.js +106 -6
  24. package/dist/esnext/entry-server.d.ts +2 -15
  25. package/dist/esnext/entry-server.js +245 -321
  26. package/dist/esnext/foundation/Analytics/Analytics.client.js +15 -13
  27. package/dist/esnext/foundation/Analytics/Analytics.server.js +27 -20
  28. package/dist/esnext/foundation/Analytics/ClientAnalytics.d.ts +4 -2
  29. package/dist/esnext/foundation/Analytics/ClientAnalytics.js +15 -13
  30. package/dist/esnext/foundation/Analytics/ServerAnalyticsRoute.server.js +7 -5
  31. package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/ServerAnalyticsConnector.server.d.ts +1 -0
  32. package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/{PerformanceMetrics.server.js → ServerAnalyticsConnector.server.js} +7 -6
  33. package/dist/esnext/foundation/Analytics/connectors/Shopify/ServerAnalyticsConnector.server.d.ts +1 -0
  34. package/dist/esnext/foundation/Analytics/connectors/Shopify/ServerAnalyticsConnector.server.js +19 -0
  35. package/dist/esnext/foundation/Analytics/connectors/Shopify/ShopifyAnalytics.client.d.ts +3 -0
  36. package/dist/esnext/foundation/Analytics/connectors/Shopify/ShopifyAnalytics.client.js +190 -0
  37. package/dist/esnext/foundation/Analytics/connectors/Shopify/ShopifyAnalytics.server.d.ts +3 -0
  38. package/dist/esnext/foundation/Analytics/connectors/Shopify/ShopifyAnalytics.server.js +24 -0
  39. package/dist/esnext/foundation/Analytics/connectors/Shopify/const.d.ts +28 -0
  40. package/dist/esnext/foundation/Analytics/connectors/Shopify/const.js +51 -0
  41. package/dist/esnext/foundation/Analytics/connectors/Shopify/utils.d.ts +3 -0
  42. package/dist/esnext/foundation/Analytics/connectors/Shopify/utils.js +56 -0
  43. package/dist/esnext/foundation/Analytics/hook.js +4 -2
  44. package/dist/esnext/foundation/Analytics/utils.d.ts +2 -0
  45. package/dist/esnext/foundation/Analytics/utils.js +21 -0
  46. package/dist/{node/framework → esnext/foundation/Cache}/cache-sub-request.d.ts +1 -1
  47. package/dist/esnext/{framework → foundation/Cache}/cache-sub-request.js +3 -3
  48. package/dist/esnext/{framework → foundation/Cache}/cache.d.ts +1 -1
  49. package/dist/esnext/{framework → foundation/Cache}/cache.js +3 -3
  50. package/dist/{node/framework/CachingStrategy → esnext/foundation/Cache/strategies}/index.d.ts +1 -1
  51. package/dist/esnext/{framework/CachingStrategy → foundation/Cache/strategies}/index.js +0 -0
  52. package/dist/esnext/foundation/Cookie/Cookie.d.ts +3 -3
  53. package/dist/{node/framework/Hydration → esnext/foundation/Html}/Html.d.ts +3 -1
  54. package/dist/esnext/{framework/Hydration → foundation/Html}/Html.js +15 -2
  55. package/dist/{node/framework/Hydration/ServerComponentRequest.server.d.ts → esnext/foundation/HydrogenRequest/HydrogenRequest.server.d.ts} +7 -3
  56. package/dist/esnext/{framework/Hydration/ServerComponentRequest.server.js → foundation/HydrogenRequest/HydrogenRequest.server.js} +1 -1
  57. package/dist/{node/framework/Hydration/ServerComponentResponse.server.d.ts → esnext/foundation/HydrogenResponse/HydrogenResponse.server.d.ts} +7 -10
  58. package/dist/esnext/{framework/Hydration/ServerComponentResponse.server.js → foundation/HydrogenResponse/HydrogenResponse.server.js} +19 -15
  59. package/dist/esnext/foundation/Router/BrowserRouter.client.js +16 -9
  60. package/dist/esnext/foundation/ServerPropsProvider/ServerPropsProvider.d.ts +2 -1
  61. package/dist/esnext/foundation/ServerPropsProvider/ServerPropsProvider.js +1 -1
  62. package/dist/esnext/foundation/ServerRequestProvider/ServerRequestProvider.d.ts +4 -4
  63. package/dist/esnext/foundation/ServerRequestProvider/ServerRequestProvider.js +2 -2
  64. package/dist/esnext/foundation/ServerStateProvider/ServerStateProvider.d.ts +1 -1
  65. package/dist/esnext/foundation/ServerStateProvider/ServerStateProvider.js +1 -1
  66. package/dist/esnext/foundation/ShopifyProvider/ShopifyProvider.server.js +1 -0
  67. package/dist/esnext/foundation/index.d.ts +1 -1
  68. package/dist/esnext/foundation/index.js +1 -1
  69. package/dist/esnext/foundation/runtime.d.ts +2 -0
  70. package/dist/esnext/foundation/runtime.js +6 -0
  71. package/dist/esnext/foundation/session/session.d.ts +3 -3
  72. package/dist/esnext/foundation/ssr-interop.d.ts +2 -2
  73. package/dist/esnext/foundation/useNavigate/useNavigate.d.ts +2 -0
  74. package/dist/esnext/foundation/useNavigate/useNavigate.js +11 -4
  75. package/dist/esnext/foundation/useQuery/hooks.js +9 -6
  76. package/dist/esnext/framework/Hydration/rsc.js +2 -0
  77. package/dist/esnext/framework/plugin.js +2 -0
  78. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.js +5 -2
  79. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-middleware.js +1 -1
  80. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-rsc.js +4 -12
  81. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-suppress-warnings.d.ts +3 -0
  82. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-suppress-warnings.js +19 -0
  83. package/dist/esnext/hooks/useParsedMetafields/useParsedMetafields.d.ts +2 -2
  84. package/dist/esnext/hooks/useProductOptions/types.d.ts +16 -14
  85. package/dist/esnext/hooks/useProductOptions/useProductOptions.client.d.ts +1 -15
  86. package/dist/esnext/hooks/useProductOptions/useProductOptions.client.js +8 -107
  87. package/dist/esnext/hooks/useShopQuery/hooks.js +12 -6
  88. package/dist/esnext/index.d.ts +6 -3
  89. package/dist/esnext/index.js +6 -3
  90. package/dist/esnext/streaming.server.d.ts +0 -1
  91. package/dist/esnext/streaming.server.js +0 -4
  92. package/dist/esnext/types.d.ts +32 -23
  93. package/dist/esnext/utilities/apiRoutes.d.ts +2 -2
  94. package/dist/esnext/utilities/graphql-tracker.js +1 -1
  95. package/dist/esnext/utilities/index.d.ts +1 -1
  96. package/dist/esnext/utilities/index.js +1 -1
  97. package/dist/esnext/utilities/isBrowser/index.d.ts +1 -0
  98. package/dist/esnext/utilities/isBrowser/index.js +1 -0
  99. package/dist/esnext/utilities/isBrowser/isBrowser.d.ts +4 -0
  100. package/dist/esnext/utilities/isBrowser/isBrowser.js +6 -0
  101. package/dist/esnext/utilities/isServer/isServer.js +2 -2
  102. package/dist/esnext/utilities/log/index.d.ts +1 -1
  103. package/dist/esnext/utilities/log/index.js +1 -1
  104. package/dist/esnext/utilities/log/log-cache-header.d.ts +4 -4
  105. package/dist/esnext/utilities/log/log-query-timeline.d.ts +3 -3
  106. package/dist/esnext/utilities/log/log.d.ts +17 -11
  107. package/dist/esnext/utilities/log/log.js +29 -20
  108. package/dist/esnext/version.d.ts +1 -1
  109. package/dist/esnext/version.js +1 -1
  110. package/dist/node/client.d.ts +16 -0
  111. package/dist/node/client.js +43 -0
  112. package/dist/node/components/AddToCartButton/AddToCartButton.client.d.ts +23 -0
  113. package/dist/node/components/AddToCartButton/AddToCartButton.client.js +74 -0
  114. package/dist/node/components/AddToCartButton/index.d.ts +1 -0
  115. package/dist/node/components/AddToCartButton/index.js +5 -0
  116. package/dist/node/components/BuyNowButton/BuyNowButton.client.d.ts +18 -0
  117. package/dist/node/components/BuyNowButton/BuyNowButton.client.js +53 -0
  118. package/dist/node/components/BuyNowButton/index.d.ts +1 -0
  119. package/dist/node/components/BuyNowButton/index.js +5 -0
  120. package/dist/node/components/CartCheckoutButton/CartCheckoutButton.client.d.ts +11 -0
  121. package/dist/node/components/CartCheckoutButton/CartCheckoutButton.client.js +44 -0
  122. package/dist/node/components/CartCheckoutButton/index.d.ts +1 -0
  123. package/dist/node/components/CartCheckoutButton/index.js +5 -0
  124. package/dist/node/components/CartEstimatedCost/CartEstimatedCost.client.d.ts +14 -0
  125. package/dist/node/components/CartEstimatedCost/CartEstimatedCost.client.js +36 -0
  126. package/dist/node/components/CartEstimatedCost/index.d.ts +1 -0
  127. package/dist/node/components/CartEstimatedCost/index.js +5 -0
  128. package/dist/node/components/CartLineImage/CartLineImage.client.d.ts +9 -0
  129. package/dist/node/components/CartLineImage/CartLineImage.client.js +18 -0
  130. package/dist/node/components/CartLineImage/index.d.ts +1 -0
  131. package/dist/node/components/CartLineImage/index.js +5 -0
  132. package/dist/node/components/CartLinePrice/CartLinePrice.client.d.ts +12 -0
  133. package/dist/node/components/CartLinePrice/CartLinePrice.client.js +28 -0
  134. package/dist/node/components/CartLinePrice/index.d.ts +1 -0
  135. package/dist/node/components/CartLinePrice/index.js +5 -0
  136. package/dist/node/components/CartLineProductTitle/CartLineProductTitle.client.d.ts +8 -0
  137. package/dist/node/components/CartLineProductTitle/CartLineProductTitle.client.js +19 -0
  138. package/dist/node/components/CartLineProductTitle/index.d.ts +1 -0
  139. package/dist/node/components/CartLineProductTitle/index.js +5 -0
  140. package/dist/node/components/CartLineProvider/CartLineProvider.client.d.ts +11 -0
  141. package/dist/node/components/CartLineProvider/CartLineProvider.client.js +15 -0
  142. package/dist/node/components/CartLineProvider/context.d.ts +26 -0
  143. package/dist/node/components/CartLineProvider/context.js +5 -0
  144. package/dist/node/components/CartLineProvider/index.d.ts +2 -0
  145. package/dist/node/components/CartLineProvider/index.js +7 -0
  146. package/dist/node/components/CartLineQuantity/CartLineQuantity.client.d.ts +8 -0
  147. package/dist/node/components/CartLineQuantity/CartLineQuantity.client.js +19 -0
  148. package/dist/node/components/CartLineQuantity/index.d.ts +1 -0
  149. package/dist/node/components/CartLineQuantity/index.js +5 -0
  150. package/dist/node/components/CartLineQuantityAdjustButton/CartLineQuantityAdjustButton.d.ts +14 -0
  151. package/dist/node/components/CartLineQuantityAdjustButton/CartLineQuantityAdjustButton.js +31 -0
  152. package/dist/node/components/CartLineQuantityAdjustButton/index.d.ts +1 -0
  153. package/dist/node/components/CartLineQuantityAdjustButton/index.js +5 -0
  154. package/dist/node/components/CartLines/CartLines.client.d.ts +15 -0
  155. package/dist/node/components/CartLines/CartLines.client.js +44 -0
  156. package/dist/node/components/CartLines/index.d.ts +1 -0
  157. package/dist/node/components/CartLines/index.js +5 -0
  158. package/dist/node/components/CartProvider/CartProvider.client.d.ts +41 -0
  159. package/dist/node/components/CartProvider/CartProvider.client.js +550 -0
  160. package/dist/node/components/CartProvider/cart-queries.d.ts +10 -0
  161. package/dist/node/components/CartProvider/cart-queries.js +203 -0
  162. package/dist/node/components/CartProvider/constants.d.ts +2 -0
  163. package/dist/node/components/CartProvider/constants.js +5 -0
  164. package/dist/node/components/CartProvider/context.d.ts +2 -0
  165. package/dist/node/components/CartProvider/context.js +5 -0
  166. package/dist/node/components/CartProvider/graphql/CartAttributesUpdateMutation.d.ts +86 -0
  167. package/dist/node/components/CartProvider/graphql/CartAttributesUpdateMutation.js +2 -0
  168. package/dist/node/components/CartProvider/graphql/CartBuyerIdentityUpdateMutation.d.ts +86 -0
  169. package/dist/node/components/CartProvider/graphql/CartBuyerIdentityUpdateMutation.js +2 -0
  170. package/dist/node/components/CartProvider/graphql/CartCreateMutation.d.ts +85 -0
  171. package/dist/node/components/CartProvider/graphql/CartCreateMutation.js +2 -0
  172. package/dist/node/components/CartProvider/graphql/CartDiscountCodesUpdateMutation.d.ts +86 -0
  173. package/dist/node/components/CartProvider/graphql/CartDiscountCodesUpdateMutation.js +2 -0
  174. package/dist/node/components/CartProvider/graphql/CartFragment.d.ts +72 -0
  175. package/dist/node/components/CartProvider/graphql/CartFragment.js +2 -0
  176. package/dist/node/components/CartProvider/graphql/CartLineAddMutation.d.ts +86 -0
  177. package/dist/node/components/CartProvider/graphql/CartLineAddMutation.js +2 -0
  178. package/dist/node/components/CartProvider/graphql/CartLineRemoveMutation.d.ts +86 -0
  179. package/dist/node/components/CartProvider/graphql/CartLineRemoveMutation.js +2 -0
  180. package/dist/node/components/CartProvider/graphql/CartLineUpdateMutation.d.ts +86 -0
  181. package/dist/node/components/CartProvider/graphql/CartLineUpdateMutation.js +2 -0
  182. package/dist/node/components/CartProvider/graphql/CartNoteUpdateMutation.d.ts +86 -0
  183. package/dist/node/components/CartProvider/graphql/CartNoteUpdateMutation.js +2 -0
  184. package/dist/node/components/CartProvider/graphql/CartQuery.d.ts +81 -0
  185. package/dist/node/components/CartProvider/graphql/CartQuery.js +2 -0
  186. package/dist/node/components/CartProvider/hooks.client.d.ts +15 -0
  187. package/dist/node/components/CartProvider/hooks.client.js +90 -0
  188. package/dist/node/components/CartProvider/index.d.ts +4 -0
  189. package/dist/node/components/CartProvider/index.js +10 -0
  190. package/dist/node/components/CartProvider/types.d.ts +102 -0
  191. package/dist/node/components/CartProvider/types.js +2 -0
  192. package/dist/node/components/CartShopPayButton/CartShopPayButton.client.d.ts +9 -0
  193. package/dist/node/components/CartShopPayButton/CartShopPayButton.client.js +46 -0
  194. package/dist/node/components/CartShopPayButton/index.d.ts +1 -0
  195. package/dist/node/components/CartShopPayButton/index.js +5 -0
  196. package/dist/node/components/ExternalVideo/ExternalVideo.d.ts +21 -0
  197. package/dist/node/components/ExternalVideo/ExternalVideo.js +21 -0
  198. package/dist/node/components/ExternalVideo/index.d.ts +1 -0
  199. package/dist/node/components/ExternalVideo/index.js +5 -0
  200. package/dist/node/components/Image/Image.d.ts +8 -0
  201. package/dist/node/components/Image/Image.js +57 -9
  202. package/dist/node/components/Link/Link.client.d.ts +25 -0
  203. package/dist/node/components/Link/Link.client.js +165 -0
  204. package/dist/node/components/Link/index.d.ts +1 -0
  205. package/dist/node/components/Link/index.js +5 -0
  206. package/dist/node/components/LocalizationProvider/LocalizationClientProvider.client.d.ts +6 -0
  207. package/dist/node/components/LocalizationProvider/LocalizationClientProvider.client.js +11 -0
  208. package/dist/node/components/LocalizationProvider/LocalizationContext.client.d.ts +6 -0
  209. package/dist/node/components/LocalizationProvider/LocalizationContext.client.js +5 -0
  210. package/dist/node/components/LocalizationProvider/LocalizationProvider.server.d.ts +33 -0
  211. package/dist/node/components/LocalizationProvider/LocalizationProvider.server.js +51 -0
  212. package/dist/node/components/MediaFile/MediaFile.d.ts +19 -0
  213. package/dist/node/components/MediaFile/MediaFile.js +39 -0
  214. package/dist/node/components/MediaFile/index.d.ts +1 -0
  215. package/dist/node/components/MediaFile/index.js +5 -0
  216. package/dist/node/components/Metafield/Metafield.client.d.ts +21 -0
  217. package/dist/node/components/Metafield/Metafield.client.js +75 -0
  218. package/dist/node/components/Metafield/index.d.ts +2 -0
  219. package/dist/node/components/Metafield/index.js +5 -0
  220. package/dist/node/components/Metafield/types.d.ts +4 -0
  221. package/dist/node/components/Metafield/types.js +2 -0
  222. package/dist/node/components/ModelViewer/ModelViewer.client.d.ts +128 -0
  223. package/dist/node/components/ModelViewer/ModelViewer.client.js +132 -0
  224. package/dist/node/components/ModelViewer/index.d.ts +1 -0
  225. package/dist/node/components/ModelViewer/index.js +5 -0
  226. package/dist/node/components/Money/Money.client.d.ts +25 -0
  227. package/dist/node/components/Money/Money.client.js +46 -0
  228. package/dist/node/components/Money/index.d.ts +1 -0
  229. package/dist/node/components/Money/index.js +5 -0
  230. package/dist/node/components/ProductOptionsProvider/ProductOptionsProvider.client.d.ts +21 -0
  231. package/dist/node/components/ProductOptionsProvider/ProductOptionsProvider.client.js +167 -0
  232. package/dist/node/components/ProductOptionsProvider/context.d.ts +2 -0
  233. package/dist/node/components/ProductOptionsProvider/context.js +5 -0
  234. package/dist/node/components/ProductOptionsProvider/index.d.ts +2 -0
  235. package/dist/node/components/ProductOptionsProvider/index.js +7 -0
  236. package/dist/node/components/ProductPrice/ProductPrice.client.d.ts +18 -0
  237. package/dist/node/components/ProductPrice/ProductPrice.client.js +61 -0
  238. package/dist/node/components/ProductPrice/index.d.ts +1 -0
  239. package/dist/node/components/ProductPrice/index.js +5 -0
  240. package/dist/node/components/Seo/CollectionSeo.client.d.ts +3 -0
  241. package/dist/node/components/Seo/CollectionSeo.client.js +22 -0
  242. package/dist/node/components/Seo/DefaultPageSeo.client.d.ts +3 -0
  243. package/dist/node/components/Seo/DefaultPageSeo.client.js +25 -0
  244. package/dist/node/components/Seo/DescriptionSeo.client.d.ts +4 -0
  245. package/dist/node/components/Seo/DescriptionSeo.client.js +17 -0
  246. package/dist/node/components/Seo/HomePageSeo.client.d.ts +2 -0
  247. package/dist/node/components/Seo/HomePageSeo.client.js +32 -0
  248. package/dist/node/components/Seo/ImageSeo.client.d.ts +3 -0
  249. package/dist/node/components/Seo/ImageSeo.client.js +17 -0
  250. package/dist/node/components/Seo/NoIndexSeo.client.d.ts +3 -0
  251. package/dist/node/components/Seo/NoIndexSeo.client.js +17 -0
  252. package/dist/node/components/Seo/PageSeo.client.d.ts +3 -0
  253. package/dist/node/components/Seo/PageSeo.client.js +20 -0
  254. package/dist/node/components/Seo/ProductSeo.client.d.ts +5 -0
  255. package/dist/node/components/Seo/ProductSeo.client.js +70 -0
  256. package/dist/node/components/Seo/Seo.client.d.ts +30 -0
  257. package/dist/node/components/Seo/Seo.client.js +38 -0
  258. package/dist/node/components/Seo/TitleSeo.client.d.ts +3 -0
  259. package/dist/node/components/Seo/TitleSeo.client.js +17 -0
  260. package/dist/node/components/Seo/TwitterSeo.client.d.ts +2 -0
  261. package/dist/node/components/Seo/TwitterSeo.client.js +16 -0
  262. package/dist/node/components/Seo/index.d.ts +1 -0
  263. package/dist/node/components/Seo/index.js +5 -0
  264. package/dist/node/components/Seo/seo-types.d.ts +17 -0
  265. package/dist/node/components/Seo/seo-types.js +2 -0
  266. package/dist/node/components/ShopPayButton/ShopPayButton.client.d.ts +38 -0
  267. package/dist/node/components/ShopPayButton/ShopPayButton.client.js +60 -0
  268. package/dist/node/components/ShopPayButton/index.d.ts +1 -0
  269. package/dist/node/components/ShopPayButton/index.js +5 -0
  270. package/dist/node/components/Video/Video.d.ts +14 -0
  271. package/dist/node/components/Video/Video.js +31 -0
  272. package/dist/node/components/Video/index.d.ts +1 -0
  273. package/dist/node/components/Video/index.js +5 -0
  274. package/dist/node/components/index.d.ts +28 -0
  275. package/dist/node/components/index.js +59 -0
  276. package/dist/node/components/types.d.ts +71 -0
  277. package/dist/node/components/types.js +11 -0
  278. package/dist/node/entry-server.d.ts +2 -15
  279. package/dist/node/entry-server.js +244 -320
  280. package/dist/node/foundation/Analytics/Analytics.client.js +15 -13
  281. package/dist/node/foundation/Analytics/Analytics.server.js +27 -20
  282. package/dist/node/foundation/Analytics/ClientAnalytics.d.ts +4 -2
  283. package/dist/node/foundation/Analytics/ClientAnalytics.js +14 -12
  284. package/dist/node/foundation/Analytics/ServerAnalyticsRoute.server.js +7 -5
  285. package/dist/node/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.client.d.ts +7 -0
  286. package/dist/node/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.client.js +68 -0
  287. package/dist/node/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetricsDebug.client.d.ts +1 -0
  288. package/dist/node/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetricsDebug.client.js +27 -0
  289. package/dist/node/foundation/Analytics/hook.js +4 -2
  290. package/dist/node/foundation/Analytics/index.d.ts +1 -0
  291. package/dist/node/foundation/Analytics/index.js +5 -0
  292. package/dist/node/foundation/Analytics/utils.d.ts +2 -0
  293. package/dist/node/foundation/Analytics/utils.js +24 -1
  294. package/dist/{esnext/framework → node/foundation/Cache}/cache-sub-request.d.ts +1 -1
  295. package/dist/node/{framework → foundation/Cache}/cache-sub-request.js +4 -4
  296. package/dist/node/{framework → foundation/Cache}/cache.d.ts +1 -1
  297. package/dist/node/{framework → foundation/Cache}/cache.js +5 -5
  298. package/dist/{esnext/framework/CachingStrategy → node/foundation/Cache/strategies}/index.d.ts +1 -1
  299. package/dist/node/{framework/CachingStrategy → foundation/Cache/strategies}/index.js +0 -0
  300. package/dist/node/foundation/Head/Head.client.d.ts +5 -0
  301. package/dist/node/foundation/Head/Head.client.js +17 -0
  302. package/dist/node/foundation/Head/index.d.ts +1 -0
  303. package/dist/node/foundation/Head/index.js +5 -0
  304. package/dist/{esnext/framework/Hydration → node/foundation/Html}/Html.d.ts +3 -1
  305. package/dist/node/{framework/Hydration → foundation/Html}/Html.js +15 -2
  306. package/dist/{esnext/framework/Hydration/ServerComponentRequest.server.d.ts → node/foundation/HydrogenRequest/HydrogenRequest.server.d.ts} +7 -3
  307. package/dist/node/{framework/Hydration/ServerComponentRequest.server.js → foundation/HydrogenRequest/HydrogenRequest.server.js} +3 -3
  308. package/dist/{esnext/framework/Hydration/ServerComponentResponse.server.d.ts → node/foundation/HydrogenResponse/HydrogenResponse.server.d.ts} +7 -10
  309. package/dist/node/{framework/Hydration/ServerComponentResponse.server.js → foundation/HydrogenResponse/HydrogenResponse.server.js} +23 -19
  310. package/dist/node/foundation/Router/BrowserRouter.client.js +16 -9
  311. package/dist/node/foundation/ServerPropsProvider/ServerPropsProvider.d.ts +2 -1
  312. package/dist/node/foundation/ServerPropsProvider/ServerPropsProvider.js +1 -1
  313. package/dist/node/foundation/ServerRequestProvider/ServerRequestProvider.d.ts +4 -4
  314. package/dist/node/foundation/ServerRequestProvider/ServerRequestProvider.js +2 -2
  315. package/dist/node/foundation/ShopifyProvider/ShopifyProvider.client.d.ts +7 -0
  316. package/dist/node/foundation/ShopifyProvider/ShopifyProvider.client.js +35 -0
  317. package/dist/node/foundation/ShopifyProvider/index.d.ts +1 -0
  318. package/dist/node/foundation/ShopifyProvider/index.js +5 -0
  319. package/dist/node/foundation/fetchSync/client/fetchSync.d.ts +10 -0
  320. package/dist/node/foundation/fetchSync/client/fetchSync.js +33 -0
  321. package/dist/node/foundation/fetchSync/server/fetchSync.d.ts +8 -0
  322. package/dist/node/foundation/fetchSync/server/fetchSync.js +33 -0
  323. package/dist/node/foundation/fetchSync/types.d.ts +5 -0
  324. package/dist/node/foundation/fetchSync/types.js +2 -0
  325. package/dist/node/foundation/index.d.ts +3 -0
  326. package/dist/node/foundation/index.js +10 -0
  327. package/dist/node/foundation/runtime.d.ts +2 -0
  328. package/dist/node/foundation/runtime.js +11 -0
  329. package/dist/node/foundation/session/session.d.ts +3 -3
  330. package/dist/node/foundation/ssr-interop.d.ts +2 -2
  331. package/dist/node/foundation/useNavigate/useNavigate.d.ts +2 -0
  332. package/dist/node/foundation/useNavigate/useNavigate.js +11 -4
  333. package/dist/node/foundation/useQuery/hooks.d.ts +36 -0
  334. package/dist/node/foundation/useQuery/hooks.js +104 -0
  335. package/dist/node/foundation/useRouteParams/RouteParamsProvider.client.d.ts +10 -0
  336. package/dist/node/foundation/useRouteParams/RouteParamsProvider.client.js +34 -0
  337. package/dist/node/foundation/useRouteParams/useRouteParams.d.ts +4 -0
  338. package/dist/node/foundation/useRouteParams/useRouteParams.js +13 -0
  339. package/dist/node/foundation/useServerProps/index.d.ts +1 -0
  340. package/dist/node/foundation/useServerProps/index.js +5 -0
  341. package/dist/node/foundation/useSession/useSession.d.ts +2 -0
  342. package/dist/node/foundation/useSession/useSession.js +12 -0
  343. package/dist/node/foundation/useShop/index.d.ts +1 -0
  344. package/dist/node/foundation/useShop/index.js +5 -0
  345. package/dist/node/foundation/useShop/use-shop.d.ts +6 -0
  346. package/dist/node/foundation/useShop/use-shop.js +18 -0
  347. package/dist/node/foundation/useUrl/index.d.ts +1 -0
  348. package/dist/node/foundation/useUrl/index.js +5 -0
  349. package/dist/node/foundation/useUrl/useUrl.d.ts +4 -0
  350. package/dist/node/foundation/useUrl/useUrl.js +32 -0
  351. package/dist/node/framework/Hydration/rsc.js +2 -0
  352. package/dist/node/framework/plugin.js +2 -0
  353. package/dist/node/framework/plugins/vite-plugin-hydrogen-config.js +5 -2
  354. package/dist/node/framework/plugins/vite-plugin-hydrogen-middleware.js +1 -1
  355. package/dist/node/framework/plugins/vite-plugin-hydrogen-rsc.js +4 -12
  356. package/dist/node/framework/plugins/vite-plugin-hydrogen-suppress-warnings.d.ts +3 -0
  357. package/dist/node/framework/plugins/vite-plugin-hydrogen-suppress-warnings.js +21 -0
  358. package/dist/node/hooks/index.d.ts +6 -0
  359. package/dist/node/hooks/index.js +28 -0
  360. package/dist/node/hooks/useCart/index.d.ts +1 -0
  361. package/dist/node/hooks/useCart/index.js +5 -0
  362. package/dist/node/hooks/useCart/useCart.d.ts +4 -0
  363. package/dist/node/hooks/useCart/useCart.js +19 -0
  364. package/dist/node/hooks/useCartLine/index.d.ts +1 -0
  365. package/dist/node/hooks/useCartLine/index.js +5 -0
  366. package/dist/node/hooks/useCartLine/useCartLine.d.ts +29 -0
  367. package/dist/node/hooks/useCartLine/useCartLine.js +16 -0
  368. package/dist/node/hooks/useCountry/index.d.ts +1 -0
  369. package/dist/node/hooks/useCountry/index.js +5 -0
  370. package/dist/node/hooks/useCountry/useCountry.d.ts +7 -0
  371. package/dist/node/hooks/useCountry/useCountry.js +21 -0
  372. package/dist/node/hooks/useLoadScript/index.d.ts +1 -0
  373. package/dist/node/hooks/useLoadScript/index.js +5 -0
  374. package/dist/node/hooks/useLoadScript/useLoadScript.client.d.ts +8 -0
  375. package/dist/node/hooks/useLoadScript/useLoadScript.client.js +27 -0
  376. package/dist/node/hooks/useMeasurement/hooks.d.ts +9 -0
  377. package/dist/node/hooks/useMeasurement/hooks.js +17 -0
  378. package/dist/node/hooks/useMeasurement/index.d.ts +1 -0
  379. package/dist/node/hooks/useMeasurement/index.js +5 -0
  380. package/dist/node/hooks/useMoney/hooks.d.ts +54 -0
  381. package/dist/node/hooks/useMoney/hooks.js +70 -0
  382. package/dist/node/hooks/useMoney/index.d.ts +1 -0
  383. package/dist/node/hooks/useMoney/index.js +5 -0
  384. package/dist/node/hooks/useParsedMetafields/index.d.ts +1 -0
  385. package/dist/node/hooks/useParsedMetafields/index.js +5 -0
  386. package/dist/node/hooks/useParsedMetafields/useParsedMetafields.d.ts +21 -0
  387. package/dist/node/hooks/useParsedMetafields/useParsedMetafields.js +25 -0
  388. package/dist/node/hooks/useProductOptions/helpers.d.ts +6 -0
  389. package/dist/node/hooks/useProductOptions/helpers.js +46 -0
  390. package/dist/node/hooks/useProductOptions/index.d.ts +2 -0
  391. package/dist/node/hooks/useProductOptions/index.js +20 -0
  392. package/dist/node/hooks/useProductOptions/types.d.ts +44 -0
  393. package/dist/node/hooks/useProductOptions/types.js +2 -0
  394. package/dist/node/hooks/useProductOptions/useProductOptions.client.d.ts +1 -0
  395. package/dist/node/hooks/useProductOptions/useProductOptions.client.js +13 -0
  396. package/dist/node/hooks/useShopQuery/hooks.d.ts +28 -0
  397. package/dist/node/hooks/useShopQuery/hooks.js +171 -0
  398. package/dist/node/hooks/useShopQuery/index.d.ts +1 -0
  399. package/dist/node/hooks/useShopQuery/index.js +5 -0
  400. package/dist/node/streaming.server.d.ts +0 -1
  401. package/dist/node/streaming.server.js +1 -6
  402. package/dist/node/types.d.ts +32 -23
  403. package/dist/node/utilities/apiRoutes.d.ts +2 -2
  404. package/dist/node/utilities/devtools.d.ts +11 -0
  405. package/dist/node/utilities/devtools.js +15 -0
  406. package/dist/node/utilities/graphql-tag.d.ts +1 -0
  407. package/dist/node/utilities/graphql-tag.js +10 -0
  408. package/dist/node/utilities/graphql-tracker.d.ts +17 -0
  409. package/dist/node/utilities/graphql-tracker.js +130 -0
  410. package/dist/node/utilities/index.d.ts +1 -1
  411. package/dist/node/utilities/index.js +3 -3
  412. package/dist/node/utilities/isBrowser/index.d.ts +1 -0
  413. package/dist/node/utilities/isBrowser/index.js +5 -0
  414. package/dist/node/utilities/isBrowser/isBrowser.d.ts +4 -0
  415. package/dist/node/utilities/isBrowser/isBrowser.js +10 -0
  416. package/dist/node/utilities/isServer/isServer.js +2 -2
  417. package/dist/node/utilities/log/index.d.ts +1 -1
  418. package/dist/node/utilities/log/index.js +1 -3
  419. package/dist/node/utilities/log/log-cache-header.d.ts +4 -4
  420. package/dist/node/utilities/log/log-query-timeline.d.ts +3 -3
  421. package/dist/node/utilities/log/log.d.ts +17 -11
  422. package/dist/node/utilities/log/log.js +30 -23
  423. package/dist/node/version.d.ts +1 -1
  424. package/dist/node/version.js +1 -1
  425. package/package.json +3 -1
  426. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +203 -52
  427. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +77 -59
  428. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +30 -30
  429. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +199 -70
  430. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +38 -35
  431. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite.development.js +9 -8
  432. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite.production.min.js +3 -3
  433. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +3 -7
  434. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +204 -53
  435. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +77 -59
  436. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +199 -70
  437. package/vendor/react-server-dom-vite/esm/react-server-dom-vite.js +9 -8
  438. package/vendor/react-server-dom-vite/package.json +1 -1
  439. package/dist/esnext/components/ProductProvider/ProductOptionsProvider.client.d.ts +0 -8
  440. package/dist/esnext/components/ProductProvider/ProductOptionsProvider.client.js +0 -12
  441. package/dist/esnext/components/ProductProvider/ProductProvider.client.d.ts +0 -24
  442. package/dist/esnext/components/ProductProvider/ProductProvider.client.js +0 -34
  443. package/dist/esnext/components/ProductProvider/context.d.ts +0 -29
  444. package/dist/esnext/components/ProductProvider/index.d.ts +0 -2
  445. package/dist/esnext/components/ProductProvider/index.js +0 -2
  446. package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.server.d.ts +0 -1
  447. package/dist/esnext/framework/config.d.ts +0 -6
  448. package/dist/esnext/framework/config.js +0 -6
  449. package/dist/esnext/framework/runtime.d.ts +0 -13
  450. package/dist/esnext/framework/runtime.js +0 -27
  451. package/dist/esnext/hooks/useProduct/index.d.ts +0 -1
  452. package/dist/esnext/hooks/useProduct/index.js +0 -1
  453. package/dist/esnext/hooks/useProduct/useProduct.d.ts +0 -52
  454. package/dist/esnext/hooks/useProduct/useProduct.js +0 -43
  455. package/dist/esnext/utilities/isClient/index.d.ts +0 -1
  456. package/dist/esnext/utilities/isClient/index.js +0 -1
  457. package/dist/esnext/utilities/isClient/isClient.d.ts +0 -4
  458. package/dist/esnext/utilities/isClient/isClient.js +0 -6
  459. package/dist/node/framework/config.d.ts +0 -6
  460. package/dist/node/framework/config.js +0 -11
  461. package/dist/node/framework/runtime.d.ts +0 -13
  462. package/dist/node/framework/runtime.js +0 -35
  463. package/dist/node/utilities/defer.d.ts +0 -6
  464. package/dist/node/utilities/defer.js +0 -18
  465. package/dist/node/utilities/isClient/index.d.ts +0 -1
  466. package/dist/node/utilities/isClient/index.js +0 -5
  467. package/dist/node/utilities/isClient/isClient.d.ts +0 -4
  468. package/dist/node/utilities/isClient/isClient.js +0 -10
@@ -1,31 +1,31 @@
1
1
  import React, { Suspense } from 'react';
2
2
  import { logServerResponse, logCacheControlHeaders, logQueryTimings, getLoggerWithContext, } from './utilities/log';
3
3
  import { getErrorMarkup } from './utilities/error';
4
- import { defer } from './utilities/defer';
5
- import { Html, applyHtmlHead } from './framework/Hydration/Html';
6
- import { ServerComponentResponse } from './framework/Hydration/ServerComponentResponse.server';
7
- import { ServerComponentRequest } from './framework/Hydration/ServerComponentRequest.server';
4
+ import { Html, applyHtmlHead } from './foundation/Html/Html';
5
+ import { HydrogenResponse } from './foundation/HydrogenResponse/HydrogenResponse.server';
6
+ import { HydrogenRequest, } from './foundation/HydrogenRequest/HydrogenRequest.server';
8
7
  import { preloadRequestCacheData, ServerRequestProvider, } from './foundation/ServerRequestProvider';
9
8
  import { getApiRouteFromURL, renderApiRoute, getApiRoutes, } from './utilities/apiRoutes';
10
9
  import { ServerPropsProvider } from './foundation/ServerPropsProvider';
11
10
  import { isBotUA } from './utilities/bot-ua';
12
- import { setContext, setCache } from './framework/runtime';
13
- import { setConfig } from './framework/config';
14
- import { ssrRenderToPipeableStream, ssrRenderToReadableStream, rscRenderToReadableStream, createFromReadableStream, isStreamingSupported, bufferReadableStream, } from './streaming.server';
11
+ import { setCache } from './foundation/runtime';
12
+ import { ssrRenderToPipeableStream, ssrRenderToReadableStream, rscRenderToReadableStream, createFromReadableStream, bufferReadableStream, } from './streaming.server';
15
13
  import { RSC_PATHNAME, EVENT_PATHNAME, EVENT_PATHNAME_REGEX } from './constants';
16
14
  import { stripScriptsFromTemplate } from './utilities/template';
15
+ import { setLogger } from './utilities/log/log';
17
16
  import { Analytics } from './foundation/Analytics/Analytics.server';
18
17
  import { ServerAnalyticsRoute } from './foundation/Analytics/ServerAnalyticsRoute.server';
19
18
  import { getSyncSessionApi } from './foundation/session/session';
20
19
  import { parseJSON } from './utilities/parse';
21
20
  import { htmlEncode } from './utilities';
21
+ import { splitCookiesString } from 'set-cookie-parser';
22
22
  const DOCTYPE = '<!DOCTYPE html>';
23
23
  const CONTENT_TYPE = 'Content-Type';
24
24
  const HTML_CONTENT_TYPE = 'text/html; charset=UTF-8';
25
25
  export const renderHydrogen = (App) => {
26
26
  const handleRequest = async function (rawRequest, options) {
27
- const { indexTemplate, streamableResponse, dev, cache, context, nonce, buyerIpHeader, } = options;
28
- const request = new ServerComponentRequest(rawRequest);
27
+ const { dev, nonce, cache, context, buyerIpHeader, indexTemplate, streamableResponse: nodeResponse, } = options;
28
+ const request = new HydrogenRequest(rawRequest);
29
29
  const url = new URL(request.url);
30
30
  const { default: inlineHydrogenConfig } = await import(
31
31
  // @ts-ignore
@@ -41,151 +41,122 @@ export const renderHydrogen = (App) => {
41
41
  };
42
42
  request.ctx.hydrogenConfig = hydrogenConfig;
43
43
  request.ctx.buyerIpHeader = buyerIpHeader;
44
+ setLogger(hydrogenConfig.logger);
44
45
  const log = getLoggerWithContext(request);
46
+ const response = new HydrogenResponse();
45
47
  const sessionApi = hydrogenConfig.session
46
48
  ? hydrogenConfig.session(log)
47
49
  : undefined;
48
- const componentResponse = new ServerComponentResponse();
49
- request.ctx.session = getSyncSessionApi(request, componentResponse, log, sessionApi);
50
+ request.ctx.session = getSyncSessionApi(request, response, log, sessionApi);
50
51
  /**
51
52
  * Inject the cache & context into the module loader so we can pull it out for subrequests.
52
53
  */
54
+ request.ctx.runtime = context;
53
55
  setCache(cache);
54
- setContext(context);
55
- setConfig({ dev });
56
56
  if (url.pathname === EVENT_PATHNAME ||
57
57
  EVENT_PATHNAME_REGEX.test(url.pathname)) {
58
58
  return ServerAnalyticsRoute(request, hydrogenConfig.serverAnalyticsConnectors);
59
59
  }
60
- const isReactHydrationRequest = url.pathname === RSC_PATHNAME;
61
- if (!isReactHydrationRequest) {
62
- const apiRoute = getApiRoute(url, hydrogenConfig.routes);
63
- // The API Route might have a default export, making it also a server component
64
- // If it does, only render the API route if the request method is GET
65
- if (apiRoute &&
66
- (!apiRoute.hasServerComponent || request.method !== 'GET')) {
67
- const apiResponse = await renderApiRoute(request, apiRoute, hydrogenConfig.shopify, sessionApi);
68
- return apiResponse instanceof Request
69
- ? handleRequest(apiResponse, options)
70
- : apiResponse;
71
- }
60
+ const isRSCRequest = url.pathname === RSC_PATHNAME;
61
+ const apiRoute = !isRSCRequest && getApiRoute(url, hydrogenConfig.routes);
62
+ // The API Route might have a default export, making it also a server component
63
+ // If it does, only render the API route if the request method is GET
64
+ if (apiRoute &&
65
+ (!apiRoute.hasServerComponent || request.method !== 'GET')) {
66
+ const apiResponse = await renderApiRoute(request, apiRoute, hydrogenConfig.shopify, sessionApi);
67
+ return apiResponse instanceof Request
68
+ ? handleRequest(apiResponse, options)
69
+ : apiResponse;
70
+ }
71
+ const state = isRSCRequest
72
+ ? parseJSON(url.searchParams.get('state') || '{}')
73
+ : { pathname: url.pathname, search: url.search };
74
+ const rsc = runRSC({ App, state, log, request, response });
75
+ if (isRSCRequest) {
76
+ const buffered = await bufferReadableStream(rsc.readable.getReader());
77
+ postRequestTasks('rsc', 200, request, response);
78
+ return new Response(buffered, {
79
+ headers: { 'cache-control': response.cacheControlHeader },
80
+ });
72
81
  }
73
- const isStreamable = (hydrogenConfig.enableStreaming
74
- ? hydrogenConfig.enableStreaming(request)
75
- : true) &&
76
- !isBotUA(url, request.headers.get('user-agent')) &&
77
- (!!streamableResponse || (await isStreamingSupported()));
78
- let template = typeof indexTemplate === 'function'
79
- ? await indexTemplate(url.toString())
80
- : indexTemplate;
81
- if (template && typeof template !== 'string') {
82
- template = template.default;
82
+ if (isBotUA(url, request.headers.get('user-agent'))) {
83
+ response.doNotStream();
83
84
  }
84
- const params = {
85
- App,
85
+ return runSSR({
86
86
  log,
87
87
  dev,
88
+ rsc,
88
89
  nonce,
90
+ state,
89
91
  request,
90
- template,
91
- isStreamable,
92
- componentResponse,
93
- response: streamableResponse,
94
- };
95
- if (isReactHydrationRequest) {
96
- return hydrate(url, params);
97
- }
98
- /**
99
- * Stream back real-user responses, but for bots/etc,
100
- * use `render` instead. This is because we need to inject <head>
101
- * things for SEO reasons.
102
- */
103
- if (isStreamable) {
104
- return stream(url, params);
105
- }
106
- return render(url, params);
92
+ response,
93
+ nodeResponse,
94
+ template: await getTemplate(indexTemplate, url),
95
+ });
107
96
  };
108
- if (__WORKER__)
97
+ if (__HYDROGEN_WORKER__)
109
98
  return handleRequest;
110
99
  return ((rawRequest, options) => handleFetchResponseInNode(handleRequest(rawRequest, options), options.streamableResponse));
111
100
  };
101
+ async function getTemplate(indexTemplate, url) {
102
+ let template = typeof indexTemplate === 'function'
103
+ ? await indexTemplate(url.toString())
104
+ : indexTemplate;
105
+ if (template && typeof template !== 'string') {
106
+ template = template.default;
107
+ }
108
+ return template;
109
+ }
112
110
  function getApiRoute(url, routes) {
113
111
  const apiRoutes = getApiRoutes(routes);
114
112
  return getApiRouteFromURL(url, apiRoutes);
115
113
  }
116
- /**
117
- * The render function is responsible for turning the provided `App` into an HTML string,
118
- * and returning any initial state that needs to be hydrated into the client version of the app.
119
- * NOTE: This is currently only used for SEO bots or Worker runtime (where Stream is not yet supported).
120
- */
121
- async function render(url, { App, request, template, componentResponse, nonce, log }) {
122
- const state = { pathname: url.pathname, search: url.search };
123
- const { AppSSR, rscReadable } = buildAppSSR({
124
- App,
125
- log,
126
- state,
127
- request,
128
- response: componentResponse,
129
- }, { template });
130
- function onErrorShell(error) {
131
- log.error(error);
132
- componentResponse.writeHead({ status: 500 });
133
- return template;
114
+ function assembleHtml({ ssrHtml, rscPayload, request, template, }) {
115
+ let html = applyHtmlHead(ssrHtml, request.ctx.head, template);
116
+ if (rscPayload) {
117
+ html = html.replace('</body>',
118
+ // This must be a function to avoid replacing
119
+ // special patterns like `$1` in `String.replace`.
120
+ () => flightContainer(rscPayload) + '</body>');
134
121
  }
135
- let [html, flight] = await Promise.all([
136
- renderToBufferedString(AppSSR, { log, nonce }).catch(onErrorShell),
137
- bufferReadableStream(rscReadable.getReader()).catch(() => null),
138
- ]);
139
- const { headers, status, statusText } = getResponseOptions(componentResponse);
140
- /**
141
- * TODO: Also add `Vary` headers for `accept-language` and any other keys
142
- * we want to shard our full-page cache for all Hydrogen storefronts.
143
- */
144
- headers.set('cache-control', componentResponse.cacheControlHeader);
145
- headers.set(CONTENT_TYPE, HTML_CONTENT_TYPE);
146
- html = applyHtmlHead(html, request.ctx.head, template);
147
- if (flight) {
148
- html = html.replace('</body>', () => flightContainer(flight) + '</body>');
149
- }
150
- postRequestTasks('ssr', status, request, componentResponse);
151
- return new Response(html, {
152
- status,
153
- statusText,
154
- headers,
155
- });
122
+ return html;
156
123
  }
157
124
  /**
158
- * Stream a response to the client. NOTE: This omits custom `<head>`
159
- * information, so this method should not be used by crawlers.
125
+ * Run the SSR/Fizz part of the App. If streaming is disabled,
126
+ * this buffers the output and applies SEO enhancements.
160
127
  */
161
- async function stream(url, { App, request, response, componentResponse, template, nonce, dev, log, }) {
162
- var _a;
163
- const state = { pathname: url.pathname, search: url.search };
164
- log.trace('start stream');
165
- const { noScriptTemplate, bootstrapScripts, bootstrapModules } = stripScriptsFromTemplate(template);
166
- const { AppSSR, rscReadable, rscDidError } = buildAppSSR({
167
- App,
168
- log,
169
- state,
170
- request,
171
- response: componentResponse,
172
- }, { template: noScriptTemplate });
173
- const rscToScriptTagReadable = new ReadableStream({
174
- start(controller) {
175
- log.trace('rsc start chunks');
176
- const encoder = new TextEncoder();
177
- bufferReadableStream(rscReadable.getReader(), (chunk) => {
178
- const metaTag = flightContainer(chunk);
179
- controller.enqueue(encoder.encode(metaTag));
180
- }).then(() => {
181
- log.trace('rsc finish chunks');
182
- return controller.close();
183
- });
184
- },
185
- });
128
+ async function runSSR({ rsc, state, request, response, nodeResponse, template, nonce, dev, log, }) {
186
129
  let ssrDidError;
187
- if (__WORKER__) {
188
- const onCompleteAll = defer();
130
+ const didError = () => { var _a; return (_a = rsc.didError()) !== null && _a !== void 0 ? _a : ssrDidError; };
131
+ const [rscReadableForFizz, rscReadableForFlight] = rsc.readable.tee();
132
+ const rscResponse = createFromReadableStream(rscReadableForFizz);
133
+ const RscConsumer = () => rscResponse.readRoot();
134
+ const { noScriptTemplate, bootstrapScripts, bootstrapModules } = stripScriptsFromTemplate(template);
135
+ const AppSSR = (React.createElement(Html, { template: response.canStream() ? noScriptTemplate : template, hydrogenConfig: request.ctx.hydrogenConfig },
136
+ React.createElement(ServerRequestProvider, { request: request, isRSC: false },
137
+ React.createElement(ServerPropsProvider, { initialServerProps: state, setServerPropsForRsc: () => { } },
138
+ React.createElement(PreloadQueries, { request: request },
139
+ React.createElement(Suspense, { fallback: null },
140
+ React.createElement(RscConsumer, null)),
141
+ React.createElement(Suspense, { fallback: null },
142
+ React.createElement(Analytics, null)))))));
143
+ log.trace('start ssr');
144
+ const rscReadable = response.canStream()
145
+ ? new ReadableStream({
146
+ start(controller) {
147
+ log.trace('rsc start chunks');
148
+ const encoder = new TextEncoder();
149
+ bufferReadableStream(rscReadableForFlight.getReader(), (chunk) => {
150
+ const metaTag = flightContainer(chunk);
151
+ controller.enqueue(encoder.encode(metaTag));
152
+ }).then(() => {
153
+ log.trace('rsc finish chunks');
154
+ return controller.close();
155
+ });
156
+ },
157
+ })
158
+ : rscReadableForFlight;
159
+ if (__HYDROGEN_WORKER__) {
189
160
  const encoder = new TextEncoder();
190
161
  const transform = new TransformStream();
191
162
  const writable = transform.writable.getWriter();
@@ -212,72 +183,82 @@ async function stream(url, { App, request, response, componentResponse, template
212
183
  headers: { [CONTENT_TYPE]: HTML_CONTENT_TYPE },
213
184
  });
214
185
  }
215
- log.trace('worker ready to stream');
216
- ssrReadable.allReady.then(() => {
217
- log.trace('worker complete stream');
218
- onCompleteAll.resolve(true);
219
- });
220
- /* eslint-disable no-inner-declarations */
221
- function prepareForStreaming(flush) {
222
- Object.assign(responseOptions, getResponseOptions(componentResponse, rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError));
186
+ if (response.canStream())
187
+ log.trace('worker ready to stream');
188
+ ssrReadable.allReady.then(() => log.trace('worker complete ssr'));
189
+ const prepareForStreaming = () => {
190
+ Object.assign(responseOptions, getResponseOptions(response, didError()));
223
191
  /**
224
192
  * TODO: This assumes `response.cache()` has been called _before_ any
225
193
  * queries which might be caught behind Suspense. Clarify this or add
226
194
  * additional checks downstream?
227
195
  */
228
- responseOptions.headers.set('cache-control', componentResponse.cacheControlHeader);
196
+ /**
197
+ * TODO: Also add `Vary` headers for `accept-language` and any other keys
198
+ * we want to shard our full-page cache for all Hydrogen storefronts.
199
+ */
200
+ responseOptions.headers.set('cache-control', response.cacheControlHeader);
229
201
  if (isRedirect(responseOptions)) {
230
202
  return false;
231
203
  }
232
- if (flush) {
233
- responseOptions.headers.set(CONTENT_TYPE, HTML_CONTENT_TYPE);
234
- writable.write(encoder.encode(DOCTYPE));
235
- if (rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError) {
236
- // This error was delayed until the headers were properly sent.
237
- writable.write(encoder.encode(getErrorMarkup((rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError))));
238
- }
239
- return true;
204
+ responseOptions.headers.set(CONTENT_TYPE, HTML_CONTENT_TYPE);
205
+ writable.write(encoder.encode(DOCTYPE));
206
+ const error = didError();
207
+ if (error) {
208
+ // This error was delayed until the headers were properly sent.
209
+ writable.write(encoder.encode(dev ? getErrorMarkup(error) : template));
240
210
  }
241
- }
242
- /* eslint-enable no-inner-declarations */
243
- const shouldReturnApp = (_a = prepareForStreaming(componentResponse.canStream())) !== null && _a !== void 0 ? _a : (await onCompleteAll.promise.then(prepareForStreaming));
244
- if (shouldReturnApp) {
211
+ return true;
212
+ };
213
+ const shouldFlushBody = response.canStream()
214
+ ? prepareForStreaming()
215
+ : await ssrReadable.allReady.then(prepareForStreaming);
216
+ if (shouldFlushBody) {
245
217
  let bufferedSsr = '';
246
218
  let isPendingSsrWrite = false;
247
- const writingSSR = bufferReadableStream(ssrReadable.getReader(), (chunk) => {
248
- bufferedSsr += chunk;
249
- if (!isPendingSsrWrite) {
250
- isPendingSsrWrite = true;
251
- setTimeout(() => {
252
- isPendingSsrWrite = false;
253
- // React can write fractional chunks synchronously.
254
- // This timeout ensures we only write full HTML tags
255
- // in order to allow RSC writing concurrently.
256
- if (bufferedSsr) {
257
- writable.write(encoder.encode(bufferedSsr));
258
- bufferedSsr = '';
259
- }
260
- }, 0);
219
+ const writingSSR = bufferReadableStream(ssrReadable.getReader(), response.canStream()
220
+ ? (chunk) => {
221
+ bufferedSsr += chunk;
222
+ if (!isPendingSsrWrite) {
223
+ isPendingSsrWrite = true;
224
+ setTimeout(() => {
225
+ isPendingSsrWrite = false;
226
+ // React can write fractional chunks synchronously.
227
+ // This timeout ensures we only write full HTML tags
228
+ // in order to allow RSC writing concurrently.
229
+ if (bufferedSsr) {
230
+ writable.write(encoder.encode(bufferedSsr));
231
+ bufferedSsr = '';
232
+ }
233
+ }, 0);
234
+ }
235
+ }
236
+ : undefined);
237
+ const writingRSC = bufferReadableStream(rscReadable.getReader(), response.canStream()
238
+ ? (scriptTag) => writable.write(encoder.encode(scriptTag))
239
+ : undefined);
240
+ Promise.all([writingSSR, writingRSC]).then(([ssrHtml, rscPayload]) => {
241
+ if (!response.canStream()) {
242
+ const html = assembleHtml({ ssrHtml, rscPayload, request, template });
243
+ writable.write(encoder.encode(html));
261
244
  }
262
- });
263
- const writingRSC = bufferReadableStream(rscToScriptTagReadable.getReader(), (scriptTag) => writable.write(encoder.encode(scriptTag)));
264
- Promise.all([writingSSR, writingRSC]).then(() => {
265
245
  // Last SSR write might be pending, delay closing the writable one tick
266
246
  setTimeout(() => writable.close(), 0);
267
- postRequestTasks('str', responseOptions.status, request, componentResponse);
247
+ postRequestTasks('str', responseOptions.status, request, response);
268
248
  });
269
249
  }
270
250
  else {
251
+ // Redirects do not write body
271
252
  writable.close();
272
- postRequestTasks('str', responseOptions.status, request, componentResponse);
253
+ postRequestTasks('str', responseOptions.status, request, response);
273
254
  }
274
- if (await isStreamingSupported()) {
255
+ if (response.canStream()) {
275
256
  return new Response(transform.readable, responseOptions);
276
257
  }
277
258
  const bufferedBody = await bufferReadableStream(transform.readable.getReader());
278
259
  return new Response(bufferedBody, responseOptions);
279
260
  }
280
- else if (response) {
261
+ else if (nodeResponse) {
281
262
  const { pipe } = ssrRenderToPipeableStream(AppSSR, {
282
263
  nonce,
283
264
  bootstrapScripts,
@@ -289,59 +270,68 @@ async function stream(url, { App, request, response, componentResponse, template
289
270
  * queries which might be caught behind Suspense. Clarify this or add
290
271
  * additional checks downstream?
291
272
  */
292
- response.setHeader('cache-control', componentResponse.cacheControlHeader);
293
- writeHeadToServerResponse(response, componentResponse, log, rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError);
294
- if (isRedirect(response)) {
273
+ writeHeadToNodeResponse(nodeResponse, response, log, didError());
274
+ if (isRedirect(nodeResponse)) {
295
275
  // Return redirects early without further rendering/streaming
296
- return response.end();
276
+ return nodeResponse.end();
297
277
  }
298
- if (!componentResponse.canStream())
278
+ if (!response.canStream())
299
279
  return;
300
- startWritingHtmlToServerResponse(response, dev ? rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError : undefined);
280
+ startWritingToNodeResponse(nodeResponse, dev ? didError() : undefined);
301
281
  setTimeout(() => {
302
282
  log.trace('node pipe response');
303
- pipe(response);
283
+ pipe(nodeResponse);
304
284
  }, 0);
305
- bufferReadableStream(rscToScriptTagReadable.getReader(), (chunk) => {
285
+ bufferReadableStream(rscReadable.getReader(), (chunk) => {
306
286
  log.trace('rsc chunk');
307
- return response.write(chunk);
287
+ return nodeResponse.write(chunk);
308
288
  });
309
289
  },
310
- onAllReady() {
311
- log.trace('node complete stream');
312
- if (componentResponse.canStream() || response.writableEnded) {
313
- postRequestTasks('str', response.statusCode, request, componentResponse);
290
+ async onAllReady() {
291
+ log.trace('node complete ssr');
292
+ if (response.canStream() || nodeResponse.writableEnded) {
293
+ postRequestTasks('str', nodeResponse.statusCode, request, response);
314
294
  return;
315
295
  }
316
- writeHeadToServerResponse(response, componentResponse, log, rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError);
317
- postRequestTasks('str', response.statusCode, request, componentResponse);
318
- if (isRedirect(response)) {
296
+ writeHeadToNodeResponse(nodeResponse, response, log, didError());
297
+ if (isRedirect(nodeResponse)) {
319
298
  // Redirects found after any async code
320
- return response.end();
299
+ return nodeResponse.end();
321
300
  }
322
- startWritingHtmlToServerResponse(response, dev ? rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError : undefined);
323
- bufferReadableStream(rscToScriptTagReadable.getReader()).then((scriptTags) => {
324
- // Piping ends the response so script tags
325
- // must be written before that.
326
- response.write(scriptTags);
327
- pipe(response);
301
+ const bufferedResponse = await createNodeWriter();
302
+ const bufferedRscPromise = bufferReadableStream(rscReadable.getReader());
303
+ let ssrHtml = '';
304
+ bufferedResponse.on('data', (chunk) => (ssrHtml += chunk.toString()));
305
+ bufferedResponse.once('error', (error) => (ssrDidError = error));
306
+ bufferedResponse.once('end', async () => {
307
+ const rscPayload = await bufferedRscPromise;
308
+ const error = didError();
309
+ startWritingToNodeResponse(nodeResponse, dev ? error : undefined);
310
+ let html = template;
311
+ if (!error) {
312
+ html = assembleHtml({ ssrHtml, rscPayload, request, template });
313
+ postRequestTasks('ssr', nodeResponse.statusCode, request, response);
314
+ }
315
+ nodeResponse.write(html);
316
+ nodeResponse.end();
328
317
  });
318
+ pipe(bufferedResponse);
329
319
  },
330
320
  onShellError(error) {
331
321
  log.error(error);
332
- if (!response.writableEnded) {
333
- writeHeadToServerResponse(response, componentResponse, log, error);
334
- startWritingHtmlToServerResponse(response, dev ? error : undefined);
335
- response.write(template);
336
- response.end();
322
+ if (!nodeResponse.writableEnded) {
323
+ writeHeadToNodeResponse(nodeResponse, response, log, error);
324
+ startWritingToNodeResponse(nodeResponse, dev ? error : undefined);
325
+ nodeResponse.write(template);
326
+ nodeResponse.end();
337
327
  }
338
328
  },
339
329
  onError(error) {
340
330
  ssrDidError = error;
341
- if (dev && response.headersSent) {
331
+ if (dev && nodeResponse.headersSent) {
342
332
  // Calling write would flush headers automatically.
343
333
  // Delay this error until headers are properly sent.
344
- response.write(getErrorMarkup(error));
334
+ nodeResponse.write(getErrorMarkup(error));
345
335
  }
346
336
  log.error(error);
347
337
  },
@@ -349,150 +339,66 @@ async function stream(url, { App, request, response, componentResponse, template
349
339
  }
350
340
  }
351
341
  /**
352
- * Stream a hydration response to the client.
342
+ * Run the RSC/Flight part of the App
353
343
  */
354
- async function hydrate(url, { App, log, request, response, isStreamable, componentResponse, }) {
355
- const state = parseJSON(url.searchParams.get('state') || '{}');
356
- const { AppRSC } = buildAppRSC({
357
- App,
358
- log,
359
- state,
360
- request,
361
- response: componentResponse,
362
- });
363
- const rscReadable = rscRenderToReadableStream(AppRSC, {
364
- onError(e) {
365
- log.error(e);
366
- },
367
- });
368
- const bufferedBody = await bufferReadableStream(rscReadable.getReader());
369
- postRequestTasks('rsc', 200, request, componentResponse);
370
- return new Response(bufferedBody, {
371
- headers: {
372
- 'cache-control': componentResponse.cacheControlHeader,
373
- },
374
- });
375
- }
376
- function buildAppRSC({ App, log, state, request, response }) {
377
- const hydrogenServerProps = { request, response, log };
378
- const serverProps = {
379
- ...state,
380
- ...hydrogenServerProps,
381
- };
344
+ function runRSC({ App, state, log, request, response }) {
345
+ const serverProps = { ...state, request, response, log };
382
346
  request.ctx.router.serverProps = serverProps;
383
347
  const AppRSC = (React.createElement(ServerRequestProvider, { request: request, isRSC: true },
384
348
  React.createElement(PreloadQueries, { request: request },
385
349
  React.createElement(App, { ...serverProps }),
386
350
  React.createElement(Suspense, { fallback: null },
387
351
  React.createElement(Analytics, null)))));
388
- return { AppRSC };
389
- }
390
- function buildAppSSR({ App, state, request, response, log }, htmlOptions) {
391
- const { AppRSC } = buildAppRSC({
392
- App,
393
- log,
394
- state,
395
- request,
396
- response,
397
- });
398
352
  let rscDidError;
399
- const [rscReadableForFizz, rscReadableForFlight] = rscRenderToReadableStream(AppRSC, {
353
+ const rscReadable = rscRenderToReadableStream(AppRSC, {
400
354
  onError(e) {
401
355
  rscDidError = e;
402
356
  log.error(e);
403
357
  },
404
- }).tee();
405
- const rscResponse = createFromReadableStream(rscReadableForFizz);
406
- const RscConsumer = () => rscResponse.readRoot();
407
- const AppSSR = (React.createElement(Html, { ...htmlOptions },
408
- React.createElement(ServerRequestProvider, { request: request, isRSC: false },
409
- React.createElement(ServerPropsProvider, { initialServerProps: state, setServerPropsForRsc: () => { } },
410
- React.createElement(PreloadQueries, { request: request },
411
- React.createElement(Suspense, { fallback: null },
412
- React.createElement(RscConsumer, null)),
413
- React.createElement(Suspense, { fallback: null },
414
- React.createElement(Analytics, null)))))));
415
- return { AppSSR, rscReadable: rscReadableForFlight, rscDidError };
358
+ });
359
+ return { readable: rscReadable, didError: () => rscDidError };
416
360
  }
417
361
  function PreloadQueries({ request, children, }) {
418
362
  const preloadQueries = request.getPreloadQueries();
419
363
  preloadRequestCacheData(request, preloadQueries);
420
364
  return React.createElement(React.Fragment, null, children);
421
365
  }
422
- async function renderToBufferedString(ReactApp, { log, nonce }) {
423
- if (__WORKER__) {
424
- const ssrReadable = await ssrRenderToReadableStream(ReactApp, {
425
- nonce,
426
- onError: (error) => log.error(error),
427
- });
428
- /**
429
- * We want to wait until `allReady` resolves before fetching the
430
- * stream body. Otherwise, React 18's streaming JS script/template tags
431
- * will be included in the output and cause issues when loading
432
- * the Client Components in the browser.
433
- */
434
- await ssrReadable.allReady;
435
- return bufferReadableStream(ssrReadable.getReader());
436
- }
437
- else {
438
- const writer = await createNodeWriter();
439
- return new Promise((resolve, reject) => {
440
- const { pipe } = ssrRenderToPipeableStream(ReactApp, {
441
- nonce,
442
- /**
443
- * When hydrating, we have to wait until `onCompleteAll` to avoid having
444
- * `template` and `script` tags inserted and rendered as part of the hydration response.
445
- */
446
- onAllReady() {
447
- let data = '';
448
- writer.on('data', (chunk) => (data += chunk.toString()));
449
- writer.once('error', reject);
450
- writer.once('end', () => resolve(data));
451
- // Tell React to start writing to the writer
452
- pipe(writer);
453
- },
454
- onShellError: reject,
455
- onError: (error) => log.error(error),
456
- });
457
- });
458
- }
459
- }
460
366
  export default renderHydrogen;
461
- function startWritingHtmlToServerResponse(response, error) {
462
- if (!response.headersSent) {
463
- response.setHeader(CONTENT_TYPE, HTML_CONTENT_TYPE);
464
- response.write(DOCTYPE);
367
+ function startWritingToNodeResponse(nodeResponse, error) {
368
+ if (!nodeResponse.headersSent) {
369
+ nodeResponse.setHeader(CONTENT_TYPE, HTML_CONTENT_TYPE);
370
+ nodeResponse.write(DOCTYPE);
465
371
  }
466
372
  if (error) {
467
373
  // This error was delayed until the headers were properly sent.
468
- response.write(getErrorMarkup(error));
374
+ nodeResponse.write(getErrorMarkup(error));
469
375
  }
470
376
  }
471
- function getResponseOptions({ headers, status, customStatus }, error) {
472
- var _a, _b;
473
- const responseInit = {};
474
- responseInit.headers = headers;
475
- if (error) {
476
- responseInit.status = 500;
477
- }
478
- else {
479
- responseInit.status = (_b = (_a = customStatus === null || customStatus === void 0 ? void 0 : customStatus.code) !== null && _a !== void 0 ? _a : status) !== null && _b !== void 0 ? _b : 200;
480
- if (customStatus === null || customStatus === void 0 ? void 0 : customStatus.text) {
481
- responseInit.statusText = customStatus.text;
482
- }
377
+ function getResponseOptions({ headers, status, statusText }, error) {
378
+ const responseInit = {
379
+ headers,
380
+ status: error ? 500 : status,
381
+ };
382
+ if (!error && statusText) {
383
+ responseInit.statusText = statusText;
483
384
  }
484
385
  return responseInit;
485
386
  }
486
- function writeHeadToServerResponse(response, serverComponentResponse, log, error) {
487
- if (response.headersSent)
387
+ function writeHeadToNodeResponse(nodeResponse, componentResponse, log, error) {
388
+ if (nodeResponse.headersSent)
488
389
  return;
489
- log.trace('writeHeadToServerResponse');
490
- const { headers, status, statusText } = getResponseOptions(serverComponentResponse, error);
491
- response.statusCode = status;
390
+ log.trace('writeHeadToNodeResponse');
391
+ /**
392
+ * TODO: Also add `Vary` headers for `accept-language` and any other keys
393
+ * we want to shard our full-page cache for all Hydrogen storefronts.
394
+ */
395
+ nodeResponse.setHeader('cache-control', componentResponse.cacheControlHeader);
396
+ const { headers, status, statusText } = getResponseOptions(componentResponse, error);
397
+ nodeResponse.statusCode = status;
492
398
  if (statusText) {
493
- response.statusMessage = statusText;
399
+ nodeResponse.statusMessage = statusText;
494
400
  }
495
- setServerHeaders(headers, response);
401
+ setNodeHeaders(headers, nodeResponse);
496
402
  }
497
403
  function isRedirect(response) {
498
404
  var _a, _b;
@@ -504,16 +410,16 @@ async function createNodeWriter() {
504
410
  // when building for workers, even though this code
505
411
  // does not run in a worker. Looks like tree-shaking
506
412
  // kicks in after the import analysis/bundle.
507
- const streamImport = __WORKER__ ? '' : 'stream';
413
+ const streamImport = __HYDROGEN_WORKER__ ? '' : 'stream';
508
414
  const { PassThrough } = await import(streamImport);
509
415
  return new PassThrough();
510
416
  }
511
417
  function flightContainer(chunk) {
512
418
  return `<meta data-flight="${htmlEncode(chunk)}" />`;
513
419
  }
514
- function postRequestTasks(type, status, request, componentResponse) {
420
+ function postRequestTasks(type, status, request, response) {
515
421
  logServerResponse(type, request, status);
516
- logCacheControlHeaders(type, request, componentResponse);
422
+ logCacheControlHeaders(type, request, response);
517
423
  logQueryTimings(type, request);
518
424
  request.savePreloadQueries();
519
425
  }
@@ -525,20 +431,38 @@ function handleFetchResponseInNode(fetchResponsePromise, nodeResponse) {
525
431
  fetchResponsePromise.then((response) => {
526
432
  if (!response)
527
433
  return;
528
- setServerHeaders(response.headers, nodeResponse);
434
+ setNodeHeaders(response.headers, nodeResponse);
529
435
  nodeResponse.statusCode = response.status;
530
436
  if (response.body) {
531
- nodeResponse.write(response.body);
437
+ if (response.body instanceof ReadableStream) {
438
+ bufferReadableStream(response.body.getReader(), (chunk) => {
439
+ nodeResponse.write(chunk);
440
+ }).then(() => nodeResponse.end());
441
+ }
442
+ else {
443
+ nodeResponse.write(response.body);
444
+ nodeResponse.end();
445
+ }
446
+ }
447
+ else {
448
+ nodeResponse.end();
532
449
  }
533
- nodeResponse.end();
534
450
  });
535
451
  }
536
452
  return fetchResponsePromise;
537
453
  }
538
- // From fetch Headers to Node Response
539
- function setServerHeaders(headers, nodeResponse) {
540
- // Headers.raw is only implemented in node-fetch, which is used by Hydrogen in dev and prod.
541
- // It is the only way for now to access `set-cookie` header as an array.
542
- // https://github.com/Shopify/hydrogen/issues/1228
543
- Object.entries(headers.raw()).forEach(([key, value]) => nodeResponse.setHeader(key, value));
454
+ /**
455
+ * Convert Headers to outgoing Node.js headers.
456
+ * Specifically, parse set-cookie headers to split them properly as separate
457
+ * `set-cookie` headers rather than a single, combined header.
458
+ */
459
+ function setNodeHeaders(headers, nodeResponse) {
460
+ for (const [key, value] of headers.entries()) {
461
+ if (key.toLowerCase() === 'set-cookie') {
462
+ nodeResponse.setHeader(key, splitCookiesString(value));
463
+ }
464
+ else {
465
+ nodeResponse.setHeader(key, value);
466
+ }
467
+ }
544
468
  }