@shopify/hydrogen 0.13.2 → 0.16.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 (174) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/dist/esnext/client.d.ts +4 -0
  3. package/dist/esnext/client.js +4 -0
  4. package/dist/esnext/components/CartProvider/CartProvider.client.js +23 -0
  5. package/dist/esnext/components/DevTools.d.ts +1 -0
  6. package/dist/esnext/components/DevTools.js +128 -0
  7. package/dist/esnext/components/Link/Link.client.d.ts +6 -0
  8. package/dist/esnext/components/Link/Link.client.js +85 -3
  9. package/dist/esnext/components/LocalizationProvider/LocalizationContext.client.d.ts +1 -1
  10. package/dist/esnext/components/LocalizationProvider/LocalizationProvider.server.d.ts +16 -0
  11. package/dist/esnext/components/LocalizationProvider/LocalizationProvider.server.js +7 -2
  12. package/dist/esnext/components/Seo/DefaultPageSeo.client.js +1 -2
  13. package/dist/esnext/constants.d.ts +6 -0
  14. package/dist/esnext/constants.js +6 -0
  15. package/dist/esnext/entry-client.js +20 -4
  16. package/dist/esnext/entry-server.d.ts +1 -1
  17. package/dist/esnext/entry-server.js +42 -23
  18. package/dist/esnext/foundation/Analytics/Analytics.client.d.ts +3 -0
  19. package/dist/esnext/foundation/Analytics/Analytics.client.js +28 -0
  20. package/dist/esnext/foundation/Analytics/Analytics.server.d.ts +1 -0
  21. package/dist/esnext/foundation/Analytics/Analytics.server.js +38 -0
  22. package/dist/esnext/foundation/Analytics/ClientAnalytics.d.ts +24 -0
  23. package/dist/esnext/foundation/Analytics/ClientAnalytics.js +91 -0
  24. package/dist/esnext/foundation/Analytics/ServerAnalyticsRoute.server.d.ts +2 -0
  25. package/dist/esnext/foundation/Analytics/ServerAnalyticsRoute.server.js +33 -0
  26. package/dist/esnext/foundation/Analytics/const.d.ts +8 -0
  27. package/dist/esnext/foundation/Analytics/const.js +8 -0
  28. package/dist/esnext/foundation/Analytics/hook.d.ts +1 -0
  29. package/dist/esnext/foundation/Analytics/hook.js +7 -0
  30. package/dist/esnext/foundation/Analytics/index.d.ts +2 -0
  31. package/dist/esnext/foundation/Analytics/index.js +2 -0
  32. package/dist/esnext/foundation/Analytics/types.d.ts +5 -0
  33. package/dist/esnext/{components/LocalizationProvider/LocalizationQuery.js → foundation/Analytics/types.js} +0 -0
  34. package/dist/esnext/foundation/Analytics/utils.d.ts +1 -0
  35. package/dist/esnext/foundation/Analytics/utils.js +8 -0
  36. package/dist/esnext/foundation/Boomerang/Boomerang.client.js +3 -1
  37. package/dist/esnext/foundation/Route/Route.server.js +4 -0
  38. package/dist/esnext/foundation/Router/BrowserRouter.client.js +68 -15
  39. package/dist/esnext/foundation/ServerRequestProvider/ServerRequestProvider.js +1 -1
  40. package/dist/esnext/foundation/ServerStateProvider/ServerStateProvider.d.ts +6 -1
  41. package/dist/esnext/foundation/ServerStateProvider/ServerStateProvider.js +27 -22
  42. package/dist/esnext/foundation/ShopifyProvider/ShopifyProvider.server.js +4 -1
  43. package/dist/esnext/foundation/ShopifyProvider/types.d.ts +5 -6
  44. package/dist/esnext/foundation/constants.d.ts +1 -1
  45. package/dist/esnext/foundation/constants.js +1 -1
  46. package/dist/esnext/foundation/fetchSync/client/fetchSync.d.ts +10 -0
  47. package/dist/esnext/foundation/fetchSync/client/fetchSync.js +27 -0
  48. package/dist/esnext/foundation/fetchSync/server/fetchSync.d.ts +8 -0
  49. package/dist/esnext/foundation/fetchSync/server/fetchSync.js +27 -0
  50. package/dist/esnext/foundation/fetchSync/types.d.ts +5 -0
  51. package/dist/esnext/foundation/fetchSync/types.js +1 -0
  52. package/dist/esnext/foundation/useQuery/hooks.d.ts +4 -2
  53. package/dist/esnext/foundation/useQuery/hooks.js +10 -6
  54. package/dist/esnext/foundation/useUrl/useUrl.js +8 -1
  55. package/dist/esnext/framework/Hydration/ServerComponentRequest.server.d.ts +1 -0
  56. package/dist/esnext/framework/Hydration/ServerComponentRequest.server.js +14 -7
  57. package/dist/esnext/framework/cache/in-memory.js +5 -5
  58. package/dist/esnext/framework/cache.d.ts +1 -10
  59. package/dist/esnext/framework/cache.js +67 -30
  60. package/dist/esnext/framework/plugin.js +10 -0
  61. package/dist/esnext/framework/plugins/vite-plugin-css-modules-rsc.js +1 -1
  62. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.js +9 -2
  63. package/dist/esnext/hooks/useParsedMetafields/useParsedMetafields.d.ts +1 -1
  64. package/dist/esnext/hooks/useShopQuery/hooks.d.ts +1 -1
  65. package/dist/esnext/hooks/useShopQuery/hooks.js +37 -22
  66. package/dist/esnext/index.d.ts +2 -0
  67. package/dist/esnext/index.js +2 -0
  68. package/dist/esnext/storefront-api-types.d.ts +150 -3
  69. package/dist/esnext/storefront-api-types.js +16 -0
  70. package/dist/esnext/types.d.ts +6 -1
  71. package/dist/esnext/utilities/apiRoutes.d.ts +2 -3
  72. package/dist/esnext/utilities/apiRoutes.js +14 -9
  73. package/dist/esnext/utilities/hash.d.ts +2 -0
  74. package/dist/esnext/utilities/hash.js +7 -0
  75. package/dist/esnext/utilities/log/log-cache-api-status.js +1 -1
  76. package/dist/esnext/utilities/log/log-cache-header.js +1 -1
  77. package/dist/esnext/utilities/log/log-query-timeline.js +1 -1
  78. package/dist/esnext/utilities/storefrontApi.d.ts +4 -0
  79. package/dist/esnext/utilities/storefrontApi.js +21 -0
  80. package/dist/esnext/utilities/suspense.d.ts +5 -0
  81. package/dist/esnext/utilities/suspense.js +32 -0
  82. package/dist/esnext/utilities/template.js +1 -1
  83. package/dist/esnext/version.d.ts +1 -1
  84. package/dist/esnext/version.js +1 -1
  85. package/dist/node/constants.d.ts +6 -0
  86. package/dist/node/constants.js +7 -1
  87. package/dist/node/entry-server.d.ts +1 -1
  88. package/dist/node/entry-server.js +41 -25
  89. package/dist/node/foundation/Analytics/Analytics.client.d.ts +3 -0
  90. package/dist/node/foundation/Analytics/Analytics.client.js +32 -0
  91. package/dist/node/foundation/Analytics/Analytics.server.d.ts +1 -0
  92. package/dist/node/foundation/Analytics/Analytics.server.js +45 -0
  93. package/dist/node/foundation/Analytics/ClientAnalytics.d.ts +24 -0
  94. package/dist/node/foundation/Analytics/ClientAnalytics.js +94 -0
  95. package/dist/node/foundation/Analytics/ServerAnalyticsRoute.server.d.ts +2 -0
  96. package/dist/node/foundation/Analytics/ServerAnalyticsRoute.server.js +37 -0
  97. package/dist/node/foundation/Analytics/const.d.ts +8 -0
  98. package/dist/node/foundation/Analytics/const.js +11 -0
  99. package/dist/node/foundation/Analytics/hook.d.ts +1 -0
  100. package/dist/node/foundation/Analytics/hook.js +11 -0
  101. package/dist/node/foundation/Analytics/index.d.ts +2 -0
  102. package/dist/node/foundation/Analytics/index.js +7 -0
  103. package/dist/node/foundation/Analytics/types.d.ts +5 -0
  104. package/dist/node/foundation/Analytics/types.js +2 -0
  105. package/dist/node/foundation/Analytics/utils.d.ts +1 -0
  106. package/dist/node/foundation/Analytics/utils.js +12 -0
  107. package/dist/node/foundation/Router/BrowserRouter.client.js +67 -14
  108. package/dist/node/foundation/ServerRequestProvider/ServerRequestProvider.js +2 -2
  109. package/dist/node/foundation/ServerStateProvider/ServerStateProvider.d.ts +6 -1
  110. package/dist/node/foundation/ServerStateProvider/ServerStateProvider.js +27 -22
  111. package/dist/node/foundation/ShopifyProvider/types.d.ts +5 -6
  112. package/dist/node/framework/Hydration/ServerComponentRequest.server.d.ts +1 -0
  113. package/dist/node/framework/Hydration/ServerComponentRequest.server.js +16 -9
  114. package/dist/node/framework/cache/in-memory.js +5 -5
  115. package/dist/node/framework/cache.d.ts +1 -10
  116. package/dist/node/framework/cache.js +71 -36
  117. package/dist/node/framework/plugin.js +10 -0
  118. package/dist/node/framework/plugins/vite-plugin-css-modules-rsc.js +1 -1
  119. package/dist/node/framework/plugins/vite-plugin-hydrogen-config.js +9 -2
  120. package/dist/node/storefront-api-types.d.ts +150 -3
  121. package/dist/node/storefront-api-types.js +17 -1
  122. package/dist/node/types.d.ts +6 -1
  123. package/dist/node/utilities/apiRoutes.d.ts +2 -3
  124. package/dist/node/utilities/apiRoutes.js +14 -9
  125. package/dist/node/utilities/flattenConnection/flattenConnection.d.ts +6 -0
  126. package/dist/node/utilities/flattenConnection/flattenConnection.js +15 -0
  127. package/dist/node/utilities/flattenConnection/index.d.ts +1 -0
  128. package/dist/node/utilities/flattenConnection/index.js +5 -0
  129. package/dist/node/utilities/hash.d.ts +2 -0
  130. package/dist/node/utilities/hash.js +11 -0
  131. package/dist/node/utilities/image_size.d.ts +30 -0
  132. package/dist/node/utilities/image_size.js +110 -0
  133. package/dist/node/utilities/index.d.ts +11 -0
  134. package/dist/node/utilities/index.js +32 -0
  135. package/dist/node/utilities/isClient/index.d.ts +1 -0
  136. package/dist/node/utilities/isClient/index.js +5 -0
  137. package/dist/node/utilities/isClient/isClient.d.ts +4 -0
  138. package/dist/node/utilities/isClient/isClient.js +10 -0
  139. package/dist/node/utilities/isServer/index.d.ts +1 -0
  140. package/dist/node/utilities/isServer/index.js +5 -0
  141. package/dist/node/utilities/isServer/isServer.d.ts +4 -0
  142. package/dist/node/utilities/isServer/isServer.js +11 -0
  143. package/dist/node/utilities/load_script.d.ts +3 -0
  144. package/dist/node/utilities/load_script.js +27 -0
  145. package/dist/node/utilities/log/log-cache-api-status.js +1 -1
  146. package/dist/node/utilities/log/log-cache-header.js +2 -2
  147. package/dist/node/utilities/log/log-query-timeline.js +2 -2
  148. package/dist/node/utilities/measurement.d.ts +3 -0
  149. package/dist/node/utilities/measurement.js +103 -0
  150. package/dist/node/utilities/parseMetafieldValue/index.d.ts +1 -0
  151. package/dist/node/utilities/parseMetafieldValue/index.js +5 -0
  152. package/dist/node/utilities/parseMetafieldValue/parseMetafieldValue.d.ts +6 -0
  153. package/dist/node/utilities/parseMetafieldValue/parseMetafieldValue.js +39 -0
  154. package/dist/node/utilities/storefrontApi.d.ts +4 -0
  155. package/dist/node/utilities/storefrontApi.js +25 -0
  156. package/dist/node/utilities/suspense.d.ts +12 -0
  157. package/dist/node/utilities/suspense.js +64 -0
  158. package/dist/node/utilities/template.js +1 -1
  159. package/dist/node/utilities/video_parameters.d.ts +47 -0
  160. package/dist/node/utilities/video_parameters.js +27 -0
  161. package/dist/node/version.d.ts +1 -1
  162. package/dist/node/version.js +1 -1
  163. package/package.json +3 -3
  164. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +9 -21
  165. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +51 -47
  166. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +30 -29
  167. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +51 -47
  168. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +17 -17
  169. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +55 -45
  170. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +9 -21
  171. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +51 -47
  172. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +51 -47
  173. package/vendor/react-server-dom-vite/package.json +3 -3
  174. package/dist/esnext/components/LocalizationProvider/LocalizationQuery.d.ts +0 -23
package/CHANGELOG.md CHANGED
@@ -1,5 +1,149 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.16.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1082](https://github.com/Shopify/hydrogen/pull/1082) [`bd14340c`](https://github.com/Shopify/hydrogen/commit/bd14340c3099a0bf375a5879410cdf0697ed22f6) Thanks [@jplhomer](https://github.com/jplhomer)! - Update `useUrl()` to allow a developer to subscribe to a reactive version of the current router location.
8
+
9
+ Example:
10
+
11
+ ```jsx
12
+ import {useUrl} from '@shopify/hydrogen/client';
13
+
14
+ function MyClientComponent() {
15
+ const url = useUrl();
16
+
17
+ useEffect(() => {
18
+ // Record navigation, analytics, etc
19
+ }, [url]);
20
+ }
21
+ ```
22
+
23
+ * [#1075](https://github.com/Shopify/hydrogen/pull/1075) [`05dea552`](https://github.com/Shopify/hydrogen/commit/05dea552c90862a125b5111993003355a019b556) Thanks [@jplhomer](https://github.com/jplhomer)! - Properly set buyer IP and secret token for API Route queryShop helper
24
+
25
+ ## 0.15.0
26
+
27
+ ### Minor Changes
28
+
29
+ - [#983](https://github.com/Shopify/hydrogen/pull/983) [`52af261b`](https://github.com/Shopify/hydrogen/commit/52af261ba2bf6ed08e232b9fb2d75e69905f4cc6) Thanks [@jplhomer](https://github.com/jplhomer)! - Introduce Suspense-friendly `fetchSync` API for server and client components.
30
+
31
+ When using `fetchSync` in server components, you provide options for caching and preloading. This is similar to the [`useQuery` hook](<[/api/hydrogen/hooks/global/useQuery](https://shopify.dev/api/hydrogen/hooks/global/usequery)>):
32
+
33
+ ```jsx
34
+ import {fetchSync, CacheMinutes} from '@shopify/hydrogen';
35
+ import {Suspense} from 'react';
36
+
37
+ export function MyServerComponent() {
38
+ return (
39
+ <Suspense fallback="Loading...">
40
+ <MyThings />
41
+ </Suspense>
42
+ );
43
+ }
44
+
45
+ function MyThings() {
46
+ const things = fetchSync('https://3p.api.com/things.json', {
47
+ preload: true,
48
+ cache: CacheMinutes(),
49
+ }).json();
50
+
51
+ return <h2>{things.title}</h2>;
52
+ }
53
+ ```
54
+
55
+ When using `fetchSync` in client components, you cannot provide options for caching and preloading. You must import `fetchSync` from `@shopify/hydrogen/client`:
56
+
57
+ ```jsx
58
+ import {fetchSync} from '@shopify/hydrogen/client';
59
+ import {Suspense} from 'react';
60
+
61
+ export function MyClientComponent() {
62
+ return (
63
+ <Suspense fallback="Loading...">
64
+ <MyThings />
65
+ </Suspense>
66
+ );
67
+ }
68
+
69
+ function MyThings() {
70
+ const things = fetchSync('https://3p.api.com/things.json').json();
71
+
72
+ return <h2>{things.title}</h2>;
73
+ }
74
+ ```
75
+
76
+ * [#890](https://github.com/Shopify/hydrogen/pull/890) [`a4c6d6c4`](https://github.com/Shopify/hydrogen/commit/a4c6d6c4d31337cecbd4d5afb76887bcd31ceb65) Thanks [@wizardlyhel](https://github.com/wizardlyhel)! - Analytics instrumentation - this provides integration points for both server
77
+ and client side analytics instrumentations
78
+
79
+ - [Usage documentation](https://shopify.dev/custom-storefronts/hydrogen/framework/analytics)
80
+
81
+ ### Patch Changes
82
+
83
+ - [#1061](https://github.com/Shopify/hydrogen/pull/1061) [`a4aa3887`](https://github.com/Shopify/hydrogen/commit/a4aa3887be9f448ec1f4322fadb9821e0d19a0b5) Thanks [@jplhomer](https://github.com/jplhomer)! - Support script tags in index.html that contain line breaks
84
+
85
+ * [#1057](https://github.com/Shopify/hydrogen/pull/1057) [`06d92ddc`](https://github.com/Shopify/hydrogen/commit/06d92ddc44e03d37d2dd8a9bbeaa5fab4c4bbbd1) Thanks [@frandiox](https://github.com/frandiox)! - Ability to concatenate requests in API route handlers without leaving the server by returning a new Request instance.
86
+
87
+ ```jsx
88
+ // src/routes/my-page.server.jsx
89
+
90
+ export async function api(request) {
91
+ if (request.method === 'POST') {
92
+ // do some work here...
93
+ }
94
+
95
+ return new Request(request.url, {method: 'GET'});
96
+ }
97
+
98
+ export default function Page() {
99
+ return (
100
+ <form action="/my-page" method="POST">
101
+ ...
102
+ </form>
103
+ );
104
+ }
105
+ ```
106
+
107
+ In the previous example, a POST request to `/my-page` would run the API handler and automatically continue with the server component rendering (GET). This is useful for handling HTML forms without waterfall requests.
108
+
109
+ - [#1049](https://github.com/Shopify/hydrogen/pull/1049) [`b88a885d`](https://github.com/Shopify/hydrogen/commit/b88a885d6b062209497a97d8ce7bcd438787d53c) Thanks [@wizardlyhel](https://github.com/wizardlyhel)! - Support sub request cache control header `stale-while-revalidate` everywhere
110
+
111
+ * [#1047](https://github.com/Shopify/hydrogen/pull/1047) [`5268bf85`](https://github.com/Shopify/hydrogen/commit/5268bf85f61f8abf0e97788b7ae925ad4f3183b2) Thanks [@jplhomer](https://github.com/jplhomer)! - Restore scroll position when navigating using the back and forward buttons.
112
+
113
+ - [#1062](https://github.com/Shopify/hydrogen/pull/1062) [`cc172ae7`](https://github.com/Shopify/hydrogen/commit/cc172ae778bad0d654adcd2f41d4a548d1d94a0a) Thanks [@jplhomer](https://github.com/jplhomer)! - Fix encoding of quotes in CSS Modules which caused hydration errors
114
+
115
+ * [#1046](https://github.com/Shopify/hydrogen/pull/1046) [`3947d53a`](https://github.com/Shopify/hydrogen/commit/3947d53a99868a1e218bfab958b824ce0484615a) Thanks [@michenly](https://github.com/michenly)! - Fixed server Cookie bug where initializing with empty string will resulted in 1 item in the Cookies Map.
116
+
117
+ - [#1059](https://github.com/Shopify/hydrogen/pull/1059) [`401f329d`](https://github.com/Shopify/hydrogen/commit/401f329d331bebc4842204d4df39c4dd6797b4e1) Thanks [@frandiox](https://github.com/frandiox)! - Fix link prefetch mismatch due to query-string
118
+
119
+ * [#1072](https://github.com/Shopify/hydrogen/pull/1072) [`47c0c184`](https://github.com/Shopify/hydrogen/commit/47c0c18411eb20fa6652a981b09fd65cbed38304) Thanks [@michenly](https://github.com/michenly)! - Improve type for ShopifyContextValue to be based on ShopifyConfig.
120
+
121
+ ## 0.14.0
122
+
123
+ ### Minor Changes
124
+
125
+ - [#1028](https://github.com/Shopify/hydrogen/pull/1028) [`ba174588`](https://github.com/Shopify/hydrogen/commit/ba174588d8f4a9f1054779a9bf32a92e8d2c921c) Thanks [@michenly](https://github.com/michenly)! - Starting from SF API version `2022-04`, the preferred way to request translatable resources is using the `@inContext` directive. See the [API docs](https://shopify.dev/api/examples/multiple-languages#retrieve-translations-with-the-storefront-api) on how to do this and which resources have translatable properties.
126
+
127
+ This causes a breaking change to the `useShopQuery` hook. The `locale` property has been removed from the argument object; `Accept-Language` is no longer being send with every request, and we are no longer using locale as part of the cache key.
128
+
129
+ The `useShop` hook will now return the `languageCode` key, which is the first two characters of the existing `locale` key.
130
+
131
+ Both `locale` & `languageCode` values are also now capitalized to make it easier to pass into a GraphQL `@inContext` directive.
132
+
133
+ * [#1020](https://github.com/Shopify/hydrogen/pull/1020) [`e9529bc8`](https://github.com/Shopify/hydrogen/commit/e9529bc81410e0d99f9d3dbdb138ae61d00f876b) Thanks [@jplhomer](https://github.com/jplhomer)! - Preload `Link` URLs by default when a user signals intent to visit the URL. This includes hovering or focusing on the URL. To disable preloading, pass `<Link preload={false} />` to the component.
134
+
135
+ ### Patch Changes
136
+
137
+ - [#1017](https://github.com/Shopify/hydrogen/pull/1017) [`4c87fb63`](https://github.com/Shopify/hydrogen/commit/4c87fb639a79da883f99c58acde0d17c713c7620) Thanks [@frandiox](https://github.com/frandiox)! - Do not cache Storefront API responses that contain GraphQL errors (amend previous fix).
138
+
139
+ * [#1039](https://github.com/Shopify/hydrogen/pull/1039) [`3a297862`](https://github.com/Shopify/hydrogen/commit/3a29786202947fab0bfe876042b37a91923ed637) Thanks [@frandiox](https://github.com/frandiox)! - Update to Vite 2.9
140
+
141
+ - [#1026](https://github.com/Shopify/hydrogen/pull/1026) [`836b064d`](https://github.com/Shopify/hydrogen/commit/836b064d1648fb1a9f209a08a82ee5c20f7dfba9) Thanks [@frehner](https://github.com/frehner)! - Updated the Typescript types and GraphQL schema to the newest updates from Storefront API 2022-04. Of note in this update is the ability to skip `edges` and go directly to `node`, for example: `product.nodes[0]` instead of `product.edges[0].node`
142
+
143
+ * [#1032](https://github.com/Shopify/hydrogen/pull/1032) [`03488083`](https://github.com/Shopify/hydrogen/commit/034880833dc500f66f9b67417c00099c283dfa67) Thanks [@jplhomer](https://github.com/jplhomer)! - Catch hydration errors related to experimental server components bugs and prevent them from being logged in production.
144
+
145
+ - [#1037](https://github.com/Shopify/hydrogen/pull/1037) [`13376efb`](https://github.com/Shopify/hydrogen/commit/13376efbe4db93efd705b6900a6198708bc37e69) Thanks [@jplhomer](https://github.com/jplhomer)! - Use new header for private Storefront token
146
+
3
147
  ## 0.13.2
4
148
 
5
149
  ### Patch Changes
@@ -2,8 +2,12 @@ export * from './components';
2
2
  export * from './hooks';
3
3
  export * from './foundation/useServerState';
4
4
  export * from './foundation/useShop';
5
+ export * from './foundation/useUrl';
5
6
  export * from './foundation/ServerStateProvider';
6
7
  export { Head } from './foundation/Head';
7
8
  export * from './utilities';
9
+ export { ClientAnalytics } from './foundation/Analytics';
8
10
  export { useRouteParams } from './foundation/useRouteParams/useRouteParams';
9
11
  export { useNavigate } from './foundation/useNavigate/useNavigate';
12
+ export { fetchSync } from './foundation/fetchSync/client/fetchSync';
13
+ export { suspendFunction, preloadFunction } from './utilities/suspense';
@@ -2,8 +2,12 @@ export * from './components';
2
2
  export * from './hooks';
3
3
  export * from './foundation/useServerState';
4
4
  export * from './foundation/useShop';
5
+ export * from './foundation/useUrl';
5
6
  export * from './foundation/ServerStateProvider';
6
7
  export { Head } from './foundation/Head';
7
8
  export * from './utilities';
9
+ export { ClientAnalytics } from './foundation/Analytics';
8
10
  export { useRouteParams } from './foundation/useRouteParams/useRouteParams';
9
11
  export { useNavigate } from './foundation/useNavigate/useNavigate';
12
+ export { fetchSync } from './foundation/fetchSync/client/fetchSync';
13
+ export { suspendFunction, preloadFunction } from './utilities/suspense';
@@ -5,6 +5,7 @@ import { useCartFetch } from './hooks';
5
5
  import { CartContext } from './context';
6
6
  import { CART_ID_STORAGE_KEY } from './constants';
7
7
  import { useServerState } from '../../foundation/useServerState';
8
+ import { ClientAnalytics } from '../../foundation/Analytics';
8
9
  function cartReducer(state, action) {
9
10
  switch (action.type) {
10
11
  case 'cartFetch': {
@@ -200,6 +201,12 @@ export function CartProvider({ children, numCartLines, onCreate, onLineAdd, onLi
200
201
  });
201
202
  }
202
203
  if ((_b = data === null || data === void 0 ? void 0 : data.cartCreate) === null || _b === void 0 ? void 0 : _b.cart) {
204
+ if (cart.lines) {
205
+ ClientAnalytics.publish(ClientAnalytics.eventNames.ADD_TO_CART, true, {
206
+ addedCartLines: cart.lines,
207
+ cart: data.cartCreate.cart,
208
+ });
209
+ }
203
210
  dispatch({
204
211
  type: 'resolve',
205
212
  cart: cartFromGraphQL(data.cartCreate.cart),
@@ -228,6 +235,10 @@ export function CartProvider({ children, numCartLines, onCreate, onLineAdd, onLi
228
235
  });
229
236
  }
230
237
  if ((_a = data === null || data === void 0 ? void 0 : data.cartLinesAdd) === null || _a === void 0 ? void 0 : _a.cart) {
238
+ ClientAnalytics.publish(ClientAnalytics.eventNames.ADD_TO_CART, true, {
239
+ addedCartLines: lines,
240
+ cart: data.cartLinesAdd.cart,
241
+ });
231
242
  dispatch({
232
243
  type: 'resolve',
233
244
  cart: cartFromGraphQL(data.cartLinesAdd.cart),
@@ -256,6 +267,10 @@ export function CartProvider({ children, numCartLines, onCreate, onLineAdd, onLi
256
267
  });
257
268
  }
258
269
  if ((_a = data === null || data === void 0 ? void 0 : data.cartLinesRemove) === null || _a === void 0 ? void 0 : _a.cart) {
270
+ ClientAnalytics.publish(ClientAnalytics.eventNames.REMOVE_FROM_CART, true, {
271
+ removedCartLines: lines,
272
+ cart: data.cartLinesRemove.cart,
273
+ });
259
274
  dispatch({
260
275
  type: 'resolve',
261
276
  cart: cartFromGraphQL(data.cartLinesRemove.cart),
@@ -284,6 +299,10 @@ export function CartProvider({ children, numCartLines, onCreate, onLineAdd, onLi
284
299
  });
285
300
  }
286
301
  if ((_a = data === null || data === void 0 ? void 0 : data.cartLinesUpdate) === null || _a === void 0 ? void 0 : _a.cart) {
302
+ ClientAnalytics.publish(ClientAnalytics.eventNames.UPDATE_CART, true, {
303
+ updatedCartLines: lines,
304
+ oldCart: state.cart,
305
+ });
287
306
  dispatch({
288
307
  type: 'resolve',
289
308
  cart: cartFromGraphQL(data.cartLinesUpdate.cart),
@@ -396,6 +415,10 @@ export function CartProvider({ children, numCartLines, onCreate, onLineAdd, onLi
396
415
  });
397
416
  }
398
417
  if ((_a = data === null || data === void 0 ? void 0 : data.cartDiscountCodesUpdate) === null || _a === void 0 ? void 0 : _a.cart) {
418
+ ClientAnalytics.publish(ClientAnalytics.eventNames.DISCOUNT_CODE_UPDATED, true, {
419
+ updatedDiscountCodes: discountCodes,
420
+ cart: data.cartDiscountCodesUpdate.cart,
421
+ });
399
422
  dispatch({
400
423
  type: 'resolve',
401
424
  cart: cartFromGraphQL(data.cartDiscountCodesUpdate.cart),
@@ -0,0 +1 @@
1
+ export default function DevTools(): JSX.Element | null;
@@ -0,0 +1,128 @@
1
+ import React, { useEffect, useState, useCallback } from 'react';
2
+ export default function DevTools() {
3
+ const [warnings, setWarnings] = useState(null);
4
+ const [open, setOpen] = useState(false);
5
+ const [activePanel, setActivePanel] = useState('warnings');
6
+ const toggleOpen = useCallback(() => setOpen((state) => !state), []);
7
+ const [hasMounted, setHasMounted] = React.useState(false);
8
+ useEffect(() => {
9
+ setHasMounted(true);
10
+ if (import.meta.hot) {
11
+ import.meta.hot.on('hydrogen', ({ type, data }) => {
12
+ if (type === 'warn') {
13
+ setWarnings((state) => [...(state || []), data]);
14
+ }
15
+ });
16
+ }
17
+ }, []);
18
+ const perfData = performance.getEntriesByType('navigation');
19
+ const entry = perfData[0];
20
+ let activePanelContent = null;
21
+ switch (activePanel) {
22
+ case 'warnings':
23
+ const warningsMarkup = warnings
24
+ ? warnings.map((war, i) => React.createElement("li", { key: war + i }, war))
25
+ : null;
26
+ activePanelContent = (React.createElement(React.Fragment, null,
27
+ React.createElement(PanelHeading, null, "Overfetched graphQL fields"),
28
+ React.createElement("ul", { style: {
29
+ fontFamily: 'monospace',
30
+ paddingTop: '1em',
31
+ fontSize: '0.9em',
32
+ } }, warningsMarkup)));
33
+ break;
34
+ case 'network':
35
+ activePanelContent = (React.createElement(React.Fragment, null,
36
+ React.createElement(PanelHeading, null, "Metrics"),
37
+ React.createElement("ul", { style: {
38
+ fontFamily: 'monospace',
39
+ paddingTop: '1em',
40
+ fontSize: '0.9em',
41
+ } }, Object.entries(entry.toJSON())
42
+ .filter(([key]) => ['duration', 'domInteractive'].includes(key))
43
+ .map(([key, value]) => (React.createElement("li", { key: key },
44
+ React.createElement("strong", null, key),
45
+ " ",
46
+ (value / 1000).toFixed(2),
47
+ "s"))))));
48
+ break;
49
+ }
50
+ const buttonText = (React.createElement("svg", { style: {
51
+ height: '3em',
52
+ width: '3em',
53
+ }, width: "131", height: "130", viewBox: "0 0 131 130", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
54
+ React.createElement("path", { d: "M64.9548 106.281L27.1377 86.1894L40.0714 79.3723L54.6329 87.1049L66.851 80.6638L52.2895 72.9313L65.2231 66.0979L103.04 86.1894L90.1065 93.0064L76.35 85.6989L64.114 92.1563L77.8884 99.4638L64.9548 106.281Z", fill: "white" }),
55
+ React.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M65.2247 25L105.178 46.2267L90.105 54.1716L76.3488 46.8642L66.2525 52.1924L80.028 59.5005L64.9532 67.446L25 46.2196L40.0734 38.2748L54.6349 46.0073L64.713 40.6944L50.1533 32.9628L65.2247 25ZM54.4262 32.9673L68.9896 40.7008L54.6315 48.27L40.0699 40.5374L29.276 46.2267L64.9569 65.1833L75.7495 59.4947L61.9761 52.1878L76.3518 44.6012L90.1087 51.9088L100.902 46.2196L65.2221 27.2634L54.4262 32.9673Z", fill: "white" })));
56
+ if (import.meta.env.DEV && hasMounted) {
57
+ return (React.createElement("div", { style: {
58
+ position: 'fixed',
59
+ right: open ? 0 : '2em',
60
+ left: open ? 0 : '2em',
61
+ bottom: open ? 0 : '-2em',
62
+ borderRadius: open ? 0 : '2em',
63
+ top: '100%',
64
+ zIndex: 10000,
65
+ display: 'flex',
66
+ flexDirection: 'column',
67
+ overflow: 'hidden',
68
+ height: open ? '75%' : '4em',
69
+ transform: open ? 'translateY(-100%)' : 'translateY(-5em)',
70
+ } },
71
+ React.createElement("button", { style: {
72
+ position: 'absolute',
73
+ top: '0.35em',
74
+ right: '1em',
75
+ overflow: 'hidden',
76
+ zIndex: 10,
77
+ }, onClick: toggleOpen }, buttonText),
78
+ React.createElement("div", { style: {
79
+ overflow: 'scroll',
80
+ color: 'white',
81
+ height: '100%',
82
+ padding: '2em',
83
+ background: 'rgba(0, 0, 0, 0.95)',
84
+ borderRadius: open ? 0 : '2em',
85
+ } },
86
+ React.createElement("div", { style: {
87
+ position: 'absolute',
88
+ padding: '1.2em 2em',
89
+ top: 0,
90
+ left: '-0.5em',
91
+ right: 0,
92
+ background: 'rgba(0, 0, 0, 0.95)',
93
+ borderRadius: open ? 0 : '2em',
94
+ display: 'flex',
95
+ alignItems: 'center',
96
+ } },
97
+ warnings && warnings.length > 0 && (React.createElement("button", { onClick: () => {
98
+ setOpen(true);
99
+ setActivePanel('warnings');
100
+ }, style: {
101
+ margin: '0 0.5em',
102
+ textDecoration: open && activePanel === 'warnings' ? 'underline' : 'none',
103
+ } },
104
+ "Warnings",
105
+ ' ',
106
+ warnings && (React.createElement("strong", { style: {
107
+ borderRadius: '2em',
108
+ padding: '.25em 0.5em',
109
+ background: 'white',
110
+ margin: '0 0.25em',
111
+ color: 'black',
112
+ textAlign: 'center',
113
+ } }, warnings.length)))),
114
+ React.createElement("button", { onClick: () => {
115
+ setOpen(true);
116
+ setActivePanel('network');
117
+ }, disabled: activePanel === 'network', style: {
118
+ margin: '0 0.5em',
119
+ textDecoration: open && activePanel === 'network' ? 'underline' : 'none',
120
+ } }, "Network")),
121
+ React.createElement("div", { style: { paddingTop: '2em' } }, activePanelContent))));
122
+ }
123
+ return null;
124
+ }
125
+ const PanelHeading = ({ children }) => (React.createElement("h1", { style: {
126
+ paddingTop: '1em',
127
+ fontWeight: 'bold',
128
+ } }, children));
@@ -8,6 +8,8 @@ export interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorEle
8
8
  clientState?: any;
9
9
  /** Whether to reload the whole document on navigation. */
10
10
  reloadDocument?: boolean;
11
+ /** Whether to prefetch the link source when the user signals intent. Defaults to `true`. For more information, refer to [Prefetching a link source](/custom-storefronts/hydrogen/framework/routes#prefetching-a-link-source). */
12
+ prefetch?: boolean;
11
13
  }
12
14
  /**
13
15
  * The `Link` component is used to navigate between routes. Because it renders an underlying `<a>` element, all
@@ -15,3 +17,7 @@ export interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorEle
15
17
  * For more information, refer to the [`<a>` element documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attributes).
16
18
  */
17
19
  export declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
20
+ /**
21
+ * Credit: Remix's <Link> component.
22
+ */
23
+ export declare function composeEventHandlers<EventType extends React.SyntheticEvent | Event>(theirHandler: ((event: EventType) => any) | undefined, ourHandler: (event: EventType) => any): (event: EventType) => any;
@@ -1,7 +1,9 @@
1
- import React, { useCallback } from 'react';
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
2
  import { useRouter } from '../../foundation/Router/BrowserRouter.client';
3
3
  import { createPath } from 'history';
4
4
  import { useNavigate } from '../../foundation/useNavigate/useNavigate';
5
+ import { useServerState } from '../../foundation/useServerState';
6
+ import { RSC_PATHNAME } from '../../constants';
5
7
  /**
6
8
  * The `Link` component is used to navigate between routes. Because it renders an underlying `<a>` element, all
7
9
  * properties available to the `<a>` element are also available to the `Link` component.
@@ -10,7 +12,13 @@ import { useNavigate } from '../../foundation/useNavigate/useNavigate';
10
12
  export const Link = React.forwardRef(function Link(props, ref) {
11
13
  const navigate = useNavigate();
12
14
  const { location } = useRouter();
13
- const { reloadDocument, target, replace: _replace, to, onClick, clientState, } = props;
15
+ const [_, startTransition] = React.useTransition();
16
+ /**
17
+ * Inspired by Remix's Link component
18
+ */
19
+ const [shouldPrefetch, setShouldPrefetch] = useState(false);
20
+ const [maybePrefetch, setMaybePrefetch] = useState(false);
21
+ const { reloadDocument, target, replace: _replace, to, onClick, clientState, prefetch = true, } = props;
14
22
  const internalClick = useCallback((e) => {
15
23
  if (onClick)
16
24
  onClick(e);
@@ -28,8 +36,82 @@ export const Link = React.forwardRef(function Link(props, ref) {
28
36
  });
29
37
  }
30
38
  }, [reloadDocument, target, _replace, to, clientState, onClick, location]);
31
- return (React.createElement("a", { ...without(props, ['to', 'replace', 'clientState', 'reloadDocument']), ref: ref, onClick: internalClick, href: props.to }, props.children));
39
+ const signalPrefetchIntent = () => {
40
+ /**
41
+ * startTransition to yield to more important updates
42
+ */
43
+ startTransition(() => {
44
+ if (prefetch) {
45
+ setMaybePrefetch(true);
46
+ }
47
+ });
48
+ };
49
+ const cancelPrefetchIntent = () => {
50
+ /**
51
+ * startTransition to yield to more important updates
52
+ */
53
+ startTransition(() => {
54
+ if (prefetch) {
55
+ setMaybePrefetch(false);
56
+ }
57
+ });
58
+ };
59
+ /**
60
+ * Wrapping `maybePrefetch` inside useEffect allows the user to quickly graze over
61
+ * a link without triggering a prefetch.
62
+ */
63
+ useEffect(() => {
64
+ if (maybePrefetch) {
65
+ const id = setTimeout(() => {
66
+ setShouldPrefetch(true);
67
+ }, 100);
68
+ return () => {
69
+ clearTimeout(id);
70
+ };
71
+ }
72
+ }, [maybePrefetch]);
73
+ const onMouseEnter = composeEventHandlers(props.onMouseEnter, signalPrefetchIntent);
74
+ const onMouseLeave = composeEventHandlers(props.onMouseLeave, cancelPrefetchIntent);
75
+ const onFocus = composeEventHandlers(props.onFocus, signalPrefetchIntent);
76
+ const onBlur = composeEventHandlers(props.onBlur, cancelPrefetchIntent);
77
+ const onTouchStart = composeEventHandlers(props.onTouchStart, signalPrefetchIntent);
78
+ return (React.createElement(React.Fragment, null,
79
+ React.createElement("a", { ...without(props, [
80
+ 'to',
81
+ 'replace',
82
+ 'clientState',
83
+ 'reloadDocument',
84
+ 'prefetch',
85
+ ]), ref: ref, onClick: internalClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onFocus: onFocus, onBlur: onBlur, onTouchStart: onTouchStart, href: props.to }, props.children),
86
+ shouldPrefetch && React.createElement(Prefetch, { pathname: to })));
32
87
  });
88
+ function Prefetch({ pathname }) {
89
+ const { getProposedServerState } = useServerState();
90
+ const { location } = useRouter();
91
+ const newPath = createPath({ pathname });
92
+ if (pathname.startsWith('http') || newPath === createPath(location)) {
93
+ return null;
94
+ }
95
+ const newLocation = new URL(newPath, window.location.href);
96
+ const proposedServerState = getProposedServerState({
97
+ pathname: newLocation.pathname,
98
+ search: newLocation.search,
99
+ });
100
+ const href = `${RSC_PATHNAME}?state=` +
101
+ encodeURIComponent(JSON.stringify(proposedServerState));
102
+ return React.createElement("link", { rel: "prefetch", as: "fetch", href: href });
103
+ }
104
+ /**
105
+ * Credit: Remix's <Link> component.
106
+ */
107
+ export function composeEventHandlers(theirHandler, ourHandler) {
108
+ return (event) => {
109
+ theirHandler === null || theirHandler === void 0 ? void 0 : theirHandler(event);
110
+ if (!event.defaultPrevented) {
111
+ ourHandler(event);
112
+ }
113
+ };
114
+ }
33
115
  function isModifiedEvent(event) {
34
116
  return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
35
117
  }
@@ -1,4 +1,4 @@
1
- import { LocalizationQuery } from './LocalizationQuery';
1
+ import type { LocalizationQuery } from './LocalizationProvider.server';
2
2
  export declare type Localization = LocalizationQuery['localization'];
3
3
  export interface LocalizationContextValue {
4
4
  country?: Localization['country'];
@@ -1,5 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { PreloadOptions } from '../../types';
3
+ import { Country, Currency } from '../../storefront-api-types';
3
4
  export interface LocalizationProviderProps {
4
5
  /** A `ReactNode` element. */
5
6
  children: ReactNode;
@@ -19,3 +20,18 @@ export interface LocalizationProviderProps {
19
20
  * `@inContext` directive as the `country` value.
20
21
  */
21
22
  export declare function LocalizationProvider(props: LocalizationProviderProps): JSX.Element;
23
+ export declare type LocalizationQuery = {
24
+ __typename?: 'QueryRoot';
25
+ } & {
26
+ localization: {
27
+ __typename?: 'Localization';
28
+ } & {
29
+ country: {
30
+ __typename?: 'Country';
31
+ } & Pick<Country, 'isoCode' | 'name'> & {
32
+ currency: {
33
+ __typename?: 'Currency';
34
+ } & Pick<Currency, 'isoCode'>;
35
+ };
36
+ };
37
+ };
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import LocalizationClientProvider from './LocalizationClientProvider.client';
3
+ import { useShop } from '../../foundation/useShop';
3
4
  import { useShopQuery } from '../../hooks/useShopQuery';
4
5
  import { CacheDays } from '../../framework/CachingStrategy';
5
6
  /**
@@ -12,15 +13,19 @@ import { CacheDays } from '../../framework/CachingStrategy';
12
13
  * `@inContext` directive as the `country` value.
13
14
  */
14
15
  export function LocalizationProvider(props) {
16
+ const { languageCode } = useShop();
15
17
  const { data: { localization }, } = useShopQuery({
16
18
  query: query,
19
+ variables: { language: languageCode },
17
20
  cache: CacheDays(),
18
21
  preload: props.preload,
19
22
  });
20
23
  return (React.createElement(LocalizationClientProvider, { localization: localization }, props.children));
21
24
  }
22
- const query = `query Localization {
23
- localization {
25
+ const query = `
26
+ query Localization($language: LanguageCode)
27
+ @inContext(language: $language) {
28
+ localization {
24
29
  country {
25
30
  isoCode
26
31
  name
@@ -5,8 +5,7 @@ import { TitleSeo } from './TitleSeo.client';
5
5
  import { DescriptionSeo } from './DescriptionSeo.client';
6
6
  import { TwitterSeo } from './TwitterSeo.client';
7
7
  export function DefaultPageSeo({ title, description, url, titleTemplate, lang, }) {
8
- const { locale } = useShop();
9
- const fallBacklang = locale.split(/[-_]/)[0];
8
+ const { languageCode: fallBacklang } = useShop();
10
9
  return (React.createElement(React.Fragment, null,
11
10
  React.createElement(Head, { defaultTitle: title !== null && title !== void 0 ? title : '', titleTemplate: titleTemplate !== null && titleTemplate !== void 0 ? titleTemplate : `%s - ${title}` },
12
11
  React.createElement("html", { lang: lang !== null && lang !== void 0 ? lang : fallBacklang }),
@@ -1 +1,7 @@
1
1
  export declare const RSC_PATHNAME = "/__rsc";
2
+ export declare const EVENT_PATHNAME = "/__event";
3
+ export declare const EVENT_PATHNAME_REGEX: RegExp;
4
+ export declare const OXYGEN_SECRET_TOKEN_ENVIRONMENT_VARIABLE = "SHOPIFY_STOREFRONT_API_SECRET_TOKEN";
5
+ export declare const STOREFRONT_API_SECRET_TOKEN_HEADER = "Shopify-Storefront-Private-Token";
6
+ export declare const STOREFRONT_API_PUBLIC_TOKEN_HEADER = "X-Shopify-Storefront-Access-Token";
7
+ export declare const STOREFRONT_API_BUYER_IP_HEADER = "Shopify-Storefront-Buyer-IP";
@@ -1 +1,7 @@
1
1
  export const RSC_PATHNAME = '/__rsc';
2
+ export const EVENT_PATHNAME = '/__event';
3
+ export const EVENT_PATHNAME_REGEX = new RegExp(`^${EVENT_PATHNAME}\/`);
4
+ export const OXYGEN_SECRET_TOKEN_ENVIRONMENT_VARIABLE = 'SHOPIFY_STOREFRONT_API_SECRET_TOKEN';
5
+ export const STOREFRONT_API_SECRET_TOKEN_HEADER = 'Shopify-Storefront-Private-Token';
6
+ export const STOREFRONT_API_PUBLIC_TOKEN_HEADER = 'X-Shopify-Storefront-Access-Token';
7
+ export const STOREFRONT_API_BUYER_IP_HEADER = 'Shopify-Storefront-Buyer-IP';
@@ -4,6 +4,7 @@ import { hydrateRoot } from 'react-dom/client';
4
4
  import { ErrorBoundary } from 'react-error-boundary';
5
5
  import { useServerResponse } from './framework/Hydration/rsc';
6
6
  import { ServerStateProvider } from './foundation/ServerStateProvider';
7
+ const DevTools = React.lazy(() => import('./components/DevTools'));
7
8
  const renderHydrogen = async (ClientWrapper, config) => {
8
9
  const root = document.getElementById('root');
9
10
  if (!root) {
@@ -19,10 +20,25 @@ const renderHydrogen = async (ClientWrapper, config) => {
19
20
  }
20
21
  // default to StrictMode on, unless explicitly turned off
21
22
  const RootComponent = (config === null || config === void 0 ? void 0 : config.strictMode) !== false ? StrictMode : Fragment;
22
- hydrateRoot(root, React.createElement(RootComponent, null,
23
- React.createElement(ErrorBoundary, { FallbackComponent: Error },
24
- React.createElement(Suspense, { fallback: null },
25
- React.createElement(Content, { clientWrapper: ClientWrapper })))));
23
+ let hasCaughtError = false;
24
+ hydrateRoot(root, React.createElement(React.Fragment, null,
25
+ React.createElement(RootComponent, null,
26
+ React.createElement(ErrorBoundary, { FallbackComponent: Error },
27
+ React.createElement(Suspense, { fallback: null },
28
+ React.createElement(Content, { clientWrapper: ClientWrapper })))),
29
+ typeof DevTools !== 'undefined' && (config === null || config === void 0 ? void 0 : config.showDevTools) ? (React.createElement(DevTools, null)) : null), {
30
+ onRecoverableError(e) {
31
+ if (__DEV__ && !hasCaughtError) {
32
+ hasCaughtError = true;
33
+ console.log(`React encountered an error while attempting to hydrate the application. ` +
34
+ `This is likely due to a bug in React's Suspense behavior related to experimental server components, ` +
35
+ `and it is safe to ignore this error.\n` +
36
+ `Visit this issue to learn more: https://github.com/Shopify/hydrogen/issues/920.\n\n` +
37
+ `The original error is printed below:`);
38
+ console.log(e);
39
+ }
40
+ },
41
+ });
26
42
  };
27
43
  export default renderHydrogen;
28
44
  function Content({ clientWrapper: ClientWrapper = ({ children }) => children, }) {
@@ -19,5 +19,5 @@ interface RequestHandlerOptions {
19
19
  export interface RequestHandler {
20
20
  (request: Request | IncomingMessage, options: RequestHandlerOptions): Promise<Response | undefined>;
21
21
  }
22
- export declare const renderHydrogen: (App: any, { shopifyConfig, routes }: ServerHandlerConfig) => RequestHandler;
22
+ export declare const renderHydrogen: (App: any, { shopifyConfig, routes, serverAnalyticsConnectors }: ServerHandlerConfig) => RequestHandler;
23
23
  export default renderHydrogen;