@shopify/hydrogen 0.14.0 → 0.16.1
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.
- package/CHANGELOG.md +124 -0
- package/dist/esnext/client.d.ts +4 -0
- package/dist/esnext/client.js +4 -0
- package/dist/esnext/components/CartProvider/CartProvider.client.js +23 -0
- package/dist/esnext/components/DevTools.d.ts +1 -0
- package/dist/esnext/components/DevTools.js +128 -0
- package/dist/esnext/components/Link/Link.client.js +1 -1
- package/dist/esnext/constants.d.ts +6 -0
- package/dist/esnext/constants.js +6 -0
- package/dist/esnext/entry-client.js +7 -4
- package/dist/esnext/entry-server.d.ts +1 -1
- package/dist/esnext/entry-server.js +29 -15
- package/dist/esnext/foundation/Analytics/Analytics.client.d.ts +3 -0
- package/dist/esnext/foundation/Analytics/Analytics.client.js +28 -0
- package/dist/esnext/foundation/Analytics/Analytics.server.d.ts +1 -0
- package/dist/esnext/foundation/Analytics/Analytics.server.js +38 -0
- package/dist/esnext/foundation/Analytics/ClientAnalytics.d.ts +24 -0
- package/dist/esnext/foundation/Analytics/ClientAnalytics.js +91 -0
- package/dist/esnext/foundation/Analytics/ServerAnalyticsRoute.server.d.ts +2 -0
- package/dist/esnext/foundation/Analytics/ServerAnalyticsRoute.server.js +33 -0
- package/dist/esnext/foundation/Analytics/const.d.ts +8 -0
- package/dist/esnext/foundation/Analytics/const.js +8 -0
- package/dist/esnext/foundation/Analytics/hook.d.ts +1 -0
- package/dist/esnext/foundation/Analytics/hook.js +7 -0
- package/dist/esnext/foundation/Analytics/index.d.ts +2 -0
- package/dist/esnext/foundation/Analytics/index.js +2 -0
- package/dist/esnext/foundation/Analytics/types.d.ts +5 -0
- package/dist/esnext/foundation/Analytics/types.js +1 -0
- package/dist/esnext/foundation/Analytics/utils.d.ts +1 -0
- package/dist/esnext/foundation/Analytics/utils.js +8 -0
- package/dist/esnext/foundation/Boomerang/Boomerang.client.js +3 -1
- package/dist/esnext/foundation/Route/Route.server.js +4 -0
- package/dist/esnext/foundation/Router/BrowserRouter.client.js +68 -15
- package/dist/esnext/foundation/ServerRequestProvider/ServerRequestProvider.js +1 -1
- package/dist/esnext/foundation/ShopifyProvider/types.d.ts +2 -5
- package/dist/esnext/foundation/fetchSync/client/fetchSync.d.ts +10 -0
- package/dist/esnext/foundation/fetchSync/client/fetchSync.js +27 -0
- package/dist/esnext/foundation/fetchSync/server/fetchSync.d.ts +8 -0
- package/dist/esnext/foundation/fetchSync/server/fetchSync.js +27 -0
- package/dist/esnext/foundation/fetchSync/types.d.ts +5 -0
- package/dist/esnext/foundation/fetchSync/types.js +1 -0
- package/dist/esnext/foundation/useQuery/hooks.d.ts +4 -2
- package/dist/esnext/foundation/useQuery/hooks.js +10 -6
- package/dist/esnext/foundation/useUrl/useUrl.js +8 -1
- package/dist/esnext/framework/Hydration/ServerComponentRequest.server.d.ts +1 -0
- package/dist/esnext/framework/Hydration/ServerComponentRequest.server.js +11 -5
- package/dist/esnext/framework/cache/in-memory.js +5 -5
- package/dist/esnext/framework/cache.d.ts +1 -2
- package/dist/esnext/framework/cache.js +67 -22
- package/dist/esnext/framework/plugin.js +10 -0
- package/dist/esnext/framework/plugins/vite-plugin-css-modules-rsc.js +1 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.js +11 -2
- package/dist/esnext/hooks/useShopQuery/hooks.js +32 -25
- package/dist/esnext/index.d.ts +2 -0
- package/dist/esnext/index.js +2 -0
- package/dist/esnext/types.d.ts +6 -1
- package/dist/esnext/utilities/apiRoutes.d.ts +2 -3
- package/dist/esnext/utilities/apiRoutes.js +14 -9
- package/dist/esnext/utilities/hash.d.ts +2 -0
- package/dist/esnext/utilities/hash.js +7 -0
- package/dist/esnext/utilities/log/log-cache-api-status.js +1 -1
- package/dist/esnext/utilities/log/log-cache-header.js +1 -1
- package/dist/esnext/utilities/log/log-query-timeline.js +1 -1
- package/dist/esnext/utilities/storefrontApi.d.ts +4 -0
- package/dist/esnext/utilities/storefrontApi.js +21 -0
- package/dist/esnext/utilities/suspense.d.ts +5 -0
- package/dist/esnext/utilities/suspense.js +32 -0
- package/dist/esnext/utilities/template.js +1 -1
- package/dist/esnext/version.d.ts +1 -1
- package/dist/esnext/version.js +1 -1
- package/dist/node/constants.d.ts +6 -0
- package/dist/node/constants.js +7 -1
- package/dist/node/entry-server.d.ts +1 -1
- package/dist/node/entry-server.js +28 -17
- package/dist/node/foundation/Analytics/Analytics.client.d.ts +3 -0
- package/dist/node/foundation/Analytics/Analytics.client.js +32 -0
- package/dist/node/foundation/Analytics/Analytics.server.d.ts +1 -0
- package/dist/node/foundation/Analytics/Analytics.server.js +45 -0
- package/dist/node/foundation/Analytics/ClientAnalytics.d.ts +24 -0
- package/dist/node/foundation/Analytics/ClientAnalytics.js +94 -0
- package/dist/node/foundation/Analytics/ServerAnalyticsRoute.server.d.ts +2 -0
- package/dist/node/foundation/Analytics/ServerAnalyticsRoute.server.js +37 -0
- package/dist/node/foundation/Analytics/const.d.ts +8 -0
- package/dist/node/foundation/Analytics/const.js +11 -0
- package/dist/node/foundation/Analytics/hook.d.ts +1 -0
- package/dist/node/foundation/Analytics/hook.js +11 -0
- package/dist/node/foundation/Analytics/index.d.ts +2 -0
- package/dist/node/foundation/Analytics/index.js +7 -0
- package/dist/node/foundation/Analytics/types.d.ts +5 -0
- package/dist/node/foundation/Analytics/types.js +2 -0
- package/dist/node/foundation/Analytics/utils.d.ts +1 -0
- package/dist/node/foundation/Analytics/utils.js +12 -0
- package/dist/node/foundation/Router/BrowserRouter.client.js +67 -14
- package/dist/node/foundation/ServerRequestProvider/ServerRequestProvider.js +2 -2
- package/dist/node/foundation/ShopifyProvider/types.d.ts +2 -5
- package/dist/node/framework/Hydration/ServerComponentRequest.server.d.ts +1 -0
- package/dist/node/framework/Hydration/ServerComponentRequest.server.js +13 -7
- package/dist/node/framework/cache/in-memory.js +5 -5
- package/dist/node/framework/cache.d.ts +1 -2
- package/dist/node/framework/cache.js +71 -27
- package/dist/node/framework/plugin.js +10 -0
- package/dist/node/framework/plugins/vite-plugin-css-modules-rsc.js +1 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-config.js +11 -2
- package/dist/node/types.d.ts +6 -1
- package/dist/node/utilities/apiRoutes.d.ts +2 -3
- package/dist/node/utilities/apiRoutes.js +14 -9
- package/dist/node/utilities/flattenConnection/flattenConnection.d.ts +6 -0
- package/dist/node/utilities/flattenConnection/flattenConnection.js +15 -0
- package/dist/node/utilities/flattenConnection/index.d.ts +1 -0
- package/dist/node/utilities/flattenConnection/index.js +5 -0
- package/dist/node/utilities/hash.d.ts +2 -0
- package/dist/node/utilities/hash.js +11 -0
- package/dist/node/utilities/image_size.d.ts +30 -0
- package/dist/node/utilities/image_size.js +110 -0
- package/dist/node/utilities/index.d.ts +11 -0
- package/dist/node/utilities/index.js +32 -0
- package/dist/node/utilities/isClient/index.d.ts +1 -0
- package/dist/node/utilities/isClient/index.js +5 -0
- package/dist/node/utilities/isClient/isClient.d.ts +4 -0
- package/dist/node/utilities/isClient/isClient.js +10 -0
- package/dist/node/utilities/isServer/index.d.ts +1 -0
- package/dist/node/utilities/isServer/index.js +5 -0
- package/dist/node/utilities/isServer/isServer.d.ts +4 -0
- package/dist/node/utilities/isServer/isServer.js +11 -0
- package/dist/node/utilities/load_script.d.ts +3 -0
- package/dist/node/utilities/load_script.js +27 -0
- package/dist/node/utilities/log/log-cache-api-status.js +1 -1
- package/dist/node/utilities/log/log-cache-header.js +2 -2
- package/dist/node/utilities/log/log-query-timeline.js +2 -2
- package/dist/node/utilities/measurement.d.ts +3 -0
- package/dist/node/utilities/measurement.js +103 -0
- package/dist/node/utilities/parseMetafieldValue/index.d.ts +1 -0
- package/dist/node/utilities/parseMetafieldValue/index.js +5 -0
- package/dist/node/utilities/parseMetafieldValue/parseMetafieldValue.d.ts +6 -0
- package/dist/node/utilities/parseMetafieldValue/parseMetafieldValue.js +39 -0
- package/dist/node/utilities/storefrontApi.d.ts +4 -0
- package/dist/node/utilities/storefrontApi.js +25 -0
- package/dist/node/utilities/suspense.d.ts +12 -0
- package/dist/node/utilities/suspense.js +64 -0
- package/dist/node/utilities/template.js +1 -1
- package/dist/node/utilities/video_parameters.d.ts +47 -0
- package/dist/node/utilities/video_parameters.js +27 -0
- package/dist/node/version.d.ts +1 -1
- package/dist/node/version.js +1 -1
- package/package.json +1 -1
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +9 -21
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +51 -47
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +30 -29
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +51 -47
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +17 -17
- package/vendor/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +55 -45
- package/vendor/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +9 -21
- package/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +51 -47
- package/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +51 -47
- package/vendor/react-server-dom-vite/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,129 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.16.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1102](https://github.com/Shopify/hydrogen/pull/1102) [`59ee791a`](https://github.com/Shopify/hydrogen/commit/59ee791ac81f41764b4ab3e5dd667c0c72b672d3) Thanks [@frandiox](https://github.com/frandiox)! - Do not call client exported functions during RSC.
|
|
8
|
+
|
|
9
|
+
## 0.16.0
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#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.
|
|
14
|
+
|
|
15
|
+
Example:
|
|
16
|
+
|
|
17
|
+
```jsx
|
|
18
|
+
import {useUrl} from '@shopify/hydrogen/client';
|
|
19
|
+
|
|
20
|
+
function MyClientComponent() {
|
|
21
|
+
const url = useUrl();
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
// Record navigation, analytics, etc
|
|
25
|
+
}, [url]);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
* [#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
|
|
30
|
+
|
|
31
|
+
## 0.15.0
|
|
32
|
+
|
|
33
|
+
### Minor Changes
|
|
34
|
+
|
|
35
|
+
- [#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.
|
|
36
|
+
|
|
37
|
+
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)>):
|
|
38
|
+
|
|
39
|
+
```jsx
|
|
40
|
+
import {fetchSync, CacheMinutes} from '@shopify/hydrogen';
|
|
41
|
+
import {Suspense} from 'react';
|
|
42
|
+
|
|
43
|
+
export function MyServerComponent() {
|
|
44
|
+
return (
|
|
45
|
+
<Suspense fallback="Loading...">
|
|
46
|
+
<MyThings />
|
|
47
|
+
</Suspense>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function MyThings() {
|
|
52
|
+
const things = fetchSync('https://3p.api.com/things.json', {
|
|
53
|
+
preload: true,
|
|
54
|
+
cache: CacheMinutes(),
|
|
55
|
+
}).json();
|
|
56
|
+
|
|
57
|
+
return <h2>{things.title}</h2>;
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
When using `fetchSync` in client components, you cannot provide options for caching and preloading. You must import `fetchSync` from `@shopify/hydrogen/client`:
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
import {fetchSync} from '@shopify/hydrogen/client';
|
|
65
|
+
import {Suspense} from 'react';
|
|
66
|
+
|
|
67
|
+
export function MyClientComponent() {
|
|
68
|
+
return (
|
|
69
|
+
<Suspense fallback="Loading...">
|
|
70
|
+
<MyThings />
|
|
71
|
+
</Suspense>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function MyThings() {
|
|
76
|
+
const things = fetchSync('https://3p.api.com/things.json').json();
|
|
77
|
+
|
|
78
|
+
return <h2>{things.title}</h2>;
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
* [#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
|
|
83
|
+
and client side analytics instrumentations
|
|
84
|
+
|
|
85
|
+
- [Usage documentation](https://shopify.dev/custom-storefronts/hydrogen/framework/analytics)
|
|
86
|
+
|
|
87
|
+
### Patch Changes
|
|
88
|
+
|
|
89
|
+
- [#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
|
|
90
|
+
|
|
91
|
+
* [#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.
|
|
92
|
+
|
|
93
|
+
```jsx
|
|
94
|
+
// src/routes/my-page.server.jsx
|
|
95
|
+
|
|
96
|
+
export async function api(request) {
|
|
97
|
+
if (request.method === 'POST') {
|
|
98
|
+
// do some work here...
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return new Request(request.url, {method: 'GET'});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default function Page() {
|
|
105
|
+
return (
|
|
106
|
+
<form action="/my-page" method="POST">
|
|
107
|
+
...
|
|
108
|
+
</form>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
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.
|
|
114
|
+
|
|
115
|
+
- [#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
|
|
116
|
+
|
|
117
|
+
* [#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.
|
|
118
|
+
|
|
119
|
+
- [#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
|
|
120
|
+
|
|
121
|
+
* [#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.
|
|
122
|
+
|
|
123
|
+
- [#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
|
|
124
|
+
|
|
125
|
+
* [#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.
|
|
126
|
+
|
|
3
127
|
## 0.14.0
|
|
4
128
|
|
|
5
129
|
### Minor Changes
|
package/dist/esnext/client.d.ts
CHANGED
|
@@ -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';
|
package/dist/esnext/client.js
CHANGED
|
@@ -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));
|
|
@@ -95,7 +95,7 @@ function Prefetch({ pathname }) {
|
|
|
95
95
|
const newLocation = new URL(newPath, window.location.href);
|
|
96
96
|
const proposedServerState = getProposedServerState({
|
|
97
97
|
pathname: newLocation.pathname,
|
|
98
|
-
search: newLocation.search
|
|
98
|
+
search: newLocation.search,
|
|
99
99
|
});
|
|
100
100
|
const href = `${RSC_PATHNAME}?state=` +
|
|
101
101
|
encodeURIComponent(JSON.stringify(proposedServerState));
|
|
@@ -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";
|
package/dist/esnext/constants.js
CHANGED
|
@@ -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) {
|
|
@@ -20,10 +21,12 @@ const renderHydrogen = async (ClientWrapper, config) => {
|
|
|
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
23
|
let hasCaughtError = false;
|
|
23
|
-
hydrateRoot(root, React.createElement(
|
|
24
|
-
React.createElement(
|
|
25
|
-
React.createElement(
|
|
26
|
-
React.createElement(
|
|
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), {
|
|
27
30
|
onRecoverableError(e) {
|
|
28
31
|
if (__DEV__ && !hasCaughtError) {
|
|
29
32
|
hasCaughtError = true;
|
|
@@ -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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { Suspense } from 'react';
|
|
2
2
|
import { logServerResponse, logCacheControlHeaders, logQueryTimings, getLoggerWithContext, } from './utilities/log';
|
|
3
3
|
import { getErrorMarkup } from './utilities/error';
|
|
4
4
|
import { defer } from './utilities/defer';
|
|
@@ -12,13 +12,16 @@ import { isBotUA } from './utilities/bot-ua';
|
|
|
12
12
|
import { setContext, setCache } from './framework/runtime';
|
|
13
13
|
import { setConfig } from './framework/config';
|
|
14
14
|
import { ssrRenderToPipeableStream, ssrRenderToReadableStream, rscRenderToReadableStream, createFromReadableStream, isStreamingSupported, bufferReadableStream, } from './streaming.server';
|
|
15
|
-
import { RSC_PATHNAME } from './constants';
|
|
15
|
+
import { RSC_PATHNAME, EVENT_PATHNAME, EVENT_PATHNAME_REGEX } from './constants';
|
|
16
16
|
import { stripScriptsFromTemplate } from './utilities/template';
|
|
17
|
+
import { Analytics } from './foundation/Analytics/Analytics.server';
|
|
18
|
+
import { ServerAnalyticsRoute } from './foundation/Analytics/ServerAnalyticsRoute.server';
|
|
17
19
|
const DOCTYPE = '<!DOCTYPE html>';
|
|
18
20
|
const CONTENT_TYPE = 'Content-Type';
|
|
19
21
|
const HTML_CONTENT_TYPE = 'text/html; charset=UTF-8';
|
|
20
|
-
export const renderHydrogen = (App, { shopifyConfig, routes }) => {
|
|
21
|
-
const handleRequest = async function (rawRequest,
|
|
22
|
+
export const renderHydrogen = (App, { shopifyConfig, routes, serverAnalyticsConnectors }) => {
|
|
23
|
+
const handleRequest = async function (rawRequest, options) {
|
|
24
|
+
const { indexTemplate, streamableResponse, dev, cache, context, nonce, buyerIpHeader, } = options;
|
|
22
25
|
const request = new ServerComponentRequest(rawRequest);
|
|
23
26
|
request.ctx.buyerIpHeader = buyerIpHeader;
|
|
24
27
|
const url = new URL(request.url);
|
|
@@ -30,24 +33,31 @@ export const renderHydrogen = (App, { shopifyConfig, routes }) => {
|
|
|
30
33
|
setCache(cache);
|
|
31
34
|
setContext(context);
|
|
32
35
|
setConfig({ dev });
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
: indexTemplate;
|
|
37
|
-
if (template && typeof template !== 'string') {
|
|
38
|
-
template = template.default;
|
|
36
|
+
if (url.pathname === EVENT_PATHNAME ||
|
|
37
|
+
EVENT_PATHNAME_REGEX.test(url.pathname)) {
|
|
38
|
+
return ServerAnalyticsRoute(request, serverAnalyticsConnectors);
|
|
39
39
|
}
|
|
40
|
+
const isReactHydrationRequest = url.pathname === RSC_PATHNAME;
|
|
40
41
|
if (!isReactHydrationRequest && routes) {
|
|
41
42
|
const apiRoute = getApiRoute(url, { routes });
|
|
42
43
|
// The API Route might have a default export, making it also a server component
|
|
43
44
|
// If it does, only render the API route if the request method is GET
|
|
44
45
|
if (apiRoute &&
|
|
45
46
|
(!apiRoute.hasServerComponent || request.method !== 'GET')) {
|
|
46
|
-
|
|
47
|
+
const apiResponse = await renderApiRoute(request, apiRoute, shopifyConfig);
|
|
48
|
+
return apiResponse instanceof Request
|
|
49
|
+
? handleRequest(apiResponse, options)
|
|
50
|
+
: apiResponse;
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
53
|
const isStreamable = !isBotUA(url, request.headers.get('user-agent')) &&
|
|
50
54
|
(!!streamableResponse || (await isStreamingSupported()));
|
|
55
|
+
let template = typeof indexTemplate === 'function'
|
|
56
|
+
? await indexTemplate(url.toString())
|
|
57
|
+
: indexTemplate;
|
|
58
|
+
if (template && typeof template !== 'string') {
|
|
59
|
+
template = template.default;
|
|
60
|
+
}
|
|
51
61
|
const params = {
|
|
52
62
|
App,
|
|
53
63
|
log,
|
|
@@ -381,7 +391,9 @@ function buildAppRSC({ App, state, request, response, log, routes, }) {
|
|
|
381
391
|
request.ctx.router.serverProps = serverProps;
|
|
382
392
|
const AppRSC = (React.createElement(ServerRequestProvider, { request: request, isRSC: true },
|
|
383
393
|
React.createElement(PreloadQueries, { request: request },
|
|
384
|
-
React.createElement(App, { ...serverProps })
|
|
394
|
+
React.createElement(App, { ...serverProps }),
|
|
395
|
+
React.createElement(Suspense, { fallback: null },
|
|
396
|
+
React.createElement(Analytics, null)))));
|
|
385
397
|
return { AppRSC };
|
|
386
398
|
}
|
|
387
399
|
function buildAppSSR({ App, state, request, response, log, routes }, htmlOptions) {
|
|
@@ -400,14 +412,16 @@ function buildAppSSR({ App, state, request, response, log, routes }, htmlOptions
|
|
|
400
412
|
React.createElement(ServerRequestProvider, { request: request, isRSC: false },
|
|
401
413
|
React.createElement(ServerStateProvider, { serverState: state, setServerState: () => { } },
|
|
402
414
|
React.createElement(PreloadQueries, { request: request },
|
|
403
|
-
React.createElement(
|
|
404
|
-
React.createElement(RscConsumer, null))
|
|
415
|
+
React.createElement(Suspense, { fallback: null },
|
|
416
|
+
React.createElement(RscConsumer, null)),
|
|
417
|
+
React.createElement(Suspense, { fallback: null },
|
|
418
|
+
React.createElement(Analytics, null)))))));
|
|
405
419
|
return { AppSSR, rscReadable: rscReadableForFlight };
|
|
406
420
|
}
|
|
407
421
|
function PreloadQueries({ request, children, }) {
|
|
408
422
|
const preloadQueries = request.getPreloadQueries();
|
|
409
423
|
preloadRequestCacheData(request, preloadQueries);
|
|
410
|
-
return children;
|
|
424
|
+
return React.createElement(React.Fragment, null, children);
|
|
411
425
|
}
|
|
412
426
|
async function renderToBufferedString(ReactApp, { log, nonce }) {
|
|
413
427
|
return new Promise(async (resolve, reject) => {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { ClientAnalytics } from './index';
|
|
3
|
+
export function Analytics({ analyticsDataFromServer, }) {
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
6
|
+
if (urlParams.has('utm_source')) {
|
|
7
|
+
ClientAnalytics.pushToPageAnalyticsData({
|
|
8
|
+
id: urlParams.get('utm_id'),
|
|
9
|
+
source: urlParams.get('utm_source'),
|
|
10
|
+
campaign: urlParams.get('utm_campaign'),
|
|
11
|
+
medium: urlParams.get('utm_medium'),
|
|
12
|
+
content: urlParams.get('utm_content'),
|
|
13
|
+
term: urlParams.get('utm_term'),
|
|
14
|
+
}, 'utm');
|
|
15
|
+
}
|
|
16
|
+
ClientAnalytics.pushToPageAnalyticsData(analyticsDataFromServer);
|
|
17
|
+
ClientAnalytics.publish(ClientAnalytics.eventNames.PAGE_VIEW, true);
|
|
18
|
+
if (analyticsDataFromServer.publishEventsOnNavigate) {
|
|
19
|
+
analyticsDataFromServer.publishEventsOnNavigate.forEach((eventName) => {
|
|
20
|
+
ClientAnalytics.publish(eventName, true);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return function cleanup() {
|
|
24
|
+
ClientAnalytics.resetPageAnalyticsData();
|
|
25
|
+
};
|
|
26
|
+
}, [analyticsDataFromServer]);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function Analytics(): JSX.Element;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useServerAnalytics } from './hook';
|
|
3
|
+
import { Analytics as AnalyticsClient } from './Analytics.client';
|
|
4
|
+
import { useServerRequest } from '../ServerRequestProvider';
|
|
5
|
+
const DELAY_KEY = 'analytics-delay';
|
|
6
|
+
export function Analytics() {
|
|
7
|
+
const cache = useServerRequest().ctx.cache;
|
|
8
|
+
// If render cache is empty, create a 50 ms delay so that React doesn't resolve this
|
|
9
|
+
// component too early and potentially cause a mismatch in hydration
|
|
10
|
+
if (cache.size === 0 && !cache.has(DELAY_KEY)) {
|
|
11
|
+
let result;
|
|
12
|
+
let promise;
|
|
13
|
+
cache.set(DELAY_KEY, () => {
|
|
14
|
+
if (result !== undefined) {
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
if (!promise) {
|
|
18
|
+
promise = new Promise((resolve) => {
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
result = true;
|
|
21
|
+
resolve(true);
|
|
22
|
+
}, 50);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
throw promise;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
// Make sure all queries have returned before rendering the Analytics server component
|
|
29
|
+
cache.forEach((cacheFn) => {
|
|
30
|
+
if (cacheFn && typeof cacheFn === 'function') {
|
|
31
|
+
const result = cacheFn.call();
|
|
32
|
+
if (result instanceof Promise)
|
|
33
|
+
throw result;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const analyticsData = useServerAnalytics();
|
|
37
|
+
return React.createElement(AnalyticsClient, { analyticsDataFromServer: analyticsData });
|
|
38
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Subscriber, SubscriberFunction } from './types';
|
|
2
|
+
declare function pushToPageAnalyticsData(data: any, namespace?: string): void;
|
|
3
|
+
declare function getPageAnalyticsData(): any;
|
|
4
|
+
declare function resetPageAnalyticsData(): void;
|
|
5
|
+
declare function publish(eventname: string, guardDup?: boolean, payload?: any): void;
|
|
6
|
+
declare function subscribe(eventname: string, callbackFunction: SubscriberFunction): Subscriber;
|
|
7
|
+
declare function pushToServer(init?: RequestInit, searchParam?: string): Promise<Response>;
|
|
8
|
+
export declare const ClientAnalytics: {
|
|
9
|
+
pushToPageAnalyticsData: typeof pushToPageAnalyticsData;
|
|
10
|
+
getPageAnalyticsData: typeof getPageAnalyticsData;
|
|
11
|
+
resetPageAnalyticsData: typeof resetPageAnalyticsData;
|
|
12
|
+
publish: typeof publish;
|
|
13
|
+
subscribe: typeof subscribe;
|
|
14
|
+
pushToServer: typeof pushToServer;
|
|
15
|
+
eventNames: {
|
|
16
|
+
PAGE_VIEW: string;
|
|
17
|
+
VIEWED_PRODUCT: string;
|
|
18
|
+
ADD_TO_CART: string;
|
|
19
|
+
REMOVE_FROM_CART: string;
|
|
20
|
+
UPDATE_CART: string;
|
|
21
|
+
DISCOUNT_CODE_UPDATED: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export {};
|