@shopify/hydrogen 0.7.0 → 0.8.2
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/dist/esnext/components/CartEstimatedCost/CartEstimatedCost.client.d.ts +1 -1
- package/dist/esnext/components/CartEstimatedCost/CartEstimatedCost.client.js +1 -1
- package/dist/esnext/components/CartLineProvider/context.d.ts +3 -3
- package/dist/esnext/components/CartLineQuantityAdjustButton/CartLineQuantityAdjustButton.js +4 -0
- package/dist/esnext/components/CartProvider/CartProvider.client.js +0 -1
- package/dist/esnext/components/ExternalVideo/ExternalVideo.d.ts +1 -1
- package/dist/esnext/components/Image/Image.d.ts +1 -1
- package/dist/esnext/components/LocalizationProvider/index.d.ts +1 -0
- package/dist/esnext/components/LocalizationProvider/index.js +1 -0
- package/dist/esnext/components/MediaFile/MediaFile.d.ts +1 -1
- package/dist/esnext/components/Metafield/Metafield.client.d.ts +1 -1
- package/dist/esnext/components/Metafield/components/StarRating/StarRating.d.ts +1 -1
- package/dist/esnext/components/Metafield/index.d.ts +2 -2
- package/dist/esnext/components/Model3D/Model3D.client.d.ts +1 -1
- package/dist/esnext/components/Money/Money.client.d.ts +1 -1
- package/dist/esnext/components/ProductPrice/ProductPrice.client.d.ts +1 -3
- package/dist/esnext/components/ProductPrice/ProductPrice.client.js +1 -3
- package/dist/esnext/components/ProductProvider/ProductProvider.client.d.ts +1 -1
- package/dist/esnext/components/ShopPayButton/ShopPayButton.client.js +1 -1
- package/dist/esnext/components/UnitPrice/UnitPrice.client.d.ts +2 -3
- package/dist/esnext/components/UnitPrice/UnitPrice.client.js +1 -2
- package/dist/esnext/components/Video/Video.d.ts +1 -1
- package/dist/esnext/components/index.d.ts +3 -2
- package/dist/esnext/components/index.js +1 -0
- package/dist/esnext/entry-client.js +4 -6
- package/dist/esnext/entry-server.js +77 -47
- package/dist/esnext/foundation/RenderCacheProvider/RenderCacheContext.d.ts +2 -0
- package/dist/esnext/foundation/RenderCacheProvider/RenderCacheContext.js +4 -0
- package/dist/esnext/foundation/RenderCacheProvider/RenderCacheProvider.d.ts +2 -0
- package/dist/esnext/foundation/RenderCacheProvider/RenderCacheProvider.js +5 -0
- package/dist/esnext/foundation/RenderCacheProvider/hook.d.ts +11 -0
- package/dist/esnext/foundation/RenderCacheProvider/hook.js +34 -0
- package/dist/esnext/foundation/RenderCacheProvider/index.d.ts +1 -0
- package/dist/esnext/foundation/RenderCacheProvider/index.js +1 -0
- package/dist/esnext/foundation/RenderCacheProvider/types.d.ts +18 -0
- package/dist/esnext/foundation/RenderCacheProvider/types.js +1 -0
- package/dist/esnext/foundation/Router/DefaultRoutes.d.ts +3 -1
- package/dist/esnext/foundation/Router/DefaultRoutes.js +2 -2
- package/dist/esnext/foundation/ServerStateProvider/ServerStateProvider.client.js +4 -2
- package/dist/esnext/foundation/ServerStateProvider/index.d.ts +2 -1
- package/dist/esnext/foundation/ShopifyProvider/ShopifyServerProvider.server.d.ts +1 -3
- package/dist/esnext/foundation/ShopifyProvider/ShopifyServerProvider.server.js +2 -4
- package/dist/esnext/foundation/ShopifyProvider/types.d.ts +0 -5
- package/dist/esnext/foundation/useQuery/hooks.d.ts +8 -6
- package/dist/esnext/foundation/useQuery/hooks.js +13 -14
- package/dist/esnext/foundation/useQuery/index.d.ts +0 -1
- package/dist/esnext/foundation/useQuery/index.js +0 -1
- package/dist/esnext/foundation/useServerState/use-server-state.d.ts +1 -1
- package/dist/esnext/foundation/useServerState/use-server-state.js +1 -1
- package/dist/esnext/foundation/useShop/use-shop.d.ts +1 -1
- package/dist/esnext/foundation/useShop/use-shop.js +1 -1
- package/dist/esnext/framework/ClientMarker/ClientMarker.js +0 -1
- package/dist/esnext/framework/Hydration/ServerComponentRequest.server.d.ts +1 -0
- package/dist/esnext/framework/Hydration/ServerComponentRequest.server.js +2 -0
- package/dist/esnext/framework/Hydration/writer.server.js +1 -0
- package/dist/esnext/framework/cache.d.ts +2 -2
- package/dist/esnext/framework/cache.js +1 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.d.ts +1 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.js +13 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-middleware.d.ts +7 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-middleware.js +15 -1
- package/dist/esnext/framework/plugins/vite-plugin-react-server-components-shim.js +1 -23
- package/dist/esnext/framework/server-components.js +25 -47
- package/dist/esnext/graphql/graphql-constants.d.ts +23 -23
- package/dist/esnext/handle-event.d.ts +1 -1
- package/dist/esnext/handle-event.js +68 -10
- package/dist/esnext/hooks/index.d.ts +1 -1
- package/dist/esnext/hooks/index.js +1 -1
- package/dist/esnext/hooks/useCartLine/useCartLine.d.ts +3 -3
- package/dist/esnext/hooks/useShopQuery/hooks.d.ts +5 -5
- package/dist/esnext/hooks/useShopQuery/hooks.js +45 -17
- package/dist/esnext/index.d.ts +2 -1
- package/dist/esnext/index.js +2 -1
- package/dist/esnext/types.d.ts +2 -1
- package/dist/esnext/utilities/fetch.js +3 -6
- package/dist/esnext/utilities/index.d.ts +1 -0
- package/dist/esnext/utilities/index.js +1 -0
- package/dist/esnext/utilities/log/index.d.ts +1 -0
- package/dist/esnext/utilities/log/index.js +1 -0
- package/dist/esnext/utilities/log/log.d.ts +17 -0
- package/dist/esnext/utilities/log/log.js +70 -0
- package/dist/esnext/utilities/suspense.d.ts +2 -2
- package/dist/esnext/utilities/suspense.js +0 -6
- package/dist/esnext/utilities/timing.d.ts +7 -0
- package/dist/esnext/utilities/timing.js +14 -0
- package/dist/esnext/version.d.ts +1 -1
- package/dist/esnext/version.js +1 -1
- package/dist/node/framework/ClientMarker/ClientMarker.js +2 -3
- package/dist/node/framework/Hydration/Cache.client.js +4 -4
- package/dist/node/framework/Hydration/HydrationContext.server.js +1 -1
- package/dist/node/framework/Hydration/ServerComponentRequest.server.d.ts +1 -0
- package/dist/node/framework/Hydration/ServerComponentRequest.server.js +2 -0
- package/dist/node/framework/Hydration/ServerComponentResponse.server.js +2 -2
- package/dist/node/framework/Hydration/react-utils.js +3 -3
- package/dist/node/framework/Hydration/wire.server.js +1 -1
- package/dist/node/framework/Hydration/writer.server.js +1 -0
- package/dist/node/framework/cache.d.ts +2 -2
- package/dist/node/framework/cache.js +5 -4
- package/dist/node/framework/middleware.js +2 -2
- package/dist/node/framework/plugin.js +5 -5
- package/dist/node/framework/plugins/vite-plugin-hydrogen-config.d.ts +1 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-config.js +13 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-middleware.d.ts +7 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-middleware.js +17 -3
- package/dist/node/framework/plugins/vite-plugin-react-server-components-shim.js +8 -30
- package/dist/node/framework/server-components.js +27 -49
- package/dist/node/handle-event.d.ts +1 -1
- package/dist/node/handle-event.js +72 -14
- package/dist/node/types.d.ts +2 -1
- package/dist/node/utilities/fetch.js +4 -7
- package/dist/node/utilities/index.d.ts +1 -0
- package/dist/node/utilities/index.js +3 -1
- package/dist/node/utilities/isServer/isServer.js +1 -1
- package/dist/node/utilities/suspense.d.ts +2 -2
- package/dist/node/utilities/suspense.js +0 -6
- package/dist/node/utilities/timing.d.ts +7 -0
- package/dist/node/utilities/timing.js +18 -0
- package/dist/node/utilities/video_parameters.js +1 -1
- package/dist/node/version.d.ts +1 -1
- package/dist/node/version.js +1 -1
- package/dist/worker/framework/Hydration/ServerComponentRequest.server.d.ts +1 -0
- package/dist/worker/framework/Hydration/ServerComponentRequest.server.js +2 -0
- package/dist/worker/framework/cache.d.ts +2 -2
- package/dist/worker/framework/cache.js +1 -1
- package/dist/worker/handle-event.d.ts +1 -1
- package/dist/worker/handle-event.js +68 -10
- package/dist/worker/types.d.ts +2 -1
- package/dist/worker/utilities/timing.d.ts +7 -0
- package/dist/worker/utilities/timing.js +14 -0
- package/package.json +10 -10
- package/dist/esnext/foundation/useQuery/QueryProvider.d.ts +0 -6
- package/dist/esnext/foundation/useQuery/QueryProvider.js +0 -13
|
@@ -7,7 +7,7 @@ export interface CartEstimatedCostProps {
|
|
|
7
7
|
children?: React.ReactNode;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* The
|
|
10
|
+
* The `CartEstimatedCost` component renders a `Money` component with the
|
|
11
11
|
* cost associated with the `amountType` prop. If no `amountType` prop is specified, then it defaults to `totalAmount`.
|
|
12
12
|
* If `children` is a function, then it will pass down the render props provided by the parent component.
|
|
13
13
|
*/
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { useCart } from '../CartProvider';
|
|
3
3
|
import { Money } from '../Money';
|
|
4
4
|
/**
|
|
5
|
-
* The
|
|
5
|
+
* The `CartEstimatedCost` component renders a `Money` component with the
|
|
6
6
|
* cost associated with the `amountType` prop. If no `amountType` prop is specified, then it defaults to `totalAmount`.
|
|
7
7
|
* If `children` is a function, then it will pass down the render props provided by the parent component.
|
|
8
8
|
*/
|
|
@@ -6,7 +6,7 @@ export declare const CartLineContext: import("react").Context<({
|
|
|
6
6
|
} & Pick<import("../../graphql/types/types").Attribute, "key" | "value">)[];
|
|
7
7
|
merchandise: {
|
|
8
8
|
__typename?: "ProductVariant" | undefined;
|
|
9
|
-
} & Pick<import("../../graphql/types/types").ProductVariant, "
|
|
9
|
+
} & Pick<import("../../graphql/types/types").ProductVariant, "id" | "title" | "availableForSale" | "requiresShipping"> & {
|
|
10
10
|
compareAtPriceV2?: import("../../graphql/types/types").Maybe<{
|
|
11
11
|
__typename?: "MoneyV2" | undefined;
|
|
12
12
|
} & {
|
|
@@ -21,12 +21,12 @@ export declare const CartLineContext: import("react").Context<({
|
|
|
21
21
|
__typename?: "Image" | undefined;
|
|
22
22
|
} & {
|
|
23
23
|
__typename?: "Image" | undefined;
|
|
24
|
-
} & Pick<import("../../graphql/types/types").Image, "
|
|
24
|
+
} & Pick<import("../../graphql/types/types").Image, "id" | "height" | "width" | "url" | "altText">> | undefined;
|
|
25
25
|
product: {
|
|
26
26
|
__typename?: "Product" | undefined;
|
|
27
27
|
} & Pick<import("../../graphql/types/types").Product, "title" | "handle">;
|
|
28
28
|
selectedOptions: ({
|
|
29
29
|
__typename?: "SelectedOption" | undefined;
|
|
30
|
-
} & Pick<import("../../graphql/types/types").SelectedOption, "
|
|
30
|
+
} & Pick<import("../../graphql/types/types").SelectedOption, "name" | "value">)[];
|
|
31
31
|
};
|
|
32
32
|
}) | null>;
|
|
@@ -17,6 +17,10 @@ export function CartLineQuantityAdjustButton(props) {
|
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
const quantity = adjust === 'decrease' ? cartLine.quantity - 1 : cartLine.quantity + 1;
|
|
20
|
+
if (quantity <= 0) {
|
|
21
|
+
removeLines([cartLine.id]);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
20
24
|
updateLines([{ id: cartLine.id, quantity }]);
|
|
21
25
|
}, ...passthroughProps }, children));
|
|
22
26
|
}
|
|
@@ -417,7 +417,6 @@ export function CartProvider({ children, numCartLines, onCreate, onLineAdd, onLi
|
|
|
417
417
|
return;
|
|
418
418
|
}
|
|
419
419
|
buyerIdentityUpdate({ countryCode }, state);
|
|
420
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
421
420
|
}, [countryCode]);
|
|
422
421
|
const cartContextValue = useMemo(() => {
|
|
423
422
|
return {
|
|
@@ -22,5 +22,5 @@ export declare function ExternalVideo<TTag extends React.ElementType = 'iframe'>
|
|
|
22
22
|
export declare namespace ExternalVideo {
|
|
23
23
|
var Fragment: string;
|
|
24
24
|
}
|
|
25
|
-
export declare const ExternalVideoFragment
|
|
25
|
+
export declare const ExternalVideoFragment = "fragment ExternalVideoFragment on ExternalVideo {\n id\n embeddedUrl\n host\n}\n\n";
|
|
26
26
|
export {};
|
|
@@ -38,5 +38,5 @@ export declare function Image<TTag extends React.ElementType = 'img'>(props: Pro
|
|
|
38
38
|
export declare namespace Image {
|
|
39
39
|
var Fragment: string;
|
|
40
40
|
}
|
|
41
|
-
export declare const ImageFragment
|
|
41
|
+
export declare const ImageFragment = "fragment ImageFragment on Image {\n id\n url\n altText\n width\n height\n}\n\n";
|
|
42
42
|
export {};
|
|
@@ -24,5 +24,5 @@ export declare function MediaFile({ media, options, ...passthroughProps }: Media
|
|
|
24
24
|
export declare namespace MediaFile {
|
|
25
25
|
var Fragment: string;
|
|
26
26
|
}
|
|
27
|
-
export declare const MediaFileFragment
|
|
27
|
+
export declare const MediaFileFragment = "\nfragment MediaFileFragment on Media {\n ... on MediaImage {\n mediaContentType\n image {\n ...ImageFragment\n }\n }\n ... on Video {\n mediaContentType\n ...VideoFragment\n }\n ... on ExternalVideo {\n mediaContentType\n ...ExternalVideoFragment\n }\n ... on Model3d {\n mediaContentType\n ...Model3DFragment\n }\n}\n\nfragment ImageFragment on Image {\n id\n url\n altText\n width\n height\n}\n\nfragment VideoFragment on Video {\n id\n previewImage {\n url\n }\n sources {\n mimeType\n url\n }\n}\n\nfragment ExternalVideoFragment on ExternalVideo {\n id\n embeddedUrl\n host\n}\n\nfragment Model3DFragment on Model3d {\n id\n alt\n mediaContentType\n previewImage {\n url\n }\n sources {\n url\n }\n}\n";
|
|
28
28
|
export {};
|
|
@@ -22,4 +22,4 @@ export declare function Metafield<TTag extends ElementType>(props: Props<TTag> &
|
|
|
22
22
|
export declare namespace Metafield {
|
|
23
23
|
var Fragment: string;
|
|
24
24
|
}
|
|
25
|
-
export declare const MetafieldFragment:
|
|
25
|
+
export declare const MetafieldFragment = "\nfragment MetafieldFragment on Metafield {\n id\n type\n namespace\n key\n value\n createdAt\n updatedAt\n description\n reference @include(if: $includeReferenceMetafieldDetails) {\n __typename\n ... on MediaImage {\n id\n mediaContentType\n image {\n ...ImageFragment\n }\n }\n }\n}\nfragment ImageFragment on Image {\n id\n url\n altText\n width\n height\n}\n";
|
|
@@ -8,5 +8,5 @@ export interface StarRatingProps {
|
|
|
8
8
|
}
|
|
9
9
|
export declare function StarRating<TTag extends ElementType>(props: Props<TTag> & StarRatingProps): JSX.Element;
|
|
10
10
|
export declare function Star({ percentFilled }: {
|
|
11
|
-
percentFilled:
|
|
11
|
+
percentFilled: number;
|
|
12
12
|
}): JSX.Element;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Metafield, MetafieldFragment } from './Metafield.client';
|
|
2
|
-
export { MetafieldType } from './types';
|
|
3
|
-
export { MetafieldFragmentFragment } from './MetafieldFragment';
|
|
2
|
+
export type { MetafieldType } from './types';
|
|
3
|
+
export type { MetafieldFragmentFragment } from './MetafieldFragment';
|
|
@@ -134,5 +134,5 @@ export declare function Model3D<TTag extends ElementType>(props: Props<TTag, Pro
|
|
|
134
134
|
export declare namespace Model3D {
|
|
135
135
|
var Fragment: string;
|
|
136
136
|
}
|
|
137
|
-
export declare const Model3DFragment
|
|
137
|
+
export declare const Model3DFragment = "fragment Model3DFragment on Model3d {\n id\n alt\n mediaContentType\n previewImage {\n url\n }\n sources {\n url\n }\n}\n\n";
|
|
138
138
|
export {};
|
|
@@ -19,4 +19,4 @@ export declare function Money<TTag extends ElementType>(props: Props<TTag> & Mon
|
|
|
19
19
|
export declare namespace Money {
|
|
20
20
|
var Fragment: string;
|
|
21
21
|
}
|
|
22
|
-
export declare const MoneyFragment
|
|
22
|
+
export declare const MoneyFragment = "fragment MoneyFragment on MoneyV2 {\n currencyCode\n amount\n}\n";
|
|
@@ -8,8 +8,6 @@ export interface ProductPriceProps {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* The `ProductPrice` component renders a `Money` component with the product
|
|
11
|
-
* [`priceRange`](/api/storefront/reference/products/productpricerange)'s `maxVariantPrice`
|
|
12
|
-
* or `minVariantPrice`, for either the regular price or compare at price range.
|
|
13
|
-
* It must be a descendent of the `ProductProvider` component.
|
|
11
|
+
* [`priceRange`](/api/storefront/reference/products/productpricerange)'s `maxVariantPrice` or `minVariantPrice`, for either the regular price or compare at price range. It must be a descendent of the `ProductProvider` component.
|
|
14
12
|
*/
|
|
15
13
|
export declare function ProductPrice<TTag extends ElementType>(props: Props<TTag> & ProductPriceProps): JSX.Element | null;
|
|
@@ -3,9 +3,7 @@ import { Money } from '../Money';
|
|
|
3
3
|
import { useProduct } from '../ProductProvider';
|
|
4
4
|
/**
|
|
5
5
|
* The `ProductPrice` component renders a `Money` component with the product
|
|
6
|
-
* [`priceRange`](/api/storefront/reference/products/productpricerange)'s `maxVariantPrice`
|
|
7
|
-
* or `minVariantPrice`, for either the regular price or compare at price range.
|
|
8
|
-
* It must be a descendent of the `ProductProvider` component.
|
|
6
|
+
* [`priceRange`](/api/storefront/reference/products/productpricerange)'s `maxVariantPrice` or `minVariantPrice`, for either the regular price or compare at price range. It must be a descendent of the `ProductProvider` component.
|
|
9
7
|
*/
|
|
10
8
|
export function ProductPrice(props) {
|
|
11
9
|
var _a, _b, _c, _d;
|
|
@@ -15,4 +15,4 @@ export declare function ProductProvider({ children, product, initialVariantId, }
|
|
|
15
15
|
export declare namespace ProductProvider {
|
|
16
16
|
var Fragment: string;
|
|
17
17
|
}
|
|
18
|
-
export declare const ProductProviderFragment:
|
|
18
|
+
export declare const ProductProviderFragment = "\nfragment ProductProviderFragment on Product {\n compareAtPriceRange {\n maxVariantPrice {\n ...MoneyFragment\n }\n minVariantPrice {\n ...MoneyFragment\n }\n }\n descriptionHtml\n handle\n id\n media(first: $numProductMedia) {\n edges {\n node {\n ...MediaFileFragment\n }\n }\n }\n metafields(first: $numProductMetafields) {\n edges {\n node {\n ...MetafieldFragment\n }\n }\n }\n priceRange {\n maxVariantPrice {\n ...MoneyFragment\n }\n minVariantPrice {\n ...MoneyFragment\n }\n }\n title\n variants(first: $numProductVariants) {\n edges {\n node {\n ...VariantFragment\n }\n }\n }\n sellingPlanGroups(first: $numProductSellingPlanGroups) {\n edges {\n node {\n ...SellingPlanGroupsFragment\n }\n }\n }\n}\n\n\nfragment MediaFileFragment on Media {\n ... on MediaImage {\n mediaContentType\n image {\n ...ImageFragment\n }\n }\n ... on Video {\n mediaContentType\n ...VideoFragment\n }\n ... on ExternalVideo {\n mediaContentType\n ...ExternalVideoFragment\n }\n ... on Model3d {\n mediaContentType\n ...Model3DFragment\n }\n}\n\n\nfragment MetafieldFragment on Metafield {\n id\n type\n namespace\n key\n value\n createdAt\n updatedAt\n description\n reference @include(if: $includeReferenceMetafieldDetails) {\n __typename\n ... on MediaImage {\n id\n mediaContentType\n image {\n ...ImageFragment\n }\n }\n }\n}\n\nfragment VariantFragment on ProductVariant {\n id\n title\n availableForSale\n image {\n ...ImageFragment\n }\n ...UnitPriceFragment\n priceV2 {\n ...MoneyFragment\n }\n compareAtPriceV2 {\n ...MoneyFragment\n }\n selectedOptions {\n name\n value\n }\n metafields(first: $numProductVariantMetafields) {\n edges {\n node {\n ...MetafieldFragment\n }\n }\n }\n sellingPlanAllocations(first: $numProductVariantSellingPlanAllocations) {\n edges {\n node {\n priceAdjustments {\n compareAtPrice {\n ...MoneyFragment\n }\n perDeliveryPrice {\n ...MoneyFragment\n }\n price {\n ...MoneyFragment\n }\n unitPrice {\n ...MoneyFragment\n }\n }\n sellingPlan {\n ...SellingPlanFragment\n }\n }\n }\n }\n}\n\n\nfragment SellingPlanGroupsFragment on SellingPlanGroup {\n sellingPlans(first:$numProductSellingPlans) {\n edges {\n node {\n ...SellingPlanFragment\n }\n }\n }\n appName\n name\n options {\n name\n values\n }\n}\nfragment MoneyFragment on MoneyV2 {\n currencyCode\n amount\n}\nfragment ImageFragment on Image {\n id\n url\n altText\n width\n height\n}\n\nfragment VideoFragment on Video {\n id\n previewImage {\n url\n }\n sources {\n mimeType\n url\n }\n}\n\nfragment ExternalVideoFragment on ExternalVideo {\n id\n embeddedUrl\n host\n}\n\nfragment Model3DFragment on Model3d {\n id\n alt\n mediaContentType\n previewImage {\n url\n }\n sources {\n url\n }\n}\n\nfragment ImageFragment on Image {\n id\n url\n altText\n width\n height\n}\n\n\nfragment SellingPlanFragment on SellingPlan {\n id\n description\n name\n options {\n name\n value\n }\n priceAdjustments {\n orderCount\n adjustmentValue {\n ...on SellingPlanFixedAmountPriceAdjustment {\n adjustmentAmount {\n ...MoneyFragment\n }\n }\n ...on SellingPlanFixedPriceAdjustment {\n price {\n ...MoneyFragment\n }\n }\n ...on SellingPlanPercentagePriceAdjustment {\n adjustmentPercentage\n }\n }\n }\n recurringDeliveries\n}\nfragment MoneyFragment on MoneyV2 {\n currencyCode\n amount\n}\nfragment ImageFragment on Image {\n id\n url\n altText\n width\n height\n}\n\n\nfragment UnitPriceFragment on ProductVariant {\n unitPriceMeasurement {\n measuredType\n quantityUnit\n quantityValue\n referenceUnit\n referenceValue\n }\n unitPrice {\n ...MoneyFragment\n }\n}\nfragment MoneyFragment on MoneyV2 {\n currencyCode\n amount\n}\nfragment MoneyFragment on MoneyV2 {\n currencyCode\n amount\n}\n\nfragment SellingPlanFragment on SellingPlan {\n id\n description\n name\n options {\n name\n value\n }\n priceAdjustments {\n orderCount\n adjustmentValue {\n ...on SellingPlanFixedAmountPriceAdjustment {\n adjustmentAmount {\n ...MoneyFragment\n }\n }\n ...on SellingPlanFixedPriceAdjustment {\n price {\n ...MoneyFragment\n }\n }\n ...on SellingPlanPercentagePriceAdjustment {\n adjustmentPercentage\n }\n }\n }\n recurringDeliveries\n}\nfragment MoneyFragment on MoneyV2 {\n currencyCode\n amount\n}";
|
|
@@ -11,7 +11,7 @@ export function ShopPayButton({ variantIds, className }) {
|
|
|
11
11
|
const { storeDomain } = useShop();
|
|
12
12
|
useEffect(() => {
|
|
13
13
|
const ids = variantIds.reduce((accumulator, gid) => {
|
|
14
|
-
const id =
|
|
14
|
+
const id = gid.split('/').pop();
|
|
15
15
|
if (id) {
|
|
16
16
|
accumulator.push(id);
|
|
17
17
|
}
|
|
@@ -13,8 +13,7 @@ export interface UnitPriceProps {
|
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* The `UnitPrice` component renders a string with a [UnitPrice](/themes/pricing-payments/unit-pricing) as the
|
|
16
|
-
* [Storefront API's `MoneyV2` object](/api/storefront/reference/common-objects/moneyv2) with a reference unit from
|
|
17
|
-
* the [Storefront API's `UnitPriceMeasurement` object](/api/storefront/reference/products/unitpricemeasurement).
|
|
16
|
+
* [Storefront API's `MoneyV2` object](/api/storefront/reference/common-objects/moneyv2) with a reference unit from the [Storefront API's `UnitPriceMeasurement` object](/api/storefront/reference/products/unitpricemeasurement).
|
|
18
17
|
*
|
|
19
18
|
* If `children` is a function, then it will provide render props for the `children` corresponding to the object
|
|
20
19
|
* returned by the `useMoney` hook and the `UnitPriceMeasurement` object.
|
|
@@ -23,4 +22,4 @@ export declare function UnitPrice<TTag extends ElementType>(props: Props<TTag> &
|
|
|
23
22
|
export declare namespace UnitPrice {
|
|
24
23
|
var Fragment: string;
|
|
25
24
|
}
|
|
26
|
-
export declare const UnitPriceFragment
|
|
25
|
+
export declare const UnitPriceFragment = "\nfragment UnitPriceFragment on ProductVariant {\n unitPriceMeasurement {\n measuredType\n quantityUnit\n quantityValue\n referenceUnit\n referenceValue\n }\n unitPrice {\n ...MoneyFragment\n }\n}\nfragment MoneyFragment on MoneyV2 {\n currencyCode\n amount\n}";
|
|
@@ -4,8 +4,7 @@ import { Money } from '../Money';
|
|
|
4
4
|
import { UnitPriceFragment as Fragment } from '../../graphql/graphql-constants';
|
|
5
5
|
/**
|
|
6
6
|
* The `UnitPrice` component renders a string with a [UnitPrice](/themes/pricing-payments/unit-pricing) as the
|
|
7
|
-
* [Storefront API's `MoneyV2` object](/api/storefront/reference/common-objects/moneyv2) with a reference unit from
|
|
8
|
-
* the [Storefront API's `UnitPriceMeasurement` object](/api/storefront/reference/products/unitpricemeasurement).
|
|
7
|
+
* [Storefront API's `MoneyV2` object](/api/storefront/reference/common-objects/moneyv2) with a reference unit from the [Storefront API's `UnitPriceMeasurement` object](/api/storefront/reference/products/unitpricemeasurement).
|
|
9
8
|
*
|
|
10
9
|
* If `children` is a function, then it will provide render props for the `children` corresponding to the object
|
|
11
10
|
* returned by the `useMoney` hook and the `UnitPriceMeasurement` object.
|
|
@@ -19,4 +19,4 @@ export declare function Video<TTag extends React.ElementType = 'video'>(props: P
|
|
|
19
19
|
export declare namespace Video {
|
|
20
20
|
var Fragment: string;
|
|
21
21
|
}
|
|
22
|
-
export declare const VideoFragment
|
|
22
|
+
export declare const VideoFragment = "fragment VideoFragment on Video {\n id\n previewImage {\n url\n }\n sources {\n mimeType\n url\n }\n}\n\n";
|
|
@@ -15,8 +15,8 @@ export type { Model3DProps } from './Model3D';
|
|
|
15
15
|
export { Model3D } from './Model3D';
|
|
16
16
|
export type { MoneyProps } from './Money';
|
|
17
17
|
export { Money } from './Money';
|
|
18
|
-
export { Metafield
|
|
19
|
-
export type { MetafieldType } from './Metafield';
|
|
18
|
+
export { Metafield } from './Metafield';
|
|
19
|
+
export type { MetafieldType, MetafieldFragmentFragment } from './Metafield';
|
|
20
20
|
export { CartLineProvider, useCartLine } from './CartLineProvider';
|
|
21
21
|
export { CartLineImage } from './CartLineImage';
|
|
22
22
|
export { CartLinePrice } from './CartLinePrice';
|
|
@@ -28,6 +28,7 @@ export { CartLines } from './CartLines';
|
|
|
28
28
|
export { CartCheckoutButton } from './CartCheckoutButton';
|
|
29
29
|
export { CartShopPayButton } from './CartShopPayButton';
|
|
30
30
|
export { CartEstimatedCost } from './CartEstimatedCost';
|
|
31
|
+
export { CartLineSelectedOptions } from './CartLineSelectedOptions';
|
|
31
32
|
export { CartProvider, useCart, useCartAttributesUpdateCallback, useCartBuyerIdentityUpdateCallback, useCartNoteUpdateCallback, useCartCheckoutUrl, useCartCreateCallback, useCartDiscountCodesUpdateCallback, useCartFetch, useCartLinesAddCallback, useCartLinesRemoveCallback, useCartLinesTotalQuantity, useCartLinesUpdateCallback, useInstantCheckout, } from './CartProvider';
|
|
32
33
|
export type { State, Status, Cart, CartWithActions, CartAction, } from './CartProvider';
|
|
33
34
|
export { ProductProvider, useProduct, ProductProviderFragment, } from './ProductProvider';
|
|
@@ -19,6 +19,7 @@ export { CartLines } from './CartLines';
|
|
|
19
19
|
export { CartCheckoutButton } from './CartCheckoutButton';
|
|
20
20
|
export { CartShopPayButton } from './CartShopPayButton';
|
|
21
21
|
export { CartEstimatedCost } from './CartEstimatedCost';
|
|
22
|
+
export { CartLineSelectedOptions } from './CartLineSelectedOptions';
|
|
22
23
|
export { CartProvider, useCart, useCartAttributesUpdateCallback, useCartBuyerIdentityUpdateCallback, useCartNoteUpdateCallback, useCartCheckoutUrl, useCartCreateCallback, useCartDiscountCodesUpdateCallback, useCartFetch, useCartLinesAddCallback, useCartLinesRemoveCallback, useCartLinesTotalQuantity, useCartLinesUpdateCallback, useInstantCheckout, } from './CartProvider';
|
|
23
24
|
export { ProductProvider, useProduct, ProductProviderFragment, } from './ProductProvider';
|
|
24
25
|
export { ProductDescription } from './ProductDescription';
|
|
@@ -6,7 +6,6 @@ import { ErrorBoundary } from 'react-error-boundary';
|
|
|
6
6
|
import { HelmetProvider } from 'react-helmet-async';
|
|
7
7
|
import { useServerResponse } from './framework/Hydration/Cache.client';
|
|
8
8
|
import { ServerStateProvider, ServerStateRouter } from './client';
|
|
9
|
-
import { QueryProvider } from './hooks';
|
|
10
9
|
const renderHydrogen = async (ClientWrapper) => {
|
|
11
10
|
const root = document.getElementById('root');
|
|
12
11
|
if (!root) {
|
|
@@ -25,11 +24,10 @@ function Content({ clientWrapper: ClientWrapper }) {
|
|
|
25
24
|
});
|
|
26
25
|
const response = useServerResponse(serverState);
|
|
27
26
|
return (React.createElement(ServerStateProvider, { serverState: serverState, setServerState: setServerState },
|
|
28
|
-
React.createElement(
|
|
29
|
-
React.createElement(
|
|
30
|
-
React.createElement(
|
|
31
|
-
|
|
32
|
-
React.createElement(ClientWrapper, null, response.read()))))));
|
|
27
|
+
React.createElement(HelmetProvider, null,
|
|
28
|
+
React.createElement(BrowserRouter, null,
|
|
29
|
+
React.createElement(ServerStateRouter, null),
|
|
30
|
+
React.createElement(ClientWrapper, null, response.read())))));
|
|
33
31
|
}
|
|
34
32
|
function Error({ error }) {
|
|
35
33
|
return (React.createElement("div", { style: { padding: '1em' } },
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
3
|
// @ts-ignore
|
|
4
|
-
|
|
4
|
+
renderToPipeableStream, // Only available in Node context
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
renderToReadableStream, // Only available in Browser/Worker context
|
|
7
|
+
} from 'react-dom/server';
|
|
8
|
+
import { logServerResponse, getLoggerFromContext, } from './utilities/log/log';
|
|
5
9
|
import { renderToString } from 'react-dom/server';
|
|
6
10
|
import { getErrorMarkup } from './utilities/error';
|
|
7
11
|
import ssrPrepass from 'react-ssr-prepass';
|
|
@@ -12,8 +16,8 @@ import { HelmetProvider } from 'react-helmet-async';
|
|
|
12
16
|
import { Html } from './framework/Hydration/Html';
|
|
13
17
|
import { HydrationWriter } from './framework/Hydration/writer.server';
|
|
14
18
|
import { ServerComponentResponse } from './framework/Hydration/ServerComponentResponse.server';
|
|
15
|
-
import { dehydrate } from 'react-query/hydration';
|
|
16
19
|
import { getCacheControlHeader } from './framework/cache';
|
|
20
|
+
import { RenderCacheProvider } from './foundation/RenderCacheProvider';
|
|
17
21
|
/**
|
|
18
22
|
* react-dom/unstable-fizz provides different entrypoints based on runtime:
|
|
19
23
|
* - `renderToReadableStream` for "browser" (aka worker)
|
|
@@ -33,7 +37,8 @@ const renderHydrogen = (App, hook) => {
|
|
|
33
37
|
* NOTE: This is currently only used for SEO bots or Worker runtime (where Stream is not yet supported).
|
|
34
38
|
*/
|
|
35
39
|
const render = async function (url, { context, request, isReactHydrationRequest, dev }) {
|
|
36
|
-
var _a, _b;
|
|
40
|
+
var _a, _b, _c, _d, _f;
|
|
41
|
+
const log = getLoggerFromContext(request);
|
|
37
42
|
const state = isReactHydrationRequest
|
|
38
43
|
? JSON.parse((_b = (_a = url.searchParams) === null || _a === void 0 ? void 0 : _a.get('state')) !== null && _b !== void 0 ? _b : '{}')
|
|
39
44
|
: { pathname: url.pathname, search: url.search };
|
|
@@ -43,8 +48,10 @@ const renderHydrogen = (App, hook) => {
|
|
|
43
48
|
context,
|
|
44
49
|
request,
|
|
45
50
|
dev,
|
|
51
|
+
log,
|
|
46
52
|
});
|
|
47
|
-
const body = await renderApp(ReactApp, state, isReactHydrationRequest);
|
|
53
|
+
const body = await renderApp(ReactApp, state, log, isReactHydrationRequest);
|
|
54
|
+
logServerResponse('ssr', log, request, (_f = (_d = (_c = componentResponse.customStatus) === null || _c === void 0 ? void 0 : _c.code) !== null && _d !== void 0 ? _d : componentResponse.status) !== null && _f !== void 0 ? _f : 200);
|
|
48
55
|
if (componentResponse.customBody) {
|
|
49
56
|
return { body: await componentResponse.customBody, url, componentResponse };
|
|
50
57
|
}
|
|
@@ -62,6 +69,7 @@ const renderHydrogen = (App, hook) => {
|
|
|
62
69
|
* information, so this method should not be used by crawlers.
|
|
63
70
|
*/
|
|
64
71
|
const stream = function (url, { context, request, response, template, dev }) {
|
|
72
|
+
const log = getLoggerFromContext(request);
|
|
65
73
|
const state = { pathname: url.pathname, search: url.search };
|
|
66
74
|
const { ReactApp, componentResponse } = buildReactApp({
|
|
67
75
|
App,
|
|
@@ -69,34 +77,36 @@ const renderHydrogen = (App, hook) => {
|
|
|
69
77
|
context,
|
|
70
78
|
request,
|
|
71
79
|
dev,
|
|
80
|
+
log,
|
|
72
81
|
});
|
|
73
82
|
response.socket.on('error', (error) => {
|
|
74
|
-
|
|
83
|
+
log.fatal(error);
|
|
75
84
|
});
|
|
76
85
|
let didError;
|
|
77
86
|
const head = template.match(/<head>(.+?)<\/head>/s)[1];
|
|
78
|
-
const {
|
|
79
|
-
React.createElement(ReactApp, { ...state })),
|
|
80
|
-
|
|
87
|
+
const { pipe, abort } = renderToPipeableStream(React.createElement(Html, { head: head },
|
|
88
|
+
React.createElement(ReactApp, { ...state })), {
|
|
89
|
+
onCompleteShell() {
|
|
81
90
|
/**
|
|
82
91
|
* TODO: This assumes `response.cache()` has been called _before_ any
|
|
83
92
|
* queries which might be caught behind Suspense. Clarify this or add
|
|
84
93
|
* additional checks downstream?
|
|
85
94
|
*/
|
|
86
95
|
response.setHeader(getCacheControlHeader({ dev }), componentResponse.cacheControlHeader);
|
|
87
|
-
writeHeadToServerResponse(response, componentResponse, didError);
|
|
96
|
+
writeHeadToServerResponse(request, response, componentResponse, log, didError);
|
|
88
97
|
if (isRedirect(response)) {
|
|
89
98
|
// Return redirects early without further rendering/streaming
|
|
90
99
|
return response.end();
|
|
91
100
|
}
|
|
92
101
|
if (!componentResponse.canStream())
|
|
93
102
|
return;
|
|
94
|
-
startWritingHtmlToServerResponse(response,
|
|
103
|
+
startWritingHtmlToServerResponse(response, pipe, dev ? didError : undefined);
|
|
95
104
|
},
|
|
96
105
|
onCompleteAll() {
|
|
106
|
+
clearTimeout(streamTimeout);
|
|
97
107
|
if (componentResponse.canStream() || response.writableEnded)
|
|
98
108
|
return;
|
|
99
|
-
writeHeadToServerResponse(response, componentResponse, didError);
|
|
109
|
+
writeHeadToServerResponse(request, response, componentResponse, log, didError);
|
|
100
110
|
if (isRedirect(response)) {
|
|
101
111
|
// Redirects found after any async code
|
|
102
112
|
return response.end();
|
|
@@ -110,7 +120,7 @@ const renderHydrogen = (App, hook) => {
|
|
|
110
120
|
}
|
|
111
121
|
}
|
|
112
122
|
else {
|
|
113
|
-
startWritingHtmlToServerResponse(response,
|
|
123
|
+
startWritingHtmlToServerResponse(response, pipe, dev ? didError : undefined);
|
|
114
124
|
}
|
|
115
125
|
},
|
|
116
126
|
onError(error) {
|
|
@@ -120,15 +130,23 @@ const renderHydrogen = (App, hook) => {
|
|
|
120
130
|
// Delay this error until headers are properly sent.
|
|
121
131
|
response.write(getErrorMarkup(error));
|
|
122
132
|
}
|
|
123
|
-
|
|
133
|
+
log.error(error);
|
|
124
134
|
},
|
|
125
135
|
});
|
|
126
|
-
setTimeout(
|
|
136
|
+
const streamTimeout = setTimeout(() => {
|
|
137
|
+
const errorMessage = `The app failed to stream after ${STREAM_ABORT_TIMEOUT_MS} ms`;
|
|
138
|
+
log.error(errorMessage);
|
|
139
|
+
if (dev && response.headersSent) {
|
|
140
|
+
response.write(getErrorMarkup(new Error(errorMessage)));
|
|
141
|
+
}
|
|
142
|
+
abort();
|
|
143
|
+
}, STREAM_ABORT_TIMEOUT_MS);
|
|
127
144
|
};
|
|
128
145
|
/**
|
|
129
146
|
* Stream a hydration response to the client.
|
|
130
147
|
*/
|
|
131
148
|
const hydrate = function (url, { context, request, response, dev }) {
|
|
149
|
+
const log = getLoggerFromContext(request);
|
|
132
150
|
const state = JSON.parse(url.searchParams.get('state') || '{}');
|
|
133
151
|
const { ReactApp, componentResponse } = buildReactApp({
|
|
134
152
|
App,
|
|
@@ -136,33 +154,41 @@ const renderHydrogen = (App, hook) => {
|
|
|
136
154
|
context,
|
|
137
155
|
request,
|
|
138
156
|
dev,
|
|
157
|
+
log,
|
|
139
158
|
});
|
|
140
159
|
response.socket.on('error', (error) => {
|
|
141
|
-
|
|
160
|
+
log.fatal(error);
|
|
142
161
|
});
|
|
143
162
|
let didError;
|
|
144
163
|
const writer = new HydrationWriter();
|
|
145
|
-
const {
|
|
146
|
-
React.createElement(ReactApp, { ...state })),
|
|
164
|
+
const { pipe, abort } = renderToPipeableStream(React.createElement(HydrationContext.Provider, { value: true },
|
|
165
|
+
React.createElement(ReactApp, { ...state })), {
|
|
147
166
|
/**
|
|
148
167
|
* When hydrating, we have to wait until `onCompleteAll` to avoid having
|
|
149
168
|
* `template` and `script` tags inserted and rendered as part of the hydration response.
|
|
150
169
|
*/
|
|
151
170
|
onCompleteAll() {
|
|
171
|
+
clearTimeout(renderTimeout);
|
|
152
172
|
// Tell React to start writing to the writer
|
|
153
|
-
|
|
173
|
+
pipe(writer);
|
|
154
174
|
// Tell React that the writer is ready to drain, which sometimes results in a last "chunk" being written.
|
|
155
175
|
writer.drain();
|
|
156
176
|
response.statusCode = didError ? 500 : 200;
|
|
157
177
|
response.setHeader(getCacheControlHeader({ dev }), componentResponse.cacheControlHeader);
|
|
158
178
|
response.end(generateWireSyntaxFromRenderedHtml(writer.toString()));
|
|
179
|
+
logServerResponse('rsc', log, request, response.statusCode);
|
|
159
180
|
},
|
|
160
181
|
onError(error) {
|
|
161
182
|
didError = error;
|
|
162
|
-
|
|
183
|
+
log.error(error);
|
|
163
184
|
},
|
|
164
185
|
});
|
|
165
|
-
setTimeout(
|
|
186
|
+
const renderTimeout = setTimeout(() => {
|
|
187
|
+
const errorMessage = `The app failed to render RSC after ${STREAM_ABORT_TIMEOUT_MS} ms`;
|
|
188
|
+
didError = new Error(errorMessage);
|
|
189
|
+
log.error(errorMessage);
|
|
190
|
+
abort();
|
|
191
|
+
}, STREAM_ABORT_TIMEOUT_MS);
|
|
166
192
|
};
|
|
167
193
|
return {
|
|
168
194
|
render,
|
|
@@ -170,12 +196,19 @@ const renderHydrogen = (App, hook) => {
|
|
|
170
196
|
hydrate,
|
|
171
197
|
};
|
|
172
198
|
};
|
|
173
|
-
function buildReactApp({ App, state, context, request, dev, }) {
|
|
199
|
+
function buildReactApp({ App, state, context, request, dev, log, }) {
|
|
200
|
+
const renderCache = {};
|
|
174
201
|
const helmetContext = {};
|
|
175
202
|
const componentResponse = new ServerComponentResponse();
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
203
|
+
const hydrogenServerProps = {
|
|
204
|
+
request,
|
|
205
|
+
response: componentResponse,
|
|
206
|
+
log,
|
|
207
|
+
};
|
|
208
|
+
const ReactApp = (props) => (React.createElement(RenderCacheProvider, { cache: renderCache },
|
|
209
|
+
React.createElement(StaticRouter, { location: { pathname: state.pathname, search: state.search }, context: context },
|
|
210
|
+
React.createElement(HelmetProvider, { context: helmetContext },
|
|
211
|
+
React.createElement(App, { ...props, ...hydrogenServerProps })))));
|
|
179
212
|
return { helmetContext, ReactApp, componentResponse };
|
|
180
213
|
}
|
|
181
214
|
function extractHeadElements(helmetContext) {
|
|
@@ -201,27 +234,31 @@ function supportsReadableStream() {
|
|
|
201
234
|
return false;
|
|
202
235
|
}
|
|
203
236
|
}
|
|
204
|
-
async function renderApp(ReactApp, state, isReactHydrationRequest) {
|
|
237
|
+
async function renderApp(ReactApp, state, log, isReactHydrationRequest) {
|
|
205
238
|
/**
|
|
206
239
|
* Temporary workaround until all Worker runtimes support ReadableStream
|
|
207
240
|
*/
|
|
208
241
|
if (isWorker && !supportsReadableStream()) {
|
|
209
|
-
return renderAppFromStringWithPrepass(ReactApp, state, isReactHydrationRequest);
|
|
242
|
+
return renderAppFromStringWithPrepass(ReactApp, state, log, isReactHydrationRequest);
|
|
210
243
|
}
|
|
211
244
|
const app = isReactHydrationRequest ? (React.createElement(HydrationContext.Provider, { value: true },
|
|
212
245
|
React.createElement(ReactApp, { ...state }))) : (React.createElement(ReactApp, { ...state }));
|
|
213
|
-
return renderAppFromBufferedStream(app, isReactHydrationRequest);
|
|
246
|
+
return renderAppFromBufferedStream(app, log, isReactHydrationRequest);
|
|
214
247
|
}
|
|
215
|
-
function renderAppFromBufferedStream(app, isReactHydrationRequest) {
|
|
248
|
+
function renderAppFromBufferedStream(app, log, isReactHydrationRequest) {
|
|
216
249
|
return new Promise((resolve, reject) => {
|
|
250
|
+
const errorTimeout = setTimeout(() => {
|
|
251
|
+
reject(new Error(`The app failed to SSR after ${STREAM_ABORT_TIMEOUT_MS} ms`));
|
|
252
|
+
}, STREAM_ABORT_TIMEOUT_MS);
|
|
217
253
|
if (isWorker) {
|
|
218
254
|
let isComplete = false;
|
|
219
255
|
const stream = renderToReadableStream(app, {
|
|
220
256
|
onCompleteAll() {
|
|
257
|
+
clearTimeout(errorTimeout);
|
|
221
258
|
isComplete = true;
|
|
222
259
|
},
|
|
223
260
|
onError(error) {
|
|
224
|
-
|
|
261
|
+
log.error(error);
|
|
225
262
|
reject(error);
|
|
226
263
|
},
|
|
227
264
|
});
|
|
@@ -252,14 +289,15 @@ function renderAppFromBufferedStream(app, isReactHydrationRequest) {
|
|
|
252
289
|
}
|
|
253
290
|
else {
|
|
254
291
|
const writer = new HydrationWriter();
|
|
255
|
-
const {
|
|
292
|
+
const { pipe } = renderToPipeableStream(app, {
|
|
256
293
|
/**
|
|
257
294
|
* When hydrating, we have to wait until `onCompleteAll` to avoid having
|
|
258
295
|
* `template` and `script` tags inserted and rendered as part of the hydration response.
|
|
259
296
|
*/
|
|
260
297
|
onCompleteAll() {
|
|
298
|
+
clearTimeout(errorTimeout);
|
|
261
299
|
// Tell React to start writing to the writer
|
|
262
|
-
|
|
300
|
+
pipe(writer);
|
|
263
301
|
// Tell React that the writer is ready to drain, which sometimes results in a last "chunk" being written.
|
|
264
302
|
writer.drain();
|
|
265
303
|
if (isReactHydrationRequest) {
|
|
@@ -270,7 +308,7 @@ function renderAppFromBufferedStream(app, isReactHydrationRequest) {
|
|
|
270
308
|
}
|
|
271
309
|
},
|
|
272
310
|
onError(error) {
|
|
273
|
-
|
|
311
|
+
log.error(error);
|
|
274
312
|
reject(error);
|
|
275
313
|
},
|
|
276
314
|
});
|
|
@@ -286,37 +324,28 @@ function renderAppFromBufferedStream(app, isReactHydrationRequest) {
|
|
|
286
324
|
* use ssr-prepass to fetch all the queries once, store
|
|
287
325
|
* the results in a context object, and re-render.
|
|
288
326
|
*/
|
|
289
|
-
async function renderAppFromStringWithPrepass(ReactApp, state, isReactHydrationRequest) {
|
|
290
|
-
const hydrationContext = {};
|
|
327
|
+
async function renderAppFromStringWithPrepass(ReactApp, state, log, isReactHydrationRequest) {
|
|
291
328
|
const app = isReactHydrationRequest ? (React.createElement(HydrationContext.Provider, { value: true },
|
|
292
|
-
React.createElement(ReactApp, {
|
|
329
|
+
React.createElement(ReactApp, { ...state }))) : (React.createElement(ReactApp, { ...state }));
|
|
293
330
|
await ssrPrepass(app);
|
|
294
|
-
/**
|
|
295
|
-
* Dehydrate all the queries made during the prepass above and store
|
|
296
|
-
* them in the context object to be used for the next render pass.
|
|
297
|
-
* This prevents rendering the Suspense fallback in `renderToString`.
|
|
298
|
-
*/
|
|
299
|
-
if (hydrationContext.queryClient) {
|
|
300
|
-
hydrationContext.dehydratedState = dehydrate(hydrationContext.queryClient);
|
|
301
|
-
}
|
|
302
331
|
const body = renderToString(app);
|
|
303
332
|
return isReactHydrationRequest
|
|
304
333
|
? generateWireSyntaxFromRenderedHtml(body)
|
|
305
334
|
: body;
|
|
306
335
|
}
|
|
307
336
|
export default renderHydrogen;
|
|
308
|
-
function startWritingHtmlToServerResponse(response,
|
|
337
|
+
function startWritingHtmlToServerResponse(response, pipe, error) {
|
|
309
338
|
if (!response.headersSent) {
|
|
310
339
|
response.setHeader('Content-type', 'text/html');
|
|
311
340
|
response.write('<!DOCTYPE html>');
|
|
312
341
|
}
|
|
313
|
-
|
|
342
|
+
pipe(response);
|
|
314
343
|
if (error) {
|
|
315
344
|
// This error was delayed until the headers were properly sent.
|
|
316
345
|
response.write(getErrorMarkup(error));
|
|
317
346
|
}
|
|
318
347
|
}
|
|
319
|
-
function writeHeadToServerResponse(response, { headers, status, customStatus }, error) {
|
|
348
|
+
function writeHeadToServerResponse(request, response, { headers, status, customStatus }, log, error) {
|
|
320
349
|
var _a, _b;
|
|
321
350
|
if (response.headersSent)
|
|
322
351
|
return;
|
|
@@ -330,6 +359,7 @@ function writeHeadToServerResponse(response, { headers, status, customStatus },
|
|
|
330
359
|
response.statusMessage = customStatus.text;
|
|
331
360
|
}
|
|
332
361
|
}
|
|
362
|
+
logServerResponse('str', log, request, response.statusCode);
|
|
333
363
|
}
|
|
334
364
|
function isRedirect(response) {
|
|
335
365
|
return response.statusCode >= 300 && response.statusCode < 400;
|