@shopify/hydrogen 0.20.0 → 0.22.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 +151 -0
- package/dist/esnext/client.d.ts +1 -0
- package/dist/esnext/client.js +1 -0
- package/dist/esnext/components/CartEstimatedCost/CartEstimatedCost.client.d.ts +1 -1
- package/dist/esnext/components/CartLinePrice/CartLinePrice.client.d.ts +1 -1
- package/dist/esnext/components/CartProvider/CartProvider.client.d.ts +7 -4
- package/dist/esnext/components/CartProvider/CartProvider.client.js +22 -12
- package/dist/esnext/components/Image/Image.d.ts +3 -3
- package/dist/esnext/components/Image/Image.js +12 -9
- package/dist/esnext/components/MediaFile/MediaFile.js +3 -2
- package/dist/esnext/components/Money/Money.client.d.ts +11 -5
- package/dist/esnext/components/Money/Money.client.js +16 -3
- package/dist/esnext/components/ProductPrice/ProductPrice.client.d.ts +1 -2
- package/dist/esnext/components/ProductPrice/ProductPrice.client.js +1 -2
- package/dist/esnext/components/Seo/NoIndexSeo.client.d.ts +3 -0
- package/dist/esnext/components/Seo/NoIndexSeo.client.js +10 -0
- package/dist/esnext/components/Seo/Seo.client.d.ts +4 -0
- package/dist/esnext/components/Seo/Seo.client.js +3 -0
- package/dist/esnext/components/index.d.ts +0 -3
- package/dist/esnext/components/index.js +0 -3
- package/dist/esnext/config.d.ts +3 -3
- package/dist/esnext/entry-client.js +0 -3
- package/dist/esnext/entry-server.d.ts +2 -2
- package/dist/esnext/entry-server.js +97 -73
- package/dist/esnext/foundation/Analytics/Analytics.client.js +1 -1
- package/dist/esnext/foundation/Analytics/ClientAnalytics.js +2 -2
- package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.client.js +2 -2
- package/dist/esnext/foundation/Analytics/index.d.ts +0 -1
- package/dist/esnext/foundation/Analytics/index.js +0 -1
- package/dist/esnext/foundation/FileRoutes/FileRoutes.server.js +5 -10
- package/dist/esnext/foundation/Router/BrowserRouter.client.d.ts +2 -1
- package/dist/esnext/foundation/Router/BrowserRouter.client.js +1 -1
- package/dist/esnext/foundation/ServerPropsProvider/ServerPropsProvider.js +0 -2
- package/dist/esnext/foundation/ServerRequestProvider/ServerRequestProvider.js +18 -3
- package/dist/esnext/foundation/ShopifyProvider/ShopifyProvider.server.js +0 -1
- package/dist/esnext/foundation/useQuery/hooks.js +8 -9
- package/dist/esnext/foundation/useRouteParams/RouteParamsProvider.client.d.ts +2 -1
- package/dist/esnext/foundation/useRouteParams/RouteParamsProvider.client.js +1 -1
- package/dist/esnext/framework/Hydration/ServerComponentRequest.server.d.ts +2 -2
- package/dist/esnext/framework/Hydration/ServerComponentResponse.server.d.ts +1 -10
- package/dist/esnext/framework/Hydration/ServerComponentResponse.server.js +2 -20
- package/dist/esnext/framework/Hydration/rsc.js +55 -7
- package/dist/esnext/framework/cache/in-memory.js +0 -6
- package/dist/esnext/framework/cache-sub-request.d.ts +17 -0
- package/dist/esnext/framework/cache-sub-request.js +64 -0
- package/dist/esnext/framework/cache.d.ts +6 -6
- package/dist/esnext/framework/cache.js +36 -33
- package/dist/esnext/framework/middleware.js +1 -15
- package/dist/esnext/framework/plugin.js +4 -0
- package/dist/esnext/framework/plugins/vite-plugin-client-imports.d.ts +2 -0
- package/dist/esnext/framework/plugins/vite-plugin-client-imports.js +25 -0
- package/dist/esnext/framework/plugins/vite-plugin-css-modules-rsc.js +8 -3
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-client-middleware.d.ts +1 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.js +2 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-middleware.js +6 -47
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-rsc.js +6 -11
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-virtual-files.d.ts +7 -0
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-virtual-files.js +99 -0
- package/dist/esnext/framework/plugins/vite-plugin-platform-entry.js +4 -4
- package/dist/esnext/framework/viteception.d.ts +4 -0
- package/dist/esnext/framework/viteception.js +15 -0
- package/dist/esnext/hooks/useShopQuery/hooks.d.ts +1 -2
- package/dist/esnext/hooks/useShopQuery/hooks.js +0 -1
- package/dist/esnext/index.d.ts +24 -9
- package/dist/esnext/index.js +24 -13
- package/dist/esnext/storefront-api-types.d.ts +1 -1
- package/dist/esnext/streaming.server.d.ts +3 -1
- package/dist/esnext/types.d.ts +13 -5
- package/dist/esnext/utilities/apiRoutes.d.ts +4 -5
- package/dist/esnext/utilities/apiRoutes.js +2 -8
- package/dist/esnext/utilities/fetch.d.ts +1 -2
- package/dist/esnext/utilities/fetch.js +1 -3
- package/dist/esnext/utilities/graphql-tag.d.ts +1 -0
- package/dist/esnext/utilities/graphql-tag.js +6 -0
- package/dist/esnext/utilities/graphql-tracker.d.ts +1 -1
- package/dist/esnext/utilities/graphql-tracker.js +4 -0
- package/dist/esnext/utilities/html-encoding.d.ts +1 -0
- package/dist/esnext/utilities/html-encoding.js +8 -0
- package/dist/esnext/utilities/index.d.ts +1 -0
- package/dist/esnext/utilities/index.js +1 -0
- package/dist/esnext/utilities/log/log-cache-api-status.js +5 -1
- package/dist/esnext/version.d.ts +1 -1
- package/dist/esnext/version.js +1 -1
- package/dist/node/components/Image/Image.d.ts +3 -3
- package/dist/node/components/Image/Image.js +12 -9
- package/dist/node/entry-server.d.ts +2 -2
- package/dist/node/entry-server.js +97 -73
- package/dist/node/foundation/Analytics/Analytics.client.js +6 -6
- package/dist/node/foundation/Analytics/ClientAnalytics.js +2 -2
- package/dist/node/foundation/Router/BrowserRouter.client.d.ts +2 -1
- package/dist/node/foundation/Router/BrowserRouter.client.js +1 -1
- package/dist/node/foundation/ServerPropsProvider/ServerPropsProvider.js +0 -2
- package/dist/node/foundation/ServerRequestProvider/ServerRequestProvider.js +18 -3
- package/dist/node/framework/Hydration/ServerComponentRequest.server.d.ts +2 -2
- package/dist/node/framework/Hydration/ServerComponentResponse.server.d.ts +1 -10
- package/dist/node/framework/Hydration/ServerComponentResponse.server.js +2 -20
- package/dist/node/framework/Hydration/rsc.js +55 -7
- package/dist/node/framework/cache/in-memory.js +0 -6
- package/dist/node/framework/cache-sub-request.d.ts +17 -0
- package/dist/node/framework/cache-sub-request.js +95 -0
- package/dist/node/framework/cache.d.ts +6 -6
- package/dist/node/framework/cache.js +38 -35
- package/dist/node/framework/middleware.js +1 -15
- package/dist/node/framework/plugin.js +4 -0
- package/dist/node/framework/plugins/vite-plugin-client-imports.d.ts +2 -0
- package/dist/node/framework/plugins/vite-plugin-client-imports.js +28 -0
- package/dist/node/framework/plugins/vite-plugin-css-modules-rsc.js +8 -3
- package/dist/node/framework/plugins/vite-plugin-hydrogen-client-middleware.d.ts +1 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-config.js +2 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-middleware.js +5 -46
- package/dist/node/framework/plugins/vite-plugin-hydrogen-rsc.js +6 -11
- package/dist/node/framework/plugins/vite-plugin-hydrogen-virtual-files.d.ts +7 -0
- package/dist/node/framework/plugins/vite-plugin-hydrogen-virtual-files.js +105 -0
- package/dist/node/framework/plugins/vite-plugin-platform-entry.js +4 -4
- package/dist/node/framework/viteception.d.ts +4 -0
- package/dist/node/framework/viteception.js +19 -0
- package/dist/node/storefront-api-types.d.ts +1 -1
- package/dist/node/streaming.server.d.ts +3 -1
- package/dist/node/types.d.ts +13 -5
- package/dist/node/utilities/apiRoutes.d.ts +4 -5
- package/dist/node/utilities/apiRoutes.js +2 -8
- package/dist/node/utilities/fetch.d.ts +1 -2
- package/dist/node/utilities/fetch.js +1 -3
- package/dist/node/utilities/html-encoding.d.ts +1 -0
- package/dist/node/utilities/html-encoding.js +12 -0
- package/dist/node/utilities/index.d.ts +1 -0
- package/dist/node/utilities/index.js +3 -1
- package/dist/node/utilities/log/log-cache-api-status.js +5 -1
- package/dist/node/version.d.ts +1 -1
- package/dist/node/version.js +1 -1
- package/package.json +6 -5
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +48 -6
- package/vendor/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +48 -6
- package/vendor/react-server-dom-vite/package.json +2 -1
- package/dist/esnext/components/ProductDescription/ProductDescription.client.d.ts +0 -13
- package/dist/esnext/components/ProductDescription/ProductDescription.client.js +0 -16
- package/dist/esnext/components/ProductDescription/index.d.ts +0 -1
- package/dist/esnext/components/ProductDescription/index.js +0 -1
- package/dist/esnext/components/ProductMetafield/ProductMetafield.client.d.ts +0 -21
- package/dist/esnext/components/ProductMetafield/ProductMetafield.client.js +0 -42
- package/dist/esnext/components/ProductMetafield/index.d.ts +0 -2
- package/dist/esnext/components/ProductMetafield/index.js +0 -1
- package/dist/esnext/components/ProductTitle/ProductTitle.client.d.ts +0 -13
- package/dist/esnext/components/ProductTitle/ProductTitle.client.js +0 -16
- package/dist/esnext/components/ProductTitle/index.d.ts +0 -1
- package/dist/esnext/components/ProductTitle/index.js +0 -1
- package/dist/esnext/components/UnitPrice/UnitPrice.client.d.ts +0 -15
- package/dist/esnext/components/UnitPrice/UnitPrice.client.js +0 -22
- package/dist/esnext/components/UnitPrice/index.d.ts +0 -1
- package/dist/esnext/components/UnitPrice/index.js +0 -1
- package/dist/esnext/utilities/findRoutePrefix.d.ts +0 -1
- package/dist/esnext/utilities/findRoutePrefix.js +0 -17
- package/dist/node/foundation/Analytics/index.d.ts +0 -2
- package/dist/node/foundation/Analytics/index.js +0 -7
- package/dist/node/utilities/findRoutePrefix.d.ts +0 -1
- package/dist/node/utilities/findRoutePrefix.js +0 -21
|
@@ -18,20 +18,27 @@ import { Analytics } from './foundation/Analytics/Analytics.server';
|
|
|
18
18
|
import { ServerAnalyticsRoute } from './foundation/Analytics/ServerAnalyticsRoute.server';
|
|
19
19
|
import { getSyncSessionApi } from './foundation/session/session';
|
|
20
20
|
import { parseJSON } from './utilities/parse';
|
|
21
|
+
import { htmlEncode } from './utilities';
|
|
21
22
|
const DOCTYPE = '<!DOCTYPE html>';
|
|
22
23
|
const CONTENT_TYPE = 'Content-Type';
|
|
23
24
|
const HTML_CONTENT_TYPE = 'text/html; charset=UTF-8';
|
|
24
|
-
export const renderHydrogen = (App
|
|
25
|
+
export const renderHydrogen = (App) => {
|
|
25
26
|
const handleRequest = async function (rawRequest, options) {
|
|
26
27
|
const { indexTemplate, streamableResponse, dev, cache, context, nonce, buyerIpHeader, } = options;
|
|
27
28
|
const request = new ServerComponentRequest(rawRequest);
|
|
28
29
|
const url = new URL(request.url);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
const { default: inlineHydrogenConfig } = await import(
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
// eslint-disable-next-line node/no-missing-import
|
|
33
|
+
'virtual__hydrogen.config.ts');
|
|
34
|
+
const { default: hydrogenRoutes } = await import(
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
// eslint-disable-next-line node/no-missing-import
|
|
37
|
+
'virtual__hydrogen-routes.server.jsx');
|
|
38
|
+
const hydrogenConfig = {
|
|
39
|
+
...inlineHydrogenConfig,
|
|
40
|
+
routes: hydrogenRoutes,
|
|
41
|
+
};
|
|
35
42
|
request.ctx.hydrogenConfig = hydrogenConfig;
|
|
36
43
|
request.ctx.buyerIpHeader = buyerIpHeader;
|
|
37
44
|
const log = getLoggerWithContext(request);
|
|
@@ -51,7 +58,7 @@ export const renderHydrogen = (App, hydrogenConfig) => {
|
|
|
51
58
|
return ServerAnalyticsRoute(request, hydrogenConfig.serverAnalyticsConnectors);
|
|
52
59
|
}
|
|
53
60
|
const isReactHydrationRequest = url.pathname === RSC_PATHNAME;
|
|
54
|
-
if (!isReactHydrationRequest
|
|
61
|
+
if (!isReactHydrationRequest) {
|
|
55
62
|
const apiRoute = getApiRoute(url, hydrogenConfig.routes);
|
|
56
63
|
// The API Route might have a default export, making it also a server component
|
|
57
64
|
// If it does, only render the API route if the request method is GET
|
|
@@ -63,7 +70,10 @@ export const renderHydrogen = (App, hydrogenConfig) => {
|
|
|
63
70
|
: apiResponse;
|
|
64
71
|
}
|
|
65
72
|
}
|
|
66
|
-
const isStreamable =
|
|
73
|
+
const isStreamable = (hydrogenConfig.enableStreaming
|
|
74
|
+
? hydrogenConfig.enableStreaming(request)
|
|
75
|
+
: true) &&
|
|
76
|
+
!isBotUA(url, request.headers.get('user-agent')) &&
|
|
67
77
|
(!!streamableResponse || (await isStreamingSupported()));
|
|
68
78
|
let template = typeof indexTemplate === 'function'
|
|
69
79
|
? await indexTemplate(url.toString())
|
|
@@ -95,7 +105,9 @@ export const renderHydrogen = (App, hydrogenConfig) => {
|
|
|
95
105
|
}
|
|
96
106
|
return render(url, params);
|
|
97
107
|
};
|
|
98
|
-
|
|
108
|
+
if (__WORKER__)
|
|
109
|
+
return handleRequest;
|
|
110
|
+
return ((rawRequest, options) => handleFetchResponseInNode(handleRequest(rawRequest, options), options.streamableResponse));
|
|
99
111
|
};
|
|
100
112
|
function getApiRoute(url, routes) {
|
|
101
113
|
const apiRoutes = getApiRoutes(routes);
|
|
@@ -108,7 +120,7 @@ function getApiRoute(url, routes) {
|
|
|
108
120
|
*/
|
|
109
121
|
async function render(url, { App, request, template, componentResponse, nonce, log }) {
|
|
110
122
|
const state = { pathname: url.pathname, search: url.search };
|
|
111
|
-
const { AppSSR } = buildAppSSR({
|
|
123
|
+
const { AppSSR, rscReadable } = buildAppSSR({
|
|
112
124
|
App,
|
|
113
125
|
log,
|
|
114
126
|
state,
|
|
@@ -120,24 +132,21 @@ async function render(url, { App, request, template, componentResponse, nonce, l
|
|
|
120
132
|
componentResponse.writeHead({ status: 500 });
|
|
121
133
|
return template;
|
|
122
134
|
}
|
|
123
|
-
let html = await
|
|
135
|
+
let [html, flight] = await Promise.all([
|
|
136
|
+
renderToBufferedString(AppSSR, { log, nonce }).catch(onErrorShell),
|
|
137
|
+
bufferReadableStream(rscReadable.getReader()).catch(() => null),
|
|
138
|
+
]);
|
|
124
139
|
const { headers, status, statusText } = getResponseOptions(componentResponse);
|
|
125
140
|
/**
|
|
126
141
|
* TODO: Also add `Vary` headers for `accept-language` and any other keys
|
|
127
142
|
* we want to shard our full-page cache for all Hydrogen storefronts.
|
|
128
143
|
*/
|
|
129
144
|
headers.set('cache-control', componentResponse.cacheControlHeader);
|
|
130
|
-
if (componentResponse.customBody) {
|
|
131
|
-
// This can be used to return sitemap.xml or any other custom response.
|
|
132
|
-
postRequestTasks('ssr', status, request, componentResponse);
|
|
133
|
-
return new Response(await componentResponse.customBody, {
|
|
134
|
-
status,
|
|
135
|
-
statusText,
|
|
136
|
-
headers,
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
145
|
headers.set(CONTENT_TYPE, HTML_CONTENT_TYPE);
|
|
140
146
|
html = applyHtmlHead(html, request.ctx.head, template);
|
|
147
|
+
if (flight) {
|
|
148
|
+
html = html.replace('</body>', () => flightContainer(flight) + '</body>');
|
|
149
|
+
}
|
|
141
150
|
postRequestTasks('ssr', status, request, componentResponse);
|
|
142
151
|
return new Response(html, {
|
|
143
152
|
status,
|
|
@@ -154,7 +163,7 @@ async function stream(url, { App, request, response, componentResponse, template
|
|
|
154
163
|
const state = { pathname: url.pathname, search: url.search };
|
|
155
164
|
log.trace('start stream');
|
|
156
165
|
const { noScriptTemplate, bootstrapScripts, bootstrapModules } = stripScriptsFromTemplate(template);
|
|
157
|
-
const { AppSSR, rscReadable } = buildAppSSR({
|
|
166
|
+
const { AppSSR, rscReadable, rscDidError } = buildAppSSR({
|
|
158
167
|
App,
|
|
159
168
|
log,
|
|
160
169
|
state,
|
|
@@ -164,13 +173,17 @@ async function stream(url, { App, request, response, componentResponse, template
|
|
|
164
173
|
const rscToScriptTagReadable = new ReadableStream({
|
|
165
174
|
start(controller) {
|
|
166
175
|
log.trace('rsc start chunks');
|
|
167
|
-
|
|
176
|
+
const encoder = new TextEncoder();
|
|
177
|
+
bufferReadableStream(rscReadable.getReader(), (chunk) => {
|
|
178
|
+
const metaTag = flightContainer(chunk);
|
|
179
|
+
controller.enqueue(encoder.encode(metaTag));
|
|
180
|
+
}).then(() => {
|
|
168
181
|
log.trace('rsc finish chunks');
|
|
169
182
|
return controller.close();
|
|
170
183
|
});
|
|
171
184
|
},
|
|
172
185
|
});
|
|
173
|
-
let
|
|
186
|
+
let ssrDidError;
|
|
174
187
|
if (__WORKER__) {
|
|
175
188
|
const onCompleteAll = defer();
|
|
176
189
|
const encoder = new TextEncoder();
|
|
@@ -184,7 +197,7 @@ async function stream(url, { App, request, response, componentResponse, template
|
|
|
184
197
|
bootstrapScripts,
|
|
185
198
|
bootstrapModules,
|
|
186
199
|
onError(error) {
|
|
187
|
-
|
|
200
|
+
ssrDidError = error;
|
|
188
201
|
if (dev && !writable.closed && !!responseOptions.status) {
|
|
189
202
|
writable.write(getErrorMarkup(error));
|
|
190
203
|
}
|
|
@@ -205,8 +218,8 @@ async function stream(url, { App, request, response, componentResponse, template
|
|
|
205
218
|
onCompleteAll.resolve(true);
|
|
206
219
|
});
|
|
207
220
|
/* eslint-disable no-inner-declarations */
|
|
208
|
-
|
|
209
|
-
Object.assign(responseOptions, getResponseOptions(componentResponse,
|
|
221
|
+
function prepareForStreaming(flush) {
|
|
222
|
+
Object.assign(responseOptions, getResponseOptions(componentResponse, rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError));
|
|
210
223
|
/**
|
|
211
224
|
* TODO: This assumes `response.cache()` has been called _before_ any
|
|
212
225
|
* queries which might be caught behind Suspense. Clarify this or add
|
|
@@ -217,21 +230,17 @@ async function stream(url, { App, request, response, componentResponse, template
|
|
|
217
230
|
return false;
|
|
218
231
|
}
|
|
219
232
|
if (flush) {
|
|
220
|
-
if (componentResponse.customBody) {
|
|
221
|
-
writable.write(encoder.encode(await componentResponse.customBody));
|
|
222
|
-
return false;
|
|
223
|
-
}
|
|
224
233
|
responseOptions.headers.set(CONTENT_TYPE, HTML_CONTENT_TYPE);
|
|
225
234
|
writable.write(encoder.encode(DOCTYPE));
|
|
226
|
-
if (
|
|
235
|
+
if (rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError) {
|
|
227
236
|
// This error was delayed until the headers were properly sent.
|
|
228
|
-
writable.write(encoder.encode(getErrorMarkup(
|
|
237
|
+
writable.write(encoder.encode(getErrorMarkup((rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError))));
|
|
229
238
|
}
|
|
230
239
|
return true;
|
|
231
240
|
}
|
|
232
241
|
}
|
|
233
242
|
/* eslint-enable no-inner-declarations */
|
|
234
|
-
const shouldReturnApp = (_a =
|
|
243
|
+
const shouldReturnApp = (_a = prepareForStreaming(componentResponse.canStream())) !== null && _a !== void 0 ? _a : (await onCompleteAll.promise.then(prepareForStreaming));
|
|
235
244
|
if (shouldReturnApp) {
|
|
236
245
|
let bufferedSsr = '';
|
|
237
246
|
let isPendingSsrWrite = false;
|
|
@@ -281,14 +290,14 @@ async function stream(url, { App, request, response, componentResponse, template
|
|
|
281
290
|
* additional checks downstream?
|
|
282
291
|
*/
|
|
283
292
|
response.setHeader('cache-control', componentResponse.cacheControlHeader);
|
|
284
|
-
writeHeadToServerResponse(response, componentResponse, log,
|
|
293
|
+
writeHeadToServerResponse(response, componentResponse, log, rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError);
|
|
285
294
|
if (isRedirect(response)) {
|
|
286
295
|
// Return redirects early without further rendering/streaming
|
|
287
296
|
return response.end();
|
|
288
297
|
}
|
|
289
298
|
if (!componentResponse.canStream())
|
|
290
299
|
return;
|
|
291
|
-
startWritingHtmlToServerResponse(response, dev ?
|
|
300
|
+
startWritingHtmlToServerResponse(response, dev ? rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError : undefined);
|
|
292
301
|
setTimeout(() => {
|
|
293
302
|
log.trace('node pipe response');
|
|
294
303
|
pipe(response);
|
|
@@ -298,22 +307,19 @@ async function stream(url, { App, request, response, componentResponse, template
|
|
|
298
307
|
return response.write(chunk);
|
|
299
308
|
});
|
|
300
309
|
},
|
|
301
|
-
|
|
310
|
+
onAllReady() {
|
|
302
311
|
log.trace('node complete stream');
|
|
303
312
|
if (componentResponse.canStream() || response.writableEnded) {
|
|
304
313
|
postRequestTasks('str', response.statusCode, request, componentResponse);
|
|
305
314
|
return;
|
|
306
315
|
}
|
|
307
|
-
writeHeadToServerResponse(response, componentResponse, log,
|
|
316
|
+
writeHeadToServerResponse(response, componentResponse, log, rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError);
|
|
308
317
|
postRequestTasks('str', response.statusCode, request, componentResponse);
|
|
309
318
|
if (isRedirect(response)) {
|
|
310
319
|
// Redirects found after any async code
|
|
311
320
|
return response.end();
|
|
312
321
|
}
|
|
313
|
-
|
|
314
|
-
return response.end(await componentResponse.customBody);
|
|
315
|
-
}
|
|
316
|
-
startWritingHtmlToServerResponse(response, dev ? didError : undefined);
|
|
322
|
+
startWritingHtmlToServerResponse(response, dev ? rscDidError !== null && rscDidError !== void 0 ? rscDidError : ssrDidError : undefined);
|
|
317
323
|
bufferReadableStream(rscToScriptTagReadable.getReader()).then((scriptTags) => {
|
|
318
324
|
// Piping ends the response so script tags
|
|
319
325
|
// must be written before that.
|
|
@@ -331,7 +337,7 @@ async function stream(url, { App, request, response, componentResponse, template
|
|
|
331
337
|
}
|
|
332
338
|
},
|
|
333
339
|
onError(error) {
|
|
334
|
-
|
|
340
|
+
ssrDidError = error;
|
|
335
341
|
if (dev && response.headersSent) {
|
|
336
342
|
// Calling write would flush headers automatically.
|
|
337
343
|
// Delay this error until headers are properly sent.
|
|
@@ -354,34 +360,18 @@ async function hydrate(url, { App, log, request, response, isStreamable, compone
|
|
|
354
360
|
request,
|
|
355
361
|
response: componentResponse,
|
|
356
362
|
});
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
return new Response(bufferedBody, {
|
|
367
|
-
headers: {
|
|
368
|
-
'cache-control': componentResponse.cacheControlHeader,
|
|
369
|
-
},
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
else if (response) {
|
|
373
|
-
const rscWriter = await import(
|
|
374
|
-
// @ts-ignore
|
|
375
|
-
'@shopify/hydrogen/vendor/react-server-dom-vite/writer.node.server');
|
|
376
|
-
const streamer = rscWriter.renderToPipeableStream(AppRSC);
|
|
377
|
-
response.writeHead(200, 'ok', {
|
|
363
|
+
const rscReadable = rscRenderToReadableStream(AppRSC, {
|
|
364
|
+
onError(e) {
|
|
365
|
+
log.error(e);
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
const bufferedBody = await bufferReadableStream(rscReadable.getReader());
|
|
369
|
+
postRequestTasks('rsc', 200, request, componentResponse);
|
|
370
|
+
return new Response(bufferedBody, {
|
|
371
|
+
headers: {
|
|
378
372
|
'cache-control': componentResponse.cacheControlHeader,
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
stream.on('finish', function () {
|
|
382
|
-
postRequestTasks('rsc', response.statusCode, request, componentResponse);
|
|
383
|
-
});
|
|
384
|
-
}
|
|
373
|
+
},
|
|
374
|
+
});
|
|
385
375
|
}
|
|
386
376
|
function buildAppRSC({ App, log, state, request, response }) {
|
|
387
377
|
const hydrogenServerProps = { request, response, log };
|
|
@@ -405,7 +395,13 @@ function buildAppSSR({ App, state, request, response, log }, htmlOptions) {
|
|
|
405
395
|
request,
|
|
406
396
|
response,
|
|
407
397
|
});
|
|
408
|
-
|
|
398
|
+
let rscDidError;
|
|
399
|
+
const [rscReadableForFizz, rscReadableForFlight] = rscRenderToReadableStream(AppRSC, {
|
|
400
|
+
onError(e) {
|
|
401
|
+
rscDidError = e;
|
|
402
|
+
log.error(e);
|
|
403
|
+
},
|
|
404
|
+
}).tee();
|
|
409
405
|
const rscResponse = createFromReadableStream(rscReadableForFizz);
|
|
410
406
|
const RscConsumer = () => rscResponse.readRoot();
|
|
411
407
|
const AppSSR = (React.createElement(Html, { ...htmlOptions },
|
|
@@ -416,7 +412,7 @@ function buildAppSSR({ App, state, request, response, log }, htmlOptions) {
|
|
|
416
412
|
React.createElement(RscConsumer, null)),
|
|
417
413
|
React.createElement(Suspense, { fallback: null },
|
|
418
414
|
React.createElement(Analytics, null)))))));
|
|
419
|
-
return { AppSSR, rscReadable: rscReadableForFlight };
|
|
415
|
+
return { AppSSR, rscReadable: rscReadableForFlight, rscDidError };
|
|
420
416
|
}
|
|
421
417
|
function PreloadQueries({ request, children, }) {
|
|
422
418
|
const preloadQueries = request.getPreloadQueries();
|
|
@@ -496,7 +492,7 @@ function writeHeadToServerResponse(response, serverComponentResponse, log, error
|
|
|
496
492
|
if (statusText) {
|
|
497
493
|
response.statusMessage = statusText;
|
|
498
494
|
}
|
|
499
|
-
|
|
495
|
+
setServerHeaders(headers, response);
|
|
500
496
|
}
|
|
501
497
|
function isRedirect(response) {
|
|
502
498
|
var _a, _b;
|
|
@@ -512,9 +508,37 @@ async function createNodeWriter() {
|
|
|
512
508
|
const { PassThrough } = await import(streamImport);
|
|
513
509
|
return new PassThrough();
|
|
514
510
|
}
|
|
511
|
+
function flightContainer(chunk) {
|
|
512
|
+
return `<meta data-flight="${htmlEncode(chunk)}" />`;
|
|
513
|
+
}
|
|
515
514
|
function postRequestTasks(type, status, request, componentResponse) {
|
|
516
515
|
logServerResponse(type, request, status);
|
|
517
516
|
logCacheControlHeaders(type, request, componentResponse);
|
|
518
517
|
logQueryTimings(type, request);
|
|
519
518
|
request.savePreloadQueries();
|
|
520
519
|
}
|
|
520
|
+
/**
|
|
521
|
+
* Ensure Node.js environments handle the fetch Response correctly.
|
|
522
|
+
*/
|
|
523
|
+
function handleFetchResponseInNode(fetchResponsePromise, nodeResponse) {
|
|
524
|
+
if (nodeResponse) {
|
|
525
|
+
fetchResponsePromise.then((response) => {
|
|
526
|
+
if (!response)
|
|
527
|
+
return;
|
|
528
|
+
setServerHeaders(response.headers, nodeResponse);
|
|
529
|
+
nodeResponse.statusCode = response.status;
|
|
530
|
+
if (response.body) {
|
|
531
|
+
nodeResponse.write(response.body);
|
|
532
|
+
}
|
|
533
|
+
nodeResponse.end();
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
return fetchResponsePromise;
|
|
537
|
+
}
|
|
538
|
+
// From fetch Headers to Node Response
|
|
539
|
+
function setServerHeaders(headers, nodeResponse) {
|
|
540
|
+
// Headers.raw is only implemented in node-fetch, which is used by Hydrogen in dev and prod.
|
|
541
|
+
// It is the only way for now to access `set-cookie` header as an array.
|
|
542
|
+
// https://github.com/Shopify/hydrogen/issues/1228
|
|
543
|
+
Object.entries(headers.raw()).forEach(([key, value]) => nodeResponse.setHeader(key, value));
|
|
544
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
|
-
import { ClientAnalytics } from './
|
|
2
|
+
import { ClientAnalytics } from './ClientAnalytics';
|
|
3
3
|
export function Analytics({ analyticsDataFromServer, }) {
|
|
4
4
|
useEffect(() => {
|
|
5
5
|
const urlParams = new URLSearchParams(window.location.search);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { getNamedspacedEventname } from './utils';
|
|
2
|
-
import { isServer } from '../../utilities';
|
|
3
2
|
import { eventNames } from './const';
|
|
4
3
|
import { EVENT_PATHNAME } from '../../constants';
|
|
4
|
+
import { META_ENV_SSR } from '../ssr-interop';
|
|
5
5
|
const subscribers = {};
|
|
6
6
|
let pageAnalyticsData = {};
|
|
7
7
|
const guardDupEvents = {};
|
|
8
8
|
const USAGE_ERROR = 'ClientAnalytics should only be used within the useEffect callback or event handlers';
|
|
9
9
|
function isInvokedFromServer() {
|
|
10
|
-
if (
|
|
10
|
+
if (META_ENV_SSR) {
|
|
11
11
|
console.warn(USAGE_ERROR);
|
|
12
12
|
return true;
|
|
13
13
|
}
|
package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
|
-
import { loadScript } from '../../../../utilities';
|
|
3
|
-
import { ClientAnalytics } from '../../
|
|
2
|
+
import { loadScript } from '../../../../utilities/load_script';
|
|
3
|
+
import { ClientAnalytics } from '../../ClientAnalytics';
|
|
4
4
|
import { useShop } from '../../../useShop';
|
|
5
5
|
const URL = 'https://cdn.shopify.com/shopifycloud/boomerang/shopify-boomerang-hydrogen.min.js';
|
|
6
6
|
export function PerformanceMetrics() {
|
|
@@ -4,28 +4,24 @@ import { log } from '../../utilities/log';
|
|
|
4
4
|
import { extractPathFromRoutesKey } from '../../utilities/apiRoutes';
|
|
5
5
|
import { useServerRequest } from '../ServerRequestProvider';
|
|
6
6
|
import { RouteParamsProvider } from '../useRouteParams/RouteParamsProvider.client';
|
|
7
|
-
import { findRoutePrefix } from '../../utilities/findRoutePrefix';
|
|
8
7
|
/**
|
|
9
8
|
* The `FileRoutes` component builds a set of default Hydrogen routes based on the output provided by Vite's
|
|
10
9
|
* [import.meta.globEager](https://vitejs.dev/guide/features.html#glob-import) method. You can have multiple
|
|
11
10
|
* instances of this component to source file routes from multiple locations.
|
|
12
11
|
*/
|
|
13
12
|
export function FileRoutes({ routes, basePath, dirPrefix }) {
|
|
14
|
-
var _a;
|
|
15
13
|
const request = useServerRequest();
|
|
16
14
|
const { routeRendered, serverProps } = request.ctx.router;
|
|
17
15
|
if (routeRendered)
|
|
18
16
|
return null;
|
|
19
17
|
if (!routes) {
|
|
20
18
|
const fileRoutes = request.ctx.hydrogenConfig.routes;
|
|
21
|
-
routes =
|
|
22
|
-
dirPrefix !== null && dirPrefix !== void 0 ? dirPrefix : (dirPrefix = fileRoutes
|
|
23
|
-
basePath !== null && basePath !== void 0 ? basePath : (basePath = fileRoutes
|
|
19
|
+
routes = fileRoutes.files;
|
|
20
|
+
dirPrefix !== null && dirPrefix !== void 0 ? dirPrefix : (dirPrefix = fileRoutes.dirPrefix);
|
|
21
|
+
basePath !== null && basePath !== void 0 ? basePath : (basePath = fileRoutes.basePath);
|
|
24
22
|
}
|
|
25
23
|
basePath !== null && basePath !== void 0 ? basePath : (basePath = '/');
|
|
26
|
-
/* eslint-disable react-hooks/rules-of-hooks */
|
|
27
24
|
const pageRoutes = useMemo(() => createPageRoutes(routes, basePath, dirPrefix), [routes, basePath, dirPrefix]);
|
|
28
|
-
/* eslint-enable react-hooks/rules-of-hooks */
|
|
29
25
|
let foundRoute, foundRouteDetails;
|
|
30
26
|
for (let i = 0; i < pageRoutes.length; i++) {
|
|
31
27
|
foundRouteDetails = matchPath(serverProps.pathname, pageRoutes[i]);
|
|
@@ -42,13 +38,12 @@ export function FileRoutes({ routes, basePath, dirPrefix }) {
|
|
|
42
38
|
}
|
|
43
39
|
return null;
|
|
44
40
|
}
|
|
45
|
-
export function createPageRoutes(pages, topLevelPath = '*', dirPrefix) {
|
|
41
|
+
export function createPageRoutes(pages, topLevelPath = '*', dirPrefix = '') {
|
|
46
42
|
const topLevelPrefix = topLevelPath.replace('*', '').replace(/\/$/, '');
|
|
47
43
|
const keys = Object.keys(pages);
|
|
48
|
-
const commonRoutePrefix = dirPrefix !== null && dirPrefix !== void 0 ? dirPrefix : findRoutePrefix(keys);
|
|
49
44
|
const routes = keys
|
|
50
45
|
.map((key) => {
|
|
51
|
-
const path = extractPathFromRoutesKey(key,
|
|
46
|
+
const path = extractPathFromRoutesKey(key, dirPrefix);
|
|
52
47
|
/**
|
|
53
48
|
* Catch-all routes [...handle].jsx don't need an exact match
|
|
54
49
|
* https://reactrouter.com/core/api/Route/exact-bool
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BrowserHistory, Location } from 'history';
|
|
2
|
-
import React, { FC } from 'react';
|
|
2
|
+
import React, { FC, ReactNode } from 'react';
|
|
3
3
|
declare type RouterContextValue = {
|
|
4
4
|
history: BrowserHistory;
|
|
5
5
|
location: Location;
|
|
@@ -7,6 +7,7 @@ declare type RouterContextValue = {
|
|
|
7
7
|
export declare const RouterContext: React.Context<{} | RouterContextValue>;
|
|
8
8
|
export declare const BrowserRouter: FC<{
|
|
9
9
|
history?: BrowserHistory;
|
|
10
|
+
children: ReactNode;
|
|
10
11
|
}>;
|
|
11
12
|
export declare function useRouter(): RouterContextValue;
|
|
12
13
|
export declare function useLocation(): Location;
|
|
@@ -5,7 +5,7 @@ import { useInternalServerProps } from '../useServerProps/use-server-props';
|
|
|
5
5
|
export const RouterContext = createContext({});
|
|
6
6
|
let isFirstLoad = true;
|
|
7
7
|
const positions = {};
|
|
8
|
-
export const BrowserRouter = ({ history: pHistory, children
|
|
8
|
+
export const BrowserRouter = ({ history: pHistory, children }) => {
|
|
9
9
|
if (META_ENV_SSR)
|
|
10
10
|
return React.createElement(React.Fragment, null, children);
|
|
11
11
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable hydrogen/no-state-in-server-components */
|
|
2
1
|
import React, { createContext, useMemo, useCallback,
|
|
3
2
|
// @ts-ignore
|
|
4
3
|
useTransition, useState, } from 'react';
|
|
@@ -64,4 +63,3 @@ export function ServerPropsProvider({ initialServerProps, setServerPropsForRsc,
|
|
|
64
63
|
]);
|
|
65
64
|
return (React.createElement(ServerPropsContext.Provider, { value: value }, children));
|
|
66
65
|
}
|
|
67
|
-
/* eslint-enable hydrogen/no-state-in-server-components */
|
|
@@ -9,12 +9,27 @@ function requestCacheRSC() {
|
|
|
9
9
|
return new Map();
|
|
10
10
|
}
|
|
11
11
|
requestCacheRSC.key = Symbol.for('HYDROGEN_REQUEST');
|
|
12
|
+
// Note: use this only during RSC/Flight rendering. The React dispatcher
|
|
13
|
+
// for SSR/Fizz rendering does not implement getCacheForType.
|
|
14
|
+
function getCacheForType(resource) {
|
|
15
|
+
var _a;
|
|
16
|
+
const dispatcher =
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
|
|
19
|
+
.ReactCurrentDispatcher.current;
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
if (__DEV__ && typeof jest !== 'undefined' && !dispatcher.getCacheForType) {
|
|
22
|
+
// Jest does not have access to the RSC runtime, mock it here:
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
return ((_a = globalThis.__jestRscCache) !== null && _a !== void 0 ? _a : (globalThis.__jestRscCache = resource()));
|
|
25
|
+
}
|
|
26
|
+
return dispatcher.getCacheForType(resource);
|
|
27
|
+
}
|
|
12
28
|
export function ServerRequestProvider({ isRSC, request, children, }) {
|
|
13
29
|
if (isRSC) {
|
|
14
30
|
// Save the request object in a React cache that is
|
|
15
31
|
// scoped to this current rendering.
|
|
16
|
-
|
|
17
|
-
const requestCache = React.unstable_getCacheForType(requestCacheRSC);
|
|
32
|
+
const requestCache = getCacheForType(requestCacheRSC);
|
|
18
33
|
requestCache.set(requestCacheRSC.key, request);
|
|
19
34
|
return children;
|
|
20
35
|
}
|
|
@@ -27,7 +42,7 @@ export function useServerRequest() {
|
|
|
27
42
|
try {
|
|
28
43
|
// This cache only works during RSC rendering:
|
|
29
44
|
// @ts-ignore
|
|
30
|
-
const cache =
|
|
45
|
+
const cache = getCacheForType(requestCacheRSC);
|
|
31
46
|
request = cache ? cache.get(requestCacheRSC.key) : null;
|
|
32
47
|
}
|
|
33
48
|
catch (_a) {
|
|
@@ -39,7 +39,6 @@ children, }) {
|
|
|
39
39
|
}
|
|
40
40
|
let actualShopifyConfig;
|
|
41
41
|
if (typeof shopifyConfig === 'function') {
|
|
42
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
43
42
|
const result = useRequestCacheData(['hydrogen-shopify-config'], () => shopifyConfig(request));
|
|
44
43
|
if (result.error) {
|
|
45
44
|
if (result.error instanceof Error) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { getLoggerWithContext, collectQueryCacheControlHeaders, collectQueryTimings,
|
|
2
|
-
import { deleteItemFromCache, generateSubRequestCacheControlHeader, getItemFromCache, isStale, setItemInCache, } from '../../framework/cache';
|
|
3
|
-
import { hashKey } from '../../utilities/hash';
|
|
1
|
+
import { getLoggerWithContext, collectQueryCacheControlHeaders, collectQueryTimings, } from '../../utilities/log';
|
|
2
|
+
import { deleteItemFromCache, generateSubRequestCacheControlHeader, getItemFromCache, isStale, setItemInCache, } from '../../framework/cache-sub-request';
|
|
4
3
|
import { runDelayedFunction } from '../../framework/runtime';
|
|
5
4
|
import { useRequestCacheData, useServerRequest } from '../ServerRequestProvider';
|
|
5
|
+
import { CacheSeconds } from '../../framework/CachingStrategy';
|
|
6
6
|
/**
|
|
7
7
|
* The `useQuery` hook executes an asynchronous operation like `fetch` in a way that
|
|
8
8
|
* supports [Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html). You can use this
|
|
@@ -48,7 +48,6 @@ function cachedQueryFnBuilder(key, queryFn, queryOptions) {
|
|
|
48
48
|
// to prevent losing the current React cycle.
|
|
49
49
|
const request = useServerRequest();
|
|
50
50
|
const log = getLoggerWithContext(request);
|
|
51
|
-
const hashedKey = hashKey(key);
|
|
52
51
|
const cacheResponse = await getItemFromCache(key);
|
|
53
52
|
async function generateNewOutput() {
|
|
54
53
|
return await queryFn();
|
|
@@ -59,15 +58,15 @@ function cachedQueryFnBuilder(key, queryFn, queryOptions) {
|
|
|
59
58
|
/**
|
|
60
59
|
* Important: Do this async
|
|
61
60
|
*/
|
|
62
|
-
if (isStale(
|
|
63
|
-
|
|
64
|
-
const lockKey = `lock-${key}`;
|
|
61
|
+
if (isStale(key, response)) {
|
|
62
|
+
const lockKey = ['lock', ...(typeof key === 'string' ? [key] : key)];
|
|
65
63
|
runDelayedFunction(async () => {
|
|
66
|
-
logCacheApiStatus('UPDATING', hashedKey);
|
|
67
64
|
const lockExists = await getItemFromCache(lockKey);
|
|
68
65
|
if (lockExists)
|
|
69
66
|
return;
|
|
70
|
-
await setItemInCache(lockKey, true
|
|
67
|
+
await setItemInCache(lockKey, true, CacheSeconds({
|
|
68
|
+
maxAge: 10,
|
|
69
|
+
}));
|
|
71
70
|
try {
|
|
72
71
|
const output = await generateNewOutput();
|
|
73
72
|
if (shouldCacheResponse(output)) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import React, { FC } from 'react';
|
|
1
|
+
import React, { FC, ReactNode } from 'react';
|
|
2
2
|
declare type RouteParamsContextValue = {
|
|
3
3
|
routeParams: Record<string, string>;
|
|
4
4
|
};
|
|
5
5
|
export declare const RouteParamsContext: React.Context<RouteParamsContextValue>;
|
|
6
6
|
export declare const RouteParamsProvider: FC<{
|
|
7
7
|
routeParams: Record<string, string>;
|
|
8
|
+
children: ReactNode;
|
|
8
9
|
}>;
|
|
9
10
|
export {};
|
|
@@ -2,6 +2,6 @@ import React, { createContext } from 'react';
|
|
|
2
2
|
export const RouteParamsContext = createContext({
|
|
3
3
|
routeParams: {},
|
|
4
4
|
});
|
|
5
|
-
export const RouteParamsProvider = ({ children, routeParams
|
|
5
|
+
export const RouteParamsProvider = ({ children, routeParams }) => {
|
|
6
6
|
return (React.createElement(RouteParamsContext.Provider, { value: { routeParams } }, children));
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ShopifyContextValue } from '../../foundation/ShopifyProvider/types';
|
|
2
2
|
import type { QueryCacheControlHeaders } from '../../utilities/log/log-cache-header';
|
|
3
3
|
import type { QueryTiming } from '../../utilities/log/log-query-timeline';
|
|
4
|
-
import type {
|
|
4
|
+
import type { ResolvedHydrogenConfig, PreloadOptions, QueryKey } from '../../types';
|
|
5
5
|
import { HelmetData as HeadData } from 'react-helmet-async';
|
|
6
6
|
import { SessionSyncApi } from '../../foundation/session/session';
|
|
7
7
|
export declare type PreloadQueryEntry = {
|
|
@@ -31,7 +31,7 @@ export declare class ServerComponentRequest extends Request {
|
|
|
31
31
|
ctx: {
|
|
32
32
|
cache: Map<string, any>;
|
|
33
33
|
head: HeadData;
|
|
34
|
-
hydrogenConfig?:
|
|
34
|
+
hydrogenConfig?: ResolvedHydrogenConfig;
|
|
35
35
|
shopifyConfig?: ShopifyContextValue;
|
|
36
36
|
queryCacheControl: Array<QueryCacheControlHeaders>;
|
|
37
37
|
queryTimings: Array<QueryTiming>;
|
|
@@ -2,15 +2,11 @@ import type { CachingStrategy } from '../../types';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
export declare class ServerComponentResponse extends Response {
|
|
4
4
|
private wait;
|
|
5
|
-
private cacheOptions
|
|
5
|
+
private cacheOptions;
|
|
6
6
|
customStatus?: {
|
|
7
7
|
code?: number;
|
|
8
8
|
text?: string;
|
|
9
9
|
};
|
|
10
|
-
/**
|
|
11
|
-
* Allow custom body to be a string or a Promise.
|
|
12
|
-
*/
|
|
13
|
-
customBody: string | Promise<string>;
|
|
14
10
|
/**
|
|
15
11
|
* Buffer the current response until all queries have resolved,
|
|
16
12
|
* and prevent it from streaming back early.
|
|
@@ -27,9 +23,4 @@ export declare class ServerComponentResponse extends Response {
|
|
|
27
23
|
redirect(location: string, status?: number): React.FunctionComponentElement<{
|
|
28
24
|
to: string;
|
|
29
25
|
}>;
|
|
30
|
-
/**
|
|
31
|
-
* Send the response from a Server Component. Renders React components to string,
|
|
32
|
-
* and returns `null` to make React happy.
|
|
33
|
-
*/
|
|
34
|
-
send(body: any): null;
|
|
35
26
|
}
|