@shopify/hydrogen 2025.7.0 → 2025.7.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/dev/{get-virtual-routes-KWSSQH4L.js → get-virtual-routes-ZEUPNZWL.js} +0 -36
- package/dist/dev/hydrogen-routes.js +1 -1
- package/dist/development/{get-virtual-routes-6PVSMJPH.js → get-virtual-routes-XE7G57DS.js} +3 -36
- package/dist/development/get-virtual-routes-XE7G57DS.js.map +1 -0
- package/dist/development/index.cjs +406 -124
- package/dist/development/index.cjs.map +1 -1
- package/dist/development/index.js +395 -81
- package/dist/development/index.js.map +1 -1
- package/dist/development/react-router-preset.d.ts +5 -5
- package/dist/development/react-router-preset.js +4 -4
- package/dist/development/react-router-preset.js.map +1 -1
- package/dist/oxygen/index.d.ts +120 -3
- package/dist/oxygen/index.js +111 -5
- package/dist/production/get-virtual-routes-MYYLGSAS.js +3 -0
- package/dist/production/get-virtual-routes-MYYLGSAS.js.map +1 -0
- package/dist/production/index.cjs +76 -76
- package/dist/production/index.cjs.map +1 -1
- package/dist/production/index.d.cts +76 -15
- package/dist/production/index.d.ts +76 -15
- package/dist/production/index.js +76 -76
- package/dist/production/index.js.map +1 -1
- package/dist/production/react-router-preset.d.ts +5 -5
- package/dist/production/react-router-preset.js +2 -2
- package/dist/vite/get-virtual-routes.d.ts +1 -17
- package/dist/vite/get-virtual-routes.js +0 -36
- package/package.json +6 -6
- package/dist/development/get-virtual-routes-6PVSMJPH.js.map +0 -1
- package/dist/oxygen/chunk-RVXKHOUX.js +0 -39
- package/dist/oxygen/chunk-T4YWBSCF.js +0 -14
- package/dist/oxygen/createRequestHandler.d.ts +0 -10
- package/dist/oxygen/createRequestHandler.js +0 -6
- package/dist/oxygen/getStorefrontHeaders-BqPh5S1b.d.ts +0 -69
- package/dist/oxygen/getStorefrontHeaders.d.ts +0 -1
- package/dist/oxygen/getStorefrontHeaders.js +0 -6
- package/dist/production/get-virtual-routes-JVKSNI4M.js +0 -3
- package/dist/production/get-virtual-routes-JVKSNI4M.js.map +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createContext, forwardRef, useContext, lazy, useMemo, useEffect, useRef, useState, createElement, Fragment as Fragment$1, Suspense } from 'react';
|
|
2
|
-
import { createContext as createContext$1, useFetcher, useFetchers, RouterContextProvider, useNavigation, useLocation, useNavigate, Link, useMatches } from 'react-router';
|
|
2
|
+
import { createContext as createContext$1, useRevalidator, useFetcher, useFetchers, RouterContextProvider, createRequestHandler as createRequestHandler$1, useNavigation, useLocation, useNavigate, Link, useMatches } from 'react-router';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
-
import { useLoadScript, createStorefrontClient as createStorefrontClient$1, SHOPIFY_STOREFRONT_ID_HEADER,
|
|
5
|
-
export { AnalyticsEventName, AnalyticsPageType, ExternalVideo, IMAGE_FRAGMENT, Image, MediaFile, ModelViewer, Money, ShopifySalesChannel, Video, customerAccountApiCustomScalars, decodeEncodedVariant, flattenConnection, getAdjacentAndFirstAvailableVariants, getClientBrowserParameters, getProductOptions, getShopifyCookies, isOptionValueCombinationInEncodedVariant, mapSelectedProductOptionToObject, parseGid, parseMetafield, sendShopifyAnalytics, storefrontApiCustomScalars, useLoadScript, useMoney, useSelectedOptionInUrlParam, useShopifyCookies } from '@shopify/hydrogen-react';
|
|
4
|
+
import { useLoadScript, useShopifyCookies, getTrackingValues, createStorefrontClient as createStorefrontClient$1, SHOPIFY_STOREFRONT_ID_HEADER, SHOPIFY_STOREFRONT_Y_HEADER, SHOPIFY_STOREFRONT_S_HEADER, SHOPIFY_UNIQUE_TOKEN_HEADER, SHOPIFY_VISIT_TOKEN_HEADER, flattenConnection, RichText as RichText$1, ShopPayButton as ShopPayButton$1, parseGid, sendShopifyAnalytics, AnalyticsEventName, AnalyticsPageType, getClientBrowserParameters } from '@shopify/hydrogen-react';
|
|
5
|
+
export { AnalyticsEventName, AnalyticsPageType, ExternalVideo, IMAGE_FRAGMENT, Image, MediaFile, ModelViewer, Money, ShopifySalesChannel, Video, customerAccountApiCustomScalars, decodeEncodedVariant, flattenConnection, getAdjacentAndFirstAvailableVariants, getClientBrowserParameters, getProductOptions, getShopifyCookies, getTrackingValues, isOptionValueCombinationInEncodedVariant, mapSelectedProductOptionToObject, parseGid, parseMetafield, sendShopifyAnalytics, storefrontApiCustomScalars, useLoadScript, useMoney, useSelectedOptionInUrlParam, useShopifyCookies } from '@shopify/hydrogen-react';
|
|
6
|
+
import { useLoadScript as useLoadScript$1 } from '@shopify/hydrogen-react/load-script';
|
|
6
7
|
import { createGraphQLClient } from '@shopify/graphql-client';
|
|
7
8
|
import { parse, stringify } from 'worktop/cookie';
|
|
8
9
|
import cspBuilder from 'content-security-policy-builder';
|
|
@@ -73,7 +74,62 @@ var AnalyticsEvent = {
|
|
|
73
74
|
// Custom
|
|
74
75
|
CUSTOM_EVENT: `custom_`
|
|
75
76
|
};
|
|
76
|
-
|
|
77
|
+
|
|
78
|
+
// src/constants.ts
|
|
79
|
+
var STOREFRONT_REQUEST_GROUP_ID_HEADER = "Custom-Storefront-Request-Group-ID";
|
|
80
|
+
var STOREFRONT_ACCESS_TOKEN_HEADER = "X-Shopify-Storefront-Access-Token";
|
|
81
|
+
var SDK_VARIANT_HEADER = "X-SDK-Variant";
|
|
82
|
+
var SDK_VARIANT_SOURCE_HEADER = "X-SDK-Variant-Source";
|
|
83
|
+
var SDK_VERSION_HEADER = "X-SDK-Version";
|
|
84
|
+
var SHOPIFY_CLIENT_IP_HEADER = "X-Shopify-Client-IP";
|
|
85
|
+
var SHOPIFY_CLIENT_IP_SIG_HEADER = "X-Shopify-Client-IP-Sig";
|
|
86
|
+
var HYDROGEN_SFAPI_PROXY_KEY = "_sfapi_proxy";
|
|
87
|
+
var HYDROGEN_SERVER_TRACKING_KEY = "_server_tracking";
|
|
88
|
+
|
|
89
|
+
// src/utils/server-timing.ts
|
|
90
|
+
function buildServerTimingHeader(values) {
|
|
91
|
+
return Object.entries(values).map(([key, value]) => value ? `${key};desc=${value}` : void 0).filter(Boolean).join(", ");
|
|
92
|
+
}
|
|
93
|
+
function appendServerTimingHeader(response, values) {
|
|
94
|
+
const header = typeof values === "string" ? values : buildServerTimingHeader(values);
|
|
95
|
+
if (header) {
|
|
96
|
+
response.headers.append("Server-Timing", header);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
var trackedTimings = ["_y", "_s", "_cmp"];
|
|
100
|
+
function extractServerTimingHeader(serverTimingHeader) {
|
|
101
|
+
const values = {};
|
|
102
|
+
if (!serverTimingHeader) return values;
|
|
103
|
+
const re = new RegExp(
|
|
104
|
+
`\\b(${trackedTimings.join("|")});desc="?([^",]+)"?`,
|
|
105
|
+
"g"
|
|
106
|
+
);
|
|
107
|
+
let match;
|
|
108
|
+
while ((match = re.exec(serverTimingHeader)) !== null) {
|
|
109
|
+
values[match[1]] = match[2];
|
|
110
|
+
}
|
|
111
|
+
return values;
|
|
112
|
+
}
|
|
113
|
+
function hasServerTimingInNavigationEntry(key) {
|
|
114
|
+
if (typeof window === "undefined") return false;
|
|
115
|
+
try {
|
|
116
|
+
const navigationEntry = window.performance.getEntriesByType(
|
|
117
|
+
"navigation"
|
|
118
|
+
)[0];
|
|
119
|
+
return !!navigationEntry?.serverTiming?.some((entry) => entry.name === key);
|
|
120
|
+
} catch (e) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function isSfapiProxyEnabled() {
|
|
125
|
+
return hasServerTimingInNavigationEntry(HYDROGEN_SFAPI_PROXY_KEY);
|
|
126
|
+
}
|
|
127
|
+
function hasServerReturnedTrackingValues() {
|
|
128
|
+
return hasServerTimingInNavigationEntry(HYDROGEN_SERVER_TRACKING_KEY);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/customer-privacy/ShopifyCustomerPrivacy.tsx
|
|
132
|
+
var CONSENT_API = "https://cdn.shopify.com/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js";
|
|
77
133
|
var CONSENT_API_WITH_BANNER = "https://cdn.shopify.com/shopifycloud/privacy-banner/storefront-banner.js";
|
|
78
134
|
function logMissingConfig(fieldName) {
|
|
79
135
|
console.error(
|
|
@@ -85,19 +141,34 @@ function useCustomerPrivacy(props) {
|
|
|
85
141
|
withPrivacyBanner = false,
|
|
86
142
|
onVisitorConsentCollected,
|
|
87
143
|
onReady,
|
|
88
|
-
|
|
144
|
+
checkoutDomain,
|
|
145
|
+
storefrontAccessToken,
|
|
146
|
+
country,
|
|
147
|
+
locale,
|
|
148
|
+
sameDomainForStorefrontApi
|
|
89
149
|
} = props;
|
|
90
|
-
|
|
150
|
+
const hasSfapiProxy = useMemo(
|
|
151
|
+
() => sameDomainForStorefrontApi ?? isSfapiProxyEnabled(),
|
|
152
|
+
[sameDomainForStorefrontApi]
|
|
153
|
+
);
|
|
154
|
+
const fetchTrackingValuesFromBrowser = useMemo(
|
|
155
|
+
() => hasSfapiProxy && !hasServerReturnedTrackingValues(),
|
|
156
|
+
[hasSfapiProxy]
|
|
157
|
+
);
|
|
158
|
+
const cookiesReady = useShopifyCookies({
|
|
159
|
+
fetchTrackingValues: fetchTrackingValuesFromBrowser,
|
|
160
|
+
storefrontAccessToken,
|
|
161
|
+
ignoreDeprecatedCookies: true
|
|
162
|
+
});
|
|
163
|
+
const initialTrackingValues = useMemo(getTrackingValues, [cookiesReady]);
|
|
164
|
+
const { revalidate } = useRevalidator();
|
|
165
|
+
useLoadScript$1(withPrivacyBanner ? CONSENT_API_WITH_BANNER : CONSENT_API, {
|
|
91
166
|
attributes: {
|
|
92
167
|
id: "customer-privacy-api"
|
|
93
168
|
}
|
|
94
169
|
});
|
|
95
|
-
const { observing, setLoaded } = useApisLoaded({
|
|
96
|
-
withPrivacyBanner,
|
|
97
|
-
onLoaded: onReady
|
|
98
|
-
});
|
|
170
|
+
const { observing, setLoaded, apisLoaded } = useApisLoaded({ withPrivacyBanner });
|
|
99
171
|
const config = useMemo(() => {
|
|
100
|
-
const { checkoutDomain, storefrontAccessToken } = consentConfig;
|
|
101
172
|
if (!checkoutDomain) logMissingConfig("checkoutDomain");
|
|
102
173
|
if (!storefrontAccessToken) logMissingConfig("storefrontAccessToken");
|
|
103
174
|
if (storefrontAccessToken.startsWith("shpat_") || storefrontAccessToken.length !== 32) {
|
|
@@ -105,18 +176,54 @@ function useCustomerPrivacy(props) {
|
|
|
105
176
|
`[h2:error:useCustomerPrivacy] It looks like you passed a private access token, make sure to use the public token`
|
|
106
177
|
);
|
|
107
178
|
}
|
|
179
|
+
const commonAncestorDomain = parseStoreDomain(checkoutDomain);
|
|
180
|
+
const sfapiDomain = (
|
|
181
|
+
// Check if standard route proxy is enabled in Hydrogen server
|
|
182
|
+
// to use it instead of doing a cross-origin request to checkout.
|
|
183
|
+
hasSfapiProxy && typeof window !== "undefined" ? window.location.host : checkoutDomain
|
|
184
|
+
);
|
|
108
185
|
const config2 = {
|
|
109
|
-
|
|
186
|
+
// This domain is used to send requests to SFAPI for setting and getting consent.
|
|
187
|
+
checkoutRootDomain: sfapiDomain,
|
|
188
|
+
// Prefix with a dot to ensure this domain is different from checkoutRootDomain.
|
|
189
|
+
// This will ensure old cookies are set for a cross-subdomain checkout setup
|
|
190
|
+
// so that we keep backward compatibility until new cookies are rolled out.
|
|
191
|
+
// Once consent-tracking-api is updated to not rely on cookies anymore, we can remove this.
|
|
192
|
+
storefrontRootDomain: commonAncestorDomain ? "." + commonAncestorDomain : void 0,
|
|
110
193
|
storefrontAccessToken,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
locale: consentConfig.locale
|
|
194
|
+
country,
|
|
195
|
+
locale
|
|
114
196
|
};
|
|
115
197
|
return config2;
|
|
116
|
-
}, [
|
|
198
|
+
}, [
|
|
199
|
+
logMissingConfig,
|
|
200
|
+
checkoutDomain,
|
|
201
|
+
storefrontAccessToken,
|
|
202
|
+
country,
|
|
203
|
+
locale
|
|
204
|
+
]);
|
|
117
205
|
useEffect(() => {
|
|
118
206
|
const consentCollectedHandler = (event) => {
|
|
207
|
+
const latestTrackingValues = getTrackingValues();
|
|
208
|
+
if (initialTrackingValues.visitToken !== latestTrackingValues.visitToken || initialTrackingValues.uniqueToken !== latestTrackingValues.uniqueToken) {
|
|
209
|
+
revalidate().catch(() => {
|
|
210
|
+
console.warn(
|
|
211
|
+
"[h2:warn:useCustomerPrivacy] Revalidation failed after consent change."
|
|
212
|
+
);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
119
215
|
if (onVisitorConsentCollected) {
|
|
216
|
+
const customerPrivacy = getCustomerPrivacy();
|
|
217
|
+
if (customerPrivacy?.shouldShowBanner()) {
|
|
218
|
+
const consentValues = customerPrivacy.currentVisitorConsent();
|
|
219
|
+
if (consentValues) {
|
|
220
|
+
const NO_VALUE = "";
|
|
221
|
+
const noInteraction = consentValues.marketing === NO_VALUE && consentValues.analytics === NO_VALUE && consentValues.preferences === NO_VALUE;
|
|
222
|
+
if (noInteraction) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
120
227
|
onVisitorConsentCollected(event.detail);
|
|
121
228
|
}
|
|
122
229
|
};
|
|
@@ -142,14 +249,11 @@ function useCustomerPrivacy(props) {
|
|
|
142
249
|
},
|
|
143
250
|
set(value) {
|
|
144
251
|
if (typeof value === "object" && value !== null && "showPreferences" in value && "loadBanner" in value) {
|
|
145
|
-
const privacyBanner = value;
|
|
146
|
-
privacyBanner.loadBanner(config);
|
|
147
252
|
customPrivacyBanner = overridePrivacyBannerMethods({
|
|
148
|
-
privacyBanner,
|
|
253
|
+
privacyBanner: value,
|
|
149
254
|
config
|
|
150
255
|
});
|
|
151
256
|
setLoaded.privacyBanner();
|
|
152
|
-
emitCustomerPrivacyApiLoaded();
|
|
153
257
|
}
|
|
154
258
|
}
|
|
155
259
|
};
|
|
@@ -183,6 +287,8 @@ function useCustomerPrivacy(props) {
|
|
|
183
287
|
const customerPrivacy = value2;
|
|
184
288
|
customCustomerPrivacy = {
|
|
185
289
|
...customerPrivacy,
|
|
290
|
+
// Note: this method is not used by the privacy-banner,
|
|
291
|
+
// it bundles its own setTrackingConsent.
|
|
186
292
|
setTrackingConsent: overrideCustomerPrivacySetTrackingConsent(
|
|
187
293
|
{ customerPrivacy, config }
|
|
188
294
|
)
|
|
@@ -192,7 +298,6 @@ function useCustomerPrivacy(props) {
|
|
|
192
298
|
customerPrivacy: customCustomerPrivacy
|
|
193
299
|
};
|
|
194
300
|
setLoaded.customerPrivacy();
|
|
195
|
-
emitCustomerPrivacyApiLoaded();
|
|
196
301
|
}
|
|
197
302
|
}
|
|
198
303
|
});
|
|
@@ -204,6 +309,24 @@ function useCustomerPrivacy(props) {
|
|
|
204
309
|
overrideCustomerPrivacySetTrackingConsent,
|
|
205
310
|
setLoaded.customerPrivacy
|
|
206
311
|
]);
|
|
312
|
+
useEffect(() => {
|
|
313
|
+
if (!apisLoaded || !cookiesReady) return;
|
|
314
|
+
const customerPrivacy = getCustomerPrivacy();
|
|
315
|
+
if (customerPrivacy && !customerPrivacy.cachedConsent) {
|
|
316
|
+
const trackingValues = getTrackingValues();
|
|
317
|
+
if (trackingValues.consent) {
|
|
318
|
+
customerPrivacy.cachedConsent = trackingValues.consent;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (withPrivacyBanner) {
|
|
322
|
+
const privacyBanner = getPrivacyBanner();
|
|
323
|
+
if (privacyBanner) {
|
|
324
|
+
privacyBanner.loadBanner(config);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
emitCustomerPrivacyApiLoaded();
|
|
328
|
+
onReady?.();
|
|
329
|
+
}, [apisLoaded, cookiesReady]);
|
|
207
330
|
const result = {
|
|
208
331
|
customerPrivacy: getCustomerPrivacy()
|
|
209
332
|
};
|
|
@@ -219,15 +342,12 @@ function emitCustomerPrivacyApiLoaded() {
|
|
|
219
342
|
const event = new CustomEvent("shopifyCustomerPrivacyApiLoaded");
|
|
220
343
|
document.dispatchEvent(event);
|
|
221
344
|
}
|
|
222
|
-
function useApisLoaded({
|
|
223
|
-
withPrivacyBanner,
|
|
224
|
-
onLoaded
|
|
225
|
-
}) {
|
|
345
|
+
function useApisLoaded({ withPrivacyBanner }) {
|
|
226
346
|
const observing = useRef({ customerPrivacy: false, privacyBanner: false });
|
|
227
|
-
const [
|
|
347
|
+
const [apisLoadedArray, setApisLoaded] = useState(
|
|
228
348
|
withPrivacyBanner ? [false, false] : [false]
|
|
229
349
|
);
|
|
230
|
-
const
|
|
350
|
+
const apisLoaded = apisLoadedArray.every(Boolean);
|
|
231
351
|
const setLoaded = {
|
|
232
352
|
customerPrivacy: () => {
|
|
233
353
|
if (withPrivacyBanner) {
|
|
@@ -243,16 +363,11 @@ function useApisLoaded({
|
|
|
243
363
|
setApisLoaded((prev) => [prev[0], true]);
|
|
244
364
|
}
|
|
245
365
|
};
|
|
246
|
-
|
|
247
|
-
if (loaded && onLoaded) {
|
|
248
|
-
onLoaded();
|
|
249
|
-
}
|
|
250
|
-
}, [loaded, onLoaded]);
|
|
251
|
-
return { observing, setLoaded };
|
|
366
|
+
return { observing, setLoaded, apisLoaded };
|
|
252
367
|
}
|
|
253
368
|
function parseStoreDomain(checkoutDomain) {
|
|
254
369
|
if (typeof window === "undefined") return;
|
|
255
|
-
const host = window.
|
|
370
|
+
const host = window.location.host;
|
|
256
371
|
const checkoutDomainParts = checkoutDomain.split(".").reverse();
|
|
257
372
|
const currentDomainParts = host.split(".").reverse();
|
|
258
373
|
const sameDomainParts = [];
|
|
@@ -261,7 +376,7 @@ function parseStoreDomain(checkoutDomain) {
|
|
|
261
376
|
sameDomainParts.push(part);
|
|
262
377
|
}
|
|
263
378
|
});
|
|
264
|
-
return sameDomainParts.reverse().join(".");
|
|
379
|
+
return sameDomainParts.reverse().join(".") || void 0;
|
|
265
380
|
}
|
|
266
381
|
function overrideCustomerPrivacySetTrackingConsent({
|
|
267
382
|
customerPrivacy,
|
|
@@ -319,7 +434,7 @@ function getPrivacyBanner() {
|
|
|
319
434
|
}
|
|
320
435
|
|
|
321
436
|
// package.json
|
|
322
|
-
var version = "2025.7.
|
|
437
|
+
var version = "2025.7.2";
|
|
323
438
|
|
|
324
439
|
// src/analytics-manager/ShopifyAnalytics.tsx
|
|
325
440
|
function getCustomerPrivacyRequired() {
|
|
@@ -339,6 +454,7 @@ function ShopifyAnalytics({
|
|
|
339
454
|
const { subscribe: subscribe2, register: register2, canTrack } = useAnalytics();
|
|
340
455
|
const [shopifyReady, setShopifyReady] = useState(false);
|
|
341
456
|
const [privacyReady, setPrivacyReady] = useState(false);
|
|
457
|
+
const [collectedConsent, setCollectedConsent] = useState("");
|
|
342
458
|
const init = useRef(false);
|
|
343
459
|
const { checkoutDomain, storefrontAccessToken, language } = consent;
|
|
344
460
|
const { ready: shopifyAnalyticsReady } = register2("Internal_Shopify_Analytics");
|
|
@@ -347,14 +463,31 @@ function ShopifyAnalytics({
|
|
|
347
463
|
locale: language,
|
|
348
464
|
checkoutDomain: !checkoutDomain ? "mock.shop" : checkoutDomain,
|
|
349
465
|
storefrontAccessToken: !storefrontAccessToken ? "abcdefghijklmnopqrstuvwxyz123456" : storefrontAccessToken,
|
|
350
|
-
|
|
351
|
-
|
|
466
|
+
// If we use privacy banner, we should wait until consent is collected.
|
|
467
|
+
// Otherwise, we can consider privacy ready immediately:
|
|
468
|
+
onReady: () => !consent.withPrivacyBanner && setPrivacyReady(true),
|
|
469
|
+
onVisitorConsentCollected: (consent2) => {
|
|
470
|
+
try {
|
|
471
|
+
setCollectedConsent(JSON.stringify(consent2));
|
|
472
|
+
} catch (e) {
|
|
473
|
+
}
|
|
474
|
+
setPrivacyReady(true);
|
|
475
|
+
}
|
|
352
476
|
});
|
|
477
|
+
const hasUserConsent = useMemo(
|
|
478
|
+
// must be initialized with true to avoid removing cookies too early
|
|
479
|
+
() => privacyReady ? canTrack() : true,
|
|
480
|
+
// Make this value depend on collectedConsent to re-run `canTrack()` when consent changes
|
|
481
|
+
[privacyReady, canTrack, collectedConsent]
|
|
482
|
+
);
|
|
353
483
|
useShopifyCookies({
|
|
354
|
-
hasUserConsent
|
|
355
|
-
// must be initialized with true
|
|
484
|
+
hasUserConsent,
|
|
356
485
|
domain,
|
|
357
|
-
checkoutDomain
|
|
486
|
+
checkoutDomain,
|
|
487
|
+
// Already done inside useCustomerPrivacy
|
|
488
|
+
fetchTrackingValues: false,
|
|
489
|
+
// Avoid creating local cookies too early
|
|
490
|
+
ignoreDeprecatedCookies: !privacyReady
|
|
358
491
|
});
|
|
359
492
|
useEffect(() => {
|
|
360
493
|
if (init.current) return;
|
|
@@ -404,11 +537,11 @@ function prepareBasePageViewPayload(payload) {
|
|
|
404
537
|
...payload.shop,
|
|
405
538
|
hasUserConsent,
|
|
406
539
|
...getClientBrowserParameters(),
|
|
407
|
-
ccpaEnforced: !customerPrivacy.saleOfDataAllowed(),
|
|
408
|
-
gdprEnforced: !(customerPrivacy.marketingAllowed() && customerPrivacy.analyticsProcessingAllowed()),
|
|
409
540
|
analyticsAllowed: customerPrivacy.analyticsProcessingAllowed(),
|
|
410
541
|
marketingAllowed: customerPrivacy.marketingAllowed(),
|
|
411
|
-
saleOfDataAllowed: customerPrivacy.saleOfDataAllowed()
|
|
542
|
+
saleOfDataAllowed: customerPrivacy.saleOfDataAllowed(),
|
|
543
|
+
ccpaEnforced: !customerPrivacy.saleOfDataAllowed(),
|
|
544
|
+
gdprEnforced: !(customerPrivacy.marketingAllowed() && customerPrivacy.analyticsProcessingAllowed())
|
|
412
545
|
};
|
|
413
546
|
return eventPayload;
|
|
414
547
|
}
|
|
@@ -841,11 +974,11 @@ function AnalyticsProvider({
|
|
|
841
974
|
shop: shopProp = null,
|
|
842
975
|
cookieDomain
|
|
843
976
|
}) {
|
|
844
|
-
const listenerSet = useRef(false);
|
|
845
977
|
const { shop } = useShopAnalytics(shopProp);
|
|
846
978
|
const [analyticsLoaded, setAnalyticsLoaded] = useState(
|
|
847
979
|
customCanTrack ? true : false
|
|
848
980
|
);
|
|
981
|
+
const [consentCollected, setConsentCollected] = useState(false);
|
|
849
982
|
const [carts, setCarts] = useState({ cart: null, prevCart: null });
|
|
850
983
|
const [canTrack, setCanTrack] = useState(
|
|
851
984
|
customCanTrack ? () => customCanTrack : () => shopifyCanTrack
|
|
@@ -913,21 +1046,21 @@ function AnalyticsProvider({
|
|
|
913
1046
|
children,
|
|
914
1047
|
!!shop && /* @__PURE__ */ jsx(AnalyticsPageView, {}),
|
|
915
1048
|
!!shop && !!currentCart && /* @__PURE__ */ jsx(CartAnalytics, { cart: currentCart, setCarts }),
|
|
916
|
-
!!shop &&
|
|
1049
|
+
!!shop && /* @__PURE__ */ jsx(
|
|
917
1050
|
ShopifyAnalytics,
|
|
918
1051
|
{
|
|
919
1052
|
consent,
|
|
920
1053
|
onReady: () => {
|
|
921
|
-
listenerSet.current = true;
|
|
922
1054
|
setAnalyticsLoaded(true);
|
|
923
1055
|
setCanTrack(
|
|
924
1056
|
customCanTrack ? () => customCanTrack : () => shopifyCanTrack
|
|
925
1057
|
);
|
|
1058
|
+
setConsentCollected(true);
|
|
926
1059
|
},
|
|
927
1060
|
domain: cookieDomain
|
|
928
1061
|
}
|
|
929
1062
|
),
|
|
930
|
-
!!shop && /* @__PURE__ */ jsx(PerfKit, { shop })
|
|
1063
|
+
!!shop && consentCollected && /* @__PURE__ */ jsx(PerfKit, { shop })
|
|
931
1064
|
] });
|
|
932
1065
|
}
|
|
933
1066
|
function useAnalytics() {
|
|
@@ -1006,6 +1139,31 @@ function getDebugHeaders(request) {
|
|
|
1006
1139
|
purpose: request ? getHeader(request, "purpose") : void 0
|
|
1007
1140
|
};
|
|
1008
1141
|
}
|
|
1142
|
+
function getStorefrontHeaders(request) {
|
|
1143
|
+
return {
|
|
1144
|
+
requestGroupId: getHeader(request, "request-id"),
|
|
1145
|
+
buyerIp: getHeader(request, "oxygen-buyer-ip"),
|
|
1146
|
+
buyerIpSig: getHeader(request, SHOPIFY_CLIENT_IP_SIG_HEADER),
|
|
1147
|
+
cookie: getHeader(request, "cookie"),
|
|
1148
|
+
// sec-purpose is added by browsers automatically when using link/prefetch or Speculation Rules
|
|
1149
|
+
purpose: getHeader(request, "sec-purpose") || getHeader(request, "purpose")
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1152
|
+
var SFAPI_RE = /^\/api\/(unstable|2\d{3}-\d{2})\/graphql\.json$/;
|
|
1153
|
+
var getSafePathname = (url) => {
|
|
1154
|
+
try {
|
|
1155
|
+
return new URL(url, "http://e.c").pathname;
|
|
1156
|
+
} catch {
|
|
1157
|
+
return "/";
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
function extractHeaders(extract, keys) {
|
|
1161
|
+
return keys.reduce((acc, key) => {
|
|
1162
|
+
const forwardedValue = extract(key);
|
|
1163
|
+
if (forwardedValue) acc.push([key, forwardedValue]);
|
|
1164
|
+
return acc;
|
|
1165
|
+
}, []);
|
|
1166
|
+
}
|
|
1009
1167
|
|
|
1010
1168
|
// src/utils/callsites.ts
|
|
1011
1169
|
function withSyncStack(promise, options = {}) {
|
|
@@ -1373,13 +1531,16 @@ async function runWithCache(cacheKey, actionFn, {
|
|
|
1373
1531
|
}
|
|
1374
1532
|
return result;
|
|
1375
1533
|
}
|
|
1534
|
+
var excludedHeaders = ["set-cookie", "server-timing"];
|
|
1376
1535
|
function toSerializableResponse(body, response) {
|
|
1377
1536
|
return [
|
|
1378
1537
|
body,
|
|
1379
1538
|
{
|
|
1380
1539
|
status: response.status,
|
|
1381
1540
|
statusText: response.statusText,
|
|
1382
|
-
headers:
|
|
1541
|
+
headers: [...response.headers].filter(
|
|
1542
|
+
([key]) => !excludedHeaders.includes(key.toLowerCase())
|
|
1543
|
+
)
|
|
1383
1544
|
}
|
|
1384
1545
|
];
|
|
1385
1546
|
}
|
|
@@ -1393,7 +1554,8 @@ async function fetchWithServerCache(url, requestInit, {
|
|
|
1393
1554
|
shouldCacheResponse,
|
|
1394
1555
|
waitUntil,
|
|
1395
1556
|
debugInfo,
|
|
1396
|
-
streamConfig
|
|
1557
|
+
streamConfig,
|
|
1558
|
+
onRawHeaders
|
|
1397
1559
|
}) {
|
|
1398
1560
|
if (!cacheOptions && (!requestInit.method || requestInit.method === "GET")) {
|
|
1399
1561
|
cacheOptions = CacheShort();
|
|
@@ -1407,6 +1569,7 @@ async function fetchWithServerCache(url, requestInit, {
|
|
|
1407
1569
|
url,
|
|
1408
1570
|
customFetchApi: async (url2, options) => {
|
|
1409
1571
|
rawResponse = await fetch(url2, options);
|
|
1572
|
+
onRawHeaders?.(rawResponse.headers);
|
|
1410
1573
|
return rawResponse;
|
|
1411
1574
|
},
|
|
1412
1575
|
headers: requestInit.headers
|
|
@@ -1430,6 +1593,7 @@ async function fetchWithServerCache(url, requestInit, {
|
|
|
1430
1593
|
);
|
|
1431
1594
|
}
|
|
1432
1595
|
const response = await fetch(url, requestInit);
|
|
1596
|
+
onRawHeaders?.(response.headers);
|
|
1433
1597
|
if (!response.ok) {
|
|
1434
1598
|
return response;
|
|
1435
1599
|
}
|
|
@@ -1653,13 +1817,6 @@ var cartSetIdDefault = (cookieOptions) => {
|
|
|
1653
1817
|
};
|
|
1654
1818
|
};
|
|
1655
1819
|
|
|
1656
|
-
// src/constants.ts
|
|
1657
|
-
var STOREFRONT_REQUEST_GROUP_ID_HEADER = "Custom-Storefront-Request-Group-ID";
|
|
1658
|
-
var STOREFRONT_ACCESS_TOKEN_HEADER = "X-Shopify-Storefront-Access-Token";
|
|
1659
|
-
var SDK_VARIANT_HEADER = "X-SDK-Variant";
|
|
1660
|
-
var SDK_VARIANT_SOURCE_HEADER = "X-SDK-Variant-Source";
|
|
1661
|
-
var SDK_VERSION_HEADER = "X-SDK-Version";
|
|
1662
|
-
|
|
1663
1820
|
// src/utils/uuid.ts
|
|
1664
1821
|
function generateUUID() {
|
|
1665
1822
|
if (typeof crypto !== "undefined" && !!crypto.randomUUID) {
|
|
@@ -1670,7 +1827,7 @@ function generateUUID() {
|
|
|
1670
1827
|
}
|
|
1671
1828
|
|
|
1672
1829
|
// src/version.ts
|
|
1673
|
-
var LIB_VERSION = "2025.7.
|
|
1830
|
+
var LIB_VERSION = "2025.7.2";
|
|
1674
1831
|
|
|
1675
1832
|
// src/utils/graphql.ts
|
|
1676
1833
|
function minifyQuery(string) {
|
|
@@ -1834,16 +1991,34 @@ function createStorefrontClient(options) {
|
|
|
1834
1991
|
contentType: "json",
|
|
1835
1992
|
buyerIp: storefrontHeaders?.buyerIp || ""
|
|
1836
1993
|
});
|
|
1994
|
+
if (storefrontHeaders?.buyerIp) {
|
|
1995
|
+
defaultHeaders[SHOPIFY_CLIENT_IP_HEADER] = storefrontHeaders.buyerIp;
|
|
1996
|
+
}
|
|
1997
|
+
if (storefrontHeaders?.buyerIpSig) {
|
|
1998
|
+
defaultHeaders[SHOPIFY_CLIENT_IP_SIG_HEADER] = storefrontHeaders.buyerIpSig;
|
|
1999
|
+
}
|
|
1837
2000
|
defaultHeaders[STOREFRONT_REQUEST_GROUP_ID_HEADER] = storefrontHeaders?.requestGroupId || generateUUID();
|
|
1838
2001
|
if (storefrontId) defaultHeaders[SHOPIFY_STOREFRONT_ID_HEADER] = storefrontId;
|
|
1839
2002
|
defaultHeaders["user-agent"] = `Hydrogen ${LIB_VERSION}`;
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
2003
|
+
const requestCookie = storefrontHeaders?.cookie ?? "";
|
|
2004
|
+
if (requestCookie) defaultHeaders["cookie"] = requestCookie;
|
|
2005
|
+
let uniqueToken;
|
|
2006
|
+
let visitToken;
|
|
2007
|
+
if (!/\b_shopify_(analytics|marketing)=/.test(requestCookie)) {
|
|
2008
|
+
const legacyUniqueToken = requestCookie.match(/\b_shopify_y=([^;]+)/)?.[1];
|
|
2009
|
+
const legacyVisitToken = requestCookie.match(/\b_shopify_s=([^;]+)/)?.[1];
|
|
2010
|
+
if (legacyUniqueToken) {
|
|
2011
|
+
defaultHeaders[SHOPIFY_STOREFRONT_Y_HEADER] = legacyUniqueToken;
|
|
2012
|
+
}
|
|
2013
|
+
if (legacyVisitToken) {
|
|
2014
|
+
defaultHeaders[SHOPIFY_STOREFRONT_S_HEADER] = legacyVisitToken;
|
|
2015
|
+
}
|
|
2016
|
+
uniqueToken = legacyUniqueToken ?? generateUUID();
|
|
2017
|
+
visitToken = legacyVisitToken ?? generateUUID();
|
|
2018
|
+
defaultHeaders[SHOPIFY_UNIQUE_TOKEN_HEADER] = uniqueToken;
|
|
2019
|
+
defaultHeaders[SHOPIFY_VISIT_TOKEN_HEADER] = visitToken;
|
|
1846
2020
|
}
|
|
2021
|
+
let collectedSubrequestHeaders;
|
|
1847
2022
|
const cacheKeyHeader = JSON.stringify({
|
|
1848
2023
|
"content-type": defaultHeaders["content-type"],
|
|
1849
2024
|
"user-agent": defaultHeaders["user-agent"],
|
|
@@ -1910,7 +2085,13 @@ function createStorefrontClient(options) {
|
|
|
1910
2085
|
graphql: graphqlData,
|
|
1911
2086
|
purpose: storefrontHeaders?.purpose
|
|
1912
2087
|
},
|
|
1913
|
-
streamConfig
|
|
2088
|
+
streamConfig,
|
|
2089
|
+
onRawHeaders: (headers2) => {
|
|
2090
|
+
collectedSubrequestHeaders ??= {
|
|
2091
|
+
setCookie: headers2.getSetCookie(),
|
|
2092
|
+
serverTiming: headers2.get("server-timing") ?? ""
|
|
2093
|
+
};
|
|
2094
|
+
}
|
|
1914
2095
|
});
|
|
1915
2096
|
const errorOptions = {
|
|
1916
2097
|
url,
|
|
@@ -2009,9 +2190,90 @@ function createStorefrontClient(options) {
|
|
|
2009
2190
|
generateCacheControlHeader,
|
|
2010
2191
|
getPublicTokenHeaders,
|
|
2011
2192
|
getPrivateTokenHeaders,
|
|
2193
|
+
getHeaders: () => ({ ...defaultHeaders }),
|
|
2012
2194
|
getShopifyDomain,
|
|
2013
2195
|
getApiUrl: getStorefrontApiUrl,
|
|
2014
|
-
i18n: i18n ?? defaultI18n
|
|
2196
|
+
i18n: i18n ?? defaultI18n,
|
|
2197
|
+
/**
|
|
2198
|
+
* Checks if the request is targeting the Storefront API endpoint.
|
|
2199
|
+
*/
|
|
2200
|
+
isStorefrontApiUrl(request) {
|
|
2201
|
+
return SFAPI_RE.test(getSafePathname(request.url ?? ""));
|
|
2202
|
+
},
|
|
2203
|
+
/**
|
|
2204
|
+
* Forwards the request to the Storefront API.
|
|
2205
|
+
*/
|
|
2206
|
+
async forward(request, options2) {
|
|
2207
|
+
const forwardedHeaders = new Headers([
|
|
2208
|
+
// Forward only a selected set of headers to the Storefront API
|
|
2209
|
+
// to avoid getting 403 errors due to unexpected headers.
|
|
2210
|
+
...extractHeaders(
|
|
2211
|
+
(key) => request.headers.get(key),
|
|
2212
|
+
[
|
|
2213
|
+
"accept",
|
|
2214
|
+
"accept-encoding",
|
|
2215
|
+
"accept-language",
|
|
2216
|
+
// Access-Control headers are used for CORS preflight requests.
|
|
2217
|
+
"access-control-request-headers",
|
|
2218
|
+
"access-control-request-method",
|
|
2219
|
+
"content-type",
|
|
2220
|
+
"content-length",
|
|
2221
|
+
"cookie",
|
|
2222
|
+
"origin",
|
|
2223
|
+
"referer",
|
|
2224
|
+
"user-agent",
|
|
2225
|
+
STOREFRONT_ACCESS_TOKEN_HEADER,
|
|
2226
|
+
SHOPIFY_UNIQUE_TOKEN_HEADER,
|
|
2227
|
+
SHOPIFY_VISIT_TOKEN_HEADER
|
|
2228
|
+
]
|
|
2229
|
+
),
|
|
2230
|
+
// Add some headers to help with geolocalization and debugging
|
|
2231
|
+
...extractHeaders(
|
|
2232
|
+
(key) => defaultHeaders[key],
|
|
2233
|
+
[
|
|
2234
|
+
SHOPIFY_CLIENT_IP_HEADER,
|
|
2235
|
+
SHOPIFY_CLIENT_IP_SIG_HEADER,
|
|
2236
|
+
SHOPIFY_STOREFRONT_ID_HEADER,
|
|
2237
|
+
STOREFRONT_REQUEST_GROUP_ID_HEADER
|
|
2238
|
+
]
|
|
2239
|
+
)
|
|
2240
|
+
]);
|
|
2241
|
+
if (storefrontHeaders?.buyerIp) {
|
|
2242
|
+
forwardedHeaders.set("x-forwarded-for", storefrontHeaders.buyerIp);
|
|
2243
|
+
}
|
|
2244
|
+
const storefrontApiVersion = options2?.storefrontApiVersion ?? getSafePathname(request.url).match(SFAPI_RE)?.[1];
|
|
2245
|
+
const sfapiResponse = await fetch(
|
|
2246
|
+
getStorefrontApiUrl({ storefrontApiVersion }),
|
|
2247
|
+
{
|
|
2248
|
+
method: request.method,
|
|
2249
|
+
body: request.body,
|
|
2250
|
+
headers: forwardedHeaders
|
|
2251
|
+
}
|
|
2252
|
+
);
|
|
2253
|
+
return new Response(sfapiResponse.body, sfapiResponse);
|
|
2254
|
+
},
|
|
2255
|
+
setCollectedSubrequestHeaders: (response) => {
|
|
2256
|
+
if (collectedSubrequestHeaders) {
|
|
2257
|
+
for (const value of collectedSubrequestHeaders.setCookie) {
|
|
2258
|
+
response.headers.append("Set-Cookie", value);
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
const serverTiming = extractServerTimingHeader(
|
|
2262
|
+
collectedSubrequestHeaders?.serverTiming
|
|
2263
|
+
);
|
|
2264
|
+
const isDocumentResponse = response.headers.get("content-type")?.startsWith("text/html");
|
|
2265
|
+
const fallbackValues = isDocumentResponse ? { _y: uniqueToken, _s: visitToken } : void 0;
|
|
2266
|
+
appendServerTimingHeader(response, {
|
|
2267
|
+
...fallbackValues,
|
|
2268
|
+
...serverTiming
|
|
2269
|
+
});
|
|
2270
|
+
if (isDocumentResponse && collectedSubrequestHeaders && // _shopify_essential cookie is always set, but we need more than that
|
|
2271
|
+
collectedSubrequestHeaders.setCookie.length > 1 && serverTiming?._y && serverTiming?._s && serverTiming?._cmp) {
|
|
2272
|
+
appendServerTimingHeader(response, {
|
|
2273
|
+
[HYDROGEN_SERVER_TRACKING_KEY]: "1"
|
|
2274
|
+
});
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2015
2277
|
}
|
|
2016
2278
|
};
|
|
2017
2279
|
}
|
|
@@ -3607,6 +3869,12 @@ function createCustomerAccountClient({
|
|
|
3607
3869
|
if (options?.countryCode) {
|
|
3608
3870
|
loginUrl.searchParams.append("region_country", options.countryCode);
|
|
3609
3871
|
}
|
|
3872
|
+
if (options?.acrValues) {
|
|
3873
|
+
loginUrl.searchParams.append("acr_values", options.acrValues);
|
|
3874
|
+
}
|
|
3875
|
+
if (options?.loginHint) {
|
|
3876
|
+
loginUrl.searchParams.append("login_hint", options.loginHint);
|
|
3877
|
+
}
|
|
3610
3878
|
const verifier = generateCodeVerifier();
|
|
3611
3879
|
const challenge = await generateCodeChallenge(verifier);
|
|
3612
3880
|
session.set(CUSTOMER_ACCOUNT_SESSION_KEY, {
|
|
@@ -3937,12 +4205,58 @@ function createHydrogenContext(options, additionalContext) {
|
|
|
3937
4205
|
});
|
|
3938
4206
|
return hybridProvider;
|
|
3939
4207
|
}
|
|
3940
|
-
function
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
4208
|
+
function createRequestHandler({
|
|
4209
|
+
build,
|
|
4210
|
+
mode,
|
|
4211
|
+
poweredByHeader = true,
|
|
4212
|
+
getLoadContext,
|
|
4213
|
+
collectTrackingInformation = true,
|
|
4214
|
+
proxyStandardRoutes = true
|
|
4215
|
+
}) {
|
|
4216
|
+
const handleRequest = createRequestHandler$1(build, mode);
|
|
4217
|
+
const appendPoweredByHeader = poweredByHeader ? (response) => response.headers.append("powered-by", "Shopify, Hydrogen") : void 0;
|
|
4218
|
+
return async (request) => {
|
|
4219
|
+
const method = request.method;
|
|
4220
|
+
if ((method === "GET" || method === "HEAD") && request.body) {
|
|
4221
|
+
return new Response(`${method} requests cannot have a body`, {
|
|
4222
|
+
status: 400
|
|
4223
|
+
});
|
|
4224
|
+
}
|
|
4225
|
+
const url = new URL(request.url);
|
|
4226
|
+
if (url.pathname.includes("//")) {
|
|
4227
|
+
return new Response(null, {
|
|
4228
|
+
status: 301,
|
|
4229
|
+
headers: {
|
|
4230
|
+
location: url.pathname.replace(/\/+/g, "/")
|
|
4231
|
+
}
|
|
4232
|
+
});
|
|
4233
|
+
}
|
|
4234
|
+
const context = await getLoadContext?.(request);
|
|
4235
|
+
const storefront = context?.storefront || context?.get?.(storefrontContext);
|
|
4236
|
+
if (proxyStandardRoutes) {
|
|
4237
|
+
if (!storefront) {
|
|
4238
|
+
warnOnce(
|
|
4239
|
+
"[h2:createRequestHandler] Storefront instance is required to proxy standard routes."
|
|
4240
|
+
);
|
|
4241
|
+
}
|
|
4242
|
+
if (storefront?.isStorefrontApiUrl(request)) {
|
|
4243
|
+
const response2 = await storefront.forward(request);
|
|
4244
|
+
appendPoweredByHeader?.(response2);
|
|
4245
|
+
return response2;
|
|
4246
|
+
}
|
|
4247
|
+
}
|
|
4248
|
+
const response = await handleRequest(request, context);
|
|
4249
|
+
if (storefront && proxyStandardRoutes) {
|
|
4250
|
+
if (collectTrackingInformation) {
|
|
4251
|
+
storefront.setCollectedSubrequestHeaders(response);
|
|
4252
|
+
}
|
|
4253
|
+
const fetchDest = request.headers.get("sec-fetch-dest");
|
|
4254
|
+
if (fetchDest && fetchDest === "document" || request.headers.get("accept")?.includes("text/html")) {
|
|
4255
|
+
appendServerTimingHeader(response, { [HYDROGEN_SFAPI_PROXY_KEY]: "1" });
|
|
4256
|
+
}
|
|
4257
|
+
}
|
|
4258
|
+
appendPoweredByHeader?.(response);
|
|
4259
|
+
return response;
|
|
3946
4260
|
};
|
|
3947
4261
|
}
|
|
3948
4262
|
var NonceContext = createContext(void 0);
|
|
@@ -4069,7 +4383,7 @@ function LazyScript({
|
|
|
4069
4383
|
|
|
4070
4384
|
// src/dev/hydrogen-routes.ts
|
|
4071
4385
|
async function hydrogenRoutes(currentRoutes) {
|
|
4072
|
-
const { getVirtualRoutesV3 } = await import('./get-virtual-routes-
|
|
4386
|
+
const { getVirtualRoutesV3 } = await import('./get-virtual-routes-XE7G57DS.js');
|
|
4073
4387
|
const { layout, routes: virtualRoutes } = await getVirtualRoutesV3();
|
|
4074
4388
|
const childVirtualRoutes = virtualRoutes.map(({ path, file, index, id }) => {
|
|
4075
4389
|
return {
|
|
@@ -4556,10 +4870,10 @@ function hydrogenPreset() {
|
|
|
4556
4870
|
ssr: true,
|
|
4557
4871
|
future: {
|
|
4558
4872
|
v8_middleware: true,
|
|
4873
|
+
v8_splitRouteModules: true,
|
|
4874
|
+
v8_viteEnvironmentApi: false,
|
|
4559
4875
|
unstable_optimizeDeps: true,
|
|
4560
|
-
|
|
4561
|
-
unstable_subResourceIntegrity: false,
|
|
4562
|
-
unstable_viteEnvironmentApi: false
|
|
4876
|
+
unstable_subResourceIntegrity: false
|
|
4563
4877
|
}
|
|
4564
4878
|
}),
|
|
4565
4879
|
reactRouterConfigResolved: ({ reactRouterConfig }) => {
|
|
@@ -4575,7 +4889,7 @@ function hydrogenPreset() {
|
|
|
4575
4889
|
}
|
|
4576
4890
|
if (reactRouterConfig.serverBundles) {
|
|
4577
4891
|
throw new Error(
|
|
4578
|
-
"[Hydrogen Preset] serverBundles is not supported in Hydrogen 2025.7.0.\nReason: React Router plugin manifest incompatibility with Hydrogen CLI.\nAlternative: Route-level code splitting via
|
|
4892
|
+
"[Hydrogen Preset] serverBundles is not supported in Hydrogen 2025.7.0.\nReason: React Router plugin manifest incompatibility with Hydrogen CLI.\nAlternative: Route-level code splitting via v8_splitRouteModules is enabled."
|
|
4579
4893
|
);
|
|
4580
4894
|
}
|
|
4581
4895
|
if (reactRouterConfig.buildEnd) {
|
|
@@ -5090,10 +5404,10 @@ var schema = {
|
|
|
5090
5404
|
if (typeof value !== "string") {
|
|
5091
5405
|
throw new Error(ERROR_PREFIX.concat("`title` should be a string"));
|
|
5092
5406
|
}
|
|
5093
|
-
if (typeof value === "string" && value.length >
|
|
5407
|
+
if (typeof value === "string" && value.length > 70) {
|
|
5094
5408
|
throw new Error(
|
|
5095
5409
|
ERROR_PREFIX.concat(
|
|
5096
|
-
"`title` should not be longer than
|
|
5410
|
+
"`title` should not be longer than 70 characters"
|
|
5097
5411
|
)
|
|
5098
5412
|
);
|
|
5099
5413
|
}
|
|
@@ -5110,7 +5424,7 @@ var schema = {
|
|
|
5110
5424
|
if (typeof value === "string" && value.length > 155) {
|
|
5111
5425
|
throw new Error(
|
|
5112
5426
|
ERROR_PREFIX.concat(
|
|
5113
|
-
"`description` should not be longer than
|
|
5427
|
+
"`description` should not be longer than 160 characters"
|
|
5114
5428
|
)
|
|
5115
5429
|
);
|
|
5116
5430
|
}
|
|
@@ -5986,6 +6300,6 @@ var QUERIES = {
|
|
|
5986
6300
|
//! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartDeliveryAddressesRemove
|
|
5987
6301
|
//! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartDeliveryAddressesUpdate
|
|
5988
6302
|
|
|
5989
|
-
export { Analytics, AnalyticsEvent, CacheCustom, CacheLong, CacheNone, CacheShort, CartForm, InMemoryCache, NonceProvider, OptimisticInput, Pagination, RichText, Script, Seo, ShopPayButton, VariantSelector, cartAttributesUpdateDefault, cartBuyerIdentityUpdateDefault, cartCreateDefault, cartDiscountCodesUpdateDefault, cartGetDefault, cartGetIdDefault, cartGiftCardCodesRemoveDefault, cartGiftCardCodesUpdateDefault, cartLinesAddDefault, cartLinesRemoveDefault, cartLinesUpdateDefault, cartMetafieldDeleteDefault, cartMetafieldsSetDefault, cartNoteUpdateDefault, cartSelectedDeliveryOptionsUpdateDefault, cartSetIdDefault, changelogHandler, createCartHandler, createContentSecurityPolicy, createCustomerAccountClient, createHydrogenContext, createStorefrontClient, createWithCache, formatAPIResult, generateCacheControlHeader, getPaginationVariables, getSelectedProductOptions, getSeoMeta, getShopAnalytics, getSitemap, getSitemapIndex, graphiqlLoader, hydrogenContext, hydrogenPreset, hydrogenRoutes, storefrontRedirect, useAnalytics, useCustomerPrivacy, useNonce, useOptimisticCart, useOptimisticData, useOptimisticVariant };
|
|
6303
|
+
export { Analytics, AnalyticsEvent, CacheCustom, CacheLong, CacheNone, CacheShort, CartForm, InMemoryCache, NonceProvider, OptimisticInput, Pagination, RichText, Script, Seo, ShopPayButton, VariantSelector, cartAttributesUpdateDefault, cartBuyerIdentityUpdateDefault, cartCreateDefault, cartDiscountCodesUpdateDefault, cartGetDefault, cartGetIdDefault, cartGiftCardCodesRemoveDefault, cartGiftCardCodesUpdateDefault, cartLinesAddDefault, cartLinesRemoveDefault, cartLinesUpdateDefault, cartMetafieldDeleteDefault, cartMetafieldsSetDefault, cartNoteUpdateDefault, cartSelectedDeliveryOptionsUpdateDefault, cartSetIdDefault, changelogHandler, createCartHandler, createContentSecurityPolicy, createCustomerAccountClient, createHydrogenContext, createRequestHandler, createStorefrontClient, createWithCache, formatAPIResult, generateCacheControlHeader, getPaginationVariables, getSelectedProductOptions, getSeoMeta, getShopAnalytics, getSitemap, getSitemapIndex, graphiqlLoader, hydrogenContext, hydrogenPreset, hydrogenRoutes, storefrontRedirect, useAnalytics, useCustomerPrivacy, useNonce, useOptimisticCart, useOptimisticData, useOptimisticVariant };
|
|
5990
6304
|
//# sourceMappingURL=index.js.map
|
|
5991
6305
|
//# sourceMappingURL=index.js.map
|