@shopify/hydrogen 0.18.0 → 0.19.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.
- package/CHANGELOG.md +88 -0
- package/dist/esnext/components/Image/Image.d.ts +6 -0
- package/dist/esnext/components/Image/Image.js +6 -3
- package/dist/esnext/components/LocalizationProvider/LocalizationClientProvider.client.js +2 -15
- package/dist/esnext/components/LocalizationProvider/LocalizationContext.client.d.ts +0 -1
- package/dist/esnext/components/LocalizationProvider/LocalizationProvider.server.d.ts +2 -6
- package/dist/esnext/components/LocalizationProvider/LocalizationProvider.server.js +10 -4
- package/dist/esnext/entry-server.js +3 -34
- package/dist/esnext/foundation/ServerStateProvider/ServerStateProvider.js +2 -0
- package/dist/esnext/foundation/useSession/useSession.d.ts +1 -1
- package/dist/esnext/foundation/useSession/useSession.js +1 -1
- package/dist/esnext/framework/Hydration/rsc.d.ts +0 -3
- package/dist/esnext/framework/Hydration/rsc.js +0 -20
- package/dist/esnext/hooks/useCountry/useCountry.d.ts +1 -11
- package/dist/esnext/hooks/useCountry/useCountry.js +1 -1
- package/dist/esnext/node.d.ts +1 -0
- package/dist/esnext/node.js +1 -0
- package/dist/esnext/utilities/bot-ua.js +4 -0
- package/dist/esnext/version.d.ts +1 -1
- package/dist/esnext/version.js +1 -1
- package/dist/node/entry-server.js +3 -34
- package/dist/node/framework/Hydration/rsc.d.ts +0 -3
- package/dist/node/framework/Hydration/rsc.js +0 -20
- package/dist/node/utilities/bot-ua.js +4 -0
- package/dist/node/version.d.ts +1 -1
- package/dist/node/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,93 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1053](https://github.com/Shopify/hydrogen/pull/1053) [`c407f304`](https://github.com/Shopify/hydrogen/commit/c407f304352e0b781fa8a729674153ee9b971977) Thanks [@blittle](https://github.com/blittle)! - The selected country is now persisted a part of the session. This means that the page can be refreshed and the country will still be selected. There are a few breaking changes:
|
|
8
|
+
|
|
9
|
+
1. `useCountry()` hook now only returns the currently selected country. The `setCountry()` method has been removed.
|
|
10
|
+
2. The `useCountry()` hook expects a `countryCode` and `countryName` to be a part of the user session.
|
|
11
|
+
3. The example `/countries` API route has been updated to accept a `POST` request to update the selected country. The CountrySelector components need to be updated to use that route.
|
|
12
|
+
|
|
13
|
+
```diff
|
|
14
|
+
// src/routes/countries.server.jsx
|
|
15
|
+
|
|
16
|
+
-export async function api(request, {queryShop}) {
|
|
17
|
+
+export async function api(request, {queryShop, session}) {
|
|
18
|
+
+ if (request.method === 'POST') {
|
|
19
|
+
+ const {isoCode, name} = await request.json();
|
|
20
|
+
+
|
|
21
|
+
+ await session.set('countryCode', isoCode);
|
|
22
|
+
+ await session.set('countryName', name);
|
|
23
|
+
+
|
|
24
|
+
+ return 'success';
|
|
25
|
+
+ }
|
|
26
|
+
|
|
27
|
+
const {
|
|
28
|
+
data: {
|
|
29
|
+
localization: {availableCountries},
|
|
30
|
+
},
|
|
31
|
+
} = await queryShop({
|
|
32
|
+
query: QUERY,
|
|
33
|
+
});
|
|
34
|
+
return availableCountries.sort((a, b) => a.name.localeCompare(b.name));
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```diff
|
|
39
|
+
// src/components/CountrySelector.client.jsx
|
|
40
|
+
|
|
41
|
+
export default function CountrySelector() {
|
|
42
|
+
const [listboxOpen, setListboxOpen] = useState(false);
|
|
43
|
+
|
|
44
|
+
- const [selectedCountry, setSelectedCountry] = useCountry();
|
|
45
|
+
+ const [selectedCountry] = useCountry();
|
|
46
|
+
|
|
47
|
+
+ const setSelectedCountry = useCallback(
|
|
48
|
+
+ ({isoCode, name}) => {
|
|
49
|
+
+ fetch(`/countries`, {
|
|
50
|
+
+ body: JSON.stringify({isoCode, name}),
|
|
51
|
+
+ method: 'POST',
|
|
52
|
+
+ })
|
|
53
|
+
+ .then(() => {
|
|
54
|
+
+ window.location.reload();
|
|
55
|
+
+ })
|
|
56
|
+
+ .catch((error) => {
|
|
57
|
+
+ console.error(error);
|
|
58
|
+
+ });
|
|
59
|
+
+ },
|
|
60
|
+
+ [],
|
|
61
|
+
+ );
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
...
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
4. Each server component page that depends on the selected country pulls it from the session with `useSession()`, rather than `serverProps`.
|
|
70
|
+
|
|
71
|
+
```diff
|
|
72
|
+
// src/routes/products/[handle].server.jsx
|
|
73
|
+
+ import { useSession } from '@shopify/hydrogen';
|
|
74
|
+
|
|
75
|
+
- export default function Product({country = {isoCode: 'US'}}) {
|
|
76
|
+
+ export default function Product() {
|
|
77
|
+
const {handle} = useRouteParams();
|
|
78
|
+
+ const {countryCode = 'US'} = useSession();
|
|
79
|
+
...
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Patch Changes
|
|
84
|
+
|
|
85
|
+
- [#1264](https://github.com/Shopify/hydrogen/pull/1264) [`dc966e86`](https://github.com/Shopify/hydrogen/commit/dc966e86b35ffc8a41d8d62e129884926b8db8bc) Thanks [@arlyxiao](https://github.com/arlyxiao)! - Add more bots into user agents
|
|
86
|
+
|
|
87
|
+
* [#1245](https://github.com/Shopify/hydrogen/pull/1245) [`07866e82`](https://github.com/Shopify/hydrogen/commit/07866e8277dfa3195ef1896b16a58df495a9155f) Thanks [@0x15f](https://github.com/0x15f)! - [#1245](https://github.com/Shopify/hydrogen/pull/1245) - Support optional `priority` prop on Image component. When `true`, the image will be eagerly loaded. Defaults to `false`.
|
|
88
|
+
|
|
89
|
+
- [#1272](https://github.com/Shopify/hydrogen/pull/1272) [`c1888652`](https://github.com/Shopify/hydrogen/commit/c188865255c5f20d9db285e375c57127030e23e6) Thanks [@wizardlyhel](https://github.com/wizardlyhel)! - Remove flight chunk
|
|
90
|
+
|
|
3
91
|
## 0.18.0
|
|
4
92
|
|
|
5
93
|
### Minor Changes
|
|
@@ -11,6 +11,12 @@ export interface BaseImageProps {
|
|
|
11
11
|
* then the value can be a property of the `loaderOptions` object (for example, `{scale: 2}`).
|
|
12
12
|
*/
|
|
13
13
|
loaderOptions?: ImageLoaderOptions['options'];
|
|
14
|
+
/**
|
|
15
|
+
* Whether the image will be immediately loaded. Defaults to `false`. This prop should be used only when
|
|
16
|
+
* the image is visible above the fold. For more information, refer to the
|
|
17
|
+
* [Image Embed element's loading attribute](https://developer.mozilla.org/enUS/docs/Web/HTML/Element/img#attr-loading).
|
|
18
|
+
*/
|
|
19
|
+
priority?: boolean;
|
|
14
20
|
}
|
|
15
21
|
interface MediaImagePropsBase extends BaseImageProps {
|
|
16
22
|
/** An object with fields that correspond to the Storefront API's
|
|
@@ -6,7 +6,7 @@ import { shopifyImageLoader, getShopifyImageDimensions, } from '../../utilities'
|
|
|
6
6
|
*/
|
|
7
7
|
export function Image(props) {
|
|
8
8
|
var _a, _b, _c, _d;
|
|
9
|
-
const { data, options, src, id, alt, width, height, loader, loaderOptions, ...passthroughProps } = props;
|
|
9
|
+
const { data, options, src, id, alt, width, height, loader, loaderOptions, priority, ...passthroughProps } = props;
|
|
10
10
|
if (!data && !src) {
|
|
11
11
|
throw new Error('Image component: requires either an `data` or `src` prop.');
|
|
12
12
|
}
|
|
@@ -21,6 +21,7 @@ export function Image(props) {
|
|
|
21
21
|
loaderOptions,
|
|
22
22
|
id,
|
|
23
23
|
alt,
|
|
24
|
+
priority,
|
|
24
25
|
})
|
|
25
26
|
: {
|
|
26
27
|
src,
|
|
@@ -29,16 +30,17 @@ export function Image(props) {
|
|
|
29
30
|
width,
|
|
30
31
|
height,
|
|
31
32
|
loader,
|
|
33
|
+
priority,
|
|
32
34
|
loaderOptions: { width, height, ...loaderOptions },
|
|
33
35
|
};
|
|
34
36
|
const srcPath = imgProps.loader
|
|
35
37
|
? imgProps.loader({ src: imgProps.src, options: imgProps.loaderOptions })
|
|
36
38
|
: imgProps.src;
|
|
37
39
|
/* eslint-disable hydrogen/prefer-image-component */
|
|
38
|
-
return (React.createElement("img", { id: (_a = imgProps.id) !== null && _a !== void 0 ? _a : '', loading:
|
|
40
|
+
return (React.createElement("img", { id: (_a = imgProps.id) !== null && _a !== void 0 ? _a : '', loading: imgProps.priority ? 'eager' : 'lazy', alt: (_b = imgProps.alt) !== null && _b !== void 0 ? _b : '', ...passthroughProps, src: srcPath, width: (_c = imgProps.width) !== null && _c !== void 0 ? _c : undefined, height: (_d = imgProps.height) !== null && _d !== void 0 ? _d : undefined }));
|
|
39
41
|
/* eslint-enable hydrogen/prefer-image-component */
|
|
40
42
|
}
|
|
41
|
-
function convertShopifyImageData({ data, options, loader, loaderOptions, id: propId, alt, }) {
|
|
43
|
+
function convertShopifyImageData({ data, options, loader, priority, loaderOptions, id: propId, alt, }) {
|
|
42
44
|
const { url: src, altText, id } = data;
|
|
43
45
|
if (!src) {
|
|
44
46
|
throw new Error(`<Image/> requires 'data.url' when using the 'data' prop`);
|
|
@@ -52,5 +54,6 @@ function convertShopifyImageData({ data, options, loader, loaderOptions, id: pro
|
|
|
52
54
|
height,
|
|
53
55
|
loader: loader ? loader : shopifyImageLoader,
|
|
54
56
|
loaderOptions: { ...options, ...loaderOptions },
|
|
57
|
+
priority,
|
|
55
58
|
};
|
|
56
59
|
}
|
|
@@ -1,18 +1,5 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { LocalizationContext } from './LocalizationContext.client';
|
|
3
|
-
import { useServerProps } from '../../foundation/useServerProps';
|
|
4
3
|
export default function LocalizationClientProvider({ localization, children, }) {
|
|
5
|
-
|
|
6
|
-
const [country, setCountry] = useState(localization.country);
|
|
7
|
-
const setter = useCallback((country) => {
|
|
8
|
-
setCountry(country);
|
|
9
|
-
setServerProps('country', country);
|
|
10
|
-
}, [setServerProps]);
|
|
11
|
-
const contextValue = useMemo(() => {
|
|
12
|
-
return {
|
|
13
|
-
country,
|
|
14
|
-
setCountry: setter,
|
|
15
|
-
};
|
|
16
|
-
}, [country, setter]);
|
|
17
|
-
return (React.createElement(LocalizationContext.Provider, { value: contextValue }, children));
|
|
4
|
+
return (React.createElement(LocalizationContext.Provider, { value: localization }, children));
|
|
18
5
|
}
|
|
@@ -2,6 +2,5 @@ import type { LocalizationQuery } from './LocalizationProvider.server';
|
|
|
2
2
|
export declare type Localization = LocalizationQuery['localization'];
|
|
3
3
|
export interface LocalizationContextValue {
|
|
4
4
|
country?: Localization['country'];
|
|
5
|
-
setCountry(country: Localization['country']): void;
|
|
6
5
|
}
|
|
7
6
|
export declare const LocalizationContext: import("react").Context<LocalizationContextValue | null>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { PreloadOptions } from '../../types';
|
|
3
|
-
import { Country
|
|
3
|
+
import { Country } from '../../storefront-api-types';
|
|
4
4
|
export interface LocalizationProviderProps {
|
|
5
5
|
/** A `ReactNode` element. */
|
|
6
6
|
children: ReactNode;
|
|
@@ -28,10 +28,6 @@ export declare type LocalizationQuery = {
|
|
|
28
28
|
} & {
|
|
29
29
|
country: {
|
|
30
30
|
__typename?: 'Country';
|
|
31
|
-
} & Pick<Country, 'isoCode' | 'name'
|
|
32
|
-
currency: {
|
|
33
|
-
__typename?: 'Currency';
|
|
34
|
-
} & Pick<Currency, 'isoCode'>;
|
|
35
|
-
};
|
|
31
|
+
} & Pick<Country, 'isoCode' | 'name'>;
|
|
36
32
|
};
|
|
37
33
|
};
|
|
@@ -3,6 +3,7 @@ import LocalizationClientProvider from './LocalizationClientProvider.client';
|
|
|
3
3
|
import { useShop } from '../../foundation/useShop';
|
|
4
4
|
import { useShopQuery } from '../../hooks/useShopQuery';
|
|
5
5
|
import { CacheDays } from '../../framework/CachingStrategy';
|
|
6
|
+
import { useSession } from '../../foundation/useSession/useSession';
|
|
6
7
|
/**
|
|
7
8
|
* The `LocalizationProvider` component automatically queries the Storefront API's
|
|
8
9
|
* [`localization`](https://shopify.dev/api/storefront/reference/common-objects/queryroot) field
|
|
@@ -14,13 +15,21 @@ import { CacheDays } from '../../framework/CachingStrategy';
|
|
|
14
15
|
*/
|
|
15
16
|
export function LocalizationProvider(props) {
|
|
16
17
|
const { languageCode } = useShop();
|
|
18
|
+
const { countryCode, countryName } = useSession();
|
|
17
19
|
const { data: { localization }, } = useShopQuery({
|
|
18
20
|
query,
|
|
19
21
|
variables: { language: languageCode },
|
|
20
22
|
cache: CacheDays(),
|
|
21
23
|
preload: props.preload,
|
|
22
24
|
});
|
|
23
|
-
return (React.createElement(LocalizationClientProvider, { localization:
|
|
25
|
+
return (React.createElement(LocalizationClientProvider, { localization: countryCode
|
|
26
|
+
? {
|
|
27
|
+
country: {
|
|
28
|
+
name: countryName,
|
|
29
|
+
isoCode: countryCode,
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
: localization }, props.children));
|
|
24
33
|
}
|
|
25
34
|
const query = `
|
|
26
35
|
query Localization($language: LanguageCode)
|
|
@@ -29,9 +38,6 @@ query Localization($language: LanguageCode)
|
|
|
29
38
|
country {
|
|
30
39
|
isoCode
|
|
31
40
|
name
|
|
32
|
-
currency {
|
|
33
|
-
isoCode
|
|
34
|
-
}
|
|
35
41
|
}
|
|
36
42
|
}
|
|
37
43
|
}
|
|
@@ -108,7 +108,7 @@ function getApiRoute(url, routes) {
|
|
|
108
108
|
*/
|
|
109
109
|
async function render(url, { App, request, template, componentResponse, nonce, log }) {
|
|
110
110
|
const state = { pathname: url.pathname, search: url.search };
|
|
111
|
-
const { AppSSR
|
|
111
|
+
const { AppSSR } = buildAppSSR({
|
|
112
112
|
App,
|
|
113
113
|
log,
|
|
114
114
|
state,
|
|
@@ -120,10 +120,7 @@ async function render(url, { App, request, template, componentResponse, nonce, l
|
|
|
120
120
|
componentResponse.writeHead({ status: 500 });
|
|
121
121
|
return template;
|
|
122
122
|
}
|
|
123
|
-
let
|
|
124
|
-
renderToBufferedString(AppSSR, { log, nonce }).catch(onErrorShell),
|
|
125
|
-
bufferReadableStream(rscReadable.getReader()).catch(() => null),
|
|
126
|
-
]);
|
|
123
|
+
let html = await renderToBufferedString(AppSSR, { log, nonce }).catch(onErrorShell);
|
|
127
124
|
const { headers, status, statusText } = getResponseOptions(componentResponse);
|
|
128
125
|
/**
|
|
129
126
|
* TODO: Also add `Vary` headers for `accept-language` and any other keys
|
|
@@ -141,13 +138,6 @@ async function render(url, { App, request, template, componentResponse, nonce, l
|
|
|
141
138
|
}
|
|
142
139
|
headers.set(CONTENT_TYPE, HTML_CONTENT_TYPE);
|
|
143
140
|
html = applyHtmlHead(html, request.ctx.head, template);
|
|
144
|
-
if (flight) {
|
|
145
|
-
html = html.replace('</body>', () => `${flightContainer({
|
|
146
|
-
init: true,
|
|
147
|
-
nonce,
|
|
148
|
-
chunk: flight,
|
|
149
|
-
})}</body>`);
|
|
150
|
-
}
|
|
151
141
|
postRequestTasks('ssr', status, request, componentResponse);
|
|
152
142
|
return new Response(html, {
|
|
153
143
|
status,
|
|
@@ -174,13 +164,7 @@ async function stream(url, { App, request, response, componentResponse, template
|
|
|
174
164
|
const rscToScriptTagReadable = new ReadableStream({
|
|
175
165
|
start(controller) {
|
|
176
166
|
log.trace('rsc start chunks');
|
|
177
|
-
|
|
178
|
-
const encoder = new TextEncoder();
|
|
179
|
-
bufferReadableStream(rscReadable.getReader(), (chunk) => {
|
|
180
|
-
const scriptTag = flightContainer({ init, chunk, nonce });
|
|
181
|
-
controller.enqueue(encoder.encode(scriptTag));
|
|
182
|
-
init = false;
|
|
183
|
-
}).then(() => {
|
|
167
|
+
bufferReadableStream(rscReadable.getReader()).then(() => {
|
|
184
168
|
log.trace('rsc finish chunks');
|
|
185
169
|
return controller.close();
|
|
186
170
|
});
|
|
@@ -528,21 +512,6 @@ async function createNodeWriter() {
|
|
|
528
512
|
const { PassThrough } = await import(streamImport);
|
|
529
513
|
return new PassThrough();
|
|
530
514
|
}
|
|
531
|
-
function flightContainer({ init, chunk, nonce, }) {
|
|
532
|
-
let script = `<script${nonce ? ` nonce="${nonce}"` : ''}>`;
|
|
533
|
-
if (init) {
|
|
534
|
-
script += 'var __flight=[];';
|
|
535
|
-
}
|
|
536
|
-
if (chunk) {
|
|
537
|
-
const normalizedChunk = chunk
|
|
538
|
-
// 1. Duplicate the escape char (\) for already escaped characters (e.g. \n or \").
|
|
539
|
-
.replace(/\\/g, String.raw `\\`)
|
|
540
|
-
// 2. Escape existing backticks to allow wrapping the whole thing in `...`.
|
|
541
|
-
.replace(/`/g, String.raw `\``);
|
|
542
|
-
script += `__flight.push(\`${normalizedChunk}\`)`;
|
|
543
|
-
}
|
|
544
|
-
return script + '</script>';
|
|
545
|
-
}
|
|
546
515
|
function postRequestTasks(type, status, request, componentResponse) {
|
|
547
516
|
logServerResponse(type, request, status);
|
|
548
517
|
logCacheControlHeaders(type, request, componentResponse);
|
|
@@ -31,6 +31,8 @@ export function ServerStateProvider({ serverState, setServerState, children, })
|
|
|
31
31
|
else {
|
|
32
32
|
newValue = input;
|
|
33
33
|
}
|
|
34
|
+
if (!newValue)
|
|
35
|
+
return { ...prev };
|
|
34
36
|
if (__DEV__) {
|
|
35
37
|
const privateProp = PRIVATE_PROPS.find((prop) => prop in newValue);
|
|
36
38
|
if (privateProp) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** The `useSession` hook reads session data in server components. */
|
|
2
|
-
export declare const useSession: () => Record<string, string
|
|
2
|
+
export declare const useSession: () => Record<string, string>;
|
|
@@ -3,6 +3,6 @@ import { useServerRequest } from '../ServerRequestProvider';
|
|
|
3
3
|
export const useSession = function () {
|
|
4
4
|
var _a;
|
|
5
5
|
const request = useServerRequest();
|
|
6
|
-
const session = (_a = request.ctx.session) === null || _a === void 0 ? void 0 : _a.get();
|
|
6
|
+
const session = ((_a = request.ctx.session) === null || _a === void 0 ? void 0 : _a.get()) || {};
|
|
7
7
|
return session;
|
|
8
8
|
};
|
|
@@ -7,26 +7,6 @@ import { createFromFetch, createFromReadableStream,
|
|
|
7
7
|
} from '@shopify/hydrogen/vendor/react-server-dom-vite';
|
|
8
8
|
import { RSC_PATHNAME } from '../../constants';
|
|
9
9
|
let rscReader;
|
|
10
|
-
if (globalThis.__flight && __flight.length > 0) {
|
|
11
|
-
const contentLoaded = new Promise((resolve) => document.addEventListener('DOMContentLoaded', resolve));
|
|
12
|
-
try {
|
|
13
|
-
rscReader = new ReadableStream({
|
|
14
|
-
start(controller) {
|
|
15
|
-
const encoder = new TextEncoder();
|
|
16
|
-
const write = (chunk) => {
|
|
17
|
-
controller.enqueue(encoder.encode(chunk));
|
|
18
|
-
return 0;
|
|
19
|
-
};
|
|
20
|
-
__flight.forEach(write);
|
|
21
|
-
__flight.push = write;
|
|
22
|
-
contentLoaded.then(() => controller.close());
|
|
23
|
-
},
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
catch (_) {
|
|
27
|
-
// Old browser, will try a new hydration request later
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
10
|
function createResponseCache() {
|
|
31
11
|
return new Map();
|
|
32
12
|
}
|
|
@@ -4,14 +4,4 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare function useCountry(): (({
|
|
6
6
|
__typename?: "Country" | undefined;
|
|
7
|
-
} & Pick<import("../../storefront-api-types").Country, "name" | "isoCode">
|
|
8
|
-
currency: {
|
|
9
|
-
__typename?: "Currency" | undefined;
|
|
10
|
-
} & Pick<import("../../storefront-api-types").Currency, "isoCode">;
|
|
11
|
-
}) | ((country: {
|
|
12
|
-
__typename?: "Country" | undefined;
|
|
13
|
-
} & Pick<import("../../storefront-api-types").Country, "name" | "isoCode"> & {
|
|
14
|
-
currency: {
|
|
15
|
-
__typename?: "Currency" | undefined;
|
|
16
|
-
} & Pick<import("../../storefront-api-types").Currency, "isoCode">;
|
|
17
|
-
}) => void) | undefined)[];
|
|
7
|
+
} & Pick<import("../../storefront-api-types").Country, "name" | "isoCode">) | undefined)[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FileSessionStorage } from './foundation/FileSessionStorage/FileSessionStorage';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FileSessionStorage } from './foundation/FileSessionStorage/FileSessionStorage';
|
package/dist/esnext/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const LIB_VERSION = "0.
|
|
1
|
+
export declare const LIB_VERSION = "0.19.0";
|
package/dist/esnext/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const LIB_VERSION = '0.
|
|
1
|
+
export const LIB_VERSION = '0.19.0';
|
|
@@ -135,7 +135,7 @@ function getApiRoute(url, routes) {
|
|
|
135
135
|
*/
|
|
136
136
|
async function render(url, { App, request, template, componentResponse, nonce, log }) {
|
|
137
137
|
const state = { pathname: url.pathname, search: url.search };
|
|
138
|
-
const { AppSSR
|
|
138
|
+
const { AppSSR } = buildAppSSR({
|
|
139
139
|
App,
|
|
140
140
|
log,
|
|
141
141
|
state,
|
|
@@ -147,10 +147,7 @@ async function render(url, { App, request, template, componentResponse, nonce, l
|
|
|
147
147
|
componentResponse.writeHead({ status: 500 });
|
|
148
148
|
return template;
|
|
149
149
|
}
|
|
150
|
-
let
|
|
151
|
-
renderToBufferedString(AppSSR, { log, nonce }).catch(onErrorShell),
|
|
152
|
-
(0, streaming_server_1.bufferReadableStream)(rscReadable.getReader()).catch(() => null),
|
|
153
|
-
]);
|
|
150
|
+
let html = await renderToBufferedString(AppSSR, { log, nonce }).catch(onErrorShell);
|
|
154
151
|
const { headers, status, statusText } = getResponseOptions(componentResponse);
|
|
155
152
|
/**
|
|
156
153
|
* TODO: Also add `Vary` headers for `accept-language` and any other keys
|
|
@@ -168,13 +165,6 @@ async function render(url, { App, request, template, componentResponse, nonce, l
|
|
|
168
165
|
}
|
|
169
166
|
headers.set(CONTENT_TYPE, HTML_CONTENT_TYPE);
|
|
170
167
|
html = (0, Html_1.applyHtmlHead)(html, request.ctx.head, template);
|
|
171
|
-
if (flight) {
|
|
172
|
-
html = html.replace('</body>', () => `${flightContainer({
|
|
173
|
-
init: true,
|
|
174
|
-
nonce,
|
|
175
|
-
chunk: flight,
|
|
176
|
-
})}</body>`);
|
|
177
|
-
}
|
|
178
168
|
postRequestTasks('ssr', status, request, componentResponse);
|
|
179
169
|
return new Response(html, {
|
|
180
170
|
status,
|
|
@@ -201,13 +191,7 @@ async function stream(url, { App, request, response, componentResponse, template
|
|
|
201
191
|
const rscToScriptTagReadable = new ReadableStream({
|
|
202
192
|
start(controller) {
|
|
203
193
|
log.trace('rsc start chunks');
|
|
204
|
-
|
|
205
|
-
const encoder = new TextEncoder();
|
|
206
|
-
(0, streaming_server_1.bufferReadableStream)(rscReadable.getReader(), (chunk) => {
|
|
207
|
-
const scriptTag = flightContainer({ init, chunk, nonce });
|
|
208
|
-
controller.enqueue(encoder.encode(scriptTag));
|
|
209
|
-
init = false;
|
|
210
|
-
}).then(() => {
|
|
194
|
+
(0, streaming_server_1.bufferReadableStream)(rscReadable.getReader()).then(() => {
|
|
211
195
|
log.trace('rsc finish chunks');
|
|
212
196
|
return controller.close();
|
|
213
197
|
});
|
|
@@ -555,21 +539,6 @@ async function createNodeWriter() {
|
|
|
555
539
|
const { PassThrough } = await Promise.resolve().then(() => __importStar(require(streamImport)));
|
|
556
540
|
return new PassThrough();
|
|
557
541
|
}
|
|
558
|
-
function flightContainer({ init, chunk, nonce, }) {
|
|
559
|
-
let script = `<script${nonce ? ` nonce="${nonce}"` : ''}>`;
|
|
560
|
-
if (init) {
|
|
561
|
-
script += 'var __flight=[];';
|
|
562
|
-
}
|
|
563
|
-
if (chunk) {
|
|
564
|
-
const normalizedChunk = chunk
|
|
565
|
-
// 1. Duplicate the escape char (\) for already escaped characters (e.g. \n or \").
|
|
566
|
-
.replace(/\\/g, String.raw `\\`)
|
|
567
|
-
// 2. Escape existing backticks to allow wrapping the whole thing in `...`.
|
|
568
|
-
.replace(/`/g, String.raw `\``);
|
|
569
|
-
script += `__flight.push(\`${normalizedChunk}\`)`;
|
|
570
|
-
}
|
|
571
|
-
return script + '</script>';
|
|
572
|
-
}
|
|
573
542
|
function postRequestTasks(type, status, request, componentResponse) {
|
|
574
543
|
(0, log_1.logServerResponse)(type, request, status);
|
|
575
544
|
(0, log_1.logCacheControlHeaders)(type, request, componentResponse);
|
|
@@ -8,26 +8,6 @@ const react_1 = require("react");
|
|
|
8
8
|
const react_server_dom_vite_1 = require("@shopify/hydrogen/vendor/react-server-dom-vite");
|
|
9
9
|
const constants_1 = require("../../constants");
|
|
10
10
|
let rscReader;
|
|
11
|
-
if (globalThis.__flight && __flight.length > 0) {
|
|
12
|
-
const contentLoaded = new Promise((resolve) => document.addEventListener('DOMContentLoaded', resolve));
|
|
13
|
-
try {
|
|
14
|
-
rscReader = new ReadableStream({
|
|
15
|
-
start(controller) {
|
|
16
|
-
const encoder = new TextEncoder();
|
|
17
|
-
const write = (chunk) => {
|
|
18
|
-
controller.enqueue(encoder.encode(chunk));
|
|
19
|
-
return 0;
|
|
20
|
-
};
|
|
21
|
-
__flight.forEach(write);
|
|
22
|
-
__flight.push = write;
|
|
23
|
-
contentLoaded.then(() => controller.close());
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
catch (_) {
|
|
28
|
-
// Old browser, will try a new hydration request later
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
11
|
function createResponseCache() {
|
|
32
12
|
return new Map();
|
|
33
13
|
}
|
package/dist/node/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const LIB_VERSION = "0.
|
|
1
|
+
export declare const LIB_VERSION = "0.19.0";
|
package/dist/node/version.js
CHANGED