@shopify/hydrogen 2026.10.0-preview.2 → 2026.10.0-preview.4
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/README.md +34 -3
- package/dist/cli/index.mjs +578 -85
- package/dist/client/client.mjs +2 -2
- package/dist/client/errors.d.mts +19 -19
- package/dist/client/errors.mjs +19 -16
- package/dist/client/errors.mjs.map +1 -1
- package/dist/client/types.d.mts +91 -10
- package/dist/core/analytics/cart-tracker.d.mts +14 -0
- package/dist/core/analytics/cart-tracker.mjs +15 -1
- package/dist/core/analytics/cart-tracker.mjs.map +1 -1
- package/dist/core/analytics/custom-consent.mjs +12 -0
- package/dist/core/analytics/custom-consent.mjs.map +1 -0
- package/dist/core/analytics/events.d.mts +7 -0
- package/dist/core/analytics/events.mjs +7 -0
- package/dist/core/analytics/events.mjs.map +1 -1
- package/dist/core/analytics/index.d.mts +1 -1
- package/dist/core/analytics/types.d.mts +152 -16
- package/dist/core/cart/actions.d.mts +47 -3
- package/dist/core/cart/actions.mjs +29 -0
- package/dist/core/cart/actions.mjs.map +1 -1
- package/dist/core/cart/attach-quantity-input.d.mts +26 -0
- package/dist/core/cart/attach-quantity-input.mjs +26 -0
- package/dist/core/cart/attach-quantity-input.mjs.map +1 -1
- package/dist/core/cart/cart.d.mts +106 -6
- package/dist/core/cart/cart.mjs +57 -6
- package/dist/core/cart/cart.mjs.map +1 -1
- package/dist/core/cart/cookie.d.mts +15 -0
- package/dist/core/cart/cookie.mjs +15 -0
- package/dist/core/cart/cookie.mjs.map +1 -1
- package/dist/core/cart/form.d.mts +61 -0
- package/dist/core/cart/form.mjs +18 -0
- package/dist/core/cart/form.mjs.map +1 -1
- package/dist/core/cart/get-cart.d.mts +43 -2
- package/dist/core/cart/get-cart.mjs +33 -0
- package/dist/core/cart/get-cart.mjs.map +1 -1
- package/dist/core/cart/index.d.mts +1 -1
- package/dist/core/cart/quantity.d.mts +17 -0
- package/dist/core/cart/quantity.mjs +17 -0
- package/dist/core/cart/quantity.mjs.map +1 -1
- package/dist/core/cart/queries.d.mts +402 -369
- package/dist/core/cart/queries.mjs +2 -1
- package/dist/core/cart/queries.mjs.map +1 -1
- package/dist/core/cart/server-handlers.d.mts +69 -0
- package/dist/core/cart/server-handlers.mjs +2 -10
- package/dist/core/cart/server-handlers.mjs.map +1 -1
- package/dist/core/cart/state.d.mts +133 -0
- package/dist/core/cart/state.mjs +8 -0
- package/dist/core/cart/state.mjs.map +1 -1
- package/dist/core/collection/collection.d.mts +18 -2
- package/dist/core/collection/collection.mjs +11 -0
- package/dist/core/collection/collection.mjs.map +1 -1
- package/dist/core/collection/index.d.mts +1 -1
- package/dist/core/collection/reconciler.d.mts +13 -4
- package/dist/core/collection/reconciler.mjs.map +1 -1
- package/dist/core/collection/state.d.mts +7 -2
- package/dist/core/collection/state.mjs.map +1 -1
- package/dist/core/collection/url.d.mts +3 -0
- package/dist/core/collection/url.mjs.map +1 -1
- package/dist/core/constants.d.mts +1 -1
- package/dist/core/constants.mjs +2 -2
- package/dist/core/constants.mjs.map +1 -1
- package/dist/core/headers.mjs +2 -2
- package/dist/core/headers.mjs.map +1 -1
- package/dist/core/index.d.mts +5 -5
- package/dist/core/logging/logging.mjs.map +1 -1
- package/dist/core/money/format.mjs +6 -3
- package/dist/core/money/format.mjs.map +1 -1
- package/dist/core/observable.mjs +0 -3
- package/dist/core/observable.mjs.map +1 -1
- package/dist/core/predictive-search/form.d.mts +1 -0
- package/dist/core/predictive-search/form.mjs +1 -0
- package/dist/core/predictive-search/form.mjs.map +1 -1
- package/dist/core/predictive-search/index.d.mts +1 -1
- package/dist/core/predictive-search/queries.d.mts +40 -4
- package/dist/core/predictive-search/queries.mjs +7 -1
- package/dist/core/predictive-search/queries.mjs.map +1 -1
- package/dist/core/predictive-search/search.d.mts +43 -10
- package/dist/core/predictive-search/search.mjs +34 -0
- package/dist/core/predictive-search/search.mjs.map +1 -1
- package/dist/core/predictive-search/server-handlers.d.mts +31 -5
- package/dist/core/predictive-search/server-handlers.mjs +5 -3
- package/dist/core/predictive-search/server-handlers.mjs.map +1 -1
- package/dist/core/predictive-search/store.d.mts +3 -1
- package/dist/core/predictive-search/store.mjs.map +1 -1
- package/dist/core/predictive-search/url.d.mts +50 -8
- package/dist/core/predictive-search/url.mjs +9 -0
- package/dist/core/predictive-search/url.mjs.map +1 -1
- package/dist/core/product/form.d.mts +21 -2
- package/dist/core/product/form.mjs +13 -0
- package/dist/core/product/form.mjs.map +1 -1
- package/dist/core/product/index.d.mts +1 -1
- package/dist/core/product/options.d.mts +2 -2
- package/dist/core/product/options.mjs +2 -2
- package/dist/core/product/options.mjs.map +1 -1
- package/dist/core/product/product-form.d.mts +33 -1
- package/dist/core/product/product-form.mjs +30 -0
- package/dist/core/product/product-form.mjs.map +1 -1
- package/dist/core/product/state.d.mts +41 -0
- package/dist/core/product/url.d.mts +6 -0
- package/dist/core/product/url.mjs.map +1 -1
- package/dist/core/request-context.d.mts +8 -5
- package/dist/core/request-context.mjs +17 -39
- package/dist/core/request-context.mjs.map +1 -1
- package/dist/core/request-routing/handle-shopify-routes.mjs +4 -1
- package/dist/core/request-routing/handle-shopify-routes.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/ajax-api.mjs +1 -1
- package/dist/core/request-routing/interceptors/api-proxy.mjs +1 -1
- package/dist/core/request-routing/interceptors/checkout.mjs +22 -6
- package/dist/core/request-routing/interceptors/checkout.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/mcp-proxy.mjs +1 -1
- package/dist/core/request-routing/interceptors/proxy.mjs +36 -10
- package/dist/core/request-routing/interceptors/proxy.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/query-param-redirect.mjs +5 -11
- package/dist/core/request-routing/interceptors/query-param-redirect.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/sfapi-proxy.mjs +19 -1
- package/dist/core/request-routing/interceptors/sfapi-proxy.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/ucp-mcp-proxy.mjs +35 -0
- package/dist/core/request-routing/interceptors/ucp-mcp-proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/well-known.mjs +1 -1
- package/dist/core/shopify-scripts/analytics.mjs +2 -2
- package/dist/core/shopify-scripts/analytics.mjs.map +1 -1
- package/dist/core/shopify-scripts/constants.mjs +4 -2
- package/dist/core/shopify-scripts/constants.mjs.map +1 -1
- package/dist/core/shopify-scripts/global.mjs +9 -4
- package/dist/core/shopify-scripts/global.mjs.map +1 -1
- package/dist/core/shopify-scripts/index.d.mts +1 -0
- package/dist/core/shopify-scripts/index.mjs +14 -12
- package/dist/core/shopify-scripts/index.mjs.map +1 -1
- package/dist/core/shopify-scripts/initialize.d.mts +1 -0
- package/dist/core/shopify-scripts/initialize.mjs +10 -3
- package/dist/core/shopify-scripts/initialize.mjs.map +1 -1
- package/dist/core/shopify-scripts/types.d.mts +6 -0
- package/dist/core/url.mjs +21 -2
- package/dist/core/url.mjs.map +1 -1
- package/dist/customer-account/client.d.mts +128 -4
- package/dist/customer-account/client.mjs +27 -1
- package/dist/customer-account/client.mjs.map +1 -1
- package/dist/customer-account/errors.d.mts +46 -0
- package/dist/customer-account/errors.mjs +46 -0
- package/dist/customer-account/errors.mjs.map +1 -1
- package/dist/customer-account/graphql.d.mts +68 -0
- package/dist/customer-account/graphql.mjs +47 -0
- package/dist/customer-account/graphql.mjs.map +1 -1
- package/dist/customer-account/session.d.mts +114 -23
- package/dist/customer-account/session.mjs +27 -12
- package/dist/customer-account/session.mjs.map +1 -1
- package/dist/customer-account/type-resolver.d.mts +23 -0
- package/dist/customer-account-api-types.d.ts +570 -374
- package/dist/customer-account.schema.json +2981 -1527
- package/dist/development/client/client.mjs +2 -2
- package/dist/development/client/errors.d.mts +19 -19
- package/dist/development/client/errors.mjs +20 -20
- package/dist/development/client/errors.mjs.map +1 -1
- package/dist/development/client/types.d.mts +91 -10
- package/dist/development/core/analytics/cart-tracker.d.mts +14 -0
- package/dist/development/core/analytics/cart-tracker.mjs +15 -1
- package/dist/development/core/analytics/cart-tracker.mjs.map +1 -1
- package/dist/development/core/analytics/custom-consent.mjs +12 -0
- package/dist/development/core/analytics/custom-consent.mjs.map +1 -0
- package/dist/development/core/analytics/events.d.mts +7 -0
- package/dist/development/core/analytics/events.mjs +7 -0
- package/dist/development/core/analytics/events.mjs.map +1 -1
- package/dist/development/core/analytics/index.d.mts +1 -1
- package/dist/development/core/analytics/types.d.mts +152 -16
- package/dist/development/core/cart/actions.d.mts +47 -3
- package/dist/development/core/cart/actions.mjs +29 -0
- package/dist/development/core/cart/actions.mjs.map +1 -1
- package/dist/development/core/cart/attach-quantity-input.d.mts +26 -0
- package/dist/development/core/cart/attach-quantity-input.mjs +26 -0
- package/dist/development/core/cart/attach-quantity-input.mjs.map +1 -1
- package/dist/development/core/cart/cart.d.mts +106 -6
- package/dist/development/core/cart/cart.mjs +57 -6
- package/dist/development/core/cart/cart.mjs.map +1 -1
- package/dist/development/core/cart/cookie.d.mts +15 -0
- package/dist/development/core/cart/cookie.mjs +15 -0
- package/dist/development/core/cart/cookie.mjs.map +1 -1
- package/dist/development/core/cart/form.d.mts +61 -0
- package/dist/development/core/cart/form.mjs +18 -0
- package/dist/development/core/cart/form.mjs.map +1 -1
- package/dist/development/core/cart/get-cart.d.mts +43 -2
- package/dist/development/core/cart/get-cart.mjs +33 -0
- package/dist/development/core/cart/get-cart.mjs.map +1 -1
- package/dist/development/core/cart/index.d.mts +1 -1
- package/dist/development/core/cart/quantity.d.mts +17 -0
- package/dist/development/core/cart/quantity.mjs +17 -0
- package/dist/development/core/cart/quantity.mjs.map +1 -1
- package/dist/development/core/cart/queries.d.mts +345 -312
- package/dist/development/core/cart/queries.mjs +2 -1
- package/dist/development/core/cart/queries.mjs.map +1 -1
- package/dist/development/core/cart/server-handlers.d.mts +69 -0
- package/dist/development/core/cart/server-handlers.mjs +2 -10
- package/dist/development/core/cart/server-handlers.mjs.map +1 -1
- package/dist/development/core/cart/state.d.mts +133 -0
- package/dist/development/core/cart/state.mjs +8 -0
- package/dist/development/core/cart/state.mjs.map +1 -1
- package/dist/development/core/collection/collection.d.mts +18 -2
- package/dist/development/core/collection/collection.mjs +11 -0
- package/dist/development/core/collection/collection.mjs.map +1 -1
- package/dist/development/core/collection/index.d.mts +1 -1
- package/dist/development/core/collection/reconciler.d.mts +13 -4
- package/dist/development/core/collection/reconciler.mjs.map +1 -1
- package/dist/development/core/collection/state.d.mts +7 -2
- package/dist/development/core/collection/state.mjs.map +1 -1
- package/dist/development/core/collection/url.d.mts +3 -0
- package/dist/development/core/collection/url.mjs.map +1 -1
- package/dist/development/core/constants.mjs +1 -1
- package/dist/development/core/constants.mjs.map +1 -1
- package/dist/development/core/development.d.mts +5 -5
- package/dist/development/core/headers.mjs +2 -2
- package/dist/development/core/headers.mjs.map +1 -1
- package/dist/development/core/index.d.mts +4 -4
- package/dist/development/core/logging/logging.mjs.map +1 -1
- package/dist/development/core/money/format.mjs +6 -3
- package/dist/development/core/money/format.mjs.map +1 -1
- package/dist/development/core/observable.mjs +0 -3
- package/dist/development/core/observable.mjs.map +1 -1
- package/dist/development/core/predictive-search/form.d.mts +1 -0
- package/dist/development/core/predictive-search/form.mjs +1 -0
- package/dist/development/core/predictive-search/form.mjs.map +1 -1
- package/dist/development/core/predictive-search/index.d.mts +1 -1
- package/dist/development/core/predictive-search/queries.d.mts +38 -2
- package/dist/development/core/predictive-search/queries.mjs +7 -1
- package/dist/development/core/predictive-search/queries.mjs.map +1 -1
- package/dist/development/core/predictive-search/search.d.mts +43 -10
- package/dist/development/core/predictive-search/search.mjs +34 -0
- package/dist/development/core/predictive-search/search.mjs.map +1 -1
- package/dist/development/core/predictive-search/server-handlers.d.mts +31 -5
- package/dist/development/core/predictive-search/server-handlers.mjs +5 -3
- package/dist/development/core/predictive-search/server-handlers.mjs.map +1 -1
- package/dist/development/core/predictive-search/store.d.mts +3 -1
- package/dist/development/core/predictive-search/store.mjs.map +1 -1
- package/dist/development/core/predictive-search/url.d.mts +50 -8
- package/dist/development/core/predictive-search/url.mjs +9 -0
- package/dist/development/core/predictive-search/url.mjs.map +1 -1
- package/dist/development/core/product/form.d.mts +21 -2
- package/dist/development/core/product/form.mjs +13 -0
- package/dist/development/core/product/form.mjs.map +1 -1
- package/dist/development/core/product/index.d.mts +1 -1
- package/dist/development/core/product/options.d.mts +2 -2
- package/dist/development/core/product/options.mjs +2 -2
- package/dist/development/core/product/options.mjs.map +1 -1
- package/dist/development/core/product/product-form.d.mts +33 -1
- package/dist/development/core/product/product-form.mjs +30 -0
- package/dist/development/core/product/product-form.mjs.map +1 -1
- package/dist/development/core/product/state.d.mts +41 -0
- package/dist/development/core/product/url.d.mts +6 -0
- package/dist/development/core/product/url.mjs.map +1 -1
- package/dist/development/core/request-context.d.mts +8 -5
- package/dist/development/core/request-context.mjs +17 -39
- package/dist/development/core/request-context.mjs.map +1 -1
- package/dist/development/core/request-routing/handle-shopify-routes.mjs +4 -1
- package/dist/development/core/request-routing/handle-shopify-routes.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/ajax-api.mjs +1 -1
- package/dist/development/core/request-routing/interceptors/api-proxy.mjs +1 -1
- package/dist/development/core/request-routing/interceptors/checkout.mjs +22 -6
- package/dist/development/core/request-routing/interceptors/checkout.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/mcp-proxy.mjs +1 -1
- package/dist/development/core/request-routing/interceptors/proxy.mjs +36 -10
- package/dist/development/core/request-routing/interceptors/proxy.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/query-param-redirect.mjs +5 -11
- package/dist/development/core/request-routing/interceptors/query-param-redirect.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/sfapi-proxy.mjs +19 -1
- package/dist/development/core/request-routing/interceptors/sfapi-proxy.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/ucp-mcp-proxy.mjs +35 -0
- package/dist/development/core/request-routing/interceptors/ucp-mcp-proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/well-known.mjs +1 -1
- package/dist/development/core/shopify-scripts/analytics.mjs +2 -2
- package/dist/development/core/shopify-scripts/analytics.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/constants.mjs +4 -2
- package/dist/development/core/shopify-scripts/constants.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/global.mjs +9 -4
- package/dist/development/core/shopify-scripts/global.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/index.d.mts +1 -0
- package/dist/development/core/shopify-scripts/index.mjs +14 -12
- package/dist/development/core/shopify-scripts/index.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/initialize.d.mts +1 -0
- package/dist/development/core/shopify-scripts/initialize.mjs +10 -3
- package/dist/development/core/shopify-scripts/initialize.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/types.d.mts +6 -0
- package/dist/development/core/url.mjs +21 -2
- package/dist/development/core/url.mjs.map +1 -1
- package/dist/development/customer-account/session.d.mts +69 -13
- package/dist/development/customer-account/session.mjs +4 -0
- package/dist/development/customer-account/session.mjs.map +1 -1
- package/dist/development/globals.d.mts +6 -5
- package/dist/development/graphql/generated/graphql-env.d.mts +459 -16
- package/dist/development/graphql/generated/storefront-api-types.d.mts +1 -1
- package/dist/development/graphql/graphql.d.mts +33 -0
- package/dist/development/graphql/graphql.mjs +30 -0
- package/dist/development/graphql/graphql.mjs.map +1 -1
- package/dist/development/graphql/type-resolver.d.mts +14 -0
- package/dist/development/react/cart.d.mts +85 -14
- package/dist/development/react/cart.mjs +123 -3
- package/dist/development/react/cart.mjs.map +1 -1
- package/dist/development/react/collection.d.mts +2 -4
- package/dist/development/react/collection.mjs.map +1 -1
- package/dist/development/react/index.d.mts +8 -6
- package/dist/development/react/index.mjs +2 -2
- package/dist/development/react/predictive-search.d.mts +68 -7
- package/dist/development/react/predictive-search.mjs +54 -12
- package/dist/development/react/predictive-search.mjs.map +1 -1
- package/dist/development/react/product.d.mts +1 -0
- package/dist/development/react/product.mjs +5 -2
- package/dist/development/react/product.mjs.map +1 -1
- package/dist/development/react/shopify-scripts.mjs +1 -0
- package/dist/development/react/shopify-scripts.mjs.map +1 -1
- package/dist/development/vue/cart.d.mts +85 -6
- package/dist/development/vue/cart.mjs +95 -0
- package/dist/development/vue/cart.mjs.map +1 -1
- package/dist/development/vue/collection.d.mts +83 -5
- package/dist/development/vue/collection.mjs +52 -0
- package/dist/development/vue/collection.mjs.map +1 -1
- package/dist/development/vue/index.d.mts +6 -4
- package/dist/development/vue/predictive-search.d.mts +53 -6
- package/dist/development/vue/predictive-search.mjs +33 -0
- package/dist/development/vue/predictive-search.mjs.map +1 -1
- package/dist/development/vue/product.d.mts +6 -2
- package/dist/development/vue/product.mjs.map +1 -1
- package/dist/development/vue/shopify-scripts.d.mts +30 -3
- package/dist/development/vue/shopify-scripts.mjs +6 -0
- package/dist/development/vue/shopify-scripts.mjs.map +1 -1
- package/dist/globals.d.mts +6 -5
- package/dist/graphql/generated/customer-account-graphql-env.d.mts +1717 -1090
- package/dist/graphql/generated/graphql-env.d.mts +459 -16
- package/dist/graphql/generated/storefront-api-types.d.mts +1 -1
- package/dist/graphql/graphql.d.mts +33 -0
- package/dist/graphql/graphql.mjs +30 -0
- package/dist/graphql/graphql.mjs.map +1 -1
- package/dist/graphql/type-resolver.d.mts +14 -0
- package/dist/react/cart.d.mts +85 -14
- package/dist/react/cart.mjs +123 -3
- package/dist/react/cart.mjs.map +1 -1
- package/dist/react/collection.d.mts +2 -4
- package/dist/react/collection.mjs.map +1 -1
- package/dist/react/index.d.mts +8 -6
- package/dist/react/index.mjs +2 -2
- package/dist/react/predictive-search.d.mts +68 -7
- package/dist/react/predictive-search.mjs +54 -12
- package/dist/react/predictive-search.mjs.map +1 -1
- package/dist/react/product.d.mts +1 -0
- package/dist/react/product.mjs +5 -2
- package/dist/react/product.mjs.map +1 -1
- package/dist/react/shopify-scripts.mjs +1 -0
- package/dist/react/shopify-scripts.mjs.map +1 -1
- package/dist/storefront-api-types.d.ts +165 -20
- package/dist/storefront.schema.json +782 -57
- package/dist/vite/customer-account.mjs +191 -0
- package/dist/vite/customer-account.mjs.map +1 -0
- package/dist/vite/local-https.mjs +13 -29
- package/dist/vite/local-https.mjs.map +1 -1
- package/dist/vite/mkcert.mjs +1 -1
- package/dist/vue/cart.d.mts +85 -6
- package/dist/vue/cart.mjs +95 -0
- package/dist/vue/cart.mjs.map +1 -1
- package/dist/vue/collection.d.mts +83 -5
- package/dist/vue/collection.mjs +52 -0
- package/dist/vue/collection.mjs.map +1 -1
- package/dist/vue/index.d.mts +6 -4
- package/dist/vue/predictive-search.d.mts +53 -6
- package/dist/vue/predictive-search.mjs +33 -0
- package/dist/vue/predictive-search.mjs.map +1 -1
- package/dist/vue/product.d.mts +6 -2
- package/dist/vue/product.mjs.map +1 -1
- package/dist/vue/shopify-scripts.d.mts +31 -4
- package/dist/vue/shopify-scripts.mjs +6 -0
- package/dist/vue/shopify-scripts.mjs.map +1 -1
- package/package.json +5 -2
- package/skills/hydrogen-analytics/SKILL.md +6 -5
- package/skills/hydrogen-analytics/references/custom-consent.md +52 -0
- package/skills/hydrogen-analytics/references/react.md +1 -1
- package/skills/hydrogen-cart-metafields/SKILL.md +133 -0
- package/skills/hydrogen-cart-ui/SKILL.md +2 -1
- package/skills/hydrogen-customer-account/SKILL.md +3 -3
- package/skills/hydrogen-local-https/SKILL.md +22 -7
- package/skills/hydrogen-request-handlers/SKILL.md +5 -5
- package/skills/hydrogen-request-handlers/references/nuxt.md +0 -6
- package/skills/hydrogen-setup/references/analytics.md +24 -23
- package/skills/hydrogen-setup/steps/1-inspect-app.md +1 -1
- package/skills/hydrogen-setup/steps/11-verify.md +1 -0
- package/skills/hydrogen-setup/steps/2-scaffold.md +22 -1
- package/skills/hydrogen-smoke-test/SKILL.md +2 -2
- package/skills/hydrogen-storefront-client/SKILL.md +4 -2
- package/skills/hydrogen-variant-form/SKILL.md +10 -4
- package/ts-plugin/package.json +5 -0
- package/dist/core/shopify-scripts/consent.mjs +0 -17
- package/dist/core/shopify-scripts/consent.mjs.map +0 -1
- package/dist/core/shopify-scripts/deprecated-cookies.mjs +0 -97
- package/dist/core/shopify-scripts/deprecated-cookies.mjs.map +0 -1
- package/dist/core/shopify-scripts/utils/cookie-domain.mjs +0 -43
- package/dist/core/shopify-scripts/utils/cookie-domain.mjs.map +0 -1
- package/dist/core/shopify-scripts/utils/tracking-values.mjs +0 -65
- package/dist/core/shopify-scripts/utils/tracking-values.mjs.map +0 -1
- package/dist/core/shopify-scripts/utils/uuid.mjs +0 -17
- package/dist/core/shopify-scripts/utils/uuid.mjs.map +0 -1
- package/dist/development/core/shopify-scripts/consent.mjs +0 -17
- package/dist/development/core/shopify-scripts/consent.mjs.map +0 -1
- package/dist/development/core/shopify-scripts/deprecated-cookies.mjs +0 -97
- package/dist/development/core/shopify-scripts/deprecated-cookies.mjs.map +0 -1
- package/dist/development/core/shopify-scripts/utils/cookie-domain.mjs +0 -43
- package/dist/development/core/shopify-scripts/utils/cookie-domain.mjs.map +0 -1
- package/dist/development/core/shopify-scripts/utils/tracking-values.mjs +0 -65
- package/dist/development/core/shopify-scripts/utils/tracking-values.mjs.map +0 -1
- package/dist/development/core/shopify-scripts/utils/uuid.mjs +0 -17
- package/dist/development/core/shopify-scripts/utils/uuid.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkout.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/checkout.ts"],"sourcesContent":["import type { StorefrontClient } from \"../../../client\";\nimport { getCart, getCartId } from \"../../cart/get-cart\";\nimport { getLogger } from \"../../logging\";\nimport { CHECKOUT_RE, isHydrogenServerHandoffPath } from \"../../url\";\nimport type { HydrogenRouteInterceptor } from \"../route-types\";\n\nconst log = getLogger(\"checkout\");\nconst
|
|
1
|
+
{"version":3,"file":"checkout.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/checkout.ts"],"sourcesContent":["import type { StorefrontClient } from \"../../../client\";\nimport { getCart, getCartId } from \"../../cart/get-cart\";\nimport { getLogger } from \"../../logging\";\nimport { BUY_PERMALINK_RE, CHECKOUT_RE, isHydrogenServerHandoffPath } from \"../../url\";\nimport type { HydrogenRouteInterceptor } from \"../route-types\";\n\nconst log = getLogger(\"checkout\");\nconst MOCK_SHOP_PERMALINK_ORIGIN = \"https://demostore.mock.shop\";\n\nexport const handleCheckoutRedirect: HydrogenRouteInterceptor = (\n url,\n { request, storefrontClient },\n) => {\n if (!isHydrogenServerHandoffPath(url.pathname)) {\n return null;\n }\n\n if (request.method !== \"GET\" && request.method !== \"HEAD\") {\n return Promise.resolve(new Response(\"Method Not Allowed\", { status: 405 }));\n }\n\n const redirectUrlPromise = CHECKOUT_RE.test(url.pathname)\n ? getCheckoutRedirectUrl(request, storefrontClient)\n : getCartRedirectUrl(request, storefrontClient);\n\n return redirectUrlPromise\n .then((redirectUrl) => {\n if (redirectUrl.pathname !== \"/\") {\n mergeSearchParams(redirectUrl, url.searchParams);\n redirectUrl.searchParams.set(\"payment\", url.searchParams.get(\"payment\") ?? \"shop_pay\");\n }\n\n return new Response(null, {\n status: 302,\n headers: { location: redirectUrl.toString() },\n });\n })\n .catch((error) => {\n log.error(\"checkout redirect request failed\", { error });\n const message = error instanceof Error ? error.message : \"Internal redirect error\";\n\n return new Response(JSON.stringify({ error: message }), {\n status: 502,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n};\n\nexport const handleBuyPermalinkRedirect: HydrogenRouteInterceptor = (\n url,\n { request, storefrontClient },\n) => {\n if (!BUY_PERMALINK_RE.test(url.pathname)) {\n return null;\n }\n\n if (request.method !== \"GET\") {\n return Promise.resolve(new Response(\"Method Not Allowed\", { status: 405 }));\n }\n\n // UCP permalink response shape (303, no-store, no-referrer), forwarded verbatim since re-encoding would alter `continue_to`.\n // https://ucp.dev/2026-08-25/specification/permalink/#redirect-resolution\n const location = `${getPermalinkOrigin(storefrontClient.storeUrl)}${url.pathname}${url.search}`;\n return Promise.resolve(\n new Response(null, {\n status: 303,\n headers: { location, \"cache-control\": \"no-store\", \"referrer-policy\": \"no-referrer\" },\n }),\n );\n};\n\nasync function getCheckoutRedirectUrl(\n request: Request,\n storefrontClient: StorefrontClient,\n): Promise<URL> {\n const cartId = getCartId(request);\n if (!cartId) return new URL(\"/\", request.url);\n\n const result = await getCart(cartId, storefrontClient);\n return result.cart?.checkoutUrl ? new URL(result.cart.checkoutUrl) : new URL(\"/\", request.url);\n}\n\nasync function getCartRedirectUrl(\n request: Request,\n storefrontClient: StorefrontClient,\n): Promise<URL> {\n const sourceUrl = new URL(request.url);\n const redirectUrl = new URL(sourceUrl.pathname, getPermalinkOrigin(storefrontClient.storeUrl));\n\n const cartId = getCartId(request);\n if (!cartId) return redirectUrl;\n\n try {\n const result = await getCart(cartId, storefrontClient);\n if (result.cart?.checkoutUrl) {\n mergeSearchParams(redirectUrl, new URL(result.cart.checkoutUrl).searchParams);\n }\n } catch (error) {\n log.warn(\"checkout redirect could not load cart permalink tracking params\", { error });\n }\n\n return redirectUrl;\n}\n\nfunction getPermalinkOrigin(storeUrl: string): string {\n const url = new URL(storeUrl);\n return isMockShopHost(url.hostname) ? MOCK_SHOP_PERMALINK_ORIGIN : url.origin;\n}\n\n// mock.shop serves many stores, each on its own host (pets.mock.shop, ...), and\n// none of them renders cart or buy permalinks, so every mock host hands off to the demo store.\nfunction isMockShopHost(hostname: string): boolean {\n return hostname === \"mock.shop\" || hostname.endsWith(\".mock.shop\");\n}\n\nfunction mergeSearchParams(target: URL, source: URLSearchParams): void {\n for (const [key, value] of source) {\n if (!target.searchParams.has(key)) target.searchParams.append(key, value);\n }\n}\n"],"mappings":";;;;;AAMA,MAAM,MAAM,UAAU,WAAW;AACjC,MAAM,6BAA6B;AAEnC,MAAa,0BACX,KACA,EAAE,SAAS,uBACR;AACH,KAAI,CAAC,4BAA4B,IAAI,SAAS,CAC5C,QAAO;AAGT,KAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,OACjD,QAAO,QAAQ,QAAQ,IAAI,SAAS,sBAAsB,EAAE,QAAQ,KAAK,CAAC,CAAC;AAO7E,SAJ2B,YAAY,KAAK,IAAI,SAAS,GACrD,uBAAuB,SAAS,iBAAiB,GACjD,mBAAmB,SAAS,iBAAiB,EAG9C,MAAM,gBAAgB;AACrB,MAAI,YAAY,aAAa,KAAK;AAChC,qBAAkB,aAAa,IAAI,aAAa;AAChD,eAAY,aAAa,IAAI,WAAW,IAAI,aAAa,IAAI,UAAU,IAAI,WAAW;;AAGxF,SAAO,IAAI,SAAS,MAAM;GACxB,QAAQ;GACR,SAAS,EAAE,UAAU,YAAY,UAAU,EAAE;GAC9C,CAAC;GACF,CACD,OAAO,UAAU;AAChB,MAAI,MAAM,oCAAoC,EAAE,OAAO,CAAC;EACxD,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AAEzD,SAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC,EAAE;GACtD,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAChD,CAAC;GACF;;AAGN,MAAa,8BACX,KACA,EAAE,SAAS,uBACR;AACH,KAAI,CAAC,iBAAiB,KAAK,IAAI,SAAS,CACtC,QAAO;AAGT,KAAI,QAAQ,WAAW,MACrB,QAAO,QAAQ,QAAQ,IAAI,SAAS,sBAAsB,EAAE,QAAQ,KAAK,CAAC,CAAC;CAK7E,MAAM,WAAW,GAAG,mBAAmB,iBAAiB,SAAS,GAAG,IAAI,WAAW,IAAI;AACvF,QAAO,QAAQ,QACb,IAAI,SAAS,MAAM;EACjB,QAAQ;EACR,SAAS;GAAE;GAAU,iBAAiB;GAAY,mBAAmB;GAAe;EACrF,CAAC,CACH;;AAGH,eAAe,uBACb,SACA,kBACc;CACd,MAAM,SAAS,UAAU,QAAQ;AACjC,KAAI,CAAC,OAAQ,QAAO,IAAI,IAAI,KAAK,QAAQ,IAAI;CAE7C,MAAM,SAAS,MAAM,QAAQ,QAAQ,iBAAiB;AACtD,QAAO,OAAO,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,YAAY,GAAG,IAAI,IAAI,KAAK,QAAQ,IAAI;;AAGhG,eAAe,mBACb,SACA,kBACc;CACd,MAAM,YAAY,IAAI,IAAI,QAAQ,IAAI;CACtC,MAAM,cAAc,IAAI,IAAI,UAAU,UAAU,mBAAmB,iBAAiB,SAAS,CAAC;CAE9F,MAAM,SAAS,UAAU,QAAQ;AACjC,KAAI,CAAC,OAAQ,QAAO;AAEpB,KAAI;EACF,MAAM,SAAS,MAAM,QAAQ,QAAQ,iBAAiB;AACtD,MAAI,OAAO,MAAM,YACf,mBAAkB,aAAa,IAAI,IAAI,OAAO,KAAK,YAAY,CAAC,aAAa;UAExE,OAAO;AACd,MAAI,KAAK,mEAAmE,EAAE,OAAO,CAAC;;AAGxF,QAAO;;AAGT,SAAS,mBAAmB,UAA0B;CACpD,MAAM,MAAM,IAAI,IAAI,SAAS;AAC7B,QAAO,eAAe,IAAI,SAAS,GAAG,6BAA6B,IAAI;;AAKzE,SAAS,eAAe,UAA2B;AACjD,QAAO,aAAa,eAAe,SAAS,SAAS,aAAa;;AAGpE,SAAS,kBAAkB,QAAa,QAA+B;AACrE,MAAK,MAAM,CAAC,KAAK,UAAU,OACzB,KAAI,CAAC,OAAO,aAAa,IAAI,IAAI,CAAE,QAAO,aAAa,OAAO,KAAK,MAAM"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MCP_REQUEST_HEADER_ALLOWLIST } from "../../headers.mjs";
|
|
2
1
|
import { MCP_RE } from "../../url.mjs";
|
|
2
|
+
import { MCP_REQUEST_HEADER_ALLOWLIST } from "../../headers.mjs";
|
|
3
3
|
import { createProxyInterceptor } from "./proxy.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/core/request-routing/interceptors/mcp-proxy.ts
|
|
@@ -3,26 +3,41 @@ import { extractHeaders } from "../../headers.mjs";
|
|
|
3
3
|
|
|
4
4
|
//#region src/core/request-routing/interceptors/proxy.ts
|
|
5
5
|
const PROXY_TIMEOUT_MS = 3e4;
|
|
6
|
+
const PROXY_ERROR_CACHE_CONTROL = "no-store";
|
|
6
7
|
function createProxyInterceptor(descriptor) {
|
|
7
8
|
const log = getLogger(descriptor.scope);
|
|
8
9
|
const formatError = descriptor.formatError ?? defaultFormatError;
|
|
9
10
|
return (url, options) => {
|
|
10
11
|
const { request, storefrontClient } = options;
|
|
11
12
|
if (!descriptor.match.test(url.pathname)) return null;
|
|
12
|
-
if (
|
|
13
|
+
if (url.searchParams.has("callback")) return Promise.resolve(new Response(JSON.stringify(formatError("JSONP requests are not supported")), {
|
|
14
|
+
status: 400,
|
|
15
|
+
headers: {
|
|
16
|
+
"content-type": "application/json",
|
|
17
|
+
"cache-control": PROXY_ERROR_CACHE_CONTROL
|
|
18
|
+
}
|
|
19
|
+
}));
|
|
20
|
+
if (descriptor.methods && !descriptor.methods.includes(request.method)) return Promise.resolve(new Response(JSON.stringify(formatError("Method Not Allowed")), {
|
|
21
|
+
status: 405,
|
|
22
|
+
headers: {
|
|
23
|
+
allow: descriptor.methods.join(", "),
|
|
24
|
+
"content-type": "application/json",
|
|
25
|
+
"cache-control": PROXY_ERROR_CACHE_CONTROL
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
13
28
|
let upstreamUrl;
|
|
14
29
|
let init;
|
|
15
30
|
try {
|
|
16
31
|
const upstreamPathname = descriptor.rewritePathname?.(url.pathname) ?? url.pathname;
|
|
17
32
|
upstreamUrl = new URL(upstreamPathname + url.search, storefrontClient.storeUrl);
|
|
18
|
-
const forwardedHeaders = createProxyRequestHeaders(descriptor, request);
|
|
19
|
-
options.requestContext.applyStorefrontRequestHeaders(forwardedHeaders);
|
|
20
|
-
descriptor.requestHeaders.prepare?.(forwardedHeaders, options, url);
|
|
21
33
|
init = {
|
|
22
34
|
method: request.method,
|
|
23
35
|
body: request.body,
|
|
24
|
-
headers:
|
|
25
|
-
|
|
36
|
+
headers: createProxyRequestHeaders(descriptor, {
|
|
37
|
+
...options,
|
|
38
|
+
url
|
|
39
|
+
}),
|
|
40
|
+
signal: AbortSignal.timeout(PROXY_TIMEOUT_MS),
|
|
26
41
|
redirect: descriptor.redirect ?? "manual"
|
|
27
42
|
};
|
|
28
43
|
if (request.body) init.duplex = "half";
|
|
@@ -32,7 +47,11 @@ function createProxyInterceptor(descriptor) {
|
|
|
32
47
|
}
|
|
33
48
|
return fetch(upstreamUrl, init).then((upstreamResponse) => {
|
|
34
49
|
const headers = createProxyResponseHeaders(upstreamResponse.headers);
|
|
35
|
-
descriptor.responseHeaders?.prepare?.(headers,
|
|
50
|
+
descriptor.responseHeaders?.prepare?.(headers, {
|
|
51
|
+
...options,
|
|
52
|
+
url,
|
|
53
|
+
response: upstreamResponse
|
|
54
|
+
});
|
|
36
55
|
options.requestContext.consumeStorefrontResponseHeaders(headers);
|
|
37
56
|
return new Response(upstreamResponse.body, {
|
|
38
57
|
status: upstreamResponse.status,
|
|
@@ -52,19 +71,26 @@ function createProxyErrorResponse(error, status, formatError) {
|
|
|
52
71
|
const message = error instanceof Error ? error.message : "Internal proxy error";
|
|
53
72
|
return new Response(JSON.stringify(formatError(message)), {
|
|
54
73
|
status,
|
|
55
|
-
headers: {
|
|
74
|
+
headers: {
|
|
75
|
+
"content-type": "application/json",
|
|
76
|
+
"cache-control": PROXY_ERROR_CACHE_CONTROL
|
|
77
|
+
}
|
|
56
78
|
});
|
|
57
79
|
}
|
|
58
|
-
function createProxyRequestHeaders(descriptor,
|
|
59
|
-
const {
|
|
80
|
+
function createProxyRequestHeaders(descriptor, options) {
|
|
81
|
+
const { request, requestContext } = options;
|
|
82
|
+
const { allow, deny, prepare } = descriptor.requestHeaders;
|
|
60
83
|
const headers = allow ? new Headers(extractHeaders((key) => request.headers.get(key), allow)) : new Headers(request.headers);
|
|
84
|
+
requestContext.applyStorefrontRequestHeaders(headers);
|
|
61
85
|
for (const header of deny ?? []) headers.delete(header);
|
|
86
|
+
prepare?.(headers, options);
|
|
62
87
|
return headers;
|
|
63
88
|
}
|
|
64
89
|
function createProxyResponseHeaders(upstreamHeaders) {
|
|
65
90
|
const headers = new Headers(upstreamHeaders);
|
|
66
91
|
headers.delete("content-encoding");
|
|
67
92
|
headers.delete("content-length");
|
|
93
|
+
headers.delete("server-timing");
|
|
68
94
|
return headers;
|
|
69
95
|
}
|
|
70
96
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/proxy.ts"],"sourcesContent":["import { extractHeaders } from \"../../headers\";\nimport { getLogger } from \"../../logging\";\nimport type { HydrogenRouteInterceptor, HydrogenRoutesOptions } from \"../route-types\";\n\nconst PROXY_TIMEOUT_MS = 30_000;\n\ntype PrepareHeaders = (headers: Headers
|
|
1
|
+
{"version":3,"file":"proxy.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/proxy.ts"],"sourcesContent":["import { extractHeaders } from \"../../headers\";\nimport { getLogger } from \"../../logging\";\nimport type { HydrogenRouteInterceptor, HydrogenRoutesOptions } from \"../route-types\";\n\nconst PROXY_TIMEOUT_MS = 30_000;\n\n// Proxy errors are transient and may be buyer-specific: never cache them.\nconst PROXY_ERROR_CACHE_CONTROL = \"no-store\";\n\ntype ProxyHeaderContext = HydrogenRoutesOptions & { url: URL };\n\ntype PrepareHeaders<ExtraContext extends object = object> = (\n headers: Headers,\n context: ProxyHeaderContext & ExtraContext,\n) => void;\n\ntype ProxyRequestHeaderOptions = (\n | { allow: readonly string[]; deny?: never }\n | { allow?: never; deny: readonly string[] }\n) & {\n prepare?: PrepareHeaders;\n};\n\ntype ProxyResponseHeaderOptions = {\n prepare?: PrepareHeaders<{ response: Response }>;\n};\n\ntype ProxyDescriptor = {\n match: RegExp;\n methods?: readonly string[];\n formatError?: (message: string) => unknown;\n redirect?: RequestRedirect;\n scope: string;\n rewritePathname?: (pathname: string) => string;\n requestHeaders: ProxyRequestHeaderOptions;\n responseHeaders?: ProxyResponseHeaderOptions;\n};\n\nexport function createProxyInterceptor(descriptor: ProxyDescriptor): HydrogenRouteInterceptor {\n const log = getLogger(descriptor.scope);\n const formatError = descriptor.formatError ?? defaultFormatError;\n\n return (url, options) => {\n const { request, storefrontClient } = options;\n if (!descriptor.match.test(url.pathname)) return null;\n\n // Disable JSONP requests for security:\n if (url.searchParams.has(\"callback\")) {\n return Promise.resolve(\n new Response(JSON.stringify(formatError(\"JSONP requests are not supported\")), {\n status: 400,\n headers: {\n \"content-type\": \"application/json\",\n \"cache-control\": PROXY_ERROR_CACHE_CONTROL,\n },\n }),\n );\n }\n\n if (descriptor.methods && !descriptor.methods.includes(request.method)) {\n // Method not allowed. Shape the body via formatError, like other errors.\n return Promise.resolve(\n new Response(JSON.stringify(formatError(\"Method Not Allowed\")), {\n status: 405,\n headers: {\n allow: descriptor.methods.join(\", \"),\n \"content-type\": \"application/json\",\n \"cache-control\": PROXY_ERROR_CACHE_CONTROL,\n },\n }),\n );\n }\n\n let upstreamUrl: URL;\n let init: RequestInit & { duplex?: \"half\" };\n try {\n const upstreamPathname = descriptor.rewritePathname?.(url.pathname) ?? url.pathname;\n upstreamUrl = new URL(upstreamPathname + url.search, storefrontClient.storeUrl);\n\n init = {\n method: request.method,\n body: request.body,\n headers: createProxyRequestHeaders(descriptor, { ...options, url }),\n signal: AbortSignal.timeout(PROXY_TIMEOUT_MS),\n redirect: descriptor.redirect ?? \"manual\",\n };\n\n // Node's fetch requires this when forwarding a streaming request body.\n if (request.body) init.duplex = \"half\";\n } catch (error) {\n log.error(\"request failed\", { error });\n return Promise.resolve(createProxyErrorResponse(error, 500, formatError));\n }\n\n return fetch(upstreamUrl, init)\n .then((upstreamResponse) => {\n const headers = createProxyResponseHeaders(upstreamResponse.headers);\n descriptor.responseHeaders?.prepare?.(headers, {\n ...options,\n url,\n response: upstreamResponse,\n });\n options.requestContext.consumeStorefrontResponseHeaders(headers);\n\n return new Response(upstreamResponse.body, {\n status: upstreamResponse.status,\n statusText: upstreamResponse.statusText,\n headers,\n });\n })\n .catch((error) => {\n log.error(\"request failed\", { error });\n return createProxyErrorResponse(error, 502, formatError);\n });\n };\n}\n\nfunction defaultFormatError(message: string): { error: string } {\n return { error: message };\n}\n\nfunction createProxyErrorResponse(\n error: unknown,\n status: number,\n formatError: (message: string) => unknown,\n): Response {\n const message = error instanceof Error ? error.message : \"Internal proxy error\";\n return new Response(JSON.stringify(formatError(message)), {\n status,\n headers: {\n \"content-type\": \"application/json\",\n \"cache-control\": PROXY_ERROR_CACHE_CONTROL,\n },\n });\n}\n\nfunction createProxyRequestHeaders(\n descriptor: ProxyDescriptor,\n options: ProxyHeaderContext,\n): Headers {\n const { request, requestContext } = options;\n const { allow, deny, prepare } = descriptor.requestHeaders;\n const headers = allow\n ? new Headers(extractHeaders((key) => request.headers.get(key), allow))\n : new Headers(request.headers);\n\n requestContext.applyStorefrontRequestHeaders(headers);\n\n for (const header of deny ?? []) headers.delete(header);\n prepare?.(headers, options);\n\n return headers;\n}\n\nexport function createProxyResponseHeaders(upstreamHeaders: Headers): Headers {\n const headers = new Headers(upstreamHeaders);\n headers.delete(\"content-encoding\");\n headers.delete(\"content-length\");\n headers.delete(\"server-timing\");\n return headers;\n}\n"],"mappings":";;;;AAIA,MAAM,mBAAmB;AAGzB,MAAM,4BAA4B;AA+BlC,SAAgB,uBAAuB,YAAuD;CAC5F,MAAM,MAAM,UAAU,WAAW,MAAM;CACvC,MAAM,cAAc,WAAW,eAAe;AAE9C,SAAQ,KAAK,YAAY;EACvB,MAAM,EAAE,SAAS,qBAAqB;AACtC,MAAI,CAAC,WAAW,MAAM,KAAK,IAAI,SAAS,CAAE,QAAO;AAGjD,MAAI,IAAI,aAAa,IAAI,WAAW,CAClC,QAAO,QAAQ,QACb,IAAI,SAAS,KAAK,UAAU,YAAY,mCAAmC,CAAC,EAAE;GAC5E,QAAQ;GACR,SAAS;IACP,gBAAgB;IAChB,iBAAiB;IAClB;GACF,CAAC,CACH;AAGH,MAAI,WAAW,WAAW,CAAC,WAAW,QAAQ,SAAS,QAAQ,OAAO,CAEpE,QAAO,QAAQ,QACb,IAAI,SAAS,KAAK,UAAU,YAAY,qBAAqB,CAAC,EAAE;GAC9D,QAAQ;GACR,SAAS;IACP,OAAO,WAAW,QAAQ,KAAK,KAAK;IACpC,gBAAgB;IAChB,iBAAiB;IAClB;GACF,CAAC,CACH;EAGH,IAAI;EACJ,IAAI;AACJ,MAAI;GACF,MAAM,mBAAmB,WAAW,kBAAkB,IAAI,SAAS,IAAI,IAAI;AAC3E,iBAAc,IAAI,IAAI,mBAAmB,IAAI,QAAQ,iBAAiB,SAAS;AAE/E,UAAO;IACL,QAAQ,QAAQ;IAChB,MAAM,QAAQ;IACd,SAAS,0BAA0B,YAAY;KAAE,GAAG;KAAS;KAAK,CAAC;IACnE,QAAQ,YAAY,QAAQ,iBAAiB;IAC7C,UAAU,WAAW,YAAY;IAClC;AAGD,OAAI,QAAQ,KAAM,MAAK,SAAS;WACzB,OAAO;AACd,OAAI,MAAM,kBAAkB,EAAE,OAAO,CAAC;AACtC,UAAO,QAAQ,QAAQ,yBAAyB,OAAO,KAAK,YAAY,CAAC;;AAG3E,SAAO,MAAM,aAAa,KAAK,CAC5B,MAAM,qBAAqB;GAC1B,MAAM,UAAU,2BAA2B,iBAAiB,QAAQ;AACpE,cAAW,iBAAiB,UAAU,SAAS;IAC7C,GAAG;IACH;IACA,UAAU;IACX,CAAC;AACF,WAAQ,eAAe,iCAAiC,QAAQ;AAEhE,UAAO,IAAI,SAAS,iBAAiB,MAAM;IACzC,QAAQ,iBAAiB;IACzB,YAAY,iBAAiB;IAC7B;IACD,CAAC;IACF,CACD,OAAO,UAAU;AAChB,OAAI,MAAM,kBAAkB,EAAE,OAAO,CAAC;AACtC,UAAO,yBAAyB,OAAO,KAAK,YAAY;IACxD;;;AAIR,SAAS,mBAAmB,SAAoC;AAC9D,QAAO,EAAE,OAAO,SAAS;;AAG3B,SAAS,yBACP,OACA,QACA,aACU;CACV,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,QAAO,IAAI,SAAS,KAAK,UAAU,YAAY,QAAQ,CAAC,EAAE;EACxD;EACA,SAAS;GACP,gBAAgB;GAChB,iBAAiB;GAClB;EACF,CAAC;;AAGJ,SAAS,0BACP,YACA,SACS;CACT,MAAM,EAAE,SAAS,mBAAmB;CACpC,MAAM,EAAE,OAAO,MAAM,YAAY,WAAW;CAC5C,MAAM,UAAU,QACZ,IAAI,QAAQ,gBAAgB,QAAQ,QAAQ,QAAQ,IAAI,IAAI,EAAE,MAAM,CAAC,GACrE,IAAI,QAAQ,QAAQ,QAAQ;AAEhC,gBAAe,8BAA8B,QAAQ;AAErD,MAAK,MAAM,UAAU,QAAQ,EAAE,CAAE,SAAQ,OAAO,OAAO;AACvD,WAAU,SAAS,QAAQ;AAE3B,QAAO;;AAGT,SAAgB,2BAA2B,iBAAmC;CAC5E,MAAM,UAAU,IAAI,QAAQ,gBAAgB;AAC5C,SAAQ,OAAO,mBAAmB;AAClC,SAAQ,OAAO,iBAAiB;AAChC,SAAQ,OAAO,gBAAgB;AAC/B,QAAO"}
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
+
import { getSameOriginPath } from "../../url.mjs";
|
|
2
|
+
|
|
1
3
|
//#region src/core/request-routing/interceptors/query-param-redirect.ts
|
|
2
4
|
function handleQueryParamRedirect(request) {
|
|
3
5
|
const url = new URL(request.url);
|
|
4
|
-
const
|
|
5
|
-
if (!
|
|
6
|
-
if (!isSameOrigin(request.url, redirectTo)) return null;
|
|
6
|
+
const location = getSameOriginPath(url.searchParams.get("return_to") || url.searchParams.get("redirect"), url.origin);
|
|
7
|
+
if (!location) return null;
|
|
7
8
|
return new Response(null, {
|
|
8
9
|
status: 301,
|
|
9
|
-
headers: { location
|
|
10
|
+
headers: { location }
|
|
10
11
|
});
|
|
11
12
|
}
|
|
12
|
-
function isSameOrigin(requestUrl, redirectUrl) {
|
|
13
|
-
try {
|
|
14
|
-
return new URL(requestUrl).origin === new URL(redirectUrl, requestUrl).origin;
|
|
15
|
-
} catch {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
13
|
|
|
20
14
|
//#endregion
|
|
21
15
|
export { handleQueryParamRedirect };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-param-redirect.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/query-param-redirect.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"query-param-redirect.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/query-param-redirect.ts"],"sourcesContent":["import { getSameOriginPath } from \"../../url\";\n\nexport function handleQueryParamRedirect(request: Request): Response | null {\n const url = new URL(request.url);\n const location = getSameOriginPath(\n url.searchParams.get(\"return_to\") || url.searchParams.get(\"redirect\"),\n url.origin,\n );\n\n if (!location) return null;\n\n return new Response(null, {\n status: 301,\n headers: { location },\n });\n}\n"],"mappings":";;;AAEA,SAAgB,yBAAyB,SAAmC;CAC1E,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;CAChC,MAAM,WAAW,kBACf,IAAI,aAAa,IAAI,YAAY,IAAI,IAAI,aAAa,IAAI,WAAW,EACrE,IAAI,OACL;AAED,KAAI,CAAC,SAAU,QAAO;AAEtB,QAAO,IAAI,SAAS,MAAM;EACxB,QAAQ;EACR,SAAS,EAAE,UAAU;EACtB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SFAPI_REQUEST_HEADER_ALLOWLIST, STOREFRONT_BUYER_IP_HEADER, STOREFRONT_ID_HEADER } from "../../headers.mjs";
|
|
2
1
|
import { SFAPI_RE } from "../../url.mjs";
|
|
2
|
+
import { CONSENT_MANAGEMENT_HEADER, SFAPI_REQUEST_HEADER_ALLOWLIST, STOREFRONT_BUYER_IP_HEADER, STOREFRONT_ID_HEADER } from "../../headers.mjs";
|
|
3
3
|
import { createProxyInterceptor } from "./proxy.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/core/request-routing/interceptors/sfapi-proxy.ts
|
|
@@ -19,8 +19,26 @@ const handleSfapiProxy = createProxyInterceptor({
|
|
|
19
19
|
if (storefrontClient.type === "private") throw new Error("requestContext.buyerIp is required for private Storefront API proxy requests");
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
|
+
responseHeaders: { prepare(headers, { request, requestContext, url, response }) {
|
|
23
|
+
if (request.headers.has("Shopify-Storefront-Consent-Management") && response.ok) {
|
|
24
|
+
const cookies = (requestContext.cookie ?? "").split(";");
|
|
25
|
+
const legacyNames = ["_shopify_y", "_shopify_s"].filter((name) => cookies.some((cookie) => cookie.trim().startsWith(`${name}=`)));
|
|
26
|
+
if (legacyNames.length) expireLegacyCookies(headers, legacyNames, url.hostname);
|
|
27
|
+
}
|
|
28
|
+
} },
|
|
22
29
|
scope: "sfapi-proxy"
|
|
23
30
|
});
|
|
31
|
+
function expireLegacyCookies(headers, legacyNames, hostname) {
|
|
32
|
+
const domains = [""];
|
|
33
|
+
if (!hostname.includes(":") && !/^[\d.]+$/.test(hostname)) {
|
|
34
|
+
const labels = hostname.split(".");
|
|
35
|
+
while (labels.length > 1) {
|
|
36
|
+
domains.push(labels.join("."));
|
|
37
|
+
labels.shift();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (const name of legacyNames) for (const domain of domains) headers.append("set-cookie", `${name}=; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax${domain ? `; Domain=${domain}` : ""}`);
|
|
41
|
+
}
|
|
24
42
|
|
|
25
43
|
//#endregion
|
|
26
44
|
export { handleSfapiProxy };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sfapi-proxy.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/sfapi-proxy.ts"],"sourcesContent":["import {\n SFAPI_REQUEST_HEADER_ALLOWLIST,\n STOREFRONT_BUYER_IP_HEADER,\n STOREFRONT_ID_HEADER,\n} from \"../../headers\";\nimport { SFAPI_RE } from \"../../url\";\nimport { createProxyInterceptor } from \"./proxy\";\n\nexport const handleSfapiProxy = createProxyInterceptor({\n match: SFAPI_RE,\n requestHeaders: {\n allow: SFAPI_REQUEST_HEADER_ALLOWLIST,\n prepare: (headers, { requestContext, storefrontClient }) => {\n headers.delete(STOREFRONT_ID_HEADER);\n if (storefrontClient.storefrontId) {\n headers.set(STOREFRONT_ID_HEADER, storefrontClient.storefrontId);\n }\n\n headers.delete(STOREFRONT_BUYER_IP_HEADER);\n const { buyerIp } = requestContext;\n if (buyerIp) {\n headers.set(STOREFRONT_BUYER_IP_HEADER, buyerIp);\n return;\n }\n if (storefrontClient.type === \"private\") {\n throw new Error(\n \"requestContext.buyerIp is required for private Storefront API proxy requests\",\n );\n }\n },\n },\n scope: \"sfapi-proxy\",\n});\n"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"sfapi-proxy.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/sfapi-proxy.ts"],"sourcesContent":["import {\n CONSENT_MANAGEMENT_HEADER,\n SFAPI_REQUEST_HEADER_ALLOWLIST,\n STOREFRONT_BUYER_IP_HEADER,\n STOREFRONT_ID_HEADER,\n} from \"../../headers\";\nimport { SFAPI_RE } from \"../../url\";\nimport { createProxyInterceptor } from \"./proxy\";\n\nexport const handleSfapiProxy = createProxyInterceptor({\n match: SFAPI_RE,\n requestHeaders: {\n allow: SFAPI_REQUEST_HEADER_ALLOWLIST,\n prepare: (headers, { requestContext, storefrontClient }) => {\n headers.delete(STOREFRONT_ID_HEADER);\n if (storefrontClient.storefrontId) {\n headers.set(STOREFRONT_ID_HEADER, storefrontClient.storefrontId);\n }\n\n headers.delete(STOREFRONT_BUYER_IP_HEADER);\n const { buyerIp } = requestContext;\n if (buyerIp) {\n headers.set(STOREFRONT_BUYER_IP_HEADER, buyerIp);\n return;\n }\n if (storefrontClient.type === \"private\") {\n throw new Error(\n \"requestContext.buyerIp is required for private Storefront API proxy requests\",\n );\n }\n },\n },\n responseHeaders: {\n prepare(headers, { request, requestContext, url, response }) {\n if (request.headers.has(CONSENT_MANAGEMENT_HEADER) && response.ok) {\n const cookies = (requestContext.cookie ?? \"\").split(\";\");\n const legacyNames = [\"_shopify_y\", \"_shopify_s\"].filter((name) =>\n cookies.some((cookie) => cookie.trim().startsWith(`${name}=`)),\n );\n if (legacyNames.length) {\n expireLegacyCookies(headers, legacyNames, url.hostname);\n }\n }\n },\n },\n scope: \"sfapi-proxy\",\n});\n\nfunction expireLegacyCookies(headers: Headers, legacyNames: string[], hostname: string): void {\n // Cookie requests omit domain attributes. Expire host-only cookies and\n // each possible domain scope used by older storefronts. Browsers reject\n // public suffixes (such as co.uk), so no public suffix list is needed here.\n const domains = [\"\"];\n if (!hostname.includes(\":\") && !/^[\\d.]+$/.test(hostname)) {\n const labels = hostname.split(\".\");\n while (labels.length > 1) {\n domains.push(labels.join(\".\"));\n labels.shift();\n }\n }\n\n for (const name of legacyNames) {\n for (const domain of domains) {\n headers.append(\n \"set-cookie\",\n `${name}=; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax${domain ? `; Domain=${domain}` : \"\"}`,\n );\n }\n }\n}\n"],"mappings":";;;;;AASA,MAAa,mBAAmB,uBAAuB;CACrD,OAAO;CACP,gBAAgB;EACd,OAAO;EACP,UAAU,SAAS,EAAE,gBAAgB,uBAAuB;AAC1D,WAAQ,OAAO,qBAAqB;AACpC,OAAI,iBAAiB,aACnB,SAAQ,IAAI,sBAAsB,iBAAiB,aAAa;AAGlE,WAAQ,OAAO,2BAA2B;GAC1C,MAAM,EAAE,YAAY;AACpB,OAAI,SAAS;AACX,YAAQ,IAAI,4BAA4B,QAAQ;AAChD;;AAEF,OAAI,iBAAiB,SAAS,UAC5B,OAAM,IAAI,MACR,+EACD;;EAGN;CACD,iBAAiB,EACf,QAAQ,SAAS,EAAE,SAAS,gBAAgB,KAAK,YAAY;AAC3D,MAAI,QAAQ,QAAQ,4CAA8B,IAAI,SAAS,IAAI;GACjE,MAAM,WAAW,eAAe,UAAU,IAAI,MAAM,IAAI;GACxD,MAAM,cAAc,CAAC,cAAc,aAAa,CAAC,QAAQ,SACvD,QAAQ,MAAM,WAAW,OAAO,MAAM,CAAC,WAAW,GAAG,KAAK,GAAG,CAAC,CAC/D;AACD,OAAI,YAAY,OACd,qBAAoB,SAAS,aAAa,IAAI,SAAS;;IAI9D;CACD,OAAO;CACR,CAAC;AAEF,SAAS,oBAAoB,SAAkB,aAAuB,UAAwB;CAI5F,MAAM,UAAU,CAAC,GAAG;AACpB,KAAI,CAAC,SAAS,SAAS,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE;EACzD,MAAM,SAAS,SAAS,MAAM,IAAI;AAClC,SAAO,OAAO,SAAS,GAAG;AACxB,WAAQ,KAAK,OAAO,KAAK,IAAI,CAAC;AAC9B,UAAO,OAAO;;;AAIlB,MAAK,MAAM,QAAQ,YACjB,MAAK,MAAM,UAAU,QACnB,SAAQ,OACN,cACA,GAAG,KAAK,2EAA2E,SAAS,YAAY,WAAW,KACpH"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { UCP_MCP_RE } from "../../url.mjs";
|
|
2
|
+
import { PROXY_REQUEST_HEADER_DENYLIST } from "../../headers.mjs";
|
|
3
|
+
import { createProxyInterceptor } from "./proxy.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/core/request-routing/interceptors/ucp-mcp-proxy.ts
|
|
6
|
+
const JSON_RPC_INTERNAL_ERROR = -32603;
|
|
7
|
+
const RESPONSE_STATE_REASON = "ucp request";
|
|
8
|
+
/**
|
|
9
|
+
* Caller-authenticated UCP pass-through. The caller owns both the
|
|
10
|
+
* Authorization header and the UCP agent profile in its request body.
|
|
11
|
+
*/
|
|
12
|
+
const proxyUcpMcpRequest = createProxyInterceptor({
|
|
13
|
+
match: UCP_MCP_RE,
|
|
14
|
+
methods: ["POST"],
|
|
15
|
+
requestHeaders: { deny: PROXY_REQUEST_HEADER_DENYLIST },
|
|
16
|
+
formatError: (message) => ({
|
|
17
|
+
jsonrpc: "2.0",
|
|
18
|
+
error: {
|
|
19
|
+
code: JSON_RPC_INTERNAL_ERROR,
|
|
20
|
+
message
|
|
21
|
+
},
|
|
22
|
+
id: null
|
|
23
|
+
}),
|
|
24
|
+
scope: "ucp-mcp-proxy"
|
|
25
|
+
});
|
|
26
|
+
const handleUcpMcpProxy = (url, options) => {
|
|
27
|
+
if (!UCP_MCP_RE.test(url.pathname)) return null;
|
|
28
|
+
options.requestContext.markResponseAsPersonalized(RESPONSE_STATE_REASON);
|
|
29
|
+
options.requestContext.markResponseAsSessionEstablishing(RESPONSE_STATE_REASON);
|
|
30
|
+
return proxyUcpMcpRequest(url, options);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { handleUcpMcpProxy };
|
|
35
|
+
//# sourceMappingURL=ucp-mcp-proxy.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ucp-mcp-proxy.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/ucp-mcp-proxy.ts"],"sourcesContent":["import { PROXY_REQUEST_HEADER_DENYLIST } from \"../../headers\";\nimport { UCP_MCP_RE } from \"../../url\";\nimport type { HydrogenRouteInterceptor } from \"../route-types\";\nimport { createProxyInterceptor } from \"./proxy\";\n\nconst JSON_RPC_INTERNAL_ERROR = -32603;\n\n// Traceability reason recorded when marking UCP MCP response state.\nconst RESPONSE_STATE_REASON = \"ucp request\";\n\n/**\n * Caller-authenticated UCP pass-through. The caller owns both the\n * Authorization header and the UCP agent profile in its request body.\n */\nconst proxyUcpMcpRequest = createProxyInterceptor({\n match: UCP_MCP_RE,\n methods: [\"POST\"],\n requestHeaders: { deny: PROXY_REQUEST_HEADER_DENYLIST },\n formatError: (message) => ({\n jsonrpc: \"2.0\",\n error: { code: JSON_RPC_INTERNAL_ERROR, message },\n id: null,\n }),\n scope: \"ucp-mcp-proxy\",\n});\n\nexport const handleUcpMcpProxy: HydrogenRouteInterceptor = (url, options) => {\n if (!UCP_MCP_RE.test(url.pathname)) return null;\n\n options.requestContext.markResponseAsPersonalized(RESPONSE_STATE_REASON);\n // UCP MCP is a sanctioned session-establishing endpoint: let the store's\n // session cookie return on a cold agent request, staying within the response\n // state gating rather than bypassing it.\n options.requestContext.markResponseAsSessionEstablishing(RESPONSE_STATE_REASON);\n return proxyUcpMcpRequest(url, options);\n};\n"],"mappings":";;;;;AAKA,MAAM,0BAA0B;AAGhC,MAAM,wBAAwB;;;;;AAM9B,MAAM,qBAAqB,uBAAuB;CAChD,OAAO;CACP,SAAS,CAAC,OAAO;CACjB,gBAAgB,EAAE,MAAM,+BAA+B;CACvD,cAAc,aAAa;EACzB,SAAS;EACT,OAAO;GAAE,MAAM;GAAyB;GAAS;EACjD,IAAI;EACL;CACD,OAAO;CACR,CAAC;AAEF,MAAa,qBAA+C,KAAK,YAAY;AAC3E,KAAI,CAAC,WAAW,KAAK,IAAI,SAAS,CAAE,QAAO;AAE3C,SAAQ,eAAe,2BAA2B,sBAAsB;AAIxE,SAAQ,eAAe,kCAAkC,sBAAsB;AAC/E,QAAO,mBAAmB,KAAK,QAAQ"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PROXY_REQUEST_HEADER_DENYLIST } from "../../headers.mjs";
|
|
2
1
|
import { WELL_KNOWN_RE } from "../../url.mjs";
|
|
2
|
+
import { PROXY_REQUEST_HEADER_DENYLIST } from "../../headers.mjs";
|
|
3
3
|
import { createProxyInterceptor } from "./proxy.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/core/request-routing/interceptors/well-known.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { asInlineScript } from "./utils/inline-script.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/core/shopify-scripts/analytics.ts
|
|
4
|
-
const initializeShopifyAnalyticsBus = (scriptData) => decodeURIComponent("(function()%7Blet%20e%3D%7Btrace%3A%60debug%60%2Cdebug%3A%60debug%60%2Cinfo%3A%60info%60%2Cwarn%3A%60warn%60%2Cerror%3A%60error%60%2Cfatal%3A%60error%60%7D%3Bfunction%20t(e%2Ct)%7Breturn%60%5Bhydrogen%3A%24%7Be%7D%3A%24%7Bt%7D%5D%60%7Dfunction%20n(n%2Cr%2Ci)%7Blet%7Bscope%3Aa%2Cerror%3Ao%2C...s%7D%3Di%3F%3F%7B%7D%2Cc%3D%5Ba%3F%60%24%7Bt(n%2Ca)%7D%20%24%7Br%7D%60%3Ar%5D%3Bo!%3D%3Dvoid%200%26%26c.push(o)%2CObject.keys(s).length%3E0%26%26c.push(s)%2Cconsole%5Be%5Bn%5D%5D(...c)%7Dlet%20r%3D%7Btrace%3A(e%2Ct)%3D%3En(%60trace%60%2Ce%2Ct)%2Cdebug%3A(e%2Ct)%3D%3En(%60debug%60%2Ce%2Ct)%2Cinfo%3A(e%2Ct)%3D%3En(%60info%60%2Ce%2Ct)%2Cwarn%3A(e%2Ct)%3D%3En(%60warn%60%2Ce%2Ct)%2Cerror%3A(e%2Ct)%3D%3En(%60error%60%2Ce%2Ct)%2Cfatal%3A(e%2Ct)%3D%3En(%60fatal%60%2Ce%2Ct)%7D%2Ci%3D%60https%3A%2F%2Fcdn.shopify.com%60%3B%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%3Blet%20a%3D%60visitorConsentCollected%60%3Bfunction%
|
|
4
|
+
const initializeShopifyAnalyticsBus = (scriptData) => decodeURIComponent("(function()%7Blet%20e%3D%7Btrace%3A%60debug%60%2Cdebug%3A%60debug%60%2Cinfo%3A%60info%60%2Cwarn%3A%60warn%60%2Cerror%3A%60error%60%2Cfatal%3A%60error%60%7D%3Bfunction%20t(e%2Ct)%7Breturn%60%5Bhydrogen%3A%24%7Be%7D%3A%24%7Bt%7D%5D%60%7Dfunction%20n(n%2Cr%2Ci)%7Blet%7Bscope%3Aa%2Cerror%3Ao%2C...s%7D%3Di%3F%3F%7B%7D%2Cc%3D%5Ba%3F%60%24%7Bt(n%2Ca)%7D%20%24%7Br%7D%60%3Ar%5D%3Bo!%3D%3Dvoid%200%26%26c.push(o)%2CObject.keys(s).length%3E0%26%26c.push(s)%2Cconsole%5Be%5Bn%5D%5D(...c)%7Dlet%20r%3D%7Btrace%3A(e%2Ct)%3D%3En(%60trace%60%2Ce%2Ct)%2Cdebug%3A(e%2Ct)%3D%3En(%60debug%60%2Ce%2Ct)%2Cinfo%3A(e%2Ct)%3D%3En(%60info%60%2Ce%2Ct)%2Cwarn%3A(e%2Ct)%3D%3En(%60warn%60%2Ce%2Ct)%2Cerror%3A(e%2Ct)%3D%3En(%60error%60%2Ce%2Ct)%2Cfatal%3A(e%2Ct)%3D%3En(%60fatal%60%2Ce%2Ct)%7D%2Ci%3D%60https%3A%2F%2Fcdn.shopify.com%60%3B%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%3Blet%20a%3D%60consentTrackingApiLoaded%60%2Co%3D%60visitorConsentCollected%60%3Bfunction%20s()%7Bif(typeof%20window%3E%60u%60)return%3Blet%20e%3Dwindow%3Breturn%20e.Shopify%3F%3F%3D%7B%7D%7Dfunction%20c(e)%7Breturn%20typeof%20e%3D%3D%60object%60%26%26!!e%26%26!Array.isArray(e)%7Dlet%20l%3DSymbol.for(%60shopify.hydrogen.custom-consent%60)%3Bfunction%20u(e)%7Blet%20t%3D(typeof%20window%3E%60u%60%3Fvoid%200%3Awindow.Shopify%3F.customerPrivacy)%3F.__internal%2Cn%3D%7BgenerateFallback%3A!0%2Ctag%3Ae%7D%3Breturn%7BuniqueToken%3At%3F.uniqueToken%3F.(n)%3F%3F%60%60%2CvisitToken%3At%3F.visitToken%3F.(n)%3F%3F%60%60%7D%7Dfunction%20d(e%2Ct)%7Blet%20n%3De.subscriptions.get(t.event)%3Bif(!n%3F.size)%7Be.nextReplaySequence%3DMath.max(e.nextReplaySequence%2Ct.sequence%2B1)%3Breturn%7Dfor(let%20i%20of%20n)try%7Bi(t.payload%2Ce.context)%7Dcatch(t)%7Br.error(%60error%20in%20analytics%20destination%20%22%24%7Be.name%7D%22%60%2C%7Bscope%3A%60analytics%60%2Cerror%3At%7D)%7De.nextReplaySequence%3DMath.max(e.nextReplaySequence%2Ct.sequence%2B1)%7Dfunction%20f(e)%7Blet%20t%3D0%2Cn%3D!0%2Ci%3D%5B%5D%2Ca%3Dnew%20Set%2Co%3Dnew%20Set%3Bfunction%20s(t%3D!1)%7Bif(!e.canTrack())%7Bt%26%26(i.length%3D0%2Cn%3D!1)%3Breturn%7Dn%3D!0%3Bfor(let%20e%20of%20a)for(let%20t%20of%20i)t.sequence%3Ce.nextReplaySequence%7C%7Cd(e%2Ct)%7Dfunction%20c(t)%7Bif(o.has(t.name))return%20r.warn(%60analytics%20destination%20%22%24%7Bt.name%7D%22%20is%20already%20registered%60%2C%7Bscope%3A%60analytics%60%7D)%2C()%3D%3E%7B%7D%3Bo.add(t.name)%3Blet%20n%3D%60hydrogen%3A%24%7Bt.name%7D%60%2Ci%3D%7Bname%3At.name%2Ccontext%3A%7BgetTrackingValues%3A()%3D%3Ee.canTrack()%3Fu(n)%3A%7BuniqueToken%3A%60%60%2CvisitToken%3A%60%60%7D%7D%2Csubscriptions%3Anew%20Map%2CnextReplaySequence%3A0%7D%2Cc%3D!1%2Cl%3D(t%2Cn)%3D%3E%7Bif(c)return()%3D%3E%7B%7D%3Bif(e.isSupportedEvent%26%26!e.isSupportedEvent(t))return%20e.warnUnsupportedEvent%3F.(t)%2C()%3D%3E%7B%7D%3Blet%20r%3Di.subscriptions.get(t)%3Breturn%20r%7C%7C(r%3Dnew%20Set%2Ci.subscriptions.set(t%2Cr))%2Cr.add(n)%2C()%3D%3E%7Blet%20e%3Di.subscriptions.get(t)%3Be%3F.delete(n)%2Ce%3F.size%3D%3D%3D0%26%26i.subscriptions.delete(t)%7D%7D%2Cd%3D()%3D%3E%7Bc%7C%7C(c%3D!0%2Ca.delete(i)%2Co.delete(t.name)%2Ci.subscriptions.clear()%2Ci.cleanup%3F.())%7D%2Cf%3De%3D%3E%7Bif(c)%7Be%3F.()%3Breturn%7Dtypeof%20e%3D%3D%60function%60%26%26(i.cleanup%3De)%2Ca.add(i)%2Cs()%7D%3Btry%7Blet%20n%3Dt.setup(%7Bsubscribe%3Al%2CgetConfig%3Ae.getConfig%7D)%3Bn%26%26typeof%20n.then%3D%3D%60function%60%3Fn.then(f).catch(e%3D%3E%7Br.error(%60error%20setting%20up%20analytics%20destination%20%22%24%7Bt.name%7D%22%60%2C%7Bscope%3A%60analytics%60%2Cerror%3Ae%7D)%2Cd()%7D)%3Af(n)%7Dcatch(e)%7Br.error(%60error%20setting%20up%20analytics%20destination%20%22%24%7Bt.name%7D%22%60%2C%7Bscope%3A%60analytics%60%2Cerror%3Ae%7D)%2Cd()%7Dreturn%20d%7Dfunction%20l(r%2Co)%7Blet%20s%3D%7Bsequence%3At%2B%2B%2Cevent%3Ar%2Cpayload%3Ao%7D%3Bif(n%26%26(i.push(s)%2Ci.length%3E500%26%26i.shift())%2Ce.canTrack())for(let%20e%20of%20a)d(e%2Cs)%7Dfunction%20f()%7Bi.length%3D0%3Bfor(let%20e%20of%20a)e.subscriptions.clear()%2Ce.cleanup%3F.()%3Ba.clear()%2Co.clear()%7Dreturn%7BaddDestination%3Ac%2ConPublish%3Al%2Creplay%3As%2Cdestroy%3Af%7D%7Dlet%20p%3D%7BPAGE_VIEWED%3A%60page_viewed%60%2CPRODUCT_VIEWED%3A%60product_viewed%60%2CCOLLECTION_VIEWED%3A%60collection_viewed%60%2CCART_VIEWED%3A%60cart_viewed%60%2CSEARCH_VIEWED%3A%60search_viewed%60%2CCART_UPDATED%3A%60cart_updated%60%2CPRODUCT_ADD_TO_CART%3A%60product_added_to_cart%60%2CPRODUCT_REMOVED_FROM_CART%3A%60product_removed_from_cart%60%7D%2Cm%3D%60gid%3A%2F%2Fshopify%2FShop%2F%60%3Bfunction%20h(e)%7Breturn%20e.startsWith(m)%3Fe%3A%60%24%7Bm%7D%24%7Be%7D%60%7Dfunction%20g(e)%7Breturn%20e%3F%7B...e%2CshopId%3Ah(e.shopId)%7D%3Anull%7Dlet%20_%3Dnew%20Set(%5Bp.PAGE_VIEWED%2Cp.PRODUCT_VIEWED%2Cp.COLLECTION_VIEWED%2Cp.CART_VIEWED%2Cp.SEARCH_VIEWED%5D)%2Cv%3Dnew%20Set(Object.values(p))%3Bfunction%20y()%7Bif(!(typeof%20window%3E%60u%60))return%20window.location.href%7Dfunction%20b(e%2Ct)%7Breturn%20Object.prototype.hasOwnProperty.call(e%2Ct)%7Dfunction%20x(e%2Ct)%7Breturn%20c(e)%3Fb(e%2C%60shop%60)%3F%7B...e%2Cshop%3Ag(e.shop)%7D%3A%7B...e%2Cshop%3At%7D%3Ae%7Dfunction%20S(e%2Ct)%7Bif(!_.has(e)%7C%7C!c(t)%7C%7Ctypeof%20t.url%3D%3D%60string%60%26%26t.url.length%3E0)return%20t%3Blet%20n%3Dy()%3Breturn%20n%3F%7B...t%2Curl%3An%7D%3At%7Dfunction%20C()%7Btry%7Blet%20e%3Dwindow.Shopify%3F.customerPrivacy%3Bif(e%3F.consentStatus!%3D%3D%60loaded%60)return!1%3Blet%20t%3De.currentVisitorConsent%3F.()%3Breturn%20c(t)%26%26t.analytics%3D%3D%3D%60no%60%3F!1%3Ae%3F.analyticsProcessingAllowed%3F.()%3F%3F!1%7Dcatch%7Breturn!1%7D%7Dfunction%20w(e)%7Breturn%20typeof%20e%3D%3D%60string%60%26%26v.has(e)%7Dfunction%20T(e)%7Br.warn(%60unsupported%20analytics%20event%20%22%24%7BString(e)%7D%22%60%2C%7Bscope%3A%60analytics%60%7D)%7Dfunction%20E()%7Btry%7Blet%20e%3Dwindow.Shopify%3F.customerPrivacy%3Breturn%20typeof%20e%3F.shouldShowGDPRBanner%3D%3D%60function%60%3Fe.shouldShowGDPRBanner()%3A!0%7Dcatch%7Breturn!0%7D%7Dfunction%20D(e)%7Breturn%20e%3D%3D%3Dvoid%200%3F%7B%7D%3Ae%7Dfunction%20O(e)%7Bif(typeof%20window%3C%60u%60%26%26window.Shopify%3F.analytics)throw%20Error(%60Analytics%20bus%20already%20initialized.%20Only%20one%20instance%20is%20allowed%20per%20page.%60)%3Blet%7Bconsent%3At%2CcustomData%3An%7D%3De%2Ci%3Dt%3F.mode%3D%3D%3D%60default-banner%60%2Cu%3Dt%3F.mode%3D%3D%3D%60custom-banner%60%2Cd%3D!u%26%26!i%2Cp%3Dg(e.shop)%2Cm%3D!1%3Bfunction%20h()%7Breturn%7Bshop%3Ap%2Cconsent%3At%2CcustomData%3An%7D%7Dlet%20_%3Df(%7BcanTrack%3A()%3D%3Ed%26%26C()%2CgetConfig%3Ah%2CisSupportedEvent%3Aw%2CwarnUnsupportedEvent%3AT%7D)%3Bfunction%20v(e%2C...t)%7Bif(m)return%3Bif(!w(e))%7BT(e)%3Breturn%7Dlet%20n%3DS(e%2Cx(D(t%5B0%5D)%2Cp))%3B_.onPublish(e%2Cn)%7Dlet%20y%3Bfunction%20b()%7Bif(typeof%20document%3E%60u%60)return%3Blet%20e%2Ct%3D!1%2Cn%3D()%3D%3E%7Bm%7C%7C(d%3D!0%2C_.replay(!0))%7D%2Cs%3Dasync()%3D%3E%7Bif(!(m%7C%7Cwindow.Shopify%3F.customerPrivacy%3F.consentStatus!%3D%3D%60loaded%60))%7Bif(u)%7Bif(!e%7C%7Ct)return%3Bt%3D!0%3Btry%7Bawait%20e()%2Cn()%7Dcatch(e)%7Br.error(%60custom%20consent%20setup%20failed%60%2C%7Bscope%3A%60consent%60%2Cerror%3Ae%7D)%7Dreturn%7Dif(i%7C%7Cc(window.privacyBanner))%7Bif(t)%7B_.replay()%3Breturn%7Dif(t%3D!0%2CE())%7Bd%3D!1%3Breturn%7Dn()%3Breturn%7D_.replay()%7D%7D%2Cf%3D()%3D%3E%7Bm%7C%7Cu%26%26(s()%2C!d)%7C%7C(t%3D!0%2Cn())%7D%3Bu%26%26Object.defineProperty(A%2Cl%2C%7Bvalue(t)%7Be%3F%3F%3Dt%2Cs()%7D%7D)%2Cdocument.addEventListener(a%2Cs)%2Cdocument.addEventListener(o%2Cf)%2Cs()%2Cy%3D()%3D%3E%7Bdocument.removeEventListener(a%2Cs)%2Cdocument.removeEventListener(o%2Cf)%7D%7Dfunction%20O()%7Bif(typeof%20window%3E%60u%60)return%3Blet%20e%3DA%2Ct%3Ds()%3Bt%26%26(t.analytics%3De)%7Dfunction%20k()%7Bm%3D!0%2C_.destroy()%2Cy%3F.()%2Ctypeof%20window%3C%60u%60%26%26window.Shopify%3F.analytics%3D%3D%3DA%26%26delete%20window.Shopify.analytics%7Dlet%20A%3D%7Bpublish%3Av%2CaddDestination%3A_.addDestination%2CgetConfig%3Ah%7D%3Breturn%20p%3F.shopId%26%26String(p.shopId).endsWith(%60%2F68817551382%60)%26%26r.warn(%60mock%20shop%20detected%3B%20analytics%20will%20not%20work%20properly%60%2C%7Bscope%3A%60analytics%60%7D)%2Cb()%2CO()%2C%7Bbus%3AA%2Cdestroy%3Ak%7D%7Dfunction%20k(e)%7Be%26%26O(e)%7Dk(__SHOPIFY_SCRIPT_DATA__)%7D)()%3B").replace("__SHOPIFY_SCRIPT_DATA__", () => (JSON.stringify(scriptData) ?? "undefined").replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029"));
|
|
5
5
|
function getShopifyAnalyticsConfig({ analytics, consent, shop }) {
|
|
6
6
|
const channel = analytics?.channel ?? "hydrogen";
|
|
7
7
|
return {
|
|
@@ -13,7 +13,7 @@ function getShopifyAnalyticsConfig({ analytics, consent, shop }) {
|
|
|
13
13
|
storefrontId: shop.storefrontId,
|
|
14
14
|
channel
|
|
15
15
|
},
|
|
16
|
-
consent: consent
|
|
16
|
+
consent: consent?.mode ? { mode: consent.mode } : {},
|
|
17
17
|
customData: analytics?.customData
|
|
18
18
|
};
|
|
19
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/analytics.ts"],"sourcesContent":["import initializeShopifyAnalyticsBus from \"../analytics/cdn/bootstrap\" with { type: \"script\" };\nimport type { StorefrontAnalyticsConfig } from \"../analytics/types\";\nimport type { ShopifyScriptTagsOptions } from \"./types\";\nimport { asInlineScript } from \"./utils/inline-script\";\n\nexport function getShopifyAnalyticsConfig({\n analytics,\n consent,\n shop,\n}: Pick<ShopifyScriptTagsOptions, \"analytics\" | \"consent\" | \"shop\">): StorefrontAnalyticsConfig {\n const channel = analytics?.channel ?? \"hydrogen\";\n\n return {\n shop:\n channel === \"headless\"\n ? { shopId: shop.shopId, channel }\n : { shopId: shop.shopId, storefrontId: shop.storefrontId, channel },\n consent: consent
|
|
1
|
+
{"version":3,"file":"analytics.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/analytics.ts"],"sourcesContent":["import initializeShopifyAnalyticsBus from \"../analytics/cdn/bootstrap\" with { type: \"script\" };\nimport type { StorefrontAnalyticsConfig } from \"../analytics/types\";\nimport type { ShopifyScriptTagsOptions } from \"./types\";\nimport { asInlineScript } from \"./utils/inline-script\";\n\nexport function getShopifyAnalyticsConfig({\n analytics,\n consent,\n shop,\n}: Pick<ShopifyScriptTagsOptions, \"analytics\" | \"consent\" | \"shop\">): StorefrontAnalyticsConfig {\n const channel = analytics?.channel ?? \"hydrogen\";\n\n return {\n shop:\n channel === \"headless\"\n ? { shopId: shop.shopId, channel }\n : { shopId: shop.shopId, storefrontId: shop.storefrontId, channel },\n consent: consent?.mode ? { mode: consent.mode } : {},\n customData: analytics?.customData,\n };\n}\n\nexport function getShopifyAnalyticsBusScript(analytics: StorefrontAnalyticsConfig): string {\n return asInlineScript(initializeShopifyAnalyticsBus)(analytics);\n}\n"],"mappings":";;;AAAA,MAAM,iCAA+B,eAAkB,mBAAgB,ioQAAuB,CAAA,QAAA,kCAAA,KAAA,UAAA,WAAA,IAAA,aAAA,QAAA,MAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA;AAK9F,SAAgB,0BAA0B,EACxC,WACA,SACA,QAC8F;CAC9F,MAAM,UAAU,WAAW,WAAW;AAEtC,QAAO;EACL,MACE,YAAY,aACR;GAAE,QAAQ,KAAK;GAAQ;GAAQ,GAC/B;GAAE,QAAQ,KAAK;GAAQ,cAAc,KAAK;GAAc;GAAS;EACvE,SAAS,SAAS,OAAO,EAAE,MAAM,QAAQ,MAAM,GAAG,EAAE;EACpD,YAAY,WAAW;EACxB;;AAGH,SAAgB,6BAA6B,WAA8C;AACzF,QAAO,eAAe,8BAA8B,CAAC,UAAU"}
|
|
@@ -4,7 +4,8 @@ const SHOPIFY_SHOP_APP_ORIGIN = "https://shop.app";
|
|
|
4
4
|
const SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-actions.js`;
|
|
5
5
|
const SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events.js`;
|
|
6
6
|
const SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events-inspector.js`;
|
|
7
|
-
const SHOPIFY_STOREFRONT_WEBMCP_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/webmcp.js`;
|
|
7
|
+
const SHOPIFY_STOREFRONT_WEBMCP_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/storefront/webmcp/webmcp.js`;
|
|
8
|
+
const SHOPIFY_ACCOUNT_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/web-components/account.js`;
|
|
8
9
|
const SHOPIFY_INBOX_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/web-components/agent.js`;
|
|
9
10
|
const SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/analytics/shopify.js`;
|
|
10
11
|
const SHOPIFY_PERF_KIT_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/perf-kit/shopify-perf-kit-spa.min.js?v2`;
|
|
@@ -12,8 +13,9 @@ const SHOPIFY_CONSENT_API_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/consent-t
|
|
|
12
13
|
const SHOPIFY_PRIVACY_BANNER_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/privacy-banner/storefront-banner.js`;
|
|
13
14
|
const SHOPIFY_CONSENT_SCRIPT_ID = "shopify-consent";
|
|
14
15
|
const SHOPIFY_PERF_KIT_SCRIPT_ID = "shopify-perfkit";
|
|
16
|
+
const CONSENT_TRACKING_API_LOADED_EVENT = "consentTrackingApiLoaded";
|
|
15
17
|
const VISITOR_CONSENT_COLLECTED_EVENT = "visitorConsentCollected";
|
|
16
18
|
|
|
17
19
|
//#endregion
|
|
18
|
-
export { SHOPIFY_CDN_ORIGIN, SHOPIFY_CONSENT_API_SCRIPT, SHOPIFY_CONSENT_SCRIPT_ID, SHOPIFY_INBOX_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT_ID, SHOPIFY_PRIVACY_BANNER_SCRIPT, SHOPIFY_SHOP_APP_ORIGIN, SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT, SHOPIFY_STOREFRONT_WEBMCP_SCRIPT, VISITOR_CONSENT_COLLECTED_EVENT };
|
|
20
|
+
export { CONSENT_TRACKING_API_LOADED_EVENT, SHOPIFY_ACCOUNT_SCRIPT, SHOPIFY_CDN_ORIGIN, SHOPIFY_CONSENT_API_SCRIPT, SHOPIFY_CONSENT_SCRIPT_ID, SHOPIFY_INBOX_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT_ID, SHOPIFY_PRIVACY_BANNER_SCRIPT, SHOPIFY_SHOP_APP_ORIGIN, SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT, SHOPIFY_STOREFRONT_WEBMCP_SCRIPT, VISITOR_CONSENT_COLLECTED_EVENT };
|
|
19
21
|
//# sourceMappingURL=constants.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/constants.ts"],"sourcesContent":["export const SHOPIFY_CDN_ORIGIN = \"https://cdn.shopify.com\";\nexport const SHOPIFY_SHOP_APP_ORIGIN = \"https://shop.app\";\nexport const SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-actions.js`;\nexport const SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events.js`;\nexport const SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events-inspector.js`;\nexport const SHOPIFY_STOREFRONT_WEBMCP_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/webmcp.js`;\nexport const SHOPIFY_INBOX_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/web-components/agent.js`;\n\nexport const SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/analytics/shopify.js`;\n\nexport const SHOPIFY_PERF_KIT_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/perf-kit/shopify-perf-kit-spa.min.js?v2`;\nexport const SHOPIFY_CONSENT_API_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js`;\nexport const SHOPIFY_PRIVACY_BANNER_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/privacy-banner/storefront-banner.js`;\n\nexport const SHOPIFY_CONSENT_SCRIPT_ID = \"shopify-consent\";\nexport const SHOPIFY_PERF_KIT_SCRIPT_ID = \"shopify-perfkit\";\n\nexport const VISITOR_CONSENT_COLLECTED_EVENT = \"visitorConsentCollected\";\n"],"mappings":";AAAA,MAAa,qBAAqB;AAClC,MAAa,0BAA0B;AACvC,MAAa,6CAA6C,GAAG,mBAAmB;AAChF,MAAa,4CAA4C,GAAG,mBAAmB;AAC/E,MAAa,sDAAsD,GAAG,mBAAmB;AACzF,MAAa,mCAAmC,GAAG,mBAAmB;AACtE,MAAa,uBAAuB,GAAG,mBAAmB;AAE1D,MAAa,sCAAsC,GAAG,mBAAmB;AAEzE,MAAa,0BAA0B,GAAG,mBAAmB;AAC7D,MAAa,6BAA6B,GAAG,mBAAmB;AAChE,MAAa,gCAAgC,GAAG,mBAAmB;AAEnE,MAAa,4BAA4B;AACzC,MAAa,6BAA6B;AAE1C,MAAa,kCAAkC"}
|
|
1
|
+
{"version":3,"file":"constants.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/constants.ts"],"sourcesContent":["export const SHOPIFY_CDN_ORIGIN = \"https://cdn.shopify.com\";\nexport const SHOPIFY_SHOP_APP_ORIGIN = \"https://shop.app\";\nexport const SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-actions.js`;\nexport const SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events.js`;\nexport const SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events-inspector.js`;\nexport const SHOPIFY_STOREFRONT_WEBMCP_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/storefront/webmcp/webmcp.js`;\nexport const SHOPIFY_ACCOUNT_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/web-components/account.js`;\nexport const SHOPIFY_INBOX_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/web-components/agent.js`;\n\nexport const SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/analytics/shopify.js`;\n\nexport const SHOPIFY_PERF_KIT_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/perf-kit/shopify-perf-kit-spa.min.js?v2`;\nexport const SHOPIFY_CONSENT_API_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js`;\nexport const SHOPIFY_PRIVACY_BANNER_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/privacy-banner/storefront-banner.js`;\n\nexport const SHOPIFY_CONSENT_SCRIPT_ID = \"shopify-consent\";\nexport const SHOPIFY_PERF_KIT_SCRIPT_ID = \"shopify-perfkit\";\n\nexport const CONSENT_TRACKING_API_LOADED_EVENT = \"consentTrackingApiLoaded\";\nexport const VISITOR_CONSENT_COLLECTED_EVENT = \"visitorConsentCollected\";\n"],"mappings":";AAAA,MAAa,qBAAqB;AAClC,MAAa,0BAA0B;AACvC,MAAa,6CAA6C,GAAG,mBAAmB;AAChF,MAAa,4CAA4C,GAAG,mBAAmB;AAC/E,MAAa,sDAAsD,GAAG,mBAAmB;AACzF,MAAa,mCAAmC,GAAG,mBAAmB;AACtE,MAAa,yBAAyB,GAAG,mBAAmB;AAC5D,MAAa,uBAAuB,GAAG,mBAAmB;AAE1D,MAAa,sCAAsC,GAAG,mBAAmB;AAEzE,MAAa,0BAA0B,GAAG,mBAAmB;AAC7D,MAAa,6BAA6B,GAAG,mBAAmB;AAChE,MAAa,gCAAgC,GAAG,mBAAmB;AAEnE,MAAa,4BAA4B;AACzC,MAAa,6BAA6B;AAE1C,MAAa,oCAAoC;AACjD,MAAa,kCAAkC"}
|
|
@@ -73,10 +73,15 @@ function getShopifyGlobalBootstrapScript({ i18n, shop }) {
|
|
|
73
73
|
apiProxyPrefix: SHOPIFY_API_PROXY_PREFIX
|
|
74
74
|
},
|
|
75
75
|
shop: normalizeMyshopifyDomain(shop.myshopifyDomain),
|
|
76
|
-
customerPrivacy: {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
customerPrivacy: { config: {
|
|
77
|
+
isHeadless: true,
|
|
78
|
+
asyncConsent: true,
|
|
79
|
+
asyncVisitorState: true,
|
|
80
|
+
debug: { hydrogen: {
|
|
81
|
+
generation: 3,
|
|
82
|
+
serverTiming: false
|
|
83
|
+
} }
|
|
84
|
+
} }
|
|
80
85
|
};
|
|
81
86
|
return asInlineScript(initializeShopifyGlobal)(config);
|
|
82
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"global.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/global.ts"],"sourcesContent":["import type { ShopifyGlobal } from \"../../globals\";\nimport type { I18nConfig } from \"../request-context\";\nimport {\n matchStandardRouteUrl,\n resolveStandardRouteUrl,\n type ShopifyRouteTemplates,\n} from \"../standard-routes/index\";\nimport { SHOPIFY_API_PROXY_PREFIX, isHydrogenServerHandoffPath } from \"../url\";\nimport initializeShopifyGlobal from \"./global-script\" with { type: \"script\" };\nimport type { ShopifyScriptsI18n } from \"./types\";\nimport type { ShopifyScriptsShop } from \"./types\";\nimport { asInlineScript } from \"./utils/inline-script\";\n\nexport type ShopifyGlobalConfig = {\n country: I18nConfig[\"country\"];\n currency?: NonNullable<ShopifyGlobal[\"currency\"]>;\n locale: Lowercase<I18nConfig[\"language\"]>;\n customerPrivacy: {\n config: NonNullable<ShopifyGlobal[\"customerPrivacy\"][\"config\"]
|
|
1
|
+
{"version":3,"file":"global.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/global.ts"],"sourcesContent":["import type { ShopifyGlobal } from \"../../globals\";\nimport type { I18nConfig } from \"../request-context\";\nimport {\n matchStandardRouteUrl,\n resolveStandardRouteUrl,\n type ShopifyRouteTemplates,\n} from \"../standard-routes/index\";\nimport { SHOPIFY_API_PROXY_PREFIX, isHydrogenServerHandoffPath } from \"../url\";\nimport initializeShopifyGlobal from \"./global-script\" with { type: \"script\" };\nimport type { ShopifyScriptsI18n } from \"./types\";\nimport type { ShopifyScriptsShop } from \"./types\";\nimport { asInlineScript } from \"./utils/inline-script\";\n\nexport type ShopifyGlobalConfig = {\n country: I18nConfig[\"country\"];\n currency?: NonNullable<ShopifyGlobal[\"currency\"]>;\n locale: Lowercase<I18nConfig[\"language\"]>;\n customerPrivacy: {\n config: NonNullable<ShopifyGlobal[\"customerPrivacy\"][\"config\"]> & {\n /** Temporary diagnostic metadata for instrumentation; does not change consent or token behavior. */\n debug: {\n hydrogen: {\n generation: number;\n serverTiming: boolean;\n };\n };\n };\n };\n routes: {\n root: string;\n apiProxyPrefix: string;\n };\n shop: string;\n};\n\nexport type IncompleteCustomerPrivacy = Partial<\n Omit<ShopifyGlobal[\"customerPrivacy\"], \"config\">\n> & {\n config?: Partial<NonNullable<ShopifyGlobal[\"customerPrivacy\"][\"config\"]>>;\n};\n\nexport type IncompleteShopifyGlobal = Partial<Omit<ShopifyGlobal, \"customerPrivacy\" | \"routes\">> & {\n customerPrivacy?: IncompleteCustomerPrivacy;\n routes?: Partial<ShopifyGlobal[\"routes\"]> & Record<string, unknown>;\n [key: string]: unknown;\n};\n\nconst DEFAULT_COUNTRY: ShopifyGlobalConfig[\"country\"] = \"US\";\nconst DEFAULT_LOCALE: ShopifyGlobalConfig[\"locale\"] = \"en\";\nconst DEFAULT_ROUTES_ROOT: ShopifyGlobalConfig[\"routes\"][\"root\"] = \"/\";\n\n/**\n * Returns the browser's `window.Shopify` object, creating it when needed.\n *\n * This is SSR-safe and returns `undefined` outside the browser.\n */\nexport function getShopifyGlobal(): IncompleteShopifyGlobal | undefined {\n if (typeof window === \"undefined\") return undefined;\n\n const shopifyWindow: { Shopify?: IncompleteShopifyGlobal } = window;\n return (shopifyWindow.Shopify ??= {});\n}\n\n/**\n * Configures Shopify runtime routing hooks used by storefront scripts.\n *\n * This is SSR-safe and no-ops outside the browser.\n */\nexport function configureShopifyRouting({\n navigate,\n routes,\n}: {\n navigate?: ShopifyGlobal[\"routes\"][\"navigate\"];\n routes?: ShopifyRouteTemplates;\n}) {\n const shopify = getShopifyGlobal();\n if (!shopify) return;\n\n const getRouteOptions = (url: string) => ({\n baseUrl: window.location.href,\n pathPrefix: shopify.routes?.root,\n routeTemplates: routes ?? {},\n url,\n });\n\n shopify.routes ??= {};\n shopify.routes.match = (url) => matchStandardRouteUrl(getRouteOptions(url));\n shopify.routes.resolve = (url) => resolveStandardRouteUrl(getRouteOptions(url));\n\n const navigateTo = navigate ?? documentNavigate;\n shopify.routes.navigate = (url) => {\n if (shouldHandoff(url)) {\n return documentNavigate(url);\n }\n\n return navigateTo(shopify.routes?.resolve?.(url) ?? url);\n };\n // Deprecated, kept for temporary backwards compat with WebMCP\n shopify.navigate = shopify.routes.navigate;\n}\n\nfunction documentNavigate(url: string): void {\n window.location.assign(url);\n}\n\nfunction shouldHandoff(url: string): boolean {\n try {\n const parsedUrl = new URL(url, window.location.href);\n\n return (\n parsedUrl.origin === window.location.origin && isHydrogenServerHandoffPath(parsedUrl.pathname)\n );\n } catch {\n return false;\n }\n}\n\nfunction getShopifyRoutesRoot(pathPrefix: I18nConfig[\"pathPrefix\"]): string {\n const normalizedPathPrefix = pathPrefix?.trim().replace(/^\\/+/, \"\").replace(/\\/+$/, \"\") ?? \"\";\n\n return normalizedPathPrefix ? `/${normalizedPathPrefix}/` : DEFAULT_ROUTES_ROOT;\n}\n\nfunction normalizeMyshopifyDomain(domain: string): string {\n return domain\n .trim()\n .replace(/^https?:\\/\\//i, \"\")\n .replace(/\\/+$/, \"\");\n}\n\n/**\n * Builds the inline bootstrap script that initializes `window.Shopify` for storefront scripts.\n */\nexport function getShopifyGlobalBootstrapScript({\n i18n,\n shop,\n}: {\n i18n?: ShopifyScriptsI18n;\n shop: ShopifyScriptsShop;\n}): string {\n const config: ShopifyGlobalConfig = {\n country: i18n?.country ?? DEFAULT_COUNTRY,\n ...(i18n?.currency !== undefined ? { currency: { active: i18n.currency.toUpperCase() } } : {}),\n // oxlint-disable-next-line typescript/consistent-type-assertions\n locale: (i18n?.language ?? DEFAULT_LOCALE).toLowerCase() as Lowercase<\n ShopifyGlobalConfig[\"locale\"]\n >,\n routes: {\n root: getShopifyRoutesRoot(i18n?.pathPrefix),\n apiProxyPrefix: SHOPIFY_API_PROXY_PREFIX,\n },\n shop: normalizeMyshopifyDomain(shop.myshopifyDomain),\n customerPrivacy: {\n config: {\n isHeadless: true,\n asyncConsent: true,\n asyncVisitorState: true,\n debug: {\n hydrogen: {\n generation: 3,\n serverTiming: false,\n },\n },\n },\n },\n };\n\n return asInlineScript(initializeShopifyGlobal)(config);\n}\n"],"mappings":";;;;;;AAQA,MAAM,2BAAyB,eAAe,mBAAsB,sUAAS,CAAA,QAAA,kCAAA,KAAA,UAAA,WAAA,IAAA,aAAA,QAAA,MAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA;AAuC7E,MAAM,kBAAkD;AACxD,MAAM,iBAAgD;AACtD,MAAM,sBAA6D;;;;;;AAOnE,SAAgB,mBAAwD;AACtE,KAAI,OAAO,WAAW,YAAa,QAAO;CAE1C,MAAM,gBAAuD;AAC7D,QAAQ,cAAc,YAAY,EAAE;;;;;;;AAQtC,SAAgB,wBAAwB,EACtC,UACA,UAIC;CACD,MAAM,UAAU,kBAAkB;AAClC,KAAI,CAAC,QAAS;CAEd,MAAM,mBAAmB,SAAiB;EACxC,SAAS,OAAO,SAAS;EACzB,YAAY,QAAQ,QAAQ;EAC5B,gBAAgB,UAAU,EAAE;EAC5B;EACD;AAED,SAAQ,WAAW,EAAE;AACrB,SAAQ,OAAO,SAAS,QAAQ,sBAAsB,gBAAgB,IAAI,CAAC;AAC3E,SAAQ,OAAO,WAAW,QAAQ,wBAAwB,gBAAgB,IAAI,CAAC;CAE/E,MAAM,aAAa,YAAY;AAC/B,SAAQ,OAAO,YAAY,QAAQ;AACjC,MAAI,cAAc,IAAI,CACpB,QAAO,iBAAiB,IAAI;AAG9B,SAAO,WAAW,QAAQ,QAAQ,UAAU,IAAI,IAAI,IAAI;;AAG1D,SAAQ,WAAW,QAAQ,OAAO;;AAGpC,SAAS,iBAAiB,KAAmB;AAC3C,QAAO,SAAS,OAAO,IAAI;;AAG7B,SAAS,cAAc,KAAsB;AAC3C,KAAI;EACF,MAAM,YAAY,IAAI,IAAI,KAAK,OAAO,SAAS,KAAK;AAEpD,SACE,UAAU,WAAW,OAAO,SAAS,UAAU,4BAA4B,UAAU,SAAQ;SAEzF;AACN,SAAO;;;AAIX,SAAS,qBAAqB,YAA8C;CAC1E,MAAM,uBAAuB,YAAY,MAAM,CAAC,QAAQ,QAAQ,GAAG,CAAC,QAAQ,QAAQ,GAAG,IAAI;AAE3F,QAAO,uBAAuB,IAAI,qBAAqB,KAAK;;AAG9D,SAAS,yBAAyB,QAAwB;AACxD,QAAO,OACJ,MAAK,CACL,QAAQ,iBAAiB,GAAE,CAC3B,QAAQ,QAAQ,GAAG;;;;;AAMxB,SAAgB,gCAAgC,EAC9C,MACA,QAIS;CACT,MAAM,SAA8B;EAClC,SAAS,MAAM,WAAW;EAC1B,GAAI,MAAM,aAAa,SAAY,EAAE,UAAU,EAAE,QAAQ,KAAK,SAAS,aAAa,EAAE,EAAE,GAAG,EAAE;EAE7F,SAAS,MAAM,YAAY,gBAAgB,aAAa;EAGxD,QAAQ;GACN,MAAM,qBAAqB,MAAM,WAAW;GAC5C,gBAAgB;GACjB;EACD,MAAM,yBAAyB,KAAK,gBAAgB;EACpD,iBAAiB,EACf,QAAQ;GACN,YAAY;GACZ,cAAc;GACd,mBAAmB;GACnB,OAAO,EACL,UAAU;IACR,YAAY;IACZ,cAAc;IACf,EACF;GACF,EACF;EACF;AAED,QAAO,eAAe,wBAAwB,CAAC,OAAO"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { getShopifyAnalyticsBusScript, getShopifyAnalyticsConfig } from "./analytics.mjs";
|
|
2
|
-
import { SHOPIFY_CDN_ORIGIN, SHOPIFY_CONSENT_API_SCRIPT, SHOPIFY_CONSENT_SCRIPT_ID, SHOPIFY_INBOX_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT, SHOPIFY_PRIVACY_BANNER_SCRIPT, SHOPIFY_SHOP_APP_ORIGIN, SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT, SHOPIFY_STOREFRONT_WEBMCP_SCRIPT, VISITOR_CONSENT_COLLECTED_EVENT } from "./constants.mjs";
|
|
3
|
-
import { getShopifyConsentTrackingScript } from "./consent.mjs";
|
|
2
|
+
import { CONSENT_TRACKING_API_LOADED_EVENT, SHOPIFY_ACCOUNT_SCRIPT, SHOPIFY_CDN_ORIGIN, SHOPIFY_CONSENT_API_SCRIPT, SHOPIFY_CONSENT_SCRIPT_ID, SHOPIFY_INBOX_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT, SHOPIFY_PRIVACY_BANNER_SCRIPT, SHOPIFY_SHOP_APP_ORIGIN, SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT, SHOPIFY_STOREFRONT_WEBMCP_SCRIPT, VISITOR_CONSENT_COLLECTED_EVENT } from "./constants.mjs";
|
|
4
3
|
import { getShopifyGlobal, getShopifyGlobalBootstrapScript } from "./global.mjs";
|
|
5
4
|
import { getPerfKitScript } from "./perfkit.mjs";
|
|
6
5
|
import { renderShopifyScriptTag } from "./render.mjs";
|
|
@@ -14,7 +13,7 @@ import { initializeShopifyScripts } from "./initialize.mjs";
|
|
|
14
13
|
* component. Frameworks without a binding can render these descriptors during SSR and call
|
|
15
14
|
* `initializeShopifyScripts()` during browser hydration.
|
|
16
15
|
*/
|
|
17
|
-
function getShopifyScriptTags({ analytics, consent, debug, i18n, nonce, shop, shopifyAnalytics = true, inbox = false }) {
|
|
16
|
+
function getShopifyScriptTags({ account = false, analytics, consent, debug, i18n, nonce, shop, shopifyAnalytics = true, inbox = false }) {
|
|
18
17
|
const nonceAttributes = nonce !== void 0 ? { nonce } : void 0;
|
|
19
18
|
const analyticsConfig = getShopifyAnalyticsConfig({
|
|
20
19
|
analytics,
|
|
@@ -87,31 +86,34 @@ function getShopifyScriptTags({ analytics, consent, debug, i18n, nonce, shop, sh
|
|
|
87
86
|
src: SHOPIFY_INBOX_SCRIPT
|
|
88
87
|
}
|
|
89
88
|
});
|
|
90
|
-
scripts.push({
|
|
89
|
+
if (account) scripts.push({
|
|
91
90
|
tagName: "script",
|
|
92
91
|
attributes: {
|
|
93
|
-
id:
|
|
92
|
+
id: "shopify-account",
|
|
93
|
+
type: "module",
|
|
94
94
|
async: true,
|
|
95
95
|
crossorigin: "anonymous",
|
|
96
96
|
...nonceAttributes,
|
|
97
|
-
src:
|
|
97
|
+
src: SHOPIFY_ACCOUNT_SCRIPT
|
|
98
98
|
}
|
|
99
99
|
});
|
|
100
100
|
scripts.push({
|
|
101
101
|
tagName: "script",
|
|
102
102
|
attributes: {
|
|
103
|
-
id: "shopify-
|
|
103
|
+
id: "shopify-analytics-bus",
|
|
104
104
|
...nonceAttributes
|
|
105
105
|
},
|
|
106
|
-
innerHTML:
|
|
106
|
+
innerHTML: getShopifyAnalyticsBusScript(analyticsConfig)
|
|
107
107
|
});
|
|
108
108
|
scripts.push({
|
|
109
109
|
tagName: "script",
|
|
110
110
|
attributes: {
|
|
111
|
-
id:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
id: SHOPIFY_CONSENT_SCRIPT_ID,
|
|
112
|
+
async: true,
|
|
113
|
+
crossorigin: "anonymous",
|
|
114
|
+
...nonceAttributes,
|
|
115
|
+
src: consent?.mode === "default-banner" ? SHOPIFY_PRIVACY_BANNER_SCRIPT : SHOPIFY_CONSENT_API_SCRIPT
|
|
116
|
+
}
|
|
115
117
|
});
|
|
116
118
|
if (shopifyAnalytics) scripts.push({
|
|
117
119
|
tagName: "script",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/index.ts"],"sourcesContent":["import { getShopifyAnalyticsBusScript, getShopifyAnalyticsConfig } from \"./analytics\";\nimport {
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/index.ts"],"sourcesContent":["import { getShopifyAnalyticsBusScript, getShopifyAnalyticsConfig } from \"./analytics\";\nimport {\n SHOPIFY_ACCOUNT_SCRIPT,\n SHOPIFY_CONSENT_API_SCRIPT,\n SHOPIFY_CDN_ORIGIN,\n SHOPIFY_CONSENT_SCRIPT_ID,\n SHOPIFY_PRIVACY_BANNER_SCRIPT,\n SHOPIFY_SHOP_APP_ORIGIN,\n SHOPIFY_INBOX_SCRIPT,\n SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT,\n} from \"./constants\";\nimport { getShopifyGlobalBootstrapScript } from \"./global\";\nimport { getPerfKitScript } from \"./perfkit\";\nimport { renderShopifyScriptTag } from \"./render\";\nimport type {\n ShopifyLinkDescriptor,\n ShopifyScriptDescriptor,\n ShopifyScriptTagDescriptors,\n ShopifyScriptTagsOptions,\n} from \"./types\";\n\nexport {\n CONSENT_TRACKING_API_LOADED_EVENT,\n SHOPIFY_ACCOUNT_SCRIPT,\n SHOPIFY_CDN_ORIGIN,\n SHOPIFY_CONSENT_API_SCRIPT,\n SHOPIFY_PERF_KIT_SCRIPT,\n SHOPIFY_PRIVACY_BANNER_SCRIPT,\n SHOPIFY_SHOP_APP_ORIGIN,\n SHOPIFY_INBOX_SCRIPT,\n SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT,\n SHOPIFY_STOREFRONT_WEBMCP_SCRIPT,\n VISITOR_CONSENT_COLLECTED_EVENT,\n} from \"./constants\";\nexport { getShopifyGlobal, getShopifyGlobalBootstrapScript } from \"./global\";\nexport { initializeShopifyScripts } from \"./initialize\";\nexport { renderShopifyScriptTag } from \"./render\";\nexport type {\n ShopifyScriptsAnalyticsConfig,\n ShopifyRoutesOptions,\n ShopifyScriptTagDescriptor,\n ShopifyScriptTagDescriptors,\n ShopifyScriptTagsOptions,\n ShopifyScriptsOptions,\n ShopifyScriptsI18n,\n ShopifyScriptsShop,\n} from \"./types\";\n\n/**\n * Returns grouped Shopify storefront script/link descriptors for SSR frameworks and bindings.\n *\n * Framework bindings wrap this with `initializeShopifyScripts()` to form their `ShopifyScripts`\n * component. Frameworks without a binding can render these descriptors during SSR and call\n * `initializeShopifyScripts()` during browser hydration.\n */\n// oxlint-disable-next-line complexity -- ordered assembly of optional Shopify script tags; each flag adds one branch and splitting would obscure the required load order\nexport function getShopifyScriptTags({\n account = false,\n analytics,\n consent,\n debug,\n i18n,\n nonce,\n shop,\n shopifyAnalytics = true,\n inbox = false,\n}: ShopifyScriptTagsOptions): ShopifyScriptTagDescriptors {\n const nonceAttributes = nonce !== undefined ? { nonce } : undefined;\n const analyticsConfig = getShopifyAnalyticsConfig({ analytics, consent, shop });\n\n const links: ShopifyLinkDescriptor[] = [\n {\n tagName: \"link\",\n attributes: {\n rel: \"preconnect\",\n href: SHOPIFY_CDN_ORIGIN,\n },\n },\n {\n tagName: \"link\",\n attributes: {\n rel: \"preconnect\",\n href: SHOPIFY_SHOP_APP_ORIGIN,\n },\n },\n {\n tagName: \"link\",\n attributes: {\n rel: \"prefetch\",\n as: \"script\",\n href: SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT,\n crossorigin: \"anonymous\",\n },\n },\n ];\n const scripts: ShopifyScriptDescriptor[] = [\n {\n tagName: \"script\",\n attributes: { id: \"shopify-global-bootstrap\", ...nonceAttributes },\n innerHTML: getShopifyGlobalBootstrapScript({ i18n, shop }),\n },\n {\n tagName: \"script\",\n attributes: {\n id: \"shopify-standard-actions\",\n type: \"module\",\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT,\n },\n },\n ];\n\n if (__DEV__ && debug?.standardEventsInspector) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-standard-events-inspector\",\n defer: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT,\n },\n });\n }\n\n if (inbox) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-inbox\",\n type: \"module\",\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_INBOX_SCRIPT,\n },\n });\n }\n\n if (account) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-account\",\n type: \"module\",\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_ACCOUNT_SCRIPT,\n },\n });\n }\n\n // Install readiness listeners before loading the async consent library so a\n // cached script cannot finish initialization before Hydrogen starts listening.\n scripts.push({\n tagName: \"script\",\n attributes: { id: \"shopify-analytics-bus\", ...nonceAttributes },\n innerHTML: getShopifyAnalyticsBusScript(analyticsConfig),\n });\n\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: SHOPIFY_CONSENT_SCRIPT_ID,\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src:\n consent?.mode === \"default-banner\"\n ? SHOPIFY_PRIVACY_BANNER_SCRIPT\n : SHOPIFY_CONSENT_API_SCRIPT,\n },\n });\n\n if (shopifyAnalytics) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-storefront-analytics\",\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT,\n },\n });\n }\n\n const perfKitScript = getPerfKitScript(shop, nonceAttributes);\n if (perfKitScript) {\n scripts.push(perfKitScript);\n }\n\n return {\n links,\n scripts,\n get tags() {\n return [...links, ...scripts];\n },\n };\n}\n\n/**\n * Renders all Shopify storefront script/link descriptors to HTML strings.\n */\nexport function renderShopifyScriptTags(options: ShopifyScriptTagsOptions): string[] {\n return getShopifyScriptTags(options).tags.map(renderShopifyScriptTag);\n}\n"],"mappings":";;;;;;;;;;;;;;;AA6DA,SAAgB,qBAAqB,EACnC,UAAU,OACV,WACA,SACA,OACA,MACA,OACA,MACA,mBAAmB,MACnB,QAAQ,SACgD;CACxD,MAAM,kBAAkB,UAAU,SAAY,EAAE,OAAO,GAAG;CAC1D,MAAM,kBAAkB,0BAA0B;EAAE;EAAW;EAAS;EAAM,CAAC;CAE/E,MAAM,QAAiC;EACrC;GACE,SAAS;GACT,YAAY;IACV,KAAK;IACL,MAAM;IACP;GACF;EACD;GACE,SAAS;GACT,YAAY;IACV,KAAK;IACL,MAAM;IACP;GACF;EACD;GACE,SAAS;GACT,YAAY;IACV,KAAK;IACL,IAAI;IACJ,MAAM;IACN,aAAa;IACd;GACF;EACF;CACD,MAAM,UAAqC,CACzC;EACE,SAAS;EACT,YAAY;GAAE,IAAI;GAA4B,GAAG;GAAiB;EAClE,WAAW,gCAAgC;GAAE;GAAM;GAAM,CAAC;EAC3D,EACD;EACE,SAAS;EACT,YAAY;GACV,IAAI;GACJ,MAAM;GACN,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CACF;AAED,KAAe,OAAO,wBACpB,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;AAGJ,KAAI,MACF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,MAAM;GACN,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;AAGJ,KAAI,QACF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,MAAM;GACN,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;AAKJ,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GAAE,IAAI;GAAyB,GAAG;GAAiB;EAC/D,WAAW,6BAA6B,gBAAgB;EACzD,CAAC;AAEF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,OAAO;GACP,aAAa;GACb,GAAG;GACH,KACE,SAAS,SAAS,mBACd,gCACA;GACP;EACF,CAAC;AAEF,KAAI,iBACF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;CAGJ,MAAM,gBAAgB,iBAAiB,MAAM,gBAAgB;AAC7D,KAAI,cACF,SAAQ,KAAK,cAAc;AAG7B,QAAO;EACL;EACA;EACA,IAAI,OAAO;AACT,UAAO,CAAC,GAAG,OAAO,GAAG,QAAQ;;EAEhC;;;;;AAMH,SAAgB,wBAAwB,SAA6C;AACnF,QAAO,qBAAqB,QAAQ,CAAC,KAAK,IAAI,uBAAuB"}
|