@shopify/hydrogen 2026.4.5 → 2026.10.0-preview.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -13
- package/bin/hydrogen.mjs +7 -0
- package/dist/cli/index.mjs +647 -0
- package/dist/client/client.d.mts +34 -0
- package/dist/client/client.mjs +206 -0
- package/dist/client/client.mjs.map +1 -0
- package/dist/client/errors.d.mts +48 -0
- package/dist/client/errors.mjs +52 -0
- package/dist/client/errors.mjs.map +1 -0
- package/dist/client/index.d.mts +4 -0
- package/dist/client/types.d.mts +147 -0
- package/dist/core/analytics/cart-tracker.d.mts +8 -0
- package/dist/core/analytics/cart-tracker.mjs +144 -0
- package/dist/core/analytics/cart-tracker.mjs.map +1 -0
- package/dist/core/analytics/events.d.mts +15 -0
- package/dist/core/analytics/events.mjs +15 -0
- package/dist/core/analytics/events.mjs.map +1 -0
- package/dist/core/analytics/index.d.mts +3 -0
- package/dist/core/analytics/types.d.mts +143 -0
- package/dist/core/analytics/utils/flatten-connection.d.mts +19 -0
- package/dist/core/analytics/utils/flatten-connection.mjs +25 -0
- package/dist/core/analytics/utils/flatten-connection.mjs.map +1 -0
- package/dist/core/cache/cache-status.mjs +17 -0
- package/dist/core/cache/cache-status.mjs.map +1 -0
- package/dist/core/cache/fetch-with-cache.d.mts +43 -0
- package/dist/core/cache/fetch-with-cache.mjs +188 -0
- package/dist/core/cache/fetch-with-cache.mjs.map +1 -0
- package/dist/core/cache/key.d.mts +6 -0
- package/dist/core/cache/key.mjs +27 -0
- package/dist/core/cache/key.mjs.map +1 -0
- package/dist/core/cache/run-with-cache.d.mts +36 -0
- package/dist/core/cache/run-with-cache.mjs +114 -0
- package/dist/core/cache/run-with-cache.mjs.map +1 -0
- package/dist/core/cache/store.d.mts +19 -0
- package/dist/core/cache/store.mjs +62 -0
- package/dist/core/cache/store.mjs.map +1 -0
- package/dist/core/cache/strategies.d.mts +39 -0
- package/dist/core/cache/strategies.mjs +70 -0
- package/dist/core/cache/strategies.mjs.map +1 -0
- package/dist/core/cart/actions.d.mts +50 -0
- package/dist/core/cart/actions.mjs +240 -0
- package/dist/core/cart/actions.mjs.map +1 -0
- package/dist/core/cart/attach-quantity-input.d.mts +5 -0
- package/dist/core/cart/attach-quantity-input.mjs +17 -0
- package/dist/core/cart/attach-quantity-input.mjs.map +1 -0
- package/dist/core/cart/buyer-identity-sync.d.mts +23 -0
- package/dist/core/cart/buyer-identity-sync.mjs +9 -0
- package/dist/core/cart/buyer-identity-sync.mjs.map +1 -0
- package/dist/core/cart/cart.d.mts +37 -0
- package/dist/core/cart/cart.mjs +1707 -0
- package/dist/core/cart/cart.mjs.map +1 -0
- package/dist/core/cart/cookie.d.mts +5 -0
- package/dist/core/cart/cookie.mjs +28 -0
- package/dist/core/cart/cookie.mjs.map +1 -0
- package/dist/core/cart/form.d.mts +130 -0
- package/dist/core/cart/form.mjs +75 -0
- package/dist/core/cart/form.mjs.map +1 -0
- package/dist/core/cart/get-cart.d.mts +25 -0
- package/dist/core/cart/get-cart.mjs +32 -0
- package/dist/core/cart/get-cart.mjs.map +1 -0
- package/dist/core/cart/index.d.mts +10 -0
- package/dist/core/cart/quantity.d.mts +10 -0
- package/dist/core/cart/quantity.mjs +14 -0
- package/dist/core/cart/quantity.mjs.map +1 -0
- package/dist/core/cart/queries.d.mts +4296 -0
- package/dist/core/cart/queries.mjs +70 -0
- package/dist/core/cart/queries.mjs.map +1 -0
- package/dist/core/cart/server-handlers.d.mts +82 -0
- package/dist/core/cart/server-handlers.mjs +322 -0
- package/dist/core/cart/server-handlers.mjs.map +1 -0
- package/dist/core/cart/state.d.mts +137 -0
- package/dist/core/cart/state.mjs +76 -0
- package/dist/core/cart/state.mjs.map +1 -0
- package/dist/core/cart/sync-quantity-inputs.mjs +16 -0
- package/dist/core/cart/sync-quantity-inputs.mjs.map +1 -0
- package/dist/core/collection/collection.d.mts +134 -0
- package/dist/core/collection/collection.mjs +170 -0
- package/dist/core/collection/collection.mjs.map +1 -0
- package/dist/core/collection/index.d.mts +6 -0
- package/dist/core/collection/reconciler.d.mts +32 -0
- package/dist/core/collection/reconciler.mjs +89 -0
- package/dist/core/collection/reconciler.mjs.map +1 -0
- package/dist/core/collection/state.d.mts +66 -0
- package/dist/core/collection/state.mjs +20 -0
- package/dist/core/collection/state.mjs.map +1 -0
- package/dist/core/collection/url.d.mts +71 -0
- package/dist/core/collection/url.mjs +376 -0
- package/dist/core/collection/url.mjs.map +1 -0
- package/dist/core/constants.d.mts +5 -0
- package/dist/core/constants.mjs +8 -0
- package/dist/core/constants.mjs.map +1 -0
- package/dist/core/headers.mjs +43 -0
- package/dist/core/headers.mjs.map +1 -0
- package/dist/core/index.d.mts +56 -0
- package/dist/core/index.mjs +45 -0
- package/dist/core/logging/logging.d.mts +21 -0
- package/dist/core/logging/logging.mjs +99 -0
- package/dist/core/logging/logging.mjs.map +1 -0
- package/dist/core/logging/types.d.mts +40 -0
- package/dist/core/logging/types.mjs +18 -0
- package/dist/core/logging/types.mjs.map +1 -0
- package/dist/core/money/cache.mjs +25 -0
- package/dist/core/money/cache.mjs.map +1 -0
- package/dist/core/money/format.d.mts +15 -0
- package/dist/core/money/format.mjs +243 -0
- package/dist/core/money/format.mjs.map +1 -0
- package/dist/core/money/types.d.mts +47 -0
- package/dist/core/observable.mjs +46 -0
- package/dist/core/observable.mjs.map +1 -0
- package/dist/core/predictive-search/constants.d.mts +5 -0
- package/dist/core/predictive-search/constants.mjs +6 -0
- package/dist/core/predictive-search/constants.mjs.map +1 -0
- package/dist/core/predictive-search/form.d.mts +31 -0
- package/dist/core/predictive-search/form.mjs +31 -0
- package/dist/core/predictive-search/form.mjs.map +1 -0
- package/dist/core/predictive-search/index.d.mts +6 -0
- package/dist/core/predictive-search/queries.d.mts +118 -0
- package/dist/core/predictive-search/queries.mjs +81 -0
- package/dist/core/predictive-search/queries.mjs.map +1 -0
- package/dist/core/predictive-search/search.d.mts +32 -0
- package/dist/core/predictive-search/search.mjs +74 -0
- package/dist/core/predictive-search/search.mjs.map +1 -0
- package/dist/core/predictive-search/server-handlers.d.mts +36 -0
- package/dist/core/predictive-search/server-handlers.mjs +113 -0
- package/dist/core/predictive-search/server-handlers.mjs.map +1 -0
- package/dist/core/predictive-search/store.d.mts +44 -0
- package/dist/core/predictive-search/store.mjs +224 -0
- package/dist/core/predictive-search/store.mjs.map +1 -0
- package/dist/core/predictive-search/url.d.mts +41 -0
- package/dist/core/predictive-search/url.mjs +71 -0
- package/dist/core/predictive-search/url.mjs.map +1 -0
- package/dist/core/product/accept-variant-id.mjs +98 -0
- package/dist/core/product/accept-variant-id.mjs.map +1 -0
- package/dist/core/product/form.d.mts +63 -0
- package/dist/core/product/form.mjs +44 -0
- package/dist/core/product/form.mjs.map +1 -0
- package/dist/core/product/index.d.mts +5 -0
- package/dist/core/product/options.d.mts +43 -0
- package/dist/core/product/options.mjs +296 -0
- package/dist/core/product/options.mjs.map +1 -0
- package/dist/core/product/product-form.d.mts +72 -0
- package/dist/core/product/product-form.mjs +158 -0
- package/dist/core/product/product-form.mjs.map +1 -0
- package/dist/core/product/state.d.mts +68 -0
- package/dist/core/product/url.d.mts +47 -0
- package/dist/core/product/url.mjs +69 -0
- package/dist/core/product/url.mjs.map +1 -0
- package/dist/core/request-context.d.mts +75 -0
- package/dist/core/request-context.mjs +141 -0
- package/dist/core/request-context.mjs.map +1 -0
- package/dist/core/request-routing/handle-shopify-redirects.d.mts +17 -0
- package/dist/core/request-routing/handle-shopify-redirects.mjs +31 -0
- package/dist/core/request-routing/handle-shopify-redirects.mjs.map +1 -0
- package/dist/core/request-routing/handle-shopify-routes.d.mts +14 -0
- package/dist/core/request-routing/handle-shopify-routes.mjs +42 -0
- package/dist/core/request-routing/handle-shopify-routes.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/admin-redirect.mjs +12 -0
- package/dist/core/request-routing/interceptors/admin-redirect.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/ajax-api.mjs +16 -0
- package/dist/core/request-routing/interceptors/ajax-api.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/api-proxy.mjs +20 -0
- package/dist/core/request-routing/interceptors/api-proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/checkout.mjs +58 -0
- package/dist/core/request-routing/interceptors/checkout.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/mcp-proxy.mjs +23 -0
- package/dist/core/request-routing/interceptors/mcp-proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/proxy.mjs +73 -0
- package/dist/core/request-routing/interceptors/proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/query-param-redirect.mjs +22 -0
- package/dist/core/request-routing/interceptors/query-param-redirect.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/sfapi-proxy.mjs +27 -0
- package/dist/core/request-routing/interceptors/sfapi-proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/standard-routes.mjs +19 -0
- package/dist/core/request-routing/interceptors/standard-routes.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/url-redirects.mjs +27 -0
- package/dist/core/request-routing/interceptors/url-redirects.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/well-known.mjs +22 -0
- package/dist/core/request-routing/interceptors/well-known.mjs.map +1 -0
- package/dist/core/request-routing/registered-routes.d.mts +7 -0
- package/dist/core/request-routing/registered-routes.mjs +72 -0
- package/dist/core/request-routing/registered-routes.mjs.map +1 -0
- package/dist/core/request-routing/route-types.d.mts +56 -0
- package/dist/core/request-routing/safe-apply-response-headers.mjs +16 -0
- package/dist/core/request-routing/safe-apply-response-headers.mjs.map +1 -0
- package/dist/core/shop-pay/shop-pay.d.mts +102 -0
- package/dist/core/shop-pay/shop-pay.mjs +289 -0
- package/dist/core/shop-pay/shop-pay.mjs.map +1 -0
- package/dist/core/shopify-scripts/analytics.mjs +26 -0
- package/dist/core/shopify-scripts/analytics.mjs.map +1 -0
- package/dist/core/shopify-scripts/consent.mjs +17 -0
- package/dist/core/shopify-scripts/consent.mjs.map +1 -0
- package/dist/core/shopify-scripts/constants.mjs +19 -0
- package/dist/core/shopify-scripts/constants.mjs.map +1 -0
- package/dist/core/shopify-scripts/deprecated-cookies.mjs +97 -0
- package/dist/core/shopify-scripts/deprecated-cookies.mjs.map +1 -0
- package/dist/core/shopify-scripts/global.d.mts +1 -0
- package/dist/core/shopify-scripts/global.mjs +86 -0
- package/dist/core/shopify-scripts/global.mjs.map +1 -0
- package/dist/core/shopify-scripts/index.d.mts +27 -0
- package/dist/core/shopify-scripts/index.mjs +135 -0
- package/dist/core/shopify-scripts/index.mjs.map +1 -0
- package/dist/core/shopify-scripts/initialize.d.mts +18 -0
- package/dist/core/shopify-scripts/initialize.mjs +27 -0
- package/dist/core/shopify-scripts/initialize.mjs.map +1 -0
- package/dist/core/shopify-scripts/page-view.mjs +49 -0
- package/dist/core/shopify-scripts/page-view.mjs.map +1 -0
- package/dist/core/shopify-scripts/perfkit.mjs +33 -0
- package/dist/core/shopify-scripts/perfkit.mjs.map +1 -0
- package/dist/core/shopify-scripts/render.d.mts +1 -0
- package/dist/core/shopify-scripts/render.mjs +23 -0
- package/dist/core/shopify-scripts/render.mjs.map +1 -0
- package/dist/core/shopify-scripts/types.d.mts +76 -0
- package/dist/core/shopify-scripts/utils/cookie-domain.mjs +43 -0
- package/dist/core/shopify-scripts/utils/cookie-domain.mjs.map +1 -0
- package/dist/core/shopify-scripts/utils/inline-script.mjs +8 -0
- package/dist/core/shopify-scripts/utils/inline-script.mjs.map +1 -0
- package/dist/core/shopify-scripts/utils/navigation.mjs +46 -0
- package/dist/core/shopify-scripts/utils/navigation.mjs.map +1 -0
- package/dist/core/shopify-scripts/utils/tracking-values.mjs +65 -0
- package/dist/core/shopify-scripts/utils/tracking-values.mjs.map +1 -0
- package/dist/core/shopify-scripts/utils/uuid.mjs +17 -0
- package/dist/core/shopify-scripts/utils/uuid.mjs.map +1 -0
- package/dist/core/shopify-scripts/webmcp.mjs +22 -0
- package/dist/core/shopify-scripts/webmcp.mjs.map +1 -0
- package/dist/core/standard-routes/build.d.mts +34 -0
- package/dist/core/standard-routes/build.mjs +54 -0
- package/dist/core/standard-routes/build.mjs.map +1 -0
- package/dist/core/standard-routes/defaults.mjs +31 -0
- package/dist/core/standard-routes/defaults.mjs.map +1 -0
- package/dist/core/standard-routes/match.mjs +108 -0
- package/dist/core/standard-routes/match.mjs.map +1 -0
- package/dist/core/standard-routes/path.mjs +58 -0
- package/dist/core/standard-routes/path.mjs.map +1 -0
- package/dist/core/standard-routes/redirects.mjs +51 -0
- package/dist/core/standard-routes/redirects.mjs.map +1 -0
- package/dist/core/standard-routes/types.d.mts +95 -0
- package/dist/core/url.mjs +42 -0
- package/dist/core/url.mjs.map +1 -0
- package/dist/core/utils/load-script.mjs +34 -0
- package/dist/core/utils/load-script.mjs.map +1 -0
- package/dist/core/utils/parse-gid.mjs +33 -0
- package/dist/core/utils/parse-gid.mjs.map +1 -0
- package/dist/core/utils/record.mjs +8 -0
- package/dist/core/utils/record.mjs.map +1 -0
- package/dist/customer-account/client.d.mts +50 -0
- package/dist/customer-account/client.mjs +239 -0
- package/dist/customer-account/client.mjs.map +1 -0
- package/dist/customer-account/errors.d.mts +28 -0
- package/dist/customer-account/errors.mjs +39 -0
- package/dist/customer-account/errors.mjs.map +1 -0
- package/dist/customer-account/graphql.d.mts +29 -0
- package/dist/customer-account/graphql.mjs +39 -0
- package/dist/customer-account/graphql.mjs.map +1 -0
- package/dist/customer-account/index.d.mts +7 -0
- package/dist/customer-account/index.mjs +7 -0
- package/dist/customer-account/session.d.mts +117 -0
- package/dist/customer-account/session.mjs +733 -0
- package/dist/customer-account/session.mjs.map +1 -0
- package/dist/customer-account/type-resolver.d.mts +11 -0
- package/dist/customer-account-api-types.d.ts +3269 -3270
- package/dist/customer-account.schema.json +50753 -1
- package/dist/development/_virtual/_@oxc-project_runtime@0.127.0/helpers/taggedTemplateLiteral.mjs +7 -0
- package/dist/development/client/client.d.mts +34 -0
- package/dist/development/client/client.mjs +206 -0
- package/dist/development/client/client.mjs.map +1 -0
- package/dist/development/client/errors.d.mts +48 -0
- package/dist/development/client/errors.mjs +57 -0
- package/dist/development/client/errors.mjs.map +1 -0
- package/dist/development/client/index.d.mts +4 -0
- package/dist/development/client/types.d.mts +147 -0
- package/dist/development/core/analytics/cart-tracker.d.mts +8 -0
- package/dist/development/core/analytics/cart-tracker.mjs +144 -0
- package/dist/development/core/analytics/cart-tracker.mjs.map +1 -0
- package/dist/development/core/analytics/events.d.mts +15 -0
- package/dist/development/core/analytics/events.mjs +15 -0
- package/dist/development/core/analytics/events.mjs.map +1 -0
- package/dist/development/core/analytics/index.d.mts +3 -0
- package/dist/development/core/analytics/types.d.mts +143 -0
- package/dist/development/core/analytics/utils/flatten-connection.d.mts +19 -0
- package/dist/development/core/analytics/utils/flatten-connection.mjs +25 -0
- package/dist/development/core/analytics/utils/flatten-connection.mjs.map +1 -0
- package/dist/development/core/cache/cache-status.mjs +17 -0
- package/dist/development/core/cache/cache-status.mjs.map +1 -0
- package/dist/development/core/cache/fetch-with-cache.d.mts +43 -0
- package/dist/development/core/cache/fetch-with-cache.mjs +188 -0
- package/dist/development/core/cache/fetch-with-cache.mjs.map +1 -0
- package/dist/development/core/cache/key.d.mts +6 -0
- package/dist/development/core/cache/key.mjs +27 -0
- package/dist/development/core/cache/key.mjs.map +1 -0
- package/dist/development/core/cache/run-with-cache.d.mts +36 -0
- package/dist/development/core/cache/run-with-cache.mjs +114 -0
- package/dist/development/core/cache/run-with-cache.mjs.map +1 -0
- package/dist/development/core/cache/store.d.mts +19 -0
- package/dist/development/core/cache/store.mjs +62 -0
- package/dist/development/core/cache/store.mjs.map +1 -0
- package/dist/development/core/cache/strategies.d.mts +39 -0
- package/dist/development/core/cache/strategies.mjs +70 -0
- package/dist/development/core/cache/strategies.mjs.map +1 -0
- package/dist/development/core/cart/actions.d.mts +50 -0
- package/dist/development/core/cart/actions.mjs +240 -0
- package/dist/development/core/cart/actions.mjs.map +1 -0
- package/dist/development/core/cart/attach-quantity-input.d.mts +5 -0
- package/dist/development/core/cart/attach-quantity-input.mjs +17 -0
- package/dist/development/core/cart/attach-quantity-input.mjs.map +1 -0
- package/dist/development/core/cart/buyer-identity-sync.d.mts +19 -0
- package/dist/development/core/cart/buyer-identity-sync.mjs +6 -0
- package/dist/development/core/cart/buyer-identity-sync.mjs.map +1 -0
- package/dist/development/core/cart/cart.d.mts +37 -0
- package/dist/development/core/cart/cart.mjs +1707 -0
- package/dist/development/core/cart/cart.mjs.map +1 -0
- package/dist/development/core/cart/cookie.d.mts +5 -0
- package/dist/development/core/cart/cookie.mjs +28 -0
- package/dist/development/core/cart/cookie.mjs.map +1 -0
- package/dist/development/core/cart/form.d.mts +130 -0
- package/dist/development/core/cart/form.mjs +75 -0
- package/dist/development/core/cart/form.mjs.map +1 -0
- package/dist/development/core/cart/get-cart.d.mts +25 -0
- package/dist/development/core/cart/get-cart.mjs +32 -0
- package/dist/development/core/cart/get-cart.mjs.map +1 -0
- package/dist/development/core/cart/index.d.mts +10 -0
- package/dist/development/core/cart/quantity.d.mts +10 -0
- package/dist/development/core/cart/quantity.mjs +14 -0
- package/dist/development/core/cart/quantity.mjs.map +1 -0
- package/dist/development/core/cart/queries.d.mts +4296 -0
- package/dist/development/core/cart/queries.mjs +70 -0
- package/dist/development/core/cart/queries.mjs.map +1 -0
- package/dist/development/core/cart/server-handlers.d.mts +82 -0
- package/dist/development/core/cart/server-handlers.mjs +322 -0
- package/dist/development/core/cart/server-handlers.mjs.map +1 -0
- package/dist/development/core/cart/state.d.mts +137 -0
- package/dist/development/core/cart/state.mjs +76 -0
- package/dist/development/core/cart/state.mjs.map +1 -0
- package/dist/development/core/cart/sync-quantity-inputs.mjs +16 -0
- package/dist/development/core/cart/sync-quantity-inputs.mjs.map +1 -0
- package/dist/development/core/collection/collection.d.mts +134 -0
- package/dist/development/core/collection/collection.mjs +170 -0
- package/dist/development/core/collection/collection.mjs.map +1 -0
- package/dist/development/core/collection/index.d.mts +6 -0
- package/dist/development/core/collection/reconciler.d.mts +32 -0
- package/dist/development/core/collection/reconciler.mjs +89 -0
- package/dist/development/core/collection/reconciler.mjs.map +1 -0
- package/dist/development/core/collection/state.d.mts +66 -0
- package/dist/development/core/collection/state.mjs +20 -0
- package/dist/development/core/collection/state.mjs.map +1 -0
- package/dist/development/core/collection/url.d.mts +71 -0
- package/dist/development/core/collection/url.mjs +376 -0
- package/dist/development/core/collection/url.mjs.map +1 -0
- package/dist/development/core/constants.mjs +7 -0
- package/dist/development/core/constants.mjs.map +1 -0
- package/dist/development/core/development.d.mts +56 -0
- package/dist/development/core/development.mjs +45 -0
- package/dist/development/core/headers.mjs +43 -0
- package/dist/development/core/headers.mjs.map +1 -0
- package/dist/development/core/index.d.mts +54 -0
- package/dist/development/core/logging/logging.d.mts +21 -0
- package/dist/development/core/logging/logging.mjs +99 -0
- package/dist/development/core/logging/logging.mjs.map +1 -0
- package/dist/development/core/logging/types.d.mts +40 -0
- package/dist/development/core/logging/types.mjs +18 -0
- package/dist/development/core/logging/types.mjs.map +1 -0
- package/dist/development/core/money/cache.mjs +25 -0
- package/dist/development/core/money/cache.mjs.map +1 -0
- package/dist/development/core/money/format.d.mts +15 -0
- package/dist/development/core/money/format.mjs +243 -0
- package/dist/development/core/money/format.mjs.map +1 -0
- package/dist/development/core/money/types.d.mts +47 -0
- package/dist/development/core/observable.mjs +46 -0
- package/dist/development/core/observable.mjs.map +1 -0
- package/dist/development/core/predictive-search/constants.d.mts +5 -0
- package/dist/development/core/predictive-search/constants.mjs +6 -0
- package/dist/development/core/predictive-search/constants.mjs.map +1 -0
- package/dist/development/core/predictive-search/form.d.mts +31 -0
- package/dist/development/core/predictive-search/form.mjs +31 -0
- package/dist/development/core/predictive-search/form.mjs.map +1 -0
- package/dist/development/core/predictive-search/index.d.mts +6 -0
- package/dist/development/core/predictive-search/queries.d.mts +118 -0
- package/dist/development/core/predictive-search/queries.mjs +81 -0
- package/dist/development/core/predictive-search/queries.mjs.map +1 -0
- package/dist/development/core/predictive-search/search.d.mts +32 -0
- package/dist/development/core/predictive-search/search.mjs +74 -0
- package/dist/development/core/predictive-search/search.mjs.map +1 -0
- package/dist/development/core/predictive-search/server-handlers.d.mts +36 -0
- package/dist/development/core/predictive-search/server-handlers.mjs +113 -0
- package/dist/development/core/predictive-search/server-handlers.mjs.map +1 -0
- package/dist/development/core/predictive-search/store.d.mts +44 -0
- package/dist/development/core/predictive-search/store.mjs +224 -0
- package/dist/development/core/predictive-search/store.mjs.map +1 -0
- package/dist/development/core/predictive-search/url.d.mts +41 -0
- package/dist/development/core/predictive-search/url.mjs +71 -0
- package/dist/development/core/predictive-search/url.mjs.map +1 -0
- package/dist/development/core/product/accept-variant-id.mjs +98 -0
- package/dist/development/core/product/accept-variant-id.mjs.map +1 -0
- package/dist/development/core/product/form.d.mts +63 -0
- package/dist/development/core/product/form.mjs +44 -0
- package/dist/development/core/product/form.mjs.map +1 -0
- package/dist/development/core/product/index.d.mts +5 -0
- package/dist/development/core/product/options.d.mts +43 -0
- package/dist/development/core/product/options.mjs +296 -0
- package/dist/development/core/product/options.mjs.map +1 -0
- package/dist/development/core/product/product-form.d.mts +72 -0
- package/dist/development/core/product/product-form.mjs +158 -0
- package/dist/development/core/product/product-form.mjs.map +1 -0
- package/dist/development/core/product/state.d.mts +68 -0
- package/dist/development/core/product/url.d.mts +47 -0
- package/dist/development/core/product/url.mjs +69 -0
- package/dist/development/core/product/url.mjs.map +1 -0
- package/dist/development/core/request-context.d.mts +75 -0
- package/dist/development/core/request-context.mjs +141 -0
- package/dist/development/core/request-context.mjs.map +1 -0
- package/dist/development/core/request-routing/handle-shopify-redirects.d.mts +17 -0
- package/dist/development/core/request-routing/handle-shopify-redirects.mjs +31 -0
- package/dist/development/core/request-routing/handle-shopify-redirects.mjs.map +1 -0
- package/dist/development/core/request-routing/handle-shopify-routes.d.mts +1 -0
- package/dist/development/core/request-routing/handle-shopify-routes.development.d.mts +11 -0
- package/dist/development/core/request-routing/handle-shopify-routes.development.mjs +16 -0
- package/dist/development/core/request-routing/handle-shopify-routes.development.mjs.map +1 -0
- package/dist/development/core/request-routing/handle-shopify-routes.mjs +42 -0
- package/dist/development/core/request-routing/handle-shopify-routes.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/admin-redirect.mjs +12 -0
- package/dist/development/core/request-routing/interceptors/admin-redirect.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/ajax-api.mjs +16 -0
- package/dist/development/core/request-routing/interceptors/ajax-api.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/api-proxy.mjs +20 -0
- package/dist/development/core/request-routing/interceptors/api-proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/checkout.mjs +58 -0
- package/dist/development/core/request-routing/interceptors/checkout.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/graphiql.mjs +46 -0
- package/dist/development/core/request-routing/interceptors/graphiql.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/mcp-proxy.mjs +23 -0
- package/dist/development/core/request-routing/interceptors/mcp-proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/proxy.mjs +73 -0
- package/dist/development/core/request-routing/interceptors/proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/query-param-redirect.mjs +22 -0
- package/dist/development/core/request-routing/interceptors/query-param-redirect.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/sfapi-proxy.mjs +27 -0
- package/dist/development/core/request-routing/interceptors/sfapi-proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/standard-routes.mjs +19 -0
- package/dist/development/core/request-routing/interceptors/standard-routes.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/url-redirects.mjs +27 -0
- package/dist/development/core/request-routing/interceptors/url-redirects.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/well-known.mjs +22 -0
- package/dist/development/core/request-routing/interceptors/well-known.mjs.map +1 -0
- package/dist/development/core/request-routing/registered-routes.d.mts +7 -0
- package/dist/development/core/request-routing/registered-routes.mjs +72 -0
- package/dist/development/core/request-routing/registered-routes.mjs.map +1 -0
- package/dist/development/core/request-routing/route-types.d.mts +56 -0
- package/dist/development/core/request-routing/safe-apply-response-headers.mjs +16 -0
- package/dist/development/core/request-routing/safe-apply-response-headers.mjs.map +1 -0
- package/dist/development/core/shop-pay/shop-pay.d.mts +102 -0
- package/dist/development/core/shop-pay/shop-pay.mjs +289 -0
- package/dist/development/core/shop-pay/shop-pay.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/analytics.mjs +26 -0
- package/dist/development/core/shopify-scripts/analytics.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/consent.mjs +17 -0
- package/dist/development/core/shopify-scripts/consent.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/constants.mjs +19 -0
- package/dist/development/core/shopify-scripts/constants.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/deprecated-cookies.mjs +97 -0
- package/dist/development/core/shopify-scripts/deprecated-cookies.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/global.d.mts +1 -0
- package/dist/development/core/shopify-scripts/global.mjs +86 -0
- package/dist/development/core/shopify-scripts/global.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/index.d.mts +27 -0
- package/dist/development/core/shopify-scripts/index.mjs +145 -0
- package/dist/development/core/shopify-scripts/index.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/initialize.d.mts +18 -0
- package/dist/development/core/shopify-scripts/initialize.mjs +27 -0
- package/dist/development/core/shopify-scripts/initialize.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/page-view.mjs +49 -0
- package/dist/development/core/shopify-scripts/page-view.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/perfkit.mjs +33 -0
- package/dist/development/core/shopify-scripts/perfkit.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/render.d.mts +1 -0
- package/dist/development/core/shopify-scripts/render.mjs +23 -0
- package/dist/development/core/shopify-scripts/render.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/types.d.mts +76 -0
- package/dist/development/core/shopify-scripts/utils/cookie-domain.mjs +43 -0
- package/dist/development/core/shopify-scripts/utils/cookie-domain.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/utils/inline-script.mjs +8 -0
- package/dist/development/core/shopify-scripts/utils/inline-script.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/utils/navigation.mjs +46 -0
- package/dist/development/core/shopify-scripts/utils/navigation.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/utils/tracking-values.mjs +65 -0
- package/dist/development/core/shopify-scripts/utils/tracking-values.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/utils/uuid.mjs +17 -0
- package/dist/development/core/shopify-scripts/utils/uuid.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/webmcp.mjs +22 -0
- package/dist/development/core/shopify-scripts/webmcp.mjs.map +1 -0
- package/dist/development/core/standard-routes/build.d.mts +34 -0
- package/dist/development/core/standard-routes/build.mjs +54 -0
- package/dist/development/core/standard-routes/build.mjs.map +1 -0
- package/dist/development/core/standard-routes/defaults.mjs +31 -0
- package/dist/development/core/standard-routes/defaults.mjs.map +1 -0
- package/dist/development/core/standard-routes/match.mjs +108 -0
- package/dist/development/core/standard-routes/match.mjs.map +1 -0
- package/dist/development/core/standard-routes/path.mjs +58 -0
- package/dist/development/core/standard-routes/path.mjs.map +1 -0
- package/dist/development/core/standard-routes/redirects.mjs +51 -0
- package/dist/development/core/standard-routes/redirects.mjs.map +1 -0
- package/dist/development/core/standard-routes/types.d.mts +95 -0
- package/dist/development/core/types.d.mts +11 -0
- package/dist/development/core/url.mjs +42 -0
- package/dist/development/core/url.mjs.map +1 -0
- package/dist/development/core/utils/load-script.mjs +34 -0
- package/dist/development/core/utils/load-script.mjs.map +1 -0
- package/dist/development/core/utils/parse-gid.mjs +33 -0
- package/dist/development/core/utils/parse-gid.mjs.map +1 -0
- package/dist/development/customer-account/session.d.mts +46 -0
- package/dist/development/customer-account/session.mjs +21 -0
- package/dist/development/customer-account/session.mjs.map +1 -0
- package/dist/development/globals.d.mts +64 -0
- package/dist/development/graphql/generated/customer-account-api-types.d.mts +13 -0
- package/dist/development/graphql/generated/graphql-env.d.mts +19280 -0
- package/dist/development/graphql/generated/storefront-api-types.d.mts +47 -0
- package/dist/development/graphql/graphql.d.mts +40 -0
- package/dist/development/graphql/graphql.mjs +16 -0
- package/dist/development/graphql/graphql.mjs.map +1 -0
- package/dist/development/graphql/index.d.mts +2 -0
- package/dist/development/graphql/scalars.d.mts +15 -0
- package/dist/development/graphql/type-resolver.d.mts +229 -0
- package/dist/development/react/cart.d.mts +44 -0
- package/dist/development/react/cart.mjs +155 -0
- package/dist/development/react/cart.mjs.map +1 -0
- package/dist/development/react/collection.d.mts +91 -0
- package/dist/development/react/collection.mjs +129 -0
- package/dist/development/react/collection.mjs.map +1 -0
- package/dist/development/react/index.d.mts +13 -0
- package/dist/development/react/index.mjs +10 -0
- package/dist/development/react/predictive-search.d.mts +49 -0
- package/dist/development/react/predictive-search.mjs +133 -0
- package/dist/development/react/predictive-search.mjs.map +1 -0
- package/dist/development/react/product.d.mts +72 -0
- package/dist/development/react/product.mjs +127 -0
- package/dist/development/react/product.mjs.map +1 -0
- package/dist/development/react/shop-pay.d.mts +9 -0
- package/dist/development/react/shop-pay.mjs +16 -0
- package/dist/development/react/shop-pay.mjs.map +1 -0
- package/dist/development/react/shopify-scripts.d.mts +20 -0
- package/dist/development/react/shopify-scripts.mjs +39 -0
- package/dist/development/react/shopify-scripts.mjs.map +1 -0
- package/dist/development/vendor/standard-actions.d.mts +134 -0
- package/dist/development/vendor/standard-events.d.mts +1107 -0
- package/dist/development/vue/cart.d.mts +46 -0
- package/dist/development/vue/cart.mjs +122 -0
- package/dist/development/vue/cart.mjs.map +1 -0
- package/dist/development/vue/collection.d.mts +46 -0
- package/dist/development/vue/collection.mjs +108 -0
- package/dist/development/vue/collection.mjs.map +1 -0
- package/dist/development/vue/index.d.mts +11 -0
- package/dist/development/vue/index.mjs +8 -0
- package/dist/development/vue/predictive-search.d.mts +124 -0
- package/dist/development/vue/predictive-search.mjs +171 -0
- package/dist/development/vue/predictive-search.mjs.map +1 -0
- package/dist/development/vue/product.d.mts +57 -0
- package/dist/development/vue/product.mjs +167 -0
- package/dist/development/vue/product.mjs.map +1 -0
- package/dist/development/vue/shop-pay.d.mts +25 -0
- package/dist/development/vue/shop-pay.mjs +35 -0
- package/dist/development/vue/shop-pay.mjs.map +1 -0
- package/dist/development/vue/shopify-scripts.d.mts +127 -0
- package/dist/development/vue/shopify-scripts.mjs +79 -0
- package/dist/development/vue/shopify-scripts.mjs.map +1 -0
- package/dist/globals.d.mts +64 -0
- package/dist/graphql/generated/customer-account-api-types.d.mts +13 -0
- package/dist/graphql/generated/customer-account-graphql-env.d.mts +22170 -0
- package/dist/graphql/generated/graphql-env.d.mts +19280 -0
- package/dist/graphql/generated/storefront-api-types.d.mts +47 -0
- package/dist/graphql/graphql.d.mts +40 -0
- package/dist/graphql/graphql.mjs +16 -0
- package/dist/graphql/graphql.mjs.map +1 -0
- package/dist/graphql/index.d.mts +2 -0
- package/dist/graphql/scalars.d.mts +26 -0
- package/dist/graphql/type-resolver.d.mts +229 -0
- package/dist/react/cart.d.mts +44 -0
- package/dist/react/cart.mjs +155 -0
- package/dist/react/cart.mjs.map +1 -0
- package/dist/react/collection.d.mts +91 -0
- package/dist/react/collection.mjs +129 -0
- package/dist/react/collection.mjs.map +1 -0
- package/dist/react/index.d.mts +13 -0
- package/dist/react/index.mjs +10 -0
- package/dist/react/predictive-search.d.mts +49 -0
- package/dist/react/predictive-search.mjs +133 -0
- package/dist/react/predictive-search.mjs.map +1 -0
- package/dist/react/product.d.mts +72 -0
- package/dist/react/product.mjs +127 -0
- package/dist/react/product.mjs.map +1 -0
- package/dist/react/shop-pay.d.mts +9 -0
- package/dist/react/shop-pay.mjs +16 -0
- package/dist/react/shop-pay.mjs.map +1 -0
- package/dist/react/shopify-scripts.d.mts +20 -0
- package/dist/react/shopify-scripts.mjs +39 -0
- package/dist/react/shopify-scripts.mjs.map +1 -0
- package/dist/storefront-api-types.d.ts +2351 -2390
- package/dist/storefront.schema.json +41534 -1
- package/dist/ts-plugin/index.cjs +68 -0
- package/dist/ts-plugin/index.cjs.map +1 -0
- package/dist/ts-plugin/index.d.cts +4 -0
- package/dist/vendor/standard-actions.d.mts +134 -0
- package/dist/vendor/standard-events.d.mts +1107 -0
- package/dist/vite/certificate-prompt.mjs +24 -0
- package/dist/vite/certificate-prompt.mjs.map +1 -0
- package/dist/vite/index.d.mts +2 -0
- package/dist/vite/index.mjs +3 -0
- package/dist/vite/local-https.d.mts +47 -0
- package/dist/vite/local-https.mjs +276 -0
- package/dist/vite/local-https.mjs.map +1 -0
- package/dist/vite/mkcert.mjs +141 -0
- package/dist/vite/mkcert.mjs.map +1 -0
- package/dist/vue/cart.d.mts +46 -0
- package/dist/vue/cart.mjs +122 -0
- package/dist/vue/cart.mjs.map +1 -0
- package/dist/vue/collection.d.mts +46 -0
- package/dist/vue/collection.mjs +108 -0
- package/dist/vue/collection.mjs.map +1 -0
- package/dist/vue/index.d.mts +11 -0
- package/dist/vue/index.mjs +8 -0
- package/dist/vue/predictive-search.d.mts +124 -0
- package/dist/vue/predictive-search.mjs +171 -0
- package/dist/vue/predictive-search.mjs.map +1 -0
- package/dist/vue/product.d.mts +57 -0
- package/dist/vue/product.mjs +167 -0
- package/dist/vue/product.mjs.map +1 -0
- package/dist/vue/shop-pay.d.mts +25 -0
- package/dist/vue/shop-pay.mjs +35 -0
- package/dist/vue/shop-pay.mjs.map +1 -0
- package/dist/vue/shopify-scripts.d.mts +127 -0
- package/dist/vue/shopify-scripts.mjs +79 -0
- package/dist/vue/shopify-scripts.mjs.map +1 -0
- package/package.json +116 -86
- package/skills/hydrogen-analytics/SKILL.md +80 -0
- package/skills/hydrogen-analytics/references/react.md +160 -0
- package/skills/hydrogen-analytics/references/vue.md +80 -0
- package/skills/hydrogen-cart-drawer/SKILL.md +248 -0
- package/skills/hydrogen-cart-drawer/references/accessibility.md +109 -0
- package/skills/hydrogen-cart-drawer/references/css.md +67 -0
- package/skills/hydrogen-cart-ui/SKILL.md +224 -0
- package/skills/hydrogen-cart-ui/references/nextjs.md +89 -0
- package/skills/hydrogen-cart-ui/references/react.md +285 -0
- package/skills/hydrogen-cart-ui/references/vue.md +228 -0
- package/skills/hydrogen-collection-browser/SKILL.md +83 -0
- package/skills/hydrogen-collection-browser/references/nextjs.md +118 -0
- package/skills/hydrogen-collection-browser/references/nuxt.md +108 -0
- package/skills/hydrogen-collection-browser/references/react.md +301 -0
- package/skills/hydrogen-customer-account/SKILL.md +107 -0
- package/skills/hydrogen-image/SKILL.md +65 -0
- package/skills/hydrogen-local-https/SKILL.md +142 -0
- package/skills/hydrogen-markets/SKILL.md +221 -0
- package/skills/hydrogen-markets/references/nextjs.md +157 -0
- package/skills/hydrogen-money/SKILL.md +67 -0
- package/skills/hydrogen-oxygen/SKILL.md +245 -0
- package/skills/hydrogen-oxygen/references/react-router.md +230 -0
- package/skills/hydrogen-predictive-search/SKILL.md +130 -0
- package/skills/hydrogen-predictive-search/references/react.md +32 -0
- package/skills/hydrogen-predictive-search/references/vue.md +40 -0
- package/skills/hydrogen-request-handlers/SKILL.md +107 -0
- package/skills/hydrogen-request-handlers/references/frameworks.md +179 -0
- package/skills/hydrogen-request-handlers/references/nextjs.md +137 -0
- package/skills/hydrogen-request-handlers/references/nuxt.md +215 -0
- package/skills/hydrogen-routing/SKILL.md +171 -0
- package/skills/hydrogen-setup/SKILL.md +50 -0
- package/skills/hydrogen-setup/references/analytics.md +624 -0
- package/skills/hydrogen-setup/steps/1-inspect-app.md +62 -0
- package/skills/hydrogen-setup/steps/10-analytics.md +10 -0
- package/skills/hydrogen-setup/steps/11-verify.md +31 -0
- package/skills/hydrogen-setup/steps/2-scaffold.md +86 -0
- package/skills/hydrogen-setup/steps/3-build-home-page.md +37 -0
- package/skills/hydrogen-setup/steps/4-collection-and-search.md +14 -0
- package/skills/hydrogen-setup/steps/5-cart.md +10 -0
- package/skills/hydrogen-setup/steps/6-product-detail-page.md +416 -0
- package/skills/hydrogen-setup/steps/7-shopify-runtime-scripts.md +69 -0
- package/skills/hydrogen-setup/steps/8-cart-drawer-and-navbar.md +35 -0
- package/skills/hydrogen-setup/steps/9-account-page.md +54 -0
- package/skills/hydrogen-shop-pay/SKILL.md +79 -0
- package/skills/hydrogen-shop-pay/references/core.md +66 -0
- package/skills/hydrogen-shop-pay/references/react.md +50 -0
- package/skills/hydrogen-shop-pay/references/vue.md +39 -0
- package/skills/hydrogen-smoke-test/SKILL.md +205 -0
- package/skills/hydrogen-storefront-client/SKILL.md +322 -0
- package/skills/hydrogen-storefront-client/references/astro.md +125 -0
- package/skills/hydrogen-storefront-client/references/caching.md +25 -0
- package/skills/hydrogen-storefront-client/references/nextjs.md +121 -0
- package/skills/hydrogen-storefront-client/references/nuxt.md +121 -0
- package/skills/hydrogen-storefront-client/references/query-validation.md +95 -0
- package/skills/hydrogen-storefront-client/references/react-router.md +81 -0
- package/skills/hydrogen-storefront-client/references/solidstart.md +131 -0
- package/skills/hydrogen-storefront-client/references/sveltekit.md +169 -0
- package/skills/hydrogen-variant-form/SKILL.md +267 -0
- package/skills/hydrogen-variant-form/references/nextjs.md +207 -0
- package/skills/hydrogen-variant-form/references/nuxt.md +95 -0
- package/skills/hydrogen-variant-form/references/react.md +71 -0
- package/dist/dev/get-virtual-routes-H72465VB.js +0 -74
- package/dist/dev/hydrogen-routes.d.ts +0 -5
- package/dist/dev/hydrogen-routes.js +0 -25
- package/dist/development/get-virtual-routes-ACFZHU42.js +0 -71
- package/dist/development/get-virtual-routes-ACFZHU42.js.map +0 -1
- package/dist/development/index.cjs +0 -6978
- package/dist/development/index.cjs.map +0 -1
- package/dist/development/index.js +0 -6631
- package/dist/development/index.js.map +0 -1
- package/dist/development/log-seo-tags-IG37ONQ2.js +0 -74
- package/dist/development/log-seo-tags-IG37ONQ2.js.map +0 -1
- package/dist/development/react-router-preset.d.ts +0 -45
- package/dist/development/react-router-preset.js +0 -49
- package/dist/development/react-router-preset.js.map +0 -1
- package/dist/index.cjs +0 -1
- package/dist/oxygen/index.d.ts +0 -197
- package/dist/oxygen/index.js +0 -107
- package/dist/production/get-virtual-routes-ZZEGQQDV.js +0 -3
- package/dist/production/get-virtual-routes-ZZEGQQDV.js.map +0 -1
- package/dist/production/index.cjs +0 -1019
- package/dist/production/index.cjs.map +0 -1
- package/dist/production/index.d.cts +0 -3260
- package/dist/production/index.d.ts +0 -3260
- package/dist/production/index.js +0 -1019
- package/dist/production/index.js.map +0 -1
- package/dist/production/log-seo-tags-TY72EQWZ.js +0 -2
- package/dist/production/log-seo-tags-TY72EQWZ.js.map +0 -1
- package/dist/production/react-router-preset.d.ts +0 -45
- package/dist/production/react-router-preset.js +0 -11
- package/dist/react-router.d.ts +0 -75
- package/dist/vite/chunk-4O5OI3OO.js +0 -127
- package/dist/vite/chunk-FAQ7TVHC.js +0 -9
- package/dist/vite/chunk-QXBQVDMY.js +0 -68
- package/dist/vite/compat-date.d.ts +0 -3
- package/dist/vite/compat-date.js +0 -6
- package/dist/vite/get-virtual-routes.d.ts +0 -21
- package/dist/vite/get-virtual-routes.js +0 -74
- package/dist/vite/hydrogen-middleware.d.ts +0 -9
- package/dist/vite/hydrogen-middleware.js +0 -7
- package/dist/vite/plugin.d.ts +0 -22
- package/dist/vite/plugin.js +0 -171
- package/dist/vite/request-events.d.ts +0 -144
- package/dist/vite/request-events.js +0 -10
- package/dist/vite/types.d.ts +0 -5
- package/dist/vite/types.js +0 -0
- package/dist/vite/virtual-routes/assets/debug-network.css +0 -609
- package/dist/vite/virtual-routes/assets/favicon-dark.svg +0 -20
- package/dist/vite/virtual-routes/assets/favicon.svg +0 -28
- package/dist/vite/virtual-routes/assets/inter-variable-font.woff2 +0 -0
- package/dist/vite/virtual-routes/assets/jetbrainsmono-variable-font.woff2 +0 -0
- package/dist/vite/virtual-routes/assets/styles.css +0 -249
- package/dist/vite/virtual-routes/components/FlameChartWrapper.jsx +0 -123
- package/dist/vite/virtual-routes/components/HydrogenLogoBaseBW.jsx +0 -32
- package/dist/vite/virtual-routes/components/HydrogenLogoBaseColor.jsx +0 -47
- package/dist/vite/virtual-routes/components/IconBanner.jsx +0 -292
- package/dist/vite/virtual-routes/components/IconClose.jsx +0 -38
- package/dist/vite/virtual-routes/components/IconDiscard.jsx +0 -44
- package/dist/vite/virtual-routes/components/IconError.jsx +0 -61
- package/dist/vite/virtual-routes/components/IconGithub.jsx +0 -23
- package/dist/vite/virtual-routes/components/IconTwitter.jsx +0 -21
- package/dist/vite/virtual-routes/components/Layout.jsx +0 -7
- package/dist/vite/virtual-routes/components/RequestDetails.jsx +0 -171
- package/dist/vite/virtual-routes/components/RequestTable.jsx +0 -91
- package/dist/vite/virtual-routes/components/RequestWaterfall.jsx +0 -151
- package/dist/vite/virtual-routes/layout.jsx +0 -33
- package/dist/vite/virtual-routes/lib/useDebugNetworkServer.jsx +0 -178
- package/dist/vite/virtual-routes/routes/[.]well-known.appspecific.com[.]chrome[.]devtools[.]json.jsx +0 -37
- package/dist/vite/virtual-routes/routes/[.]well-known.appspecific.com[.]chrome[.]devtools[.]json.tsx +0 -79
- package/dist/vite/virtual-routes/routes/graphiql.jsx +0 -5
- package/dist/vite/virtual-routes/routes/index.jsx +0 -265
- package/dist/vite/virtual-routes/routes/subrequest-profiler.jsx +0 -243
- package/dist/vite/virtual-routes/virtual-root-with-layout.jsx +0 -63
- package/dist/vite/virtual-routes/virtual-root.jsx +0 -67
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-form.mjs","names":[],"sources":["../../../src/core/product/product-form.ts"],"sourcesContent":["import type { CartStore } from \"../cart/cart\";\nimport type {\n CartLine,\n CartNetworkEntry,\n CartState,\n CartUserError,\n CartWarning,\n} from \"../cart/state\";\nimport { createObservable } from \"../observable\";\nimport {\n buildProductOptions,\n type DecodedVariantCache,\n selectedOptionsFromMap,\n selectedOptionsToMap,\n} from \"./options\";\nimport type {\n ProductInput,\n ProductOptionValueFrom,\n ProductOptionValueInput,\n ProductVariantFrom,\n ProductVariantInput,\n SelectedOption,\n VariantOptionState,\n} from \"./state\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ProductFormErrors {\n userErrors: CartUserError[];\n warnings: CartWarning[];\n networkErrors: CartNetworkEntry[];\n}\n\n/** Live state snapshot emitted by a {@link ProductFormStore}. */\nexport interface ProductFormStoreState<\n TVariant extends ProductVariantInput = ProductVariantInput,\n TOptionValue extends ProductOptionValueInput = ProductOptionValueInput,\n> {\n options: VariantOptionState<TVariant, TOptionValue>[];\n selectedOptions: SelectedOption[];\n selectedVariant: TVariant | null;\n errors: ProductFormErrors;\n matchedLineItem: CartLine | null;\n}\n\nexport type ProductFormOptions<TProduct extends ProductInput = ProductInput> =\n ProductFormStoreState<ProductVariantFrom<TProduct>, ProductOptionValueFrom<TProduct>>[\"options\"];\n\n/**\n * Result returned by {@link ProductFormStore.selectOption}.\n *\n * - `resolved` — a specific variant was matched for the full selection.\n * - `unresolved` — the selection is valid but not yet complete.\n * - `invalid` — the option name or value does not exist on the product.\n */\nexport type VariantSelectionResult<TVariant extends ProductVariantInput = ProductVariantInput> =\n | {\n status: \"resolved\";\n selectedOptions: SelectedOption[];\n selectedVariant: TVariant;\n }\n | {\n status: \"unresolved\";\n selectedOptions: SelectedOption[];\n selectedVariant: null;\n }\n | {\n status: \"invalid\";\n selectedOptions: SelectedOption[];\n selectedVariant: null;\n reason: string;\n };\n\n/** A selection result that is not invalid — either resolved or unresolved. */\nexport type ValidProductSelectionResult<TProduct extends ProductInput = ProductInput> = Exclude<\n VariantSelectionResult<ProductVariantFrom<TProduct>>,\n { status: \"invalid\" }\n>;\n\nexport type CreateProductFormStoreOptions = {\n selectedOptions?: SelectedOption[];\n};\n\n/** Manages variant selection + cart integration for a product form. */\nexport interface ProductFormStore<\n TProduct extends ProductInput = ProductInput,\n TVariant extends ProductVariantInput = ProductVariantFrom<TProduct>,\n> {\n getState(): ProductFormStoreState<TVariant, ProductOptionValueFrom<TProduct>>;\n subscribe(\n listener: (state: ProductFormStoreState<TVariant, ProductOptionValueFrom<TProduct>>) => void,\n ): () => void;\n selectOption(name: string, value: string): VariantSelectionResult<TVariant>;\n hydrate(product: TProduct, opts?: { selectedOptions?: SelectedOption[] }): void;\n reset(): void;\n destroy(): void;\n handleFormSubmit(event: SubmitEvent): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\nexport function getSelectedVariant<TVariant extends ProductVariantInput>(\n options: VariantOptionState<TVariant, ProductOptionValueInput>[],\n): TVariant | null {\n return options[0]?.values.find((v) => v.selected)?.variant ?? null;\n}\n\nexport function canAddToCart<TProduct extends ProductInput>(\n product: TProduct,\n options: VariantOptionState<ProductVariantFrom<TProduct>, ProductOptionValueFrom<TProduct>>[],\n): boolean {\n if (product.requiresSellingPlan) return false;\n const variant = getSelectedVariant(options);\n return variant !== null && variant.availableForSale;\n}\n\n/**\n * Finds the first cart line whose merchandise ID matches.\n * When selling plans are used, the same merchandise ID can appear on multiple\n * cart lines — this returns the first match. Future attribute-based matching\n * will narrow to the exact line.\n */\nexport function findCartLineByMerchandiseId(\n lines: CartLine[],\n merchandiseId: string,\n): CartLine | null {\n return lines.find((l) => l.merchandise?.id === merchandiseId) ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Internal context\n// ---------------------------------------------------------------------------\n\ntype ProductFormStoreContext<TProduct extends ProductInput> = {\n observable: ReturnType<\n typeof createObservable<\n ProductFormStoreState<ProductVariantFrom<TProduct>, ProductOptionValueFrom<TProduct>>\n >\n >;\n cartStore: CartStore;\n currentProduct: TProduct;\n initialProduct: TProduct;\n initialSelectedOptions: SelectedOption[];\n decodedVariantCache: DecodedVariantCache;\n destroyed: boolean;\n unsubCart: () => void;\n};\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createProductFormStore<TProduct extends ProductInput>(\n product: TProduct,\n cartStore: CartStore,\n options: CreateProductFormStoreOptions = {},\n): ProductFormStore<TProduct, ProductVariantFrom<TProduct>> {\n const decodedVariantCache: DecodedVariantCache = new Map();\n const initialSelectedOptions = resolveSelectedOptions(product, options.selectedOptions);\n\n const variantState = buildVariantState(product, initialSelectedOptions, decodedVariantCache);\n\n const context: ProductFormStoreContext<TProduct> = {\n observable: createObservable(deriveFullState(variantState, cartStore.getState())),\n cartStore,\n currentProduct: product,\n initialProduct: product,\n initialSelectedOptions,\n decodedVariantCache,\n destroyed: false,\n unsubCart: () => {},\n };\n\n context.unsubCart = cartStore.subscribe(() => {\n if (context.destroyed) return;\n syncFromCart(context);\n });\n\n return {\n getState: () => context.observable.state,\n subscribe: (listener) => context.observable.subscribe(listener),\n selectOption: (name, value) => selectOption(context, name, value),\n hydrate: (nextProduct, opts) => hydrate(context, nextProduct, opts),\n reset: () => reset(context),\n destroy: () => destroy(context),\n handleFormSubmit: (event) => handleFormSubmit(context, event),\n };\n}\n\n// ---------------------------------------------------------------------------\n// State builders\n// ---------------------------------------------------------------------------\n\ntype VariantOnlyState<TProduct extends ProductInput> = {\n options: VariantOptionState<ProductVariantFrom<TProduct>, ProductOptionValueFrom<TProduct>>[];\n selectedOptions: SelectedOption[];\n};\n\nfunction buildVariantState<TProduct extends ProductInput>(\n product: TProduct,\n selectedOptions: SelectedOption[],\n cache: DecodedVariantCache,\n): VariantOnlyState<TProduct> {\n return {\n options: buildProductOptions(product, selectedOptions, cache),\n selectedOptions,\n };\n}\n\nfunction deriveFullState<TProduct extends ProductInput>(\n variant: VariantOnlyState<TProduct>,\n cartState: CartState,\n): ProductFormStoreState<ProductVariantFrom<TProduct>, ProductOptionValueFrom<TProduct>> {\n const selectedVariant = getSelectedVariant(variant.options);\n const matchedLineItem = selectedVariant\n ? findCartLineByMerchandiseId(cartState.data.lines.nodes, selectedVariant.id)\n : null;\n\n const lineErrors = matchedLineItem ? cartState.errors.lines.get(matchedLineItem.id) : undefined;\n\n return {\n options: variant.options,\n selectedOptions: variant.selectedOptions,\n selectedVariant,\n errors: {\n userErrors: [...cartState.errors.cart.userErrors, ...(lineErrors?.userErrors ?? [])],\n warnings: [...cartState.errors.cart.warnings, ...(lineErrors?.warnings ?? [])],\n networkErrors: cartState.errors.network,\n },\n matchedLineItem,\n };\n}\n\nfunction resolveSelectedOptions<TProduct extends ProductInput>(\n product: TProduct,\n requested?: SelectedOption[],\n): SelectedOption[] {\n return product.selectedOrFirstAvailableVariant?.selectedOptions ?? requested ?? [];\n}\n\n// ---------------------------------------------------------------------------\n// Actions\n// ---------------------------------------------------------------------------\n\nfunction selectOption<TProduct extends ProductInput>(\n context: ProductFormStoreContext<TProduct>,\n name: string,\n value: string,\n): VariantSelectionResult<ProductVariantFrom<TProduct>> {\n const { options, selectedOptions } = context.observable.state;\n const option = options.find((o) => o.name === name);\n const optionValue = option?.values.find((v) => v.name === value);\n\n if (!option || !optionValue) {\n return invalid(selectedOptions, `Unknown option \"${name}\" value \"${value}\".`);\n }\n\n if (!optionValue.exists) {\n return invalid(\n selectedOptions,\n `Option \"${name}\" value \"${value}\" does not resolve to a product variant.`,\n );\n }\n\n const nextSelectedOptionMap = {\n ...selectedOptionsToMap(selectedOptions),\n [name]: value,\n };\n const nextSelectedOptions = selectedOptionsFromMap(context.currentProduct, nextSelectedOptionMap);\n\n return applySelection(\n context,\n optionValue.variant\n ? {\n status: \"resolved\",\n selectedOptions: optionValue.variant.selectedOptions,\n selectedVariant: optionValue.variant as ProductVariantFrom<TProduct>,\n }\n : {\n status: \"unresolved\",\n selectedOptions: nextSelectedOptions,\n selectedVariant: null,\n },\n );\n}\n\nfunction hydrate<TProduct extends ProductInput>(\n context: ProductFormStoreContext<TProduct>,\n product: TProduct,\n opts: { selectedOptions?: SelectedOption[] } = {},\n): void {\n context.currentProduct = product;\n context.decodedVariantCache.clear();\n const selectedOptions =\n product.selectedOrFirstAvailableVariant?.selectedOptions ??\n opts.selectedOptions ??\n context.observable.state.selectedOptions;\n const variantState = buildVariantState(product, selectedOptions, context.decodedVariantCache);\n context.observable.setState(deriveFullState(variantState, context.cartStore.getState()));\n}\n\nfunction reset<TProduct extends ProductInput>(context: ProductFormStoreContext<TProduct>): void {\n context.currentProduct = context.initialProduct;\n context.decodedVariantCache.clear();\n const variantState = buildVariantState(\n context.initialProduct,\n context.initialSelectedOptions,\n context.decodedVariantCache,\n );\n context.observable.setState(deriveFullState(variantState, context.cartStore.getState()));\n}\n\nfunction destroy<TProduct extends ProductInput>(context: ProductFormStoreContext<TProduct>): void {\n context.destroyed = true;\n context.unsubCart();\n context.decodedVariantCache.clear();\n}\n\nfunction buildAddToCartDetail<TProduct extends ProductInput>(\n context: ProductFormStoreContext<TProduct>,\n): Record<string, unknown> | undefined {\n const { selectedVariant } = context.observable.state;\n if (!selectedVariant) return undefined;\n\n return {\n products: [\n {\n id: selectedVariant.id,\n title: selectedVariant.title,\n product: selectedVariant.product\n ? { title: selectedVariant.product.title, handle: selectedVariant.product.handle }\n : undefined,\n selectedOptions: selectedVariant.selectedOptions,\n image: selectedVariant.image,\n price: selectedVariant.price,\n },\n ],\n };\n}\n\nasync function handleFormSubmit<TProduct extends ProductInput>(\n context: ProductFormStoreContext<TProduct>,\n event: SubmitEvent,\n): Promise<void> {\n const eventDetail = buildAddToCartDetail(context);\n await context.cartStore.handleFormSubmit(event, eventDetail);\n}\n\nfunction applySelection<TProduct extends ProductInput>(\n context: ProductFormStoreContext<TProduct>,\n result: Exclude<VariantSelectionResult<ProductVariantFrom<TProduct>>, { status: \"invalid\" }>,\n): VariantSelectionResult<ProductVariantFrom<TProduct>> {\n const variantState = buildVariantState(\n context.currentProduct,\n result.selectedOptions,\n context.decodedVariantCache,\n );\n context.observable.setState(deriveFullState(variantState, context.cartStore.getState()));\n return result;\n}\n\nfunction hasCartDerivedFieldsChanged<TVariant extends ProductVariantInput>(\n prev: ProductFormStoreState<TVariant, ProductOptionValueInput>,\n next: ProductFormStoreState<TVariant, ProductOptionValueInput>,\n): boolean {\n return (\n prev.matchedLineItem !== next.matchedLineItem ||\n prev.selectedVariant !== next.selectedVariant ||\n prev.errors.userErrors !== next.errors.userErrors ||\n prev.errors.warnings !== next.errors.warnings ||\n prev.errors.networkErrors !== next.errors.networkErrors\n );\n}\n\nfunction syncFromCart<TProduct extends ProductInput>(\n context: ProductFormStoreContext<TProduct>,\n): void {\n const prev = context.observable.state;\n const next = deriveFullState(\n { options: prev.options, selectedOptions: prev.selectedOptions },\n context.cartStore.getState(),\n );\n\n if (hasCartDerivedFieldsChanged(prev, next)) {\n context.observable.setState(next);\n }\n}\n\nfunction invalid<TVariant extends ProductVariantInput>(\n selectedOptions: SelectedOption[],\n reason: string,\n): VariantSelectionResult<TVariant> {\n return {\n status: \"invalid\",\n selectedOptions,\n selectedVariant: null,\n reason,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
//#region src/core/product/state.d.ts
|
|
2
|
+
interface Money {
|
|
3
|
+
amount: string;
|
|
4
|
+
currencyCode: string;
|
|
5
|
+
}
|
|
6
|
+
interface ProductPriceRange {
|
|
7
|
+
minVariantPrice: Money;
|
|
8
|
+
maxVariantPrice?: Money;
|
|
9
|
+
}
|
|
10
|
+
interface SelectedOption {
|
|
11
|
+
name: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}
|
|
14
|
+
interface ProductVariantInput {
|
|
15
|
+
id: string;
|
|
16
|
+
title: string;
|
|
17
|
+
availableForSale: boolean;
|
|
18
|
+
selectedOptions: SelectedOption[];
|
|
19
|
+
price: Money;
|
|
20
|
+
compareAtPrice?: Money | null;
|
|
21
|
+
image?: unknown;
|
|
22
|
+
product?: {
|
|
23
|
+
handle: string;
|
|
24
|
+
title?: string | null;
|
|
25
|
+
} | null;
|
|
26
|
+
sku?: string | null;
|
|
27
|
+
}
|
|
28
|
+
interface ProductOptionInput<TVariant extends ProductVariantInput = ProductVariantInput> {
|
|
29
|
+
name: string;
|
|
30
|
+
optionValues: Array<ProductOptionValueInput<TVariant>>;
|
|
31
|
+
}
|
|
32
|
+
interface ProductOptionValueInput<TVariant extends ProductVariantInput = ProductVariantInput> {
|
|
33
|
+
name: string;
|
|
34
|
+
firstSelectableVariant?: TVariant | null;
|
|
35
|
+
swatch?: unknown;
|
|
36
|
+
}
|
|
37
|
+
interface ProductInput<TVariant extends ProductVariantInput = ProductVariantInput> {
|
|
38
|
+
id: string;
|
|
39
|
+
title: string;
|
|
40
|
+
handle: string;
|
|
41
|
+
vendor?: string | null;
|
|
42
|
+
priceRange?: ProductPriceRange;
|
|
43
|
+
requiresSellingPlan?: boolean | null;
|
|
44
|
+
encodedVariantExistence?: string | null;
|
|
45
|
+
encodedVariantAvailability?: string | null;
|
|
46
|
+
options: ProductOptionInput<TVariant>[];
|
|
47
|
+
selectedOrFirstAvailableVariant: TVariant | null;
|
|
48
|
+
adjacentVariants: TVariant[];
|
|
49
|
+
}
|
|
50
|
+
type ProductVariantFrom<TProduct extends ProductInput> = TProduct extends ProductInput<infer TVariant> ? TVariant : ProductVariantInput;
|
|
51
|
+
type ProductOptionValueFrom<TProduct extends ProductInput> = TProduct["options"][number]["optionValues"][number];
|
|
52
|
+
interface VariantOptionValueState<TVariant extends ProductVariantInput = ProductVariantInput, TOptionValue extends ProductOptionValueInput = ProductOptionValueInput> {
|
|
53
|
+
name: string;
|
|
54
|
+
swatch?: TOptionValue["swatch"];
|
|
55
|
+
selected: boolean;
|
|
56
|
+
exists: boolean;
|
|
57
|
+
available: boolean;
|
|
58
|
+
variant: TVariant | null;
|
|
59
|
+
selectedOptions: SelectedOption[];
|
|
60
|
+
handle: string;
|
|
61
|
+
}
|
|
62
|
+
interface VariantOptionState<TVariant extends ProductVariantInput = ProductVariantInput, TOptionValue extends ProductOptionValueInput = ProductOptionValueInput> {
|
|
63
|
+
name: string;
|
|
64
|
+
values: VariantOptionValueState<TVariant, TOptionValue>[];
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { ProductInput, ProductOptionInput, ProductOptionValueFrom, ProductOptionValueInput, ProductVariantFrom, ProductVariantInput, SelectedOption, VariantOptionState, VariantOptionValueState };
|
|
68
|
+
//# sourceMappingURL=state.d.mts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { SelectedOption } from "./state.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/core/product/url.d.ts
|
|
4
|
+
type ProductSelectionLinkStyle = "options" | "variant";
|
|
5
|
+
/**
|
|
6
|
+
* Builds the search params for a product-page link representing a variant selection.
|
|
7
|
+
*
|
|
8
|
+
* Existing `base` params are preserved (`?ref=campaign` survives navigation), except the
|
|
9
|
+
* reserved `variant` param and every param named in `optionNames` or `selectedOptions`,
|
|
10
|
+
* which are always removed before the new selection is written. This keeps stale selection
|
|
11
|
+
* state from leaking between navigations, including across combined-listing products.
|
|
12
|
+
*
|
|
13
|
+
* Two link styles:
|
|
14
|
+
* - `"options"` (default): one param per selected option, e.g. `?Color=Red&Size=M`.
|
|
15
|
+
* - `"variant"`: a single `?variant=<numeric id>` param (Liquid parity), for shareable
|
|
16
|
+
* links. Falls back to option params when `variant` is absent — a partial selection has
|
|
17
|
+
* no matching variant, so a variant link is not constructible.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const searchParams = buildProductSelectionSearchParams({
|
|
22
|
+
* selectedOptions: result.selectedOptions,
|
|
23
|
+
* variant: result.selectedVariant,
|
|
24
|
+
* optionNames: product.options.map((option) => option.name),
|
|
25
|
+
* base: new URLSearchParams(location.search),
|
|
26
|
+
* });
|
|
27
|
+
* const url = `/products/${handle}${searchParams.size ? `?${searchParams}` : ""}`;
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
declare function buildProductSelectionSearchParams({
|
|
31
|
+
style,
|
|
32
|
+
selectedOptions,
|
|
33
|
+
variant,
|
|
34
|
+
optionNames,
|
|
35
|
+
base
|
|
36
|
+
}: {
|
|
37
|
+
style?: ProductSelectionLinkStyle;
|
|
38
|
+
selectedOptions: readonly SelectedOption[];
|
|
39
|
+
variant?: {
|
|
40
|
+
id: string;
|
|
41
|
+
} | null;
|
|
42
|
+
optionNames: readonly string[];
|
|
43
|
+
base?: URLSearchParams;
|
|
44
|
+
}): URLSearchParams;
|
|
45
|
+
//#endregion
|
|
46
|
+
export { ProductSelectionLinkStyle, buildProductSelectionSearchParams };
|
|
47
|
+
//# sourceMappingURL=url.d.mts.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//#region src/core/product/url.ts
|
|
2
|
+
const VARIANT_GID_PREFIX = "gid://shopify/ProductVariant/";
|
|
3
|
+
/**
|
|
4
|
+
* Reserved product-page search param carrying a numeric variant id (`?variant=41820371452004`),
|
|
5
|
+
* matching Liquid storefront URLs. Never treated as a product option name.
|
|
6
|
+
*/
|
|
7
|
+
const VARIANT_SEARCH_PARAM = "variant";
|
|
8
|
+
/**
|
|
9
|
+
* Converts a `?variant=` search param value into a variant id (gid).
|
|
10
|
+
*
|
|
11
|
+
* Anything that is not a plain positive integer of a plausible length is treated as absent
|
|
12
|
+
* (`null`) so malformed links degrade to the default variant instead of producing invalid
|
|
13
|
+
* API lookups or log spam.
|
|
14
|
+
*/
|
|
15
|
+
function parseVariantSearchParam(value) {
|
|
16
|
+
if (!value || !/^\d{1,30}$/.test(value)) return null;
|
|
17
|
+
return `${VARIANT_GID_PREFIX}${value}`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Extracts the numeric `?variant=` search param value from a variant id (gid).
|
|
21
|
+
* Returns `null` for ids that are not canonical `gid://shopify/ProductVariant/<numeric>` ids.
|
|
22
|
+
*/
|
|
23
|
+
function getVariantSearchParamValue(variantId) {
|
|
24
|
+
if (!variantId.startsWith(VARIANT_GID_PREFIX)) return null;
|
|
25
|
+
const numericId = variantId.slice(29);
|
|
26
|
+
return /^\d+$/.test(numericId) ? numericId : null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Builds the search params for a product-page link representing a variant selection.
|
|
30
|
+
*
|
|
31
|
+
* Existing `base` params are preserved (`?ref=campaign` survives navigation), except the
|
|
32
|
+
* reserved `variant` param and every param named in `optionNames` or `selectedOptions`,
|
|
33
|
+
* which are always removed before the new selection is written. This keeps stale selection
|
|
34
|
+
* state from leaking between navigations, including across combined-listing products.
|
|
35
|
+
*
|
|
36
|
+
* Two link styles:
|
|
37
|
+
* - `"options"` (default): one param per selected option, e.g. `?Color=Red&Size=M`.
|
|
38
|
+
* - `"variant"`: a single `?variant=<numeric id>` param (Liquid parity), for shareable
|
|
39
|
+
* links. Falls back to option params when `variant` is absent — a partial selection has
|
|
40
|
+
* no matching variant, so a variant link is not constructible.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const searchParams = buildProductSelectionSearchParams({
|
|
45
|
+
* selectedOptions: result.selectedOptions,
|
|
46
|
+
* variant: result.selectedVariant,
|
|
47
|
+
* optionNames: product.options.map((option) => option.name),
|
|
48
|
+
* base: new URLSearchParams(location.search),
|
|
49
|
+
* });
|
|
50
|
+
* const url = `/products/${handle}${searchParams.size ? `?${searchParams}` : ""}`;
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
function buildProductSelectionSearchParams({ style = "options", selectedOptions, variant, optionNames, base }) {
|
|
54
|
+
const searchParams = new URLSearchParams(base);
|
|
55
|
+
searchParams.delete(VARIANT_SEARCH_PARAM);
|
|
56
|
+
for (const name of optionNames) searchParams.delete(name);
|
|
57
|
+
for (const option of selectedOptions) searchParams.delete(option.name);
|
|
58
|
+
const variantSearchParamValue = style === "variant" && variant ? getVariantSearchParamValue(variant.id) : null;
|
|
59
|
+
if (variantSearchParamValue) {
|
|
60
|
+
searchParams.set(VARIANT_SEARCH_PARAM, variantSearchParamValue);
|
|
61
|
+
return searchParams;
|
|
62
|
+
}
|
|
63
|
+
for (const option of selectedOptions) searchParams.set(option.name, option.value);
|
|
64
|
+
return searchParams;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//#endregion
|
|
68
|
+
export { VARIANT_SEARCH_PARAM, buildProductSelectionSearchParams, parseVariantSearchParam };
|
|
69
|
+
//# sourceMappingURL=url.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.mjs","names":[],"sources":["../../../src/core/product/url.ts"],"sourcesContent":["import type { SelectedOption } from \"./state\";\n\nconst VARIANT_GID_PREFIX = \"gid://shopify/ProductVariant/\";\n\n/**\n * Reserved product-page search param carrying a numeric variant id (`?variant=41820371452004`),\n * matching Liquid storefront URLs. Never treated as a product option name.\n */\nexport const VARIANT_SEARCH_PARAM = \"variant\";\n\n/**\n * Converts a `?variant=` search param value into a variant id (gid).\n *\n * Anything that is not a plain positive integer of a plausible length is treated as absent\n * (`null`) so malformed links degrade to the default variant instead of producing invalid\n * API lookups or log spam.\n */\nexport function parseVariantSearchParam(value: string | null): string | null {\n if (!value || !/^\\d{1,30}$/.test(value)) return null;\n return `${VARIANT_GID_PREFIX}${value}`;\n}\n\n/**\n * Extracts the numeric `?variant=` search param value from a variant id (gid).\n * Returns `null` for ids that are not canonical `gid://shopify/ProductVariant/<numeric>` ids.\n */\nexport function getVariantSearchParamValue(variantId: string): string | null {\n if (!variantId.startsWith(VARIANT_GID_PREFIX)) return null;\n\n const numericId = variantId.slice(VARIANT_GID_PREFIX.length);\n return /^\\d+$/.test(numericId) ? numericId : null;\n}\n\nexport type ProductSelectionLinkStyle = \"options\" | \"variant\";\n\n/**\n * Builds the search params for a product-page link representing a variant selection.\n *\n * Existing `base` params are preserved (`?ref=campaign` survives navigation), except the\n * reserved `variant` param and every param named in `optionNames` or `selectedOptions`,\n * which are always removed before the new selection is written. This keeps stale selection\n * state from leaking between navigations, including across combined-listing products.\n *\n * Two link styles:\n * - `\"options\"` (default): one param per selected option, e.g. `?Color=Red&Size=M`.\n * - `\"variant\"`: a single `?variant=<numeric id>` param (Liquid parity), for shareable\n * links. Falls back to option params when `variant` is absent — a partial selection has\n * no matching variant, so a variant link is not constructible.\n *\n * @example\n * ```ts\n * const searchParams = buildProductSelectionSearchParams({\n * selectedOptions: result.selectedOptions,\n * variant: result.selectedVariant,\n * optionNames: product.options.map((option) => option.name),\n * base: new URLSearchParams(location.search),\n * });\n * const url = `/products/${handle}${searchParams.size ? `?${searchParams}` : \"\"}`;\n * ```\n */\nexport function buildProductSelectionSearchParams({\n style = \"options\",\n selectedOptions,\n variant,\n optionNames,\n base,\n}: {\n style?: ProductSelectionLinkStyle;\n selectedOptions: readonly SelectedOption[];\n variant?: { id: string } | null;\n optionNames: readonly string[];\n base?: URLSearchParams;\n}): URLSearchParams {\n const searchParams = new URLSearchParams(base);\n\n searchParams.delete(VARIANT_SEARCH_PARAM);\n for (const name of optionNames) searchParams.delete(name);\n for (const option of selectedOptions) searchParams.delete(option.name);\n\n const variantSearchParamValue =\n style === \"variant\" && variant ? getVariantSearchParamValue(variant.id) : null;\n\n if (variantSearchParamValue) {\n searchParams.set(VARIANT_SEARCH_PARAM, variantSearchParamValue);\n return searchParams;\n }\n\n for (const option of selectedOptions) {\n searchParams.set(option.name, option.value);\n }\n\n return searchParams;\n}\n"],"mappings":";AAEA,MAAM,qBAAqB;;;;;AAM3B,MAAa,uBAAuB;;;;;;;;AASpC,SAAgB,wBAAwB,OAAqC;AAC3E,KAAI,CAAC,SAAS,CAAC,aAAa,KAAK,MAAM,CAAE,QAAO;AAChD,QAAO,GAAG,qBAAqB;;;;;;AAOjC,SAAgB,2BAA2B,WAAkC;AAC3E,KAAI,CAAC,UAAU,WAAW,mBAAmB,CAAE,QAAO;CAEtD,MAAM,YAAY,UAAU,MAAM,GAA0B;AAC5D,QAAO,QAAQ,KAAK,UAAU,GAAG,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8B/C,SAAgB,kCAAkC,EAChD,QAAQ,WACR,iBACA,SACA,aACA,QAOkB;CAClB,MAAM,eAAe,IAAI,gBAAgB,KAAK;AAE9C,cAAa,OAAO,qBAAqB;AACzC,MAAK,MAAM,QAAQ,YAAa,cAAa,OAAO,KAAK;AACzD,MAAK,MAAM,UAAU,gBAAiB,cAAa,OAAO,OAAO,KAAK;CAEtE,MAAM,0BACJ,UAAU,aAAa,UAAU,2BAA2B,QAAQ,GAAG,GAAG;AAE5E,KAAI,yBAAyB;AAC3B,eAAa,IAAI,sBAAsB,wBAAwB;AAC/D,SAAO;;AAGT,MAAK,MAAM,UAAU,gBACnB,cAAa,IAAI,OAAO,MAAM,OAAO,MAAM;AAG7C,QAAO"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { CountryCode, LanguageCode } from "../graphql/generated/customer-account-api-types.mjs";
|
|
2
|
+
import { CountryCode as CountryCode$1, LanguageCode as LanguageCode$1 } from "../graphql/generated/storefront-api-types.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/core/request-context.d.ts
|
|
5
|
+
type StorefrontRequest = Pick<Request, "headers"> & Partial<Pick<Request, "method" | "signal" | "url">>;
|
|
6
|
+
type ShopifyLanguageCode = Extract<LanguageCode$1, LanguageCode>;
|
|
7
|
+
type ShopifyCountryCode = Extract<CountryCode$1, CountryCode>;
|
|
8
|
+
type I18nConfig = {
|
|
9
|
+
language: ShopifyLanguageCode;
|
|
10
|
+
country: ShopifyCountryCode; /** Optional app route prefix for localized paths, for example "/es-es". */
|
|
11
|
+
pathPrefix?: string;
|
|
12
|
+
};
|
|
13
|
+
type NormalizedI18nConfig<I18n extends I18nConfig = I18nConfig> = Omit<I18n, "pathPrefix"> & {
|
|
14
|
+
pathPrefix: string;
|
|
15
|
+
};
|
|
16
|
+
type ShopifyRequestContextInputBase<I18n extends I18nConfig = I18nConfig> = {
|
|
17
|
+
request: StorefrontRequest;
|
|
18
|
+
i18n: I18n;
|
|
19
|
+
};
|
|
20
|
+
type ShopifyRequestContextInput<I18n extends I18nConfig = I18nConfig> = ShopifyRequestContextInputBase<I18n> & {
|
|
21
|
+
buyerIp?: never;
|
|
22
|
+
};
|
|
23
|
+
type ShopifyRequestContextWithBuyerIpInput<I18n extends I18nConfig = I18nConfig> = ShopifyRequestContextInputBase<I18n> & {
|
|
24
|
+
buyerIp: string;
|
|
25
|
+
};
|
|
26
|
+
type ShopifyRequestContextBase = {
|
|
27
|
+
/**
|
|
28
|
+
* Compile-time brand so callers use createShopifyRequestContext().
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
readonly __hydrogenShopifyRequestContextBrand: never; /** @internal */
|
|
32
|
+
cookie?: string; /** @internal */
|
|
33
|
+
uniqueToken?: string; /** @internal */
|
|
34
|
+
visitToken?: string; /** @internal */
|
|
35
|
+
legacyTokens?: boolean; /** @internal */
|
|
36
|
+
readonly buyerIp?: string; /** @internal */
|
|
37
|
+
requestGroupId: string; /** @internal */
|
|
38
|
+
signal?: AbortSignal; /** @internal */
|
|
39
|
+
url?: string; /** @internal */
|
|
40
|
+
storefrontOrigin?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Apply request-scoped headers required by every Shopify storefront subrequest.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
applyStorefrontRequestHeaders(headers: Headers): void;
|
|
46
|
+
/**
|
|
47
|
+
* Capture the first fresh storefront response headers for replay onto the final app response.
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
captureSubrequestHeaders(headers: Headers): void;
|
|
51
|
+
/**
|
|
52
|
+
* Consume storefront proxy response state for gated replay onto the final app response.
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
55
|
+
consumeStorefrontResponseHeaders(headers: Headers): void;
|
|
56
|
+
/**
|
|
57
|
+
* Mark the final app response as influenced by private customer state.
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
markResponseAsPersonalized(reason: string): void;
|
|
61
|
+
i18n: NormalizedI18nConfig; /** Return incoming request headers plus request lifecycle headers for proxy/origin handoff. */
|
|
62
|
+
getForwardedRequestHeaders(): Headers; /** Apply important response headers for the correct functioning of Hydrogen storefronts. */
|
|
63
|
+
applyResponseHeaders(headers: Headers): void;
|
|
64
|
+
};
|
|
65
|
+
type ShopifyRequestContext<I18n extends I18nConfig = I18nConfig> = ShopifyRequestContextBase & {
|
|
66
|
+
i18n: NormalizedI18nConfig<I18n>;
|
|
67
|
+
};
|
|
68
|
+
type ShopifyRequestContextWithBuyerIp<I18n extends I18nConfig = I18nConfig> = ShopifyRequestContext<I18n> & {
|
|
69
|
+
readonly buyerIp: string;
|
|
70
|
+
};
|
|
71
|
+
declare function createShopifyRequestContext<const I18n extends I18nConfig>(input: ShopifyRequestContextWithBuyerIpInput<I18n>): ShopifyRequestContextWithBuyerIp<I18n>;
|
|
72
|
+
declare function createShopifyRequestContext<const I18n extends I18nConfig>(input: ShopifyRequestContextInput<I18n>): ShopifyRequestContext<I18n>;
|
|
73
|
+
//#endregion
|
|
74
|
+
export { I18nConfig, ShopifyRequestContext, ShopifyRequestContextWithBuyerIp, createShopifyRequestContext };
|
|
75
|
+
//# sourceMappingURL=request-context.d.mts.map
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { normalizePathPrefix } from "./standard-routes/path.mjs";
|
|
2
|
+
import { STOREFRONT_API_VERSION } from "./constants.mjs";
|
|
3
|
+
import { CONSENT_MANAGEMENT_HEADER, HYDROGEN_VERSION_HEADER, REQUEST_GROUP_ID_HEADER, SDK_VARIANT_HEADER, SDK_VARIANT_SOURCE_HEADER, SDK_VERSION_HEADER, SERVER_TIMING_HEADER, SHOPIFY_STOREFRONT_ORIGIN_HEADER, SHOPIFY_STOREFRONT_S_HEADER, SHOPIFY_STOREFRONT_Y_HEADER, SHOPIFY_UNIQUE_TOKEN_HEADER, SHOPIFY_VISIT_TOKEN_HEADER, STOREFRONT_URL_HEADER, applyPrivateResponseCacheHeaders } from "./headers.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/core/request-context.ts
|
|
6
|
+
const SHOPIFY_ESSENTIAL_COOKIE = "_shopify_essential";
|
|
7
|
+
const SHOPIFY_TRACKING_COOKIES = ["_shopify_analytics", "_shopify_marketing"];
|
|
8
|
+
const SHOPIFY_COOKIES = new Set([SHOPIFY_ESSENTIAL_COOKIE, ...SHOPIFY_TRACKING_COOKIES]);
|
|
9
|
+
function createShopifyRequestContext(input) {
|
|
10
|
+
const { request } = input;
|
|
11
|
+
if (!input.i18n?.country || !input.i18n?.language) throw new Error("i18n with country and language is required for Shopify request contexts.");
|
|
12
|
+
if (input.buyerIp !== void 0 && !input.buyerIp) throw new Error("buyerIp must be non-empty when provided");
|
|
13
|
+
const requestMethod = request.method?.toUpperCase();
|
|
14
|
+
const i18n = normalizeI18n(input.i18n);
|
|
15
|
+
const cookieHeader = request.headers.get("cookie") || void 0;
|
|
16
|
+
const inboundCookies = parseCookieHeader(cookieHeader);
|
|
17
|
+
const hasEssentialCookie = inboundCookies.has(SHOPIFY_ESSENTIAL_COOKIE);
|
|
18
|
+
const hasTrackingCookie = SHOPIFY_TRACKING_COOKIES.some((name) => inboundCookies.has(name));
|
|
19
|
+
const isConsentManagementRequest = request.headers.get(CONSENT_MANAGEMENT_HEADER) === "1";
|
|
20
|
+
const url = request.url ?? request.headers.get("x-storefront-url") ?? void 0;
|
|
21
|
+
const storefrontOrigin = getUrlOrigin(url);
|
|
22
|
+
const context = {
|
|
23
|
+
...cookieHeader && { cookie: cookieHeader },
|
|
24
|
+
i18n,
|
|
25
|
+
...url && { url },
|
|
26
|
+
...storefrontOrigin && { storefrontOrigin },
|
|
27
|
+
...input.buyerIp && { buyerIp: input.buyerIp },
|
|
28
|
+
requestGroupId: request.headers.get("Custom-Storefront-Request-Group-ID") ?? request.headers.get("x-request-id") ?? request.headers.get("request-id") ?? crypto.randomUUID(),
|
|
29
|
+
...isDocumentRequest(request) && { documentRequest: true },
|
|
30
|
+
...request.signal && { signal: request.signal }
|
|
31
|
+
};
|
|
32
|
+
let capturedSubrequestHeaders;
|
|
33
|
+
let personalizedResponseReason;
|
|
34
|
+
const captureSubrequestHeaders = (headers) => {
|
|
35
|
+
capturedSubrequestHeaders ??= {
|
|
36
|
+
serverTiming: headers.get("Server-Timing") ?? "",
|
|
37
|
+
setCookie: headers.getSetCookie()
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
if (!hasTrackingCookie) {
|
|
41
|
+
const legacyUniqueToken = inboundCookies.get("_shopify_y");
|
|
42
|
+
const legacyVisitToken = inboundCookies.get("_shopify_s");
|
|
43
|
+
const headerUniqueToken = request.headers.get("X-Shopify-UniqueToken") ?? void 0;
|
|
44
|
+
const headerVisitToken = request.headers.get("X-Shopify-VisitToken") ?? void 0;
|
|
45
|
+
if (legacyUniqueToken || legacyVisitToken) context.legacyTokens = true;
|
|
46
|
+
context.uniqueToken = legacyUniqueToken ?? headerUniqueToken;
|
|
47
|
+
context.visitToken = legacyVisitToken ?? headerVisitToken;
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
...context,
|
|
51
|
+
getForwardedRequestHeaders() {
|
|
52
|
+
const headers = new Headers(request.headers);
|
|
53
|
+
applyStorefrontRequestHeaders(context, headers);
|
|
54
|
+
if (context.url) headers.set(STOREFRONT_URL_HEADER, context.url);
|
|
55
|
+
return headers;
|
|
56
|
+
},
|
|
57
|
+
applyStorefrontRequestHeaders(headers) {
|
|
58
|
+
applyStorefrontRequestHeaders(context, headers);
|
|
59
|
+
},
|
|
60
|
+
captureSubrequestHeaders,
|
|
61
|
+
consumeStorefrontResponseHeaders(headers) {
|
|
62
|
+
if (headers.has("Server-Timing") || headers.getSetCookie().length > 0) captureSubrequestHeaders(headers);
|
|
63
|
+
headers.delete("set-cookie");
|
|
64
|
+
headers.delete(SERVER_TIMING_HEADER);
|
|
65
|
+
},
|
|
66
|
+
markResponseAsPersonalized(reason) {
|
|
67
|
+
personalizedResponseReason ??= reason;
|
|
68
|
+
},
|
|
69
|
+
applyResponseHeaders(headers) {
|
|
70
|
+
headers.set("powered-by", "Shopify, Hydrogen");
|
|
71
|
+
const isDocumentResponse = context.documentRequest || (headers.get("content-type")?.startsWith("text/html") ?? false);
|
|
72
|
+
const mayReturnShopifyState = requestMethod !== void 0 && requestMethod !== "GET" && requestMethod !== "HEAD" && !isDocumentResponse && (hasEssentialCookie || isConsentManagementRequest);
|
|
73
|
+
if (capturedSubrequestHeaders && mayReturnShopifyState) {
|
|
74
|
+
const existingSetCookies = new Set(headers.getSetCookie());
|
|
75
|
+
for (const value of capturedSubrequestHeaders.setCookie) {
|
|
76
|
+
if (existingSetCookies.has(value)) continue;
|
|
77
|
+
headers.append("set-cookie", value);
|
|
78
|
+
existingSetCookies.add(value);
|
|
79
|
+
}
|
|
80
|
+
const capturedServerTiming = capturedSubrequestHeaders.serverTiming;
|
|
81
|
+
const existingServerTiming = headers.get("Server-Timing") ?? "";
|
|
82
|
+
if (capturedServerTiming !== "" && existingServerTiming !== capturedServerTiming && !existingServerTiming.startsWith(`${capturedServerTiming}, `) && !existingServerTiming.endsWith(`, ${capturedServerTiming}`)) headers.set(SERVER_TIMING_HEADER, existingServerTiming ? `${existingServerTiming}, ${capturedServerTiming}` : capturedServerTiming);
|
|
83
|
+
}
|
|
84
|
+
const returnsCapturedState = mayReturnShopifyState && Boolean(capturedSubrequestHeaders?.serverTiming || capturedSubrequestHeaders?.setCookie.length);
|
|
85
|
+
if (personalizedResponseReason || returnsCapturedState || headers.getSetCookie().some(isShopifySetCookie)) applyPrivateResponseCacheHeaders(headers);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function normalizeI18n(i18n) {
|
|
90
|
+
return {
|
|
91
|
+
...i18n,
|
|
92
|
+
pathPrefix: normalizePathPrefix(i18n.pathPrefix)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function applyStorefrontRequestHeaders(context, headers) {
|
|
96
|
+
headers.set(SDK_VARIANT_HEADER, "hydrogen");
|
|
97
|
+
headers.set(SDK_VARIANT_SOURCE_HEADER, "kit");
|
|
98
|
+
headers.set(SDK_VERSION_HEADER, STOREFRONT_API_VERSION);
|
|
99
|
+
headers.set(HYDROGEN_VERSION_HEADER, "2026.10.0-preview.2");
|
|
100
|
+
headers.set(REQUEST_GROUP_ID_HEADER, context.requestGroupId);
|
|
101
|
+
if (context.cookie) headers.set("cookie", context.cookie);
|
|
102
|
+
else headers.delete("cookie");
|
|
103
|
+
if (context.storefrontOrigin) headers.set(SHOPIFY_STOREFRONT_ORIGIN_HEADER, context.storefrontOrigin);
|
|
104
|
+
else headers.delete(SHOPIFY_STOREFRONT_ORIGIN_HEADER);
|
|
105
|
+
if (context.uniqueToken) headers.set(SHOPIFY_UNIQUE_TOKEN_HEADER, context.uniqueToken);
|
|
106
|
+
if (context.visitToken) headers.set(SHOPIFY_VISIT_TOKEN_HEADER, context.visitToken);
|
|
107
|
+
if (context.legacyTokens && context.uniqueToken) headers.set(SHOPIFY_STOREFRONT_Y_HEADER, context.uniqueToken);
|
|
108
|
+
if (context.legacyTokens && context.visitToken) headers.set(SHOPIFY_STOREFRONT_S_HEADER, context.visitToken);
|
|
109
|
+
}
|
|
110
|
+
function getUrlOrigin(url) {
|
|
111
|
+
if (!url) return void 0;
|
|
112
|
+
try {
|
|
113
|
+
return new URL(url).origin;
|
|
114
|
+
} catch {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function isDocumentRequest(request) {
|
|
119
|
+
if (request.method && request.method !== "GET" && request.method !== "HEAD") return false;
|
|
120
|
+
if (request.headers.get("sec-fetch-dest") === "document") return true;
|
|
121
|
+
return request.headers.get("accept")?.includes("text/html") ?? false;
|
|
122
|
+
}
|
|
123
|
+
function parseCookieHeader(cookieHeader) {
|
|
124
|
+
const cookies = /* @__PURE__ */ new Map();
|
|
125
|
+
if (!cookieHeader) return cookies;
|
|
126
|
+
for (const cookie of cookieHeader.split(";")) {
|
|
127
|
+
const separator = cookie.indexOf("=");
|
|
128
|
+
if (separator < 0) continue;
|
|
129
|
+
const name = cookie.slice(0, separator).trim();
|
|
130
|
+
if (!cookies.has(name)) cookies.set(name, cookie.slice(separator + 1));
|
|
131
|
+
}
|
|
132
|
+
return cookies;
|
|
133
|
+
}
|
|
134
|
+
function isShopifySetCookie(value) {
|
|
135
|
+
const name = value.match(/^\s*([^=;\s]+)\s*=/)?.[1];
|
|
136
|
+
return name !== void 0 && SHOPIFY_COOKIES.has(name);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
//#endregion
|
|
140
|
+
export { createShopifyRequestContext };
|
|
141
|
+
//# sourceMappingURL=request-context.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context.mjs","names":[],"sources":["../../src/core/request-context.ts"],"sourcesContent":["import type {\n CountryCode as CustomerAccountCountryCode,\n LanguageCode as CustomerAccountLanguageCode,\n} from \"../graphql/generated/customer-account-api-types\";\nimport type {\n CountryCode as StorefrontCountryCode,\n LanguageCode as StorefrontLanguageCode,\n} from \"../graphql/generated/storefront-api-types\";\nimport { STOREFRONT_API_VERSION } from \"./constants\";\nimport {\n applyPrivateResponseCacheHeaders,\n CONSENT_MANAGEMENT_HEADER,\n HYDROGEN_VERSION_HEADER,\n REQUEST_GROUP_ID_HEADER,\n SDK_VARIANT_HEADER,\n SDK_VARIANT_SOURCE_HEADER,\n SDK_VERSION_HEADER,\n SERVER_TIMING_HEADER,\n SHOPIFY_STOREFRONT_ORIGIN_HEADER,\n SHOPIFY_STOREFRONT_S_HEADER,\n SHOPIFY_STOREFRONT_Y_HEADER,\n SHOPIFY_UNIQUE_TOKEN_HEADER,\n SHOPIFY_VISIT_TOKEN_HEADER,\n STOREFRONT_URL_HEADER,\n} from \"./headers\";\nimport { normalizePathPrefix } from \"./standard-routes/path\";\n\nconst SHOPIFY_ESSENTIAL_COOKIE = \"_shopify_essential\";\nconst SHOPIFY_TRACKING_COOKIES = [\"_shopify_analytics\", \"_shopify_marketing\"];\nconst SHOPIFY_COOKIES = new Set([SHOPIFY_ESSENTIAL_COOKIE, ...SHOPIFY_TRACKING_COOKIES]);\n\ntype StorefrontRequest = Pick<Request, \"headers\"> &\n Partial<Pick<Request, \"method\" | \"signal\" | \"url\">>;\n\nexport type ShopifyLanguageCode = Extract<StorefrontLanguageCode, CustomerAccountLanguageCode>;\nexport type ShopifyCountryCode = Extract<StorefrontCountryCode, CustomerAccountCountryCode>;\n\nexport type I18nConfig = {\n language: ShopifyLanguageCode;\n country: ShopifyCountryCode;\n /** Optional app route prefix for localized paths, for example \"/es-es\". */\n pathPrefix?: string;\n};\n\ntype NormalizedI18nConfig<I18n extends I18nConfig = I18nConfig> = Omit<I18n, \"pathPrefix\"> & {\n pathPrefix: string;\n};\n\ntype ShopifyRequestContextInputBase<I18n extends I18nConfig = I18nConfig> = {\n request: StorefrontRequest;\n i18n: I18n;\n};\n\ntype ShopifyRequestContextInput<I18n extends I18nConfig = I18nConfig> =\n ShopifyRequestContextInputBase<I18n> & { buyerIp?: never };\n\ntype ShopifyRequestContextWithBuyerIpInput<I18n extends I18nConfig = I18nConfig> =\n ShopifyRequestContextInputBase<I18n> & { buyerIp: string };\n\ntype ShopifyRequestContextBase = {\n // -- Private fields --\n /**\n * Compile-time brand so callers use createShopifyRequestContext().\n * @internal\n */\n readonly __hydrogenShopifyRequestContextBrand: never;\n /** @internal */\n cookie?: string;\n /** @internal */\n uniqueToken?: string;\n /** @internal */\n visitToken?: string;\n /** @internal */\n legacyTokens?: boolean;\n /** @internal */\n readonly buyerIp?: string;\n /** @internal */\n requestGroupId: string;\n /** @internal */\n signal?: AbortSignal;\n /** @internal */\n url?: string;\n /** @internal */\n storefrontOrigin?: string;\n /**\n * Apply request-scoped headers required by every Shopify storefront subrequest.\n * @internal\n */\n applyStorefrontRequestHeaders(headers: Headers): void;\n /**\n * Capture the first fresh storefront response headers for replay onto the final app response.\n * @internal\n */\n captureSubrequestHeaders(headers: Headers): void;\n /**\n * Consume storefront proxy response state for gated replay onto the final app response.\n * @internal\n */\n consumeStorefrontResponseHeaders(headers: Headers): void;\n /**\n * Mark the final app response as influenced by private customer state.\n * @internal\n */\n markResponseAsPersonalized(reason: string): void;\n\n // -- Public fields --\n i18n: NormalizedI18nConfig;\n /** Return incoming request headers plus request lifecycle headers for proxy/origin handoff. */\n getForwardedRequestHeaders(): Headers;\n /** Apply important response headers for the correct functioning of Hydrogen storefronts. */\n applyResponseHeaders(headers: Headers): void;\n};\n\nexport type ShopifyRequestContext<I18n extends I18nConfig = I18nConfig> =\n ShopifyRequestContextBase & {\n i18n: NormalizedI18nConfig<I18n>;\n };\n\nexport type ShopifyRequestContextWithBuyerIp<I18n extends I18nConfig = I18nConfig> =\n ShopifyRequestContext<I18n> & { readonly buyerIp: string };\n\ntype Context<I18n extends I18nConfig = I18nConfig> = {\n cookie?: string;\n uniqueToken?: string;\n visitToken?: string;\n legacyTokens?: boolean;\n buyerIp?: string;\n requestGroupId: string;\n signal?: AbortSignal;\n url?: string;\n storefrontOrigin?: string;\n i18n: NormalizedI18nConfig<I18n>;\n documentRequest?: boolean;\n};\n\nexport function createShopifyRequestContext<const I18n extends I18nConfig>(\n input: ShopifyRequestContextWithBuyerIpInput<I18n>,\n): ShopifyRequestContextWithBuyerIp<I18n>;\nexport function createShopifyRequestContext<const I18n extends I18nConfig>(\n input: ShopifyRequestContextInput<I18n>,\n): ShopifyRequestContext<I18n>;\nexport function createShopifyRequestContext<const I18n extends I18nConfig>(\n input: ShopifyRequestContextInputBase<I18n> & { buyerIp?: string },\n): ShopifyRequestContext<I18n> {\n const { request } = input;\n\n if (!input.i18n?.country || !input.i18n?.language) {\n throw new Error(\"i18n with country and language is required for Shopify request contexts.\");\n }\n\n if (input.buyerIp !== undefined && !input.buyerIp) {\n throw new Error(\"buyerIp must be non-empty when provided\");\n }\n\n const requestMethod = request.method?.toUpperCase();\n const i18n = normalizeI18n(input.i18n);\n const cookieHeader = request.headers.get(\"cookie\") || undefined;\n const inboundCookies = parseCookieHeader(cookieHeader);\n const hasEssentialCookie = inboundCookies.has(SHOPIFY_ESSENTIAL_COOKIE);\n const hasTrackingCookie = SHOPIFY_TRACKING_COOKIES.some((name) => inboundCookies.has(name));\n const isConsentManagementRequest = request.headers.get(CONSENT_MANAGEMENT_HEADER) === \"1\";\n const url = request.url ?? request.headers.get(STOREFRONT_URL_HEADER) ?? undefined;\n const storefrontOrigin = getUrlOrigin(url);\n const context = {\n ...(cookieHeader && { cookie: cookieHeader }),\n i18n,\n ...(url && { url }),\n ...(storefrontOrigin && { storefrontOrigin }),\n ...(input.buyerIp && { buyerIp: input.buyerIp }),\n requestGroupId:\n request.headers.get(REQUEST_GROUP_ID_HEADER) ??\n request.headers.get(\"x-request-id\") ??\n request.headers.get(\"request-id\") ??\n crypto.randomUUID(),\n ...(isDocumentRequest(request) && { documentRequest: true }),\n ...(request.signal && { signal: request.signal }),\n } as Context<I18n>;\n\n let capturedSubrequestHeaders:\n | {\n serverTiming: string;\n setCookie: string[];\n }\n | undefined;\n let personalizedResponseReason: string | undefined;\n\n const captureSubrequestHeaders = (headers: Headers): void => {\n // Capture this the first time we get a fresh response to increase the\n // chance of returning it from the main server response. The main response\n // needs headers set at send time, while the body can stream later, so this\n // may not be used if subrequests finish after the main response is sent.\n capturedSubrequestHeaders ??= {\n serverTiming: headers.get(SERVER_TIMING_HEADER) ?? \"\",\n setCookie: headers.getSetCookie(),\n };\n };\n\n if (!hasTrackingCookie) {\n const legacyUniqueToken = inboundCookies.get(\"_shopify_y\");\n const legacyVisitToken = inboundCookies.get(\"_shopify_s\");\n const headerUniqueToken = request.headers.get(SHOPIFY_UNIQUE_TOKEN_HEADER) ?? undefined;\n const headerVisitToken = request.headers.get(SHOPIFY_VISIT_TOKEN_HEADER) ?? undefined;\n\n if (legacyUniqueToken || legacyVisitToken) context.legacyTokens = true;\n\n context.uniqueToken = legacyUniqueToken ?? headerUniqueToken;\n context.visitToken = legacyVisitToken ?? headerVisitToken;\n }\n\n return {\n ...context,\n getForwardedRequestHeaders() {\n const headers = new Headers(request.headers);\n applyStorefrontRequestHeaders(context, headers);\n if (context.url) headers.set(STOREFRONT_URL_HEADER, context.url);\n return headers;\n },\n applyStorefrontRequestHeaders(headers) {\n applyStorefrontRequestHeaders(context, headers);\n },\n captureSubrequestHeaders,\n consumeStorefrontResponseHeaders(headers) {\n if (headers.has(SERVER_TIMING_HEADER) || headers.getSetCookie().length > 0) {\n captureSubrequestHeaders(headers);\n }\n headers.delete(\"set-cookie\");\n headers.delete(SERVER_TIMING_HEADER);\n },\n markResponseAsPersonalized(reason) {\n personalizedResponseReason ??= reason;\n },\n applyResponseHeaders(headers) {\n headers.set(\"powered-by\", \"Shopify, Hydrogen\");\n\n // Documents may be shared or streamed, so they must not carry buyer-specific state.\n const isDocumentResponse =\n context.documentRequest || (headers.get(\"content-type\")?.startsWith(\"text/html\") ?? false);\n\n // Keep GET and HEAD responses cacheable, and fail closed when the request method is unknown.\n // Cold sessions may only be established by the explicitly marked consent request.\n const mayReturnShopifyState =\n requestMethod !== undefined &&\n requestMethod !== \"GET\" &&\n requestMethod !== \"HEAD\" &&\n !isDocumentResponse &&\n (hasEssentialCookie || isConsentManagementRequest);\n\n // Replay state captured from fresh SFAPI and proxy responses when allowed.\n if (capturedSubrequestHeaders && mayReturnShopifyState) {\n const existingSetCookies = new Set(headers.getSetCookie());\n for (const value of capturedSubrequestHeaders.setCookie) {\n if (existingSetCookies.has(value)) continue;\n headers.append(\"set-cookie\", value);\n existingSetCookies.add(value);\n }\n\n const capturedServerTiming = capturedSubrequestHeaders.serverTiming;\n const existingServerTiming = headers.get(SERVER_TIMING_HEADER) ?? \"\";\n const shouldAppendServerTiming =\n capturedServerTiming !== \"\" &&\n existingServerTiming !== capturedServerTiming &&\n !existingServerTiming.startsWith(`${capturedServerTiming}, `) &&\n !existingServerTiming.endsWith(`, ${capturedServerTiming}`);\n if (shouldAppendServerTiming) {\n headers.set(\n SERVER_TIMING_HEADER,\n existingServerTiming\n ? `${existingServerTiming}, ${capturedServerTiming}`\n : capturedServerTiming,\n );\n }\n }\n\n // Responses containing buyer-specific or replayed state must not enter shared caches.\n const returnsCapturedState =\n mayReturnShopifyState &&\n Boolean(\n capturedSubrequestHeaders?.serverTiming || capturedSubrequestHeaders?.setCookie.length,\n );\n\n if (\n personalizedResponseReason ||\n returnsCapturedState ||\n headers.getSetCookie().some(isShopifySetCookie)\n ) {\n applyPrivateResponseCacheHeaders(headers);\n }\n },\n } as ShopifyRequestContext<I18n>;\n}\n\nfunction normalizeI18n<I18n extends I18nConfig>(i18n: I18n): NormalizedI18nConfig<I18n> {\n return {\n ...i18n,\n pathPrefix: normalizePathPrefix(i18n.pathPrefix),\n } as NormalizedI18nConfig<I18n>;\n}\n\nfunction applyStorefrontRequestHeaders(context: Context, headers: Headers): void {\n headers.set(SDK_VARIANT_HEADER, \"hydrogen\");\n headers.set(SDK_VARIANT_SOURCE_HEADER, \"kit\");\n headers.set(SDK_VERSION_HEADER, STOREFRONT_API_VERSION);\n headers.set(HYDROGEN_VERSION_HEADER, __HYDROGEN_VERSION__);\n headers.set(REQUEST_GROUP_ID_HEADER, context.requestGroupId);\n\n if (context.cookie) headers.set(\"cookie\", context.cookie);\n else headers.delete(\"cookie\");\n if (context.storefrontOrigin) {\n headers.set(SHOPIFY_STOREFRONT_ORIGIN_HEADER, context.storefrontOrigin);\n } else headers.delete(SHOPIFY_STOREFRONT_ORIGIN_HEADER);\n\n // Some Storefront API consumers still rely on these headers instead of cookies.\n if (context.uniqueToken) headers.set(SHOPIFY_UNIQUE_TOKEN_HEADER, context.uniqueToken);\n if (context.visitToken) headers.set(SHOPIFY_VISIT_TOKEN_HEADER, context.visitToken);\n if (context.legacyTokens && context.uniqueToken) {\n headers.set(SHOPIFY_STOREFRONT_Y_HEADER, context.uniqueToken);\n }\n if (context.legacyTokens && context.visitToken) {\n headers.set(SHOPIFY_STOREFRONT_S_HEADER, context.visitToken);\n }\n}\n\nfunction getUrlOrigin(url: string | undefined): string | undefined {\n if (!url) return undefined;\n try {\n return new URL(url).origin;\n } catch {\n return undefined;\n }\n}\n\nfunction isDocumentRequest(request: StorefrontRequest): boolean {\n if (request.method && request.method !== \"GET\" && request.method !== \"HEAD\") return false;\n\n const destination = request.headers.get(\"sec-fetch-dest\");\n if (destination === \"document\") return true;\n\n return request.headers.get(\"accept\")?.includes(\"text/html\") ?? false;\n}\n\nfunction parseCookieHeader(cookieHeader: string | undefined): Map<string, string> {\n const cookies = new Map<string, string>();\n if (!cookieHeader) return cookies;\n\n for (const cookie of cookieHeader.split(\";\")) {\n const separator = cookie.indexOf(\"=\");\n if (separator < 0) continue;\n\n const name = cookie.slice(0, separator).trim();\n if (!cookies.has(name)) cookies.set(name, cookie.slice(separator + 1));\n }\n\n return cookies;\n}\n\nfunction isShopifySetCookie(value: string): boolean {\n const name = value.match(/^\\s*([^=;\\s]+)\\s*=/)?.[1];\n return name !== undefined && SHOPIFY_COOKIES.has(name);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StorefrontClient } from "../../client/types.mjs";
|
|
2
|
+
import { ShopifyRouteTemplates } from "../standard-routes/types.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/core/request-routing/handle-shopify-redirects.d.ts
|
|
5
|
+
type RedirectOptions = {
|
|
6
|
+
request: Request;
|
|
7
|
+
storefrontClient: StorefrontClient;
|
|
8
|
+
routeTemplates: ShopifyRouteTemplates;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Resolves Shopify redirects after framework routing returns a 404. Matched
|
|
12
|
+
* responses already include request-context response headers.
|
|
13
|
+
*/
|
|
14
|
+
declare function handleShopifyRedirects(options: RedirectOptions): Promise<Response | null>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { RedirectOptions, handleShopifyRedirects };
|
|
17
|
+
//# sourceMappingURL=handle-shopify-redirects.d.mts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getLogger } from "../logging/logging.mjs";
|
|
2
|
+
import { handleAdminRedirect } from "./interceptors/admin-redirect.mjs";
|
|
3
|
+
import { handleQueryParamRedirect } from "./interceptors/query-param-redirect.mjs";
|
|
4
|
+
import { handleUrlRedirects } from "./interceptors/url-redirects.mjs";
|
|
5
|
+
import { handleStandardRouteRedirects } from "./interceptors/standard-routes.mjs";
|
|
6
|
+
import { safeApplyResponseHeaders } from "./safe-apply-response-headers.mjs";
|
|
7
|
+
|
|
8
|
+
//#region src/core/request-routing/handle-shopify-redirects.ts
|
|
9
|
+
const log = getLogger("redirects");
|
|
10
|
+
/**
|
|
11
|
+
* Resolves Shopify redirects after framework routing returns a 404. Matched
|
|
12
|
+
* responses already include request-context response headers.
|
|
13
|
+
*/
|
|
14
|
+
async function handleShopifyRedirects(options) {
|
|
15
|
+
const { request, storefrontClient } = options;
|
|
16
|
+
let redirect = null;
|
|
17
|
+
try {
|
|
18
|
+
redirect = handleAdminRedirect(options);
|
|
19
|
+
redirect ??= handleStandardRouteRedirects(options);
|
|
20
|
+
redirect ??= handleQueryParamRedirect(request);
|
|
21
|
+
redirect ??= await handleUrlRedirects(options);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
const url = new URL(request.url);
|
|
24
|
+
log.error(`failed to resolve Shopify redirects for route ${url.pathname}`, { error });
|
|
25
|
+
}
|
|
26
|
+
return redirect ? safeApplyResponseHeaders(redirect, storefrontClient.requestContext) : null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { handleShopifyRedirects };
|
|
31
|
+
//# sourceMappingURL=handle-shopify-redirects.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-shopify-redirects.mjs","names":[],"sources":["../../../src/core/request-routing/handle-shopify-redirects.ts"],"sourcesContent":["import type { StorefrontClient } from \"../../client\";\nimport { getLogger } from \"../logging\";\nimport type { ShopifyRouteTemplates } from \"../standard-routes/index\";\nimport { handleAdminRedirect } from \"./interceptors/admin-redirect\";\nimport { handleQueryParamRedirect } from \"./interceptors/query-param-redirect\";\nimport { handleStandardRouteRedirects } from \"./interceptors/standard-routes\";\nimport { handleUrlRedirects } from \"./interceptors/url-redirects\";\nimport { safeApplyResponseHeaders } from \"./safe-apply-response-headers\";\n\nconst log = getLogger(\"redirects\");\n\nexport type RedirectOptions = {\n request: Request;\n storefrontClient: StorefrontClient;\n routeTemplates: ShopifyRouteTemplates;\n};\n\n/**\n * Resolves Shopify redirects after framework routing returns a 404. Matched\n * responses already include request-context response headers.\n */\nexport async function handleShopifyRedirects(options: RedirectOptions): Promise<Response | null> {\n const { request, storefrontClient } = options;\n let redirect: Response | null = null;\n\n try {\n redirect = handleAdminRedirect(options);\n redirect ??= handleStandardRouteRedirects(options);\n redirect ??= handleQueryParamRedirect(request);\n redirect ??= await handleUrlRedirects(options);\n } catch (error) {\n const url = new URL(request.url);\n log.error(`failed to resolve Shopify redirects for route ${url.pathname}`, { error });\n }\n\n return redirect ? safeApplyResponseHeaders(redirect, storefrontClient.requestContext) : null;\n}\n"],"mappings":";;;;;;;;AASA,MAAM,MAAM,UAAU,YAAY;;;;;AAYlC,eAAsB,uBAAuB,SAAoD;CAC/F,MAAM,EAAE,SAAS,qBAAqB;CACtC,IAAI,WAA4B;AAEhC,KAAI;AACF,aAAW,oBAAoB,QAAQ;AACvC,eAAa,6BAA6B,QAAQ;AAClD,eAAa,yBAAyB,QAAQ;AAC9C,eAAa,MAAM,mBAAmB,QAAQ;UACvC,OAAO;EACd,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;AAChC,MAAI,MAAM,iDAAiD,IAAI,YAAY,EAAE,OAAO,CAAC;;AAGvF,QAAO,WAAW,yBAAyB,UAAU,iBAAiB,eAAe,GAAG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { HydrogenRouteHandler } from "./route-types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/core/request-routing/handle-shopify-routes.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Matches a request against Shopify standard routes and any registered handler
|
|
6
|
+
* groups, returning a raw `Response` (redirect or JSON) when one matches, or
|
|
7
|
+
* `null` when none do. Use it as the first step of request handling, before
|
|
8
|
+
* framework routing. Matched responses already include request-context
|
|
9
|
+
* response headers.
|
|
10
|
+
*/
|
|
11
|
+
declare const handleShopifyRoutes: HydrogenRouteHandler;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { handleShopifyRoutes };
|
|
14
|
+
//# sourceMappingURL=handle-shopify-routes.d.mts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { safeApplyResponseHeaders } from "./safe-apply-response-headers.mjs";
|
|
2
|
+
import { handleProductVariantId } from "../product/accept-variant-id.mjs";
|
|
3
|
+
import { handleAjaxApi } from "./interceptors/ajax-api.mjs";
|
|
4
|
+
import { handleShopifyApiProxy } from "./interceptors/api-proxy.mjs";
|
|
5
|
+
import { handleCheckoutRedirect } from "./interceptors/checkout.mjs";
|
|
6
|
+
import { handleMcpProxy } from "./interceptors/mcp-proxy.mjs";
|
|
7
|
+
import { handleSfapiProxy } from "./interceptors/sfapi-proxy.mjs";
|
|
8
|
+
import { handleWellKnownProxy } from "./interceptors/well-known.mjs";
|
|
9
|
+
import { handleShopifyRouteHandlers } from "./registered-routes.mjs";
|
|
10
|
+
|
|
11
|
+
//#region src/core/request-routing/handle-shopify-routes.ts
|
|
12
|
+
const SHOPIFY_ROUTE_INTERCEPTORS = [
|
|
13
|
+
handleShopifyApiProxy,
|
|
14
|
+
handleSfapiProxy,
|
|
15
|
+
handleProductVariantId,
|
|
16
|
+
handleShopifyRouteHandlers,
|
|
17
|
+
handleCheckoutRedirect,
|
|
18
|
+
handleWellKnownProxy,
|
|
19
|
+
handleMcpProxy,
|
|
20
|
+
handleAjaxApi
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Matches a request against Shopify standard routes and any registered handler
|
|
24
|
+
* groups, returning a raw `Response` (redirect or JSON) when one matches, or
|
|
25
|
+
* `null` when none do. Use it as the first step of request handling, before
|
|
26
|
+
* framework routing. Matched responses already include request-context
|
|
27
|
+
* response headers.
|
|
28
|
+
*/
|
|
29
|
+
const handleShopifyRoutes = (options) => {
|
|
30
|
+
if (options.requestContext !== options.storefrontClient.requestContext) throw new Error("handleShopifyRoutes must receive the same requestContext used by storefrontClient.");
|
|
31
|
+
const url = new URL(options.request.url);
|
|
32
|
+
for (const interceptor of SHOPIFY_ROUTE_INTERCEPTORS) {
|
|
33
|
+
const responsePromise = interceptor(url, options);
|
|
34
|
+
if (!responsePromise) continue;
|
|
35
|
+
return responsePromise.then((response) => safeApplyResponseHeaders(response, options.requestContext));
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { handleShopifyRoutes };
|
|
42
|
+
//# sourceMappingURL=handle-shopify-routes.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-shopify-routes.mjs","names":[],"sources":["../../../src/core/request-routing/handle-shopify-routes.ts"],"sourcesContent":["import { handleProductVariantId } from \"../product/accept-variant-id\";\nimport { handleAjaxApi } from \"./interceptors/ajax-api\";\nimport { handleShopifyApiProxy } from \"./interceptors/api-proxy\";\nimport { handleCheckoutRedirect } from \"./interceptors/checkout\";\nimport { handleMcpProxy } from \"./interceptors/mcp-proxy\";\nimport { handleSfapiProxy } from \"./interceptors/sfapi-proxy\";\nimport { handleWellKnownProxy } from \"./interceptors/well-known\";\nimport { handleShopifyRouteHandlers } from \"./registered-routes\";\nimport type { HydrogenRouteHandler, HydrogenRouteInterceptor } from \"./route-types\";\nimport { safeApplyResponseHeaders } from \"./safe-apply-response-headers\";\n\nconst SHOPIFY_ROUTE_INTERCEPTORS = [\n handleShopifyApiProxy,\n handleSfapiProxy,\n handleProductVariantId,\n handleShopifyRouteHandlers,\n handleCheckoutRedirect,\n handleWellKnownProxy,\n handleMcpProxy,\n handleAjaxApi,\n] satisfies readonly HydrogenRouteInterceptor[];\n\n/**\n * Matches a request against Shopify standard routes and any registered handler\n * groups, returning a raw `Response` (redirect or JSON) when one matches, or\n * `null` when none do. Use it as the first step of request handling, before\n * framework routing. Matched responses already include request-context\n * response headers.\n */\nexport const handleShopifyRoutes: HydrogenRouteHandler = (options) => {\n if (options.requestContext !== options.storefrontClient.requestContext) {\n throw new Error(\n \"handleShopifyRoutes must receive the same requestContext used by storefrontClient.\",\n );\n }\n\n const url = new URL(options.request.url);\n\n for (const interceptor of SHOPIFY_ROUTE_INTERCEPTORS) {\n const responsePromise = interceptor(url, options);\n if (!responsePromise) continue;\n\n return responsePromise.then((response) =>\n safeApplyResponseHeaders(response, options.requestContext),\n );\n }\n\n return null;\n};\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,6BAA6B;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;;;;;AASD,MAAa,uBAA6C,YAAY;AACpE,KAAI,QAAQ,mBAAmB,QAAQ,iBAAiB,eACtD,OAAM,IAAI,MACR,qFACD;CAGH,MAAM,MAAM,IAAI,IAAI,QAAQ,QAAQ,IAAI;AAExC,MAAK,MAAM,eAAe,4BAA4B;EACpD,MAAM,kBAAkB,YAAY,KAAK,QAAQ;AACjD,MAAI,CAAC,gBAAiB;AAEtB,SAAO,gBAAgB,MAAM,aAC3B,yBAAyB,UAAU,QAAQ,eAAe,CAC3D;;AAGH,QAAO"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/core/request-routing/interceptors/admin-redirect.ts
|
|
2
|
+
function handleAdminRedirect({ request, storefrontClient }) {
|
|
3
|
+
if (new URL(request.url).pathname !== "/admin") return null;
|
|
4
|
+
return new Response(null, {
|
|
5
|
+
status: 301,
|
|
6
|
+
headers: { location: new URL("/admin", storefrontClient.storeUrl).toString() }
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { handleAdminRedirect };
|
|
12
|
+
//# sourceMappingURL=admin-redirect.mjs.map
|