@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,1707 @@
|
|
|
1
|
+
import { getLogger } from "../logging/logging.mjs";
|
|
2
|
+
import { createObservable } from "../observable.mjs";
|
|
3
|
+
import { SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT, VISITOR_CONSENT_COLLECTED_EVENT } from "../shopify-scripts/constants.mjs";
|
|
4
|
+
import { getCartAttributeFormEntries } from "./form.mjs";
|
|
5
|
+
import { DEFAULT_MINIMUM_QUANTITY, sanitizeQuantity } from "./quantity.mjs";
|
|
6
|
+
import { createCartState, createEmptyCartState, createEmptyErrorGroup } from "./state.mjs";
|
|
7
|
+
import { syncQuantityInputs } from "./sync-quantity-inputs.mjs";
|
|
8
|
+
|
|
9
|
+
//#region src/core/cart/cart.ts
|
|
10
|
+
const log = getLogger("cart");
|
|
11
|
+
const OPTIMISTIC_LINE_ID_PREFIX = "optimistic:";
|
|
12
|
+
const LINE_KEY_PREFIX = "line:";
|
|
13
|
+
const MERCHANDISE_KEY_PREFIX = "merchandise:";
|
|
14
|
+
const DISCOUNT_KEY_PREFIX = "discount:";
|
|
15
|
+
const NOTE_KEY = "note";
|
|
16
|
+
const ATTRIBUTES_KEY = "attributes";
|
|
17
|
+
const DISCOUNT_CODES_KEY = "discount-codes";
|
|
18
|
+
const REVALIDATION_ERROR_KEY = "cart-revalidation";
|
|
19
|
+
const TRANSACTION_EVENT_TOKEN_KEY = "__shopifyHydrogenCartTransaction";
|
|
20
|
+
const DEFAULT_ADD_QUANTITY = 1;
|
|
21
|
+
const NOOP = () => {};
|
|
22
|
+
const EMPTY_QUANTITY = 0;
|
|
23
|
+
const FNV1A_OFFSET_BASIS = 2166136261;
|
|
24
|
+
const FNV1A_PRIME = 16777619;
|
|
25
|
+
const CART_REVALIDATION_ERROR_MESSAGE = "Something went wrong refreshing your cart. Please try again.";
|
|
26
|
+
const STANDARD_ACTION_TIMEOUT_IN_MS = 3e4;
|
|
27
|
+
var CartNetworkError = class extends Error {
|
|
28
|
+
status;
|
|
29
|
+
constructor(status) {
|
|
30
|
+
super("Something went wrong updating your cart. Please try again.");
|
|
31
|
+
this.name = "CartNetworkError";
|
|
32
|
+
this.status = status;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
function defineTransactionTypes(definitions) {
|
|
36
|
+
return definitions;
|
|
37
|
+
}
|
|
38
|
+
function getTransactionDefinition(type) {
|
|
39
|
+
return CART_TRANSACTION_TYPES[type];
|
|
40
|
+
}
|
|
41
|
+
let configuredCartEndpoint = null;
|
|
42
|
+
let hasConfiguredUpdateCart = false;
|
|
43
|
+
let standardActionsPromise = null;
|
|
44
|
+
const connectedCartStores = /* @__PURE__ */ new Set();
|
|
45
|
+
let cartConsentListenerAttached = false;
|
|
46
|
+
function getLines(cart) {
|
|
47
|
+
return cart.lines.nodes;
|
|
48
|
+
}
|
|
49
|
+
function setLines(cart, lines) {
|
|
50
|
+
if (cart.lines.nodes === lines) return cart;
|
|
51
|
+
return {
|
|
52
|
+
...cart,
|
|
53
|
+
lines: {
|
|
54
|
+
...cart.lines,
|
|
55
|
+
nodes: lines
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function reconcileCartLines(cart, lines) {
|
|
60
|
+
const currentLines = getLines(cart);
|
|
61
|
+
if (currentLines === lines) return cart;
|
|
62
|
+
const currentLoadedQuantity = currentLines.reduce((total, line) => total + line.quantity, EMPTY_QUANTITY);
|
|
63
|
+
const nextLoadedQuantity = lines.reduce((total, line) => total + line.quantity, EMPTY_QUANTITY);
|
|
64
|
+
const totalQuantity = cart.totalQuantity + nextLoadedQuantity - currentLoadedQuantity;
|
|
65
|
+
return setLines({
|
|
66
|
+
...cart,
|
|
67
|
+
totalQuantity
|
|
68
|
+
}, lines);
|
|
69
|
+
}
|
|
70
|
+
function normalizeKeys(keys) {
|
|
71
|
+
if (keys === void 0) return [];
|
|
72
|
+
return typeof keys === "string" ? [keys] : [...new Set(keys)];
|
|
73
|
+
}
|
|
74
|
+
function lineKey(lineId) {
|
|
75
|
+
return `${LINE_KEY_PREFIX}${lineId}`;
|
|
76
|
+
}
|
|
77
|
+
function compareAttributes(left, right) {
|
|
78
|
+
if (left.key !== right.key) return left.key < right.key ? -1 : 1;
|
|
79
|
+
if (left.value === null) return right.value === null ? 0 : -1;
|
|
80
|
+
if (right.value === null) return 1;
|
|
81
|
+
if (left.value !== right.value) return left.value < right.value ? -1 : 1;
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
function normalizeAttributes(attributes) {
|
|
85
|
+
if (!attributes?.length) return [];
|
|
86
|
+
return attributes.toSorted(compareAttributes);
|
|
87
|
+
}
|
|
88
|
+
function sameAttributes(left, right) {
|
|
89
|
+
const normalizedLeft = normalizeAttributes(left);
|
|
90
|
+
const normalizedRight = normalizeAttributes(right);
|
|
91
|
+
if (normalizedLeft.length !== normalizedRight.length) return false;
|
|
92
|
+
return normalizedLeft.every((attribute, index) => attribute.key === normalizedRight[index].key && attribute.value === normalizedRight[index].value);
|
|
93
|
+
}
|
|
94
|
+
function hashString(value) {
|
|
95
|
+
let hash = FNV1A_OFFSET_BASIS;
|
|
96
|
+
for (const character of value) {
|
|
97
|
+
hash ^= character.codePointAt(0) ?? 0;
|
|
98
|
+
hash = Math.imul(hash, FNV1A_PRIME);
|
|
99
|
+
}
|
|
100
|
+
return (hash >>> 0).toString(36);
|
|
101
|
+
}
|
|
102
|
+
function merchandiseKey(line) {
|
|
103
|
+
return `${MERCHANDISE_KEY_PREFIX}${JSON.stringify({
|
|
104
|
+
merchandiseId: line.merchandiseId,
|
|
105
|
+
sellingPlanId: line.sellingPlanId ?? null,
|
|
106
|
+
attributes: normalizeAttributes(line.attributes)
|
|
107
|
+
})}`;
|
|
108
|
+
}
|
|
109
|
+
function isRecord(value) {
|
|
110
|
+
return typeof value === "object" && value !== null;
|
|
111
|
+
}
|
|
112
|
+
function isAttribute(value) {
|
|
113
|
+
return isRecord(value) && typeof value.key === "string" && typeof value.value === "string";
|
|
114
|
+
}
|
|
115
|
+
function parseMerchandiseKey(key) {
|
|
116
|
+
if (!key.startsWith(MERCHANDISE_KEY_PREFIX)) return void 0;
|
|
117
|
+
const value = key.slice(12);
|
|
118
|
+
let parsed;
|
|
119
|
+
try {
|
|
120
|
+
parsed = JSON.parse(value);
|
|
121
|
+
} catch {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (!isRecord(parsed) || typeof parsed.merchandiseId !== "string") return void 0;
|
|
125
|
+
if (parsed.sellingPlanId !== null && typeof parsed.sellingPlanId !== "string") return void 0;
|
|
126
|
+
if (!Array.isArray(parsed.attributes) || !parsed.attributes.every(isAttribute)) return void 0;
|
|
127
|
+
const attributes = normalizeAttributes(parsed.attributes);
|
|
128
|
+
return {
|
|
129
|
+
merchandiseId: parsed.merchandiseId,
|
|
130
|
+
...parsed.sellingPlanId ? { sellingPlanId: parsed.sellingPlanId } : {},
|
|
131
|
+
...attributes.length > 0 ? { attributes } : {}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function optimisticLineId(line) {
|
|
135
|
+
const sellingPlanSuffix = line.sellingPlanId ? `:${line.sellingPlanId}` : "";
|
|
136
|
+
const attributes = normalizeAttributes(line.attributes);
|
|
137
|
+
const attributesSuffix = attributes.length > 0 ? `:${hashString(JSON.stringify(attributes))}` : "";
|
|
138
|
+
return `${OPTIMISTIC_LINE_ID_PREFIX}${line.merchandiseId}${sellingPlanSuffix}${attributesSuffix}`;
|
|
139
|
+
}
|
|
140
|
+
function cartResponseFromStandardEvent(cart) {
|
|
141
|
+
const response = cart;
|
|
142
|
+
const lines = Array.isArray(cart.lines) ? cart.lines : response.lines.nodes;
|
|
143
|
+
const connection = Array.isArray(cart.lines) ? { nodes: lines } : {
|
|
144
|
+
...response.lines,
|
|
145
|
+
nodes: lines
|
|
146
|
+
};
|
|
147
|
+
return {
|
|
148
|
+
...response,
|
|
149
|
+
lines: connection
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function isPromiseLike(value) {
|
|
153
|
+
return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
154
|
+
}
|
|
155
|
+
function shallowEqualRecord(left, right) {
|
|
156
|
+
const leftRecord = left;
|
|
157
|
+
const rightRecord = right;
|
|
158
|
+
const leftKeys = Object.keys(leftRecord);
|
|
159
|
+
if (leftKeys.length !== Object.keys(rightRecord).length) return false;
|
|
160
|
+
return leftKeys.every((key) => Object.is(leftRecord[key], rightRecord[key]));
|
|
161
|
+
}
|
|
162
|
+
function reuseLineReferences(previous, next) {
|
|
163
|
+
const previousById = new Map(previous.map((line) => [line.id, line]));
|
|
164
|
+
let changed = previous.length !== next.length;
|
|
165
|
+
const shared = next.map((line, index) => {
|
|
166
|
+
const prior = previousById.get(line.id);
|
|
167
|
+
const value = prior && shallowEqualRecord(prior, line) ? prior : line;
|
|
168
|
+
if (previous[index] !== value) changed = true;
|
|
169
|
+
return value;
|
|
170
|
+
});
|
|
171
|
+
return changed ? shared : previous;
|
|
172
|
+
}
|
|
173
|
+
function sameSet(left, right) {
|
|
174
|
+
return left.size === right.size && [...left].every((value) => right.has(value));
|
|
175
|
+
}
|
|
176
|
+
function reuseVisibleReferences(previous, next) {
|
|
177
|
+
const lines = reuseLineReferences(getLines(previous.data), getLines(next.data));
|
|
178
|
+
const dataWithLines = setLines(next.data, lines);
|
|
179
|
+
const data = shallowEqualRecord(previous.data, dataWithLines) ? previous.data : dataWithLines;
|
|
180
|
+
const pendingLines = sameSet(previous.pending.lines, next.pending.lines) ? previous.pending.lines : next.pending.lines;
|
|
181
|
+
const pendingDiscountCodes = sameSet(previous.pending.discountCodes, next.pending.discountCodes) ? previous.pending.discountCodes : next.pending.discountCodes;
|
|
182
|
+
const nextPending = {
|
|
183
|
+
lines: pendingLines,
|
|
184
|
+
note: next.pending.note,
|
|
185
|
+
attributes: next.pending.attributes,
|
|
186
|
+
discountCodes: pendingDiscountCodes,
|
|
187
|
+
cost: next.pending.cost
|
|
188
|
+
};
|
|
189
|
+
const pending = shallowEqualRecord(previous.pending, nextPending) ? previous.pending : nextPending;
|
|
190
|
+
if (previous.data === data && previous.loading === next.loading && previous.revalidating === next.revalidating && previous.errors === next.errors && previous.pending === pending) return previous;
|
|
191
|
+
return {
|
|
192
|
+
...next,
|
|
193
|
+
data,
|
|
194
|
+
pending
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
function derivePending(state, transactions) {
|
|
198
|
+
const lines = /* @__PURE__ */ new Set();
|
|
199
|
+
const discountCodes = /* @__PURE__ */ new Set();
|
|
200
|
+
let note = false;
|
|
201
|
+
let attributes = false;
|
|
202
|
+
let cost = false;
|
|
203
|
+
for (const transaction of transactions) for (const key of transaction.pendingKeys) {
|
|
204
|
+
if (key === NOTE_KEY) note = true;
|
|
205
|
+
if (key === ATTRIBUTES_KEY) attributes = true;
|
|
206
|
+
if (key.startsWith(LINE_KEY_PREFIX)) {
|
|
207
|
+
lines.add(key.slice(5));
|
|
208
|
+
cost = true;
|
|
209
|
+
}
|
|
210
|
+
if (key.startsWith(DISCOUNT_KEY_PREFIX)) {
|
|
211
|
+
discountCodes.add(key.slice(9));
|
|
212
|
+
cost = true;
|
|
213
|
+
}
|
|
214
|
+
const addition = parseMerchandiseKey(key);
|
|
215
|
+
if (!addition) continue;
|
|
216
|
+
const line = findLineForAddition(getLines(state.data), addition);
|
|
217
|
+
if (line) lines.add(line.id);
|
|
218
|
+
cost = true;
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
lines,
|
|
222
|
+
note,
|
|
223
|
+
attributes,
|
|
224
|
+
discountCodes,
|
|
225
|
+
cost
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function projectVisibleState(store) {
|
|
229
|
+
let state = store.settled;
|
|
230
|
+
for (const transaction of store.transactions) state = transaction.projectPayload(state);
|
|
231
|
+
state = {
|
|
232
|
+
...state,
|
|
233
|
+
pending: derivePending(state, store.transactions)
|
|
234
|
+
};
|
|
235
|
+
for (const error of store.projectedErrors) state = error.project(state);
|
|
236
|
+
if (store.revalidation.visible) state = {
|
|
237
|
+
...state,
|
|
238
|
+
revalidating: true
|
|
239
|
+
};
|
|
240
|
+
return state;
|
|
241
|
+
}
|
|
242
|
+
function publishVisibleState(store) {
|
|
243
|
+
const previous = store.observable.state;
|
|
244
|
+
const next = reuseVisibleReferences(previous, projectVisibleState(store));
|
|
245
|
+
if (configuredCartEndpoint && previous !== next) {
|
|
246
|
+
const previousLines = new Map(getLines(previous.data).map((line) => [line.id, line]));
|
|
247
|
+
const changedQuantities = getLines(next.data).filter((line) => previousLines.get(line.id)?.quantity !== line.quantity).map((line) => ({
|
|
248
|
+
id: line.id,
|
|
249
|
+
quantity: line.quantity
|
|
250
|
+
}));
|
|
251
|
+
if (changedQuantities.length > 0) syncQuantityInputs(changedQuantities, configuredCartEndpoint);
|
|
252
|
+
}
|
|
253
|
+
store.observable.setState(next);
|
|
254
|
+
}
|
|
255
|
+
function sharesKey(left, right) {
|
|
256
|
+
const rightKeys = new Set(right);
|
|
257
|
+
return left.some((key) => rightKeys.has(key));
|
|
258
|
+
}
|
|
259
|
+
function clearProjectedErrors(store, keys) {
|
|
260
|
+
if (keys.length === 0) return;
|
|
261
|
+
store.projectedErrors = store.projectedErrors.filter((error) => !sharesKey(error.keys, keys));
|
|
262
|
+
}
|
|
263
|
+
function addProjectedError(store, keys, projector) {
|
|
264
|
+
const timestampMs = Date.now();
|
|
265
|
+
store.projectedErrors.push({
|
|
266
|
+
keys,
|
|
267
|
+
project: (state) => projector(state, timestampMs)
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
function createOwner(store, keys) {
|
|
271
|
+
if (keys.length === 0) return null;
|
|
272
|
+
const owner = {
|
|
273
|
+
controller: new AbortController(),
|
|
274
|
+
token: {}
|
|
275
|
+
};
|
|
276
|
+
for (const key of keys) {
|
|
277
|
+
store.keyedOwners.get(key)?.controller.abort();
|
|
278
|
+
store.keyedOwners.set(key, owner);
|
|
279
|
+
}
|
|
280
|
+
return owner;
|
|
281
|
+
}
|
|
282
|
+
function ownsSignalKeys(store, transaction) {
|
|
283
|
+
if (!transaction.owner) return true;
|
|
284
|
+
return transaction.signalKeys.every((key) => store.keyedOwners.get(key)?.token === transaction.owner?.token);
|
|
285
|
+
}
|
|
286
|
+
function releaseSignalKeys(store, transaction) {
|
|
287
|
+
if (!transaction.owner) return;
|
|
288
|
+
for (const key of transaction.signalKeys) if (store.keyedOwners.get(key)?.token === transaction.owner.token) store.keyedOwners.delete(key);
|
|
289
|
+
}
|
|
290
|
+
function getErrorGroup(map, key) {
|
|
291
|
+
const existing = map.get(key);
|
|
292
|
+
if (existing) return existing;
|
|
293
|
+
const group = createEmptyErrorGroup();
|
|
294
|
+
map.set(key, group);
|
|
295
|
+
return group;
|
|
296
|
+
}
|
|
297
|
+
function toCartUserError(error) {
|
|
298
|
+
return {
|
|
299
|
+
code: error.code ?? null,
|
|
300
|
+
message: error.message,
|
|
301
|
+
...error.field ? { field: error.field } : {}
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
function toCartWarning(warning) {
|
|
305
|
+
return {
|
|
306
|
+
code: warning.code ?? "UNKNOWN",
|
|
307
|
+
message: warning.message
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
function findFieldIndex(field, ...keys) {
|
|
311
|
+
if (!field) return void 0;
|
|
312
|
+
const index = field.findIndex((part, fieldIndex) => keys.includes(part) && /^\d+$/.test(field[fieldIndex + 1] ?? ""));
|
|
313
|
+
return index === -1 ? void 0 : Number(field[index + 1]);
|
|
314
|
+
}
|
|
315
|
+
function isCartLineId(value) {
|
|
316
|
+
return typeof value === "string" && value.startsWith("gid://shopify/CartLine/");
|
|
317
|
+
}
|
|
318
|
+
function groupLineErrors(failure, lineIds) {
|
|
319
|
+
const lines = /* @__PURE__ */ new Map();
|
|
320
|
+
const cart = createEmptyErrorGroup();
|
|
321
|
+
for (const error of failure?.userErrors ?? []) {
|
|
322
|
+
const lineIndex = findFieldIndex(error.field, "lines", "lineIds");
|
|
323
|
+
const lineId = lineIndex === void 0 ? void 0 : lineIds[lineIndex];
|
|
324
|
+
(lineId ? getErrorGroup(lines, lineId) : cart).userErrors.push(toCartUserError(error));
|
|
325
|
+
}
|
|
326
|
+
for (const warning of failure?.warnings ?? []) (isCartLineId(warning.target) ? getErrorGroup(lines, warning.target) : cart).warnings.push(toCartWarning(warning));
|
|
327
|
+
return {
|
|
328
|
+
lines,
|
|
329
|
+
cart
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
function isDiscountWarning(code) {
|
|
333
|
+
return typeof code === "string" && code.startsWith("DISCOUNT_");
|
|
334
|
+
}
|
|
335
|
+
function addDiscountWarning(codes, cart, warning, nonApplicableCodes) {
|
|
336
|
+
if (!isDiscountWarning(warning.code) || nonApplicableCodes.length === 0) {
|
|
337
|
+
cart.warnings.push(toCartWarning(warning));
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
for (const code of nonApplicableCodes) getErrorGroup(codes, code).warnings.push(toCartWarning(warning));
|
|
341
|
+
}
|
|
342
|
+
function groupDiscountErrors(failure, discountCodes, resolvedDiscountCodes) {
|
|
343
|
+
const codes = /* @__PURE__ */ new Map();
|
|
344
|
+
const cart = createEmptyErrorGroup();
|
|
345
|
+
for (const error of failure?.userErrors ?? []) {
|
|
346
|
+
const codeIndex = findFieldIndex(error.field, "discountCodes");
|
|
347
|
+
const code = codeIndex === void 0 ? void 0 : discountCodes[codeIndex];
|
|
348
|
+
(code ? getErrorGroup(codes, code) : cart).userErrors.push(toCartUserError(error));
|
|
349
|
+
}
|
|
350
|
+
const nonApplicableCodes = resolvedDiscountCodes?.filter((code) => !code.applicable).map((code) => code.code) ?? [];
|
|
351
|
+
for (const warning of failure?.warnings ?? []) addDiscountWarning(codes, cart, warning, nonApplicableCodes);
|
|
352
|
+
return {
|
|
353
|
+
discountCodes: codes,
|
|
354
|
+
cart
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
function groupAttributeErrors(failure, attributes) {
|
|
358
|
+
const attributeErrors = /* @__PURE__ */ new Map();
|
|
359
|
+
const cart = createEmptyErrorGroup();
|
|
360
|
+
for (const error of failure?.userErrors ?? []) {
|
|
361
|
+
const attributeIndex = findFieldIndex(error.field, "attributes");
|
|
362
|
+
const key = attributeIndex === void 0 ? void 0 : attributes[attributeIndex]?.key;
|
|
363
|
+
(key ? getErrorGroup(attributeErrors, key) : cart).userErrors.push(toCartUserError(error));
|
|
364
|
+
}
|
|
365
|
+
for (const warning of failure?.warnings ?? []) cart.warnings.push(toCartWarning(warning));
|
|
366
|
+
return {
|
|
367
|
+
attributes: attributeErrors,
|
|
368
|
+
cart
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
function toCartErrorGroup(failure) {
|
|
372
|
+
return {
|
|
373
|
+
userErrors: (failure?.userErrors ?? []).map(toCartUserError),
|
|
374
|
+
warnings: (failure?.warnings ?? []).map(toCartWarning)
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function extractCartActionFailure(error) {
|
|
378
|
+
const cause = error?.cause;
|
|
379
|
+
return Array.isArray(cause?.userErrors) || Array.isArray(cause?.warnings) ? cause : void 0;
|
|
380
|
+
}
|
|
381
|
+
function createNetworkEntry(error) {
|
|
382
|
+
if (error instanceof CartNetworkError) return {
|
|
383
|
+
message: error.message,
|
|
384
|
+
status: error.status
|
|
385
|
+
};
|
|
386
|
+
return { message: error instanceof Error ? error.message : "Cart update failed" };
|
|
387
|
+
}
|
|
388
|
+
function mergeErrorGroups(left, right) {
|
|
389
|
+
return {
|
|
390
|
+
userErrors: [...left.userErrors, ...right.userErrors],
|
|
391
|
+
warnings: [...left.warnings, ...right.warnings]
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
function writeNetworkError(state, error, timestampMs) {
|
|
395
|
+
return {
|
|
396
|
+
...state,
|
|
397
|
+
errors: {
|
|
398
|
+
...state.errors,
|
|
399
|
+
network: [...state.errors.network, createNetworkEntry(error)],
|
|
400
|
+
networkUpdatedAt: timestampMs,
|
|
401
|
+
lastUpdatedAt: timestampMs
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
function projectLineErrors(state, failure, lineIds, timestampMs) {
|
|
406
|
+
if (!failure) return state;
|
|
407
|
+
const grouped = groupLineErrors(failure, lineIds);
|
|
408
|
+
return {
|
|
409
|
+
...state,
|
|
410
|
+
errors: {
|
|
411
|
+
...state.errors,
|
|
412
|
+
lines: new Map([...state.errors.lines, ...grouped.lines]),
|
|
413
|
+
cart: mergeErrorGroups(state.errors.cart, grouped.cart),
|
|
414
|
+
linesUpdatedAt: timestampMs,
|
|
415
|
+
cartUpdatedAt: timestampMs,
|
|
416
|
+
lastUpdatedAt: timestampMs
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function projectDiscountErrors(state, failure, discountCodes, timestampMs, resolvedDiscountCodes) {
|
|
421
|
+
if (!failure) return state;
|
|
422
|
+
const grouped = groupDiscountErrors(failure, discountCodes, resolvedDiscountCodes);
|
|
423
|
+
return {
|
|
424
|
+
...state,
|
|
425
|
+
errors: {
|
|
426
|
+
...state.errors,
|
|
427
|
+
discountCodes: new Map([...state.errors.discountCodes, ...grouped.discountCodes]),
|
|
428
|
+
cart: mergeErrorGroups(state.errors.cart, grouped.cart),
|
|
429
|
+
discountCodesUpdatedAt: timestampMs,
|
|
430
|
+
cartUpdatedAt: timestampMs,
|
|
431
|
+
lastUpdatedAt: timestampMs
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
function projectNoteErrors(state, failure, timestampMs) {
|
|
436
|
+
if (!failure) return state;
|
|
437
|
+
return {
|
|
438
|
+
...state,
|
|
439
|
+
errors: {
|
|
440
|
+
...state.errors,
|
|
441
|
+
note: toCartErrorGroup(failure),
|
|
442
|
+
noteUpdatedAt: timestampMs,
|
|
443
|
+
lastUpdatedAt: timestampMs
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
function projectAttributeErrors(state, failure, attributes, timestampMs) {
|
|
448
|
+
if (!failure) return state;
|
|
449
|
+
const grouped = groupAttributeErrors(failure, attributes);
|
|
450
|
+
return {
|
|
451
|
+
...state,
|
|
452
|
+
errors: {
|
|
453
|
+
...state.errors,
|
|
454
|
+
attributes: new Map([...state.errors.attributes, ...grouped.attributes]),
|
|
455
|
+
cart: mergeErrorGroups(state.errors.cart, grouped.cart),
|
|
456
|
+
attributesUpdatedAt: timestampMs,
|
|
457
|
+
cartUpdatedAt: timestampMs,
|
|
458
|
+
lastUpdatedAt: timestampMs
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function extractProductDetails(detail) {
|
|
463
|
+
const products = detail?.products;
|
|
464
|
+
if (!Array.isArray(products)) return [];
|
|
465
|
+
return products.filter((product) => typeof product === "object" && product !== null && "id" in product && typeof product.id === "string");
|
|
466
|
+
}
|
|
467
|
+
function getLineSellingPlanId(line) {
|
|
468
|
+
return line.sellingPlanAllocation?.sellingPlan.id;
|
|
469
|
+
}
|
|
470
|
+
function hasKnownLineIdentity(line) {
|
|
471
|
+
return Object.hasOwn(line, "attributes") && Object.hasOwn(line, "sellingPlanAllocation");
|
|
472
|
+
}
|
|
473
|
+
function hasAdditionIdentityDetails(addition) {
|
|
474
|
+
return addition.sellingPlanId !== void 0 || normalizeAttributes(addition.attributes).length > 0;
|
|
475
|
+
}
|
|
476
|
+
function lineMatchesAddition(line, addition) {
|
|
477
|
+
if (line.id === optimisticLineId(addition)) return true;
|
|
478
|
+
if (line.merchandise?.id !== addition.merchandiseId) return false;
|
|
479
|
+
if (!hasKnownLineIdentity(line)) return !hasAdditionIdentityDetails(addition);
|
|
480
|
+
if (getLineSellingPlanId(line) !== addition.sellingPlanId) return false;
|
|
481
|
+
return sameAttributes(line.attributes, addition.attributes);
|
|
482
|
+
}
|
|
483
|
+
function findLineForAddition(lines, addition) {
|
|
484
|
+
return lines.find((line) => lineMatchesAddition(line, addition));
|
|
485
|
+
}
|
|
486
|
+
function findAvailableLineForAddition(lines, addition, usedLineIds) {
|
|
487
|
+
return lines.find((line) => !usedLineIds.has(line.id) && lineMatchesAddition(line, addition));
|
|
488
|
+
}
|
|
489
|
+
function findResponseLineForAddition(serverLines, currentLines, addition, usedLineIds, canInferSingleLine, remainingAdditions) {
|
|
490
|
+
const exact = findAvailableLineForAddition(serverLines, addition, usedLineIds);
|
|
491
|
+
if (exact) return exact;
|
|
492
|
+
const currentLine = findLineForAddition(currentLines, addition);
|
|
493
|
+
const matchingCurrentLine = serverLines.find((line) => !usedLineIds.has(line.id) && line.id === currentLine?.id);
|
|
494
|
+
if (matchingCurrentLine) return matchingCurrentLine;
|
|
495
|
+
const currentLineIds = new Set(currentLines.map((line) => line.id));
|
|
496
|
+
const newLines = serverLines.filter((line) => !usedLineIds.has(line.id) && !currentLineIds.has(line.id));
|
|
497
|
+
if (remainingAdditions === newLines.length && newLines.length === 1) return newLines[0];
|
|
498
|
+
return canInferSingleLine ? serverLines.find((line) => !usedLineIds.has(line.id)) : void 0;
|
|
499
|
+
}
|
|
500
|
+
function withAdditionMerchandise(line, addition, products) {
|
|
501
|
+
if (line.merchandise) return line;
|
|
502
|
+
const product = products.find((candidate) => candidate.id === addition.merchandiseId);
|
|
503
|
+
if (!product) return line;
|
|
504
|
+
const { price: _price, ...merchandise } = product;
|
|
505
|
+
return {
|
|
506
|
+
...line,
|
|
507
|
+
merchandise
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
function replaceOrPrependLine(lines, previous, next) {
|
|
511
|
+
if (previous) return lines.map((line) => line === previous ? next : line);
|
|
512
|
+
if (lines.some((line) => line.id === next.id)) return lines.map((line) => line.id === next.id ? next : line);
|
|
513
|
+
return [next, ...lines];
|
|
514
|
+
}
|
|
515
|
+
function mergeAddResponseLines(currentLines, serverLines, payload) {
|
|
516
|
+
let lines = currentLines;
|
|
517
|
+
const usedLineIds = /* @__PURE__ */ new Set();
|
|
518
|
+
const canInferSingleLine = payload.lines.length === 1 && serverLines.length === 1;
|
|
519
|
+
for (const addition of payload.lines) {
|
|
520
|
+
const remainingAdditions = payload.lines.length - usedLineIds.size;
|
|
521
|
+
const serverLine = findResponseLineForAddition(serverLines, lines, addition, usedLineIds, canInferSingleLine, remainingAdditions);
|
|
522
|
+
if (!serverLine) continue;
|
|
523
|
+
usedLineIds.add(serverLine.id);
|
|
524
|
+
const previous = findLineForAddition(lines, addition) ?? lines.find((line) => line.id === serverLine.id);
|
|
525
|
+
const next = withAdditionMerchandise(serverLine, addition, payload.products);
|
|
526
|
+
lines = replaceOrPrependLine(lines, previous, mergeServerLine(previous, next));
|
|
527
|
+
}
|
|
528
|
+
return lines;
|
|
529
|
+
}
|
|
530
|
+
function resolveAddLineIds(currentLines, serverLines, payload) {
|
|
531
|
+
const usedLineIds = /* @__PURE__ */ new Set();
|
|
532
|
+
const canInferSingleLine = payload.lines.length === 1 && serverLines.length === 1;
|
|
533
|
+
return payload.lines.map((addition) => {
|
|
534
|
+
const serverLine = findResponseLineForAddition(serverLines, currentLines, addition, usedLineIds, canInferSingleLine, payload.lines.length - usedLineIds.size);
|
|
535
|
+
if (serverLine) {
|
|
536
|
+
usedLineIds.add(serverLine.id);
|
|
537
|
+
return serverLine.id;
|
|
538
|
+
}
|
|
539
|
+
return findLineForAddition(currentLines, addition)?.id ?? "";
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
function getAddErrorKeys(payload, lineIds, failure) {
|
|
543
|
+
const keys = new Set(payload.lines.map(merchandiseKey));
|
|
544
|
+
for (const lineId of lineIds) if (lineId) keys.add(lineKey(lineId));
|
|
545
|
+
for (const warning of failure?.warnings ?? []) if (isCartLineId(warning.target)) keys.add(lineKey(warning.target));
|
|
546
|
+
return [...keys];
|
|
547
|
+
}
|
|
548
|
+
function mergeServerLine(previous, next) {
|
|
549
|
+
if (!previous) return next;
|
|
550
|
+
const merchandise = next.merchandise ? {
|
|
551
|
+
...previous.merchandise,
|
|
552
|
+
...next.merchandise
|
|
553
|
+
} : previous.merchandise;
|
|
554
|
+
return {
|
|
555
|
+
...previous,
|
|
556
|
+
...next,
|
|
557
|
+
...merchandise ? { merchandise } : {}
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
function hasProjectedErrors(result) {
|
|
561
|
+
return (result?.userErrors?.length ?? 0) > 0 || (result?.warnings?.length ?? 0) > 0;
|
|
562
|
+
}
|
|
563
|
+
function transportAddToCart(payload, signal, updateCart, cartId) {
|
|
564
|
+
return updateCart({
|
|
565
|
+
...cartId && { cartId },
|
|
566
|
+
lines: payload.lines
|
|
567
|
+
}, {
|
|
568
|
+
signal,
|
|
569
|
+
...payload.eventDetail && { event: { detail: payload.eventDetail } }
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
const CART_TRANSACTION_TYPES = defineTransactionTypes({
|
|
573
|
+
add_to_cart: {
|
|
574
|
+
payload: {},
|
|
575
|
+
transport: transportAddToCart,
|
|
576
|
+
projectPayload: (state, payload) => {
|
|
577
|
+
let lines = getLines(state.data);
|
|
578
|
+
let linesChanged = false;
|
|
579
|
+
for (const addition of payload.lines) {
|
|
580
|
+
const existing = findLineForAddition(lines, addition);
|
|
581
|
+
if (existing) {
|
|
582
|
+
lines = lines.map((line) => line === existing ? {
|
|
583
|
+
...line,
|
|
584
|
+
quantity: line.quantity + addition.quantity
|
|
585
|
+
} : line);
|
|
586
|
+
linesChanged = true;
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
const product = payload.products.find((candidate) => candidate.id === addition.merchandiseId);
|
|
590
|
+
if (!product) continue;
|
|
591
|
+
const { price, ...merchandise } = product;
|
|
592
|
+
const amount = price ?? {
|
|
593
|
+
amount: "0",
|
|
594
|
+
currencyCode: ""
|
|
595
|
+
};
|
|
596
|
+
lines = [{
|
|
597
|
+
id: optimisticLineId(addition),
|
|
598
|
+
quantity: addition.quantity,
|
|
599
|
+
attributes: addition.attributes ?? [],
|
|
600
|
+
sellingPlanAllocation: addition.sellingPlanId ? { sellingPlan: { id: addition.sellingPlanId } } : null,
|
|
601
|
+
merchandise,
|
|
602
|
+
cost: {
|
|
603
|
+
totalAmount: amount,
|
|
604
|
+
subtotalAmount: amount,
|
|
605
|
+
amountPerQuantity: amount,
|
|
606
|
+
compareAtAmountPerQuantity: null
|
|
607
|
+
}
|
|
608
|
+
}, ...lines];
|
|
609
|
+
linesChanged = true;
|
|
610
|
+
}
|
|
611
|
+
const addedQuantity = payload.lines.reduce((total, line) => total + line.quantity, 0);
|
|
612
|
+
const data = setLines({
|
|
613
|
+
...state.data,
|
|
614
|
+
totalQuantity: state.data.totalQuantity + addedQuantity
|
|
615
|
+
}, linesChanged ? lines : getLines(state.data));
|
|
616
|
+
return {
|
|
617
|
+
...state,
|
|
618
|
+
data
|
|
619
|
+
};
|
|
620
|
+
},
|
|
621
|
+
projectPromise: (state, result, payload, addError) => {
|
|
622
|
+
const currentLines = getLines(state.data);
|
|
623
|
+
const cart = result.cart ? cartResponseFromStandardEvent(result.cart) : void 0;
|
|
624
|
+
const serverLines = cart ? getLines(cart) : [];
|
|
625
|
+
const lineIds = resolveAddLineIds(currentLines, serverLines, payload);
|
|
626
|
+
if (hasProjectedErrors(result)) addError((current, timestampMs) => projectLineErrors(current, result, lineIds, timestampMs), getAddErrorKeys(payload, lineIds, result));
|
|
627
|
+
if (!cart) return state;
|
|
628
|
+
const lines = mergeAddResponseLines(currentLines, serverLines, payload);
|
|
629
|
+
return {
|
|
630
|
+
...state,
|
|
631
|
+
data: reconcileCartLines(state.data, lines)
|
|
632
|
+
};
|
|
633
|
+
},
|
|
634
|
+
getPendingKeys: (state, payload) => {
|
|
635
|
+
const keys = [];
|
|
636
|
+
const lines = getLines(state.data);
|
|
637
|
+
for (const addition of payload.lines) {
|
|
638
|
+
keys.push(merchandiseKey(addition));
|
|
639
|
+
const existing = findLineForAddition(lines, addition);
|
|
640
|
+
if (existing) keys.push(lineKey(existing.id));
|
|
641
|
+
if (!existing && payload.products.some((product) => product.id === addition.merchandiseId)) keys.push(lineKey(optimisticLineId(addition)));
|
|
642
|
+
}
|
|
643
|
+
return keys;
|
|
644
|
+
},
|
|
645
|
+
getErrorKeys: (_state, payload) => payload.lines.map(merchandiseKey),
|
|
646
|
+
removeSupersededPayload: (older, successful) => {
|
|
647
|
+
const successfulKeys = new Set(successful.lines.map(merchandiseKey));
|
|
648
|
+
const lines = older.lines.filter((line) => !successfulKeys.has(merchandiseKey(line)));
|
|
649
|
+
return lines.length > 0 ? {
|
|
650
|
+
...older,
|
|
651
|
+
lines
|
|
652
|
+
} : void 0;
|
|
653
|
+
}
|
|
654
|
+
},
|
|
655
|
+
change_line_quantity: {
|
|
656
|
+
payload: {},
|
|
657
|
+
transport: (payload, signal, updateCart) => updateCart({ lines: [{
|
|
658
|
+
id: payload.lineId,
|
|
659
|
+
quantity: payload.quantity
|
|
660
|
+
}] }, { signal }),
|
|
661
|
+
projectPayload: (state, payload) => {
|
|
662
|
+
const previous = getLines(state.data);
|
|
663
|
+
if (!previous.find((line) => line.id === payload.lineId)) return state;
|
|
664
|
+
const lines = payload.quantity === 0 ? previous.filter((line) => line.id !== payload.lineId) : previous.map((line) => line.id === payload.lineId ? {
|
|
665
|
+
...line,
|
|
666
|
+
quantity: payload.quantity
|
|
667
|
+
} : line);
|
|
668
|
+
return {
|
|
669
|
+
...state,
|
|
670
|
+
data: reconcileCartLines(state.data, lines)
|
|
671
|
+
};
|
|
672
|
+
},
|
|
673
|
+
projectPromise: (state, result, payload, addError) => {
|
|
674
|
+
if (hasProjectedErrors(result)) addError((current, timestampMs) => projectLineErrors(current, result, [payload.lineId], timestampMs));
|
|
675
|
+
if (!result.cart) return state;
|
|
676
|
+
const serverLines = getLines(cartResponseFromStandardEvent(result.cart));
|
|
677
|
+
const matching = serverLines.find((line) => line.id === payload.lineId);
|
|
678
|
+
const previous = getLines(state.data);
|
|
679
|
+
let lines = previous.filter((line) => line.id !== payload.lineId);
|
|
680
|
+
if (matching) {
|
|
681
|
+
const prior = previous.find((line) => line.id === payload.lineId);
|
|
682
|
+
lines = previous.map((line) => line.id === payload.lineId ? mergeServerLine(prior, matching) : line);
|
|
683
|
+
} else if (payload.quantity > 0 && previous.length === 1 && serverLines.length === 1) lines = [mergeServerLine(previous[0], serverLines[0])];
|
|
684
|
+
return {
|
|
685
|
+
...state,
|
|
686
|
+
data: reconcileCartLines(state.data, lines)
|
|
687
|
+
};
|
|
688
|
+
},
|
|
689
|
+
getSignalKeys: (_state, payload) => lineKey(payload.lineId)
|
|
690
|
+
},
|
|
691
|
+
set_discount_codes: {
|
|
692
|
+
payload: {},
|
|
693
|
+
transport: (payload, signal, updateCart) => updateCart({ discountCodes: payload.discountCodes }, { signal }),
|
|
694
|
+
projectPayload: (state, payload) => {
|
|
695
|
+
const discountCodes = payload.discountCodes.map((code) => {
|
|
696
|
+
return {
|
|
697
|
+
code,
|
|
698
|
+
applicable: state.data.discountCodes.find((discount) => discount.code === code)?.applicable ?? false
|
|
699
|
+
};
|
|
700
|
+
});
|
|
701
|
+
return {
|
|
702
|
+
...state,
|
|
703
|
+
data: {
|
|
704
|
+
...state.data,
|
|
705
|
+
discountCodes
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
},
|
|
709
|
+
projectPromise: (state, result, payload, addError, options) => {
|
|
710
|
+
const resolvedCodes = result.cart ? cartResponseFromStandardEvent(result.cart).discountCodes : void 0;
|
|
711
|
+
if (hasProjectedErrors(result)) addError((current, timestampMs) => projectDiscountErrors(current, result, payload.discountCodes, timestampMs, resolvedCodes));
|
|
712
|
+
if (!result.cart) return state;
|
|
713
|
+
const cart = cartResponseFromStandardEvent(result.cart);
|
|
714
|
+
if (options.mergeServerCart) return {
|
|
715
|
+
...state,
|
|
716
|
+
data: mergeAuthoritativeCartData(state.data, cart)
|
|
717
|
+
};
|
|
718
|
+
return {
|
|
719
|
+
...state,
|
|
720
|
+
data: {
|
|
721
|
+
...state.data,
|
|
722
|
+
discountCodes: cart.discountCodes
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
},
|
|
726
|
+
getSignalKeys: () => DISCOUNT_CODES_KEY,
|
|
727
|
+
getPendingKeys: (state, payload) => {
|
|
728
|
+
const current = new Set(state.data.discountCodes.map((discount) => discount.code));
|
|
729
|
+
const next = new Set(payload.discountCodes);
|
|
730
|
+
return [...new Set([...current, ...next])].filter((code) => current.has(code) !== next.has(code)).map((code) => `${DISCOUNT_KEY_PREFIX}${code}`);
|
|
731
|
+
}
|
|
732
|
+
},
|
|
733
|
+
set_note: {
|
|
734
|
+
payload: {},
|
|
735
|
+
transport: (payload, signal, updateCart) => updateCart({ note: payload.note }, { signal }),
|
|
736
|
+
projectPayload: (state, payload) => ({
|
|
737
|
+
...state,
|
|
738
|
+
data: {
|
|
739
|
+
...state.data,
|
|
740
|
+
note: payload.note
|
|
741
|
+
}
|
|
742
|
+
}),
|
|
743
|
+
projectPromise: (state, result, payload, addError) => {
|
|
744
|
+
if (hasProjectedErrors(result)) addError((current, timestampMs) => projectNoteErrors(current, result, timestampMs));
|
|
745
|
+
if (!result.cart) return state;
|
|
746
|
+
return {
|
|
747
|
+
...state,
|
|
748
|
+
data: {
|
|
749
|
+
...state.data,
|
|
750
|
+
note: payload.note
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
},
|
|
754
|
+
getSignalKeys: () => NOTE_KEY
|
|
755
|
+
},
|
|
756
|
+
set_attributes: {
|
|
757
|
+
payload: {},
|
|
758
|
+
transport: (payload, signal, updateCart) => updateCart({ attributes: payload.attributes }, { signal }),
|
|
759
|
+
projectPayload: (state, payload) => ({
|
|
760
|
+
...state,
|
|
761
|
+
data: {
|
|
762
|
+
...state.data,
|
|
763
|
+
attributes: payload.attributes
|
|
764
|
+
}
|
|
765
|
+
}),
|
|
766
|
+
projectPromise: (state, result, payload, addError) => {
|
|
767
|
+
if (hasProjectedErrors(result)) addError((current, timestampMs) => projectAttributeErrors(current, result, payload.attributes, timestampMs));
|
|
768
|
+
if (!result.cart || (result.userErrors?.length ?? 0) > 0) return state;
|
|
769
|
+
return {
|
|
770
|
+
...state,
|
|
771
|
+
data: {
|
|
772
|
+
...state.data,
|
|
773
|
+
attributes: payload.attributes
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
},
|
|
777
|
+
getSignalKeys: () => ATTRIBUTES_KEY
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
function getTransactionProjectionKeys(definition, state, payload, signalKeys) {
|
|
781
|
+
return {
|
|
782
|
+
pendingKeys: normalizeKeys(definition.getPendingKeys?.(state, payload) ?? signalKeys),
|
|
783
|
+
errorKeys: normalizeKeys(definition.getErrorKeys?.(state, payload) ?? signalKeys)
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
function resolveTransactionIdentity(store, definition, payload, reservation, identity) {
|
|
787
|
+
const state = store.observable.state;
|
|
788
|
+
if (identity) {
|
|
789
|
+
const projectedKeys = getTransactionProjectionKeys(definition, state, payload, identity.signalKeys);
|
|
790
|
+
const pendingKeys = identity.pendingKeys ?? projectedKeys.pendingKeys;
|
|
791
|
+
const errorKeys = identity.errorKeys ?? projectedKeys.errorKeys;
|
|
792
|
+
return {
|
|
793
|
+
...identity,
|
|
794
|
+
pendingKeys,
|
|
795
|
+
errorKeys
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
if (reservation) {
|
|
799
|
+
const id = store.nextTransactionId++;
|
|
800
|
+
return {
|
|
801
|
+
...reservation,
|
|
802
|
+
id,
|
|
803
|
+
sequence: id,
|
|
804
|
+
generation: store.generation,
|
|
805
|
+
requiresRevalidation: false
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
const signalKeys = normalizeKeys(definition.getSignalKeys?.(state, payload));
|
|
809
|
+
const { pendingKeys, errorKeys } = getTransactionProjectionKeys(definition, state, payload, signalKeys);
|
|
810
|
+
const id = store.nextTransactionId++;
|
|
811
|
+
return {
|
|
812
|
+
id,
|
|
813
|
+
sequence: id,
|
|
814
|
+
generation: store.generation,
|
|
815
|
+
owner: createOwner(store, signalKeys),
|
|
816
|
+
signalKeys,
|
|
817
|
+
pendingKeys,
|
|
818
|
+
errorKeys,
|
|
819
|
+
requiresRevalidation: false
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
function createPendingTransaction(store, type, definition, payload, promise, reservation, identity) {
|
|
823
|
+
const { id, sequence, generation, owner, signalKeys, pendingKeys, errorKeys, requiresRevalidation } = resolveTransactionIdentity(store, definition, payload, reservation, identity);
|
|
824
|
+
const transaction = {
|
|
825
|
+
id,
|
|
826
|
+
sequence,
|
|
827
|
+
generation,
|
|
828
|
+
type,
|
|
829
|
+
payload,
|
|
830
|
+
signalKeys,
|
|
831
|
+
pendingKeys,
|
|
832
|
+
errorKeys,
|
|
833
|
+
requiresRevalidation,
|
|
834
|
+
owner,
|
|
835
|
+
promise,
|
|
836
|
+
projectPayload: (current) => definition.projectPayload(current, payload),
|
|
837
|
+
projectPromise: (current, result, addError) => definition.projectPromise(current, result, payload, addError, { mergeServerCart: !transaction.requiresRevalidation }),
|
|
838
|
+
trimAfter: (successful) => trimPendingTransaction(store, type, definition, payload, promise, {
|
|
839
|
+
id,
|
|
840
|
+
sequence,
|
|
841
|
+
generation,
|
|
842
|
+
owner,
|
|
843
|
+
signalKeys,
|
|
844
|
+
pendingKeys,
|
|
845
|
+
errorKeys,
|
|
846
|
+
requiresRevalidation: transaction.requiresRevalidation
|
|
847
|
+
}, successful)
|
|
848
|
+
};
|
|
849
|
+
return transaction;
|
|
850
|
+
}
|
|
851
|
+
function trimPendingTransaction(store, type, definition, payload, promise, identity, successful) {
|
|
852
|
+
let remaining = payload;
|
|
853
|
+
let nextIdentity = identity;
|
|
854
|
+
if (successful.type === type && definition.removeSupersededPayload) {
|
|
855
|
+
const trimmed = definition.removeSupersededPayload(payload, successful.payload);
|
|
856
|
+
if (!trimmed) return void 0;
|
|
857
|
+
remaining = trimmed;
|
|
858
|
+
nextIdentity = {
|
|
859
|
+
...identity,
|
|
860
|
+
pendingKeys: void 0,
|
|
861
|
+
errorKeys: void 0
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
return createPendingTransaction(store, type, definition, remaining, promise, void 0, nextIdentity);
|
|
865
|
+
}
|
|
866
|
+
function addSnapshotFields(state, result) {
|
|
867
|
+
if (!result.cart) return state;
|
|
868
|
+
const cart = cartResponseFromStandardEvent(result.cart);
|
|
869
|
+
return {
|
|
870
|
+
...state,
|
|
871
|
+
data: {
|
|
872
|
+
...state.data,
|
|
873
|
+
id: cart.id,
|
|
874
|
+
checkoutUrl: cart.checkoutUrl ?? state.data.checkoutUrl,
|
|
875
|
+
updatedAt: cart.updatedAt ?? state.data.updatedAt,
|
|
876
|
+
totalQuantity: cart.totalQuantity,
|
|
877
|
+
cost: cart.cost
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
function addSnapshotIdentity(state, result) {
|
|
882
|
+
if (!result.cart || state.data.id) return state;
|
|
883
|
+
const cart = cartResponseFromStandardEvent(result.cart);
|
|
884
|
+
return {
|
|
885
|
+
...state,
|
|
886
|
+
data: {
|
|
887
|
+
...state.data,
|
|
888
|
+
id: cart.id
|
|
889
|
+
}
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
function removeTransaction(store, transactionId) {
|
|
893
|
+
const index = store.transactions.findIndex((transaction) => transaction.id === transactionId);
|
|
894
|
+
if (index === -1) return null;
|
|
895
|
+
const [transaction] = store.transactions.splice(index, 1);
|
|
896
|
+
return transaction;
|
|
897
|
+
}
|
|
898
|
+
function trimOlderRelativeTransactions(store, successful) {
|
|
899
|
+
store.transactions = store.transactions.flatMap((transaction) => {
|
|
900
|
+
if (transaction.sequence >= successful.sequence) return [transaction];
|
|
901
|
+
const trimmed = transaction.trimAfter(successful);
|
|
902
|
+
return trimmed ? [trimmed] : [];
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
function fulfillTransaction(store, transactionId, result) {
|
|
906
|
+
const transaction = store.transactions.find((candidate) => candidate.id === transactionId);
|
|
907
|
+
if (!transaction || transaction.generation !== store.generation) return;
|
|
908
|
+
store.observedPromises.delete(transaction.promise);
|
|
909
|
+
if (!ownsSignalKeys(store, transaction)) {
|
|
910
|
+
removeTransaction(store, transactionId);
|
|
911
|
+
publishVisibleState(store);
|
|
912
|
+
revalidateCartWhenIdle(store);
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
store.settled = transaction.projectPromise(store.settled, result, (projector, keys) => addProjectedError(store, keys ?? transaction.errorKeys, projector));
|
|
916
|
+
store.settled = addSnapshotIdentity(store.settled, result);
|
|
917
|
+
if (result.cart && !transaction.requiresRevalidation && transaction.sequence >= store.lastSnapshotSequence) {
|
|
918
|
+
store.settled = addSnapshotFields(store.settled, result);
|
|
919
|
+
store.lastSnapshotSequence = transaction.sequence;
|
|
920
|
+
}
|
|
921
|
+
removeTransaction(store, transactionId);
|
|
922
|
+
if (result.cart) trimOlderRelativeTransactions(store, transaction);
|
|
923
|
+
releaseSignalKeys(store, transaction);
|
|
924
|
+
publishVisibleState(store);
|
|
925
|
+
revalidateCartWhenIdle(store);
|
|
926
|
+
}
|
|
927
|
+
function rejectedResult(failure) {
|
|
928
|
+
return {
|
|
929
|
+
cart: null,
|
|
930
|
+
...failure
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
function rejectTransaction(store, transactionId, error) {
|
|
934
|
+
const transaction = store.transactions.find((candidate) => candidate.id === transactionId);
|
|
935
|
+
if (!transaction || transaction.generation !== store.generation) return;
|
|
936
|
+
store.observedPromises.delete(transaction.promise);
|
|
937
|
+
const owned = ownsSignalKeys(store, transaction);
|
|
938
|
+
removeTransaction(store, transactionId);
|
|
939
|
+
releaseSignalKeys(store, transaction);
|
|
940
|
+
if (owned) {
|
|
941
|
+
const failure = extractCartActionFailure(error);
|
|
942
|
+
if (failure) transaction.projectPromise(store.settled, rejectedResult(failure), (projector, keys) => addProjectedError(store, keys ?? transaction.errorKeys, projector));
|
|
943
|
+
if (!failure && !isAbortError(error)) addProjectedError(store, transaction.errorKeys, (state, timestampMs) => writeNetworkError(state, error, timestampMs));
|
|
944
|
+
}
|
|
945
|
+
publishVisibleState(store);
|
|
946
|
+
revalidateCartWhenIdle(store);
|
|
947
|
+
}
|
|
948
|
+
function enqueueTransaction(store, type, payload, promise, reservedTransaction, eventToken) {
|
|
949
|
+
const expectedEventIndex = store.expectedEvents.findIndex((expected) => expected.token === eventToken);
|
|
950
|
+
if (expectedEventIndex !== -1) {
|
|
951
|
+
store.expectedEvents.splice(expectedEventIndex, 1);
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
if (store.observedPromises.has(promise)) return;
|
|
955
|
+
store.observedPromises.add(promise);
|
|
956
|
+
const releaseObservedPromise = () => {
|
|
957
|
+
store.observedPromises.delete(promise);
|
|
958
|
+
};
|
|
959
|
+
promise.then(releaseObservedPromise, releaseObservedPromise);
|
|
960
|
+
const activeReservation = store.reservation?.type === type ? store.reservation : void 0;
|
|
961
|
+
const reservation = reservedTransaction ?? activeReservation;
|
|
962
|
+
if (reservation) reservation.consumed = true;
|
|
963
|
+
const transaction = createPendingTransaction(store, type, getTransactionDefinition(type), reservation ? reservation.payload : payload, promise, reservation);
|
|
964
|
+
store.mutationRevision += 1;
|
|
965
|
+
markOverlappingTransactionForRevalidation(store, transaction);
|
|
966
|
+
clearProjectedErrors(store, transaction.errorKeys);
|
|
967
|
+
store.transactions.push(transaction);
|
|
968
|
+
if (!reservation) observeMutationTransport(store, promise);
|
|
969
|
+
publishVisibleState(store);
|
|
970
|
+
promise.then((result) => fulfillTransaction(store, transaction.id, result), (error) => rejectTransaction(store, transaction.id, error));
|
|
971
|
+
}
|
|
972
|
+
function markOverlappingTransactionForRevalidation(store, transaction) {
|
|
973
|
+
if (store.transactions.length === 0 && !store.revalidation.active && store.activeMutationTransports.size === 0) return;
|
|
974
|
+
transaction.requiresRevalidation = true;
|
|
975
|
+
for (const pending of store.transactions) pending.requiresRevalidation = true;
|
|
976
|
+
requestCartRevalidation(store);
|
|
977
|
+
}
|
|
978
|
+
function requestCartRevalidation(store) {
|
|
979
|
+
store.revalidation.requested = true;
|
|
980
|
+
store.revalidation.visible = true;
|
|
981
|
+
store.revalidation.active?.controller.abort();
|
|
982
|
+
}
|
|
983
|
+
function observeMutationTransport(store, promise) {
|
|
984
|
+
if (store.activeMutationTransports.has(promise)) return;
|
|
985
|
+
store.activeMutationTransports.add(promise);
|
|
986
|
+
const releaseTransport = () => {
|
|
987
|
+
store.activeMutationTransports.delete(promise);
|
|
988
|
+
revalidateCartWhenIdle(store);
|
|
989
|
+
};
|
|
990
|
+
promise.then(releaseTransport, releaseTransport);
|
|
991
|
+
}
|
|
992
|
+
function createTransactionEventToken() {
|
|
993
|
+
return crypto.randomUUID();
|
|
994
|
+
}
|
|
995
|
+
function withTransactionEventToken(updateCart, token) {
|
|
996
|
+
return (payload, options) => updateCart(payload, {
|
|
997
|
+
...options,
|
|
998
|
+
event: {
|
|
999
|
+
...options?.event,
|
|
1000
|
+
detail: {
|
|
1001
|
+
...options?.event?.detail,
|
|
1002
|
+
[TRANSACTION_EVENT_TOKEN_KEY]: token
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
function getTransactionEventToken(detail) {
|
|
1008
|
+
const token = detail?.[TRANSACTION_EVENT_TOKEN_KEY];
|
|
1009
|
+
return typeof token === "string" ? token : void 0;
|
|
1010
|
+
}
|
|
1011
|
+
function reserveTransaction(store, type, payload) {
|
|
1012
|
+
const definition = getTransactionDefinition(type);
|
|
1013
|
+
const state = store.observable.state;
|
|
1014
|
+
const signalKeys = normalizeKeys(definition.getSignalKeys?.(state, payload));
|
|
1015
|
+
const pendingKeys = normalizeKeys(definition.getPendingKeys?.(state, payload) ?? signalKeys);
|
|
1016
|
+
const errorKeys = normalizeKeys(definition.getErrorKeys?.(state, payload) ?? signalKeys);
|
|
1017
|
+
clearProjectedErrors(store, errorKeys);
|
|
1018
|
+
return {
|
|
1019
|
+
type,
|
|
1020
|
+
payload,
|
|
1021
|
+
signalKeys,
|
|
1022
|
+
pendingKeys,
|
|
1023
|
+
errorKeys,
|
|
1024
|
+
owner: createOwner(store, signalKeys),
|
|
1025
|
+
consumed: false
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
function createTransactionSignal(store, reservation) {
|
|
1029
|
+
const signals = [store.lifecycleController.signal, AbortSignal.timeout(STANDARD_ACTION_TIMEOUT_IN_MS)];
|
|
1030
|
+
if (reservation.owner) signals.push(reservation.owner.controller.signal);
|
|
1031
|
+
return AbortSignal.any(signals);
|
|
1032
|
+
}
|
|
1033
|
+
async function dispatchTransaction(store, type, payload) {
|
|
1034
|
+
if (type === "add_to_cart" && !store.observable.state.data.id) return dispatchInitialCartAdd(store, payload);
|
|
1035
|
+
return dispatchTransactionNow(store, type, payload);
|
|
1036
|
+
}
|
|
1037
|
+
async function dispatchTransactionNow(store, type, payload) {
|
|
1038
|
+
const generation = store.generation;
|
|
1039
|
+
const { updateCart } = await getShopifyStandardActions();
|
|
1040
|
+
if (generation !== store.generation) return;
|
|
1041
|
+
const reservation = reserveTransaction(store, type, payload);
|
|
1042
|
+
store.reservation = reservation;
|
|
1043
|
+
const signal = createTransactionSignal(store, reservation);
|
|
1044
|
+
const eventToken = createTransactionEventToken();
|
|
1045
|
+
const correlatedUpdateCart = withTransactionEventToken(updateCart, eventToken);
|
|
1046
|
+
let promise;
|
|
1047
|
+
try {
|
|
1048
|
+
promise = getTransactionDefinition(type).transport(payload, signal, correlatedUpdateCart);
|
|
1049
|
+
} finally {
|
|
1050
|
+
store.reservation = null;
|
|
1051
|
+
}
|
|
1052
|
+
if (!reservation.consumed) {
|
|
1053
|
+
enqueueTransaction(store, type, payload, promise, reservation);
|
|
1054
|
+
store.expectedEvents.push({ token: eventToken });
|
|
1055
|
+
}
|
|
1056
|
+
observeMutationTransport(store, promise);
|
|
1057
|
+
try {
|
|
1058
|
+
await promise;
|
|
1059
|
+
} catch (error) {
|
|
1060
|
+
if (isAbortError(error)) return;
|
|
1061
|
+
throw error;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
function createDeferredCartMutation() {
|
|
1065
|
+
let resolveMutation;
|
|
1066
|
+
let rejectMutation;
|
|
1067
|
+
return {
|
|
1068
|
+
promise: new Promise((resolve, reject) => {
|
|
1069
|
+
resolveMutation = resolve;
|
|
1070
|
+
rejectMutation = reject;
|
|
1071
|
+
}),
|
|
1072
|
+
resolve: (result) => resolveMutation?.(result),
|
|
1073
|
+
reject: (error) => rejectMutation?.(error)
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
function startQueuedInitialAdd(store, queued, cartId) {
|
|
1077
|
+
if (queued.generation !== store.generation || queued.signal.aborted) {
|
|
1078
|
+
queued.deferred.reject(new DOMException("The operation was aborted.", "AbortError"));
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
getShopifyStandardActions().then(({ updateCart }) => {
|
|
1082
|
+
if (queued.generation !== store.generation || queued.signal.aborted) {
|
|
1083
|
+
queued.deferred.reject(new DOMException("The operation was aborted.", "AbortError"));
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
const eventToken = createTransactionEventToken();
|
|
1087
|
+
const expectedEvent = { token: eventToken };
|
|
1088
|
+
store.expectedEvents.push(expectedEvent);
|
|
1089
|
+
let transport;
|
|
1090
|
+
try {
|
|
1091
|
+
transport = transportAddToCart(queued.payload, queued.signal, withTransactionEventToken(updateCart, eventToken), cartId);
|
|
1092
|
+
} catch (error) {
|
|
1093
|
+
const expectedIndex = store.expectedEvents.indexOf(expectedEvent);
|
|
1094
|
+
if (expectedIndex !== -1) store.expectedEvents.splice(expectedIndex, 1);
|
|
1095
|
+
queued.deferred.reject(error);
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
observeMutationTransport(store, transport);
|
|
1099
|
+
transport.then(queued.deferred.resolve, queued.deferred.reject);
|
|
1100
|
+
}, queued.deferred.reject);
|
|
1101
|
+
}
|
|
1102
|
+
function releaseQueuedInitialAdds(store) {
|
|
1103
|
+
const gate = store.identityTransportGate;
|
|
1104
|
+
if (gate.active || gate.waiting.length === 0) return;
|
|
1105
|
+
const cartId = store.settled.data.id;
|
|
1106
|
+
if (cartId) {
|
|
1107
|
+
const waiting = gate.waiting.splice(0);
|
|
1108
|
+
for (const queued of waiting) startQueuedInitialAdd(store, queued, cartId);
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
const queued = gate.waiting.shift();
|
|
1112
|
+
if (!queued) return;
|
|
1113
|
+
gate.active = queued;
|
|
1114
|
+
const releaseNext = () => {
|
|
1115
|
+
if (gate.active !== queued) return;
|
|
1116
|
+
gate.active = null;
|
|
1117
|
+
releaseQueuedInitialAdds(store);
|
|
1118
|
+
};
|
|
1119
|
+
queued.deferred.promise.then(releaseNext, releaseNext);
|
|
1120
|
+
startQueuedInitialAdd(store, queued, store.settled.data.id ?? void 0);
|
|
1121
|
+
}
|
|
1122
|
+
async function dispatchInitialCartAdd(store, payload) {
|
|
1123
|
+
const gate = store.identityTransportGate;
|
|
1124
|
+
const deferred = createDeferredCartMutation();
|
|
1125
|
+
const reservation = reserveTransaction(store, "add_to_cart", payload);
|
|
1126
|
+
const signal = createTransactionSignal(store, reservation);
|
|
1127
|
+
const queued = {
|
|
1128
|
+
deferred,
|
|
1129
|
+
generation: store.generation,
|
|
1130
|
+
payload,
|
|
1131
|
+
reservation,
|
|
1132
|
+
signal
|
|
1133
|
+
};
|
|
1134
|
+
enqueueTransaction(store, "add_to_cart", payload, deferred.promise, reservation);
|
|
1135
|
+
gate.waiting.push(queued);
|
|
1136
|
+
releaseQueuedInitialAdds(store);
|
|
1137
|
+
signal.addEventListener("abort", () => {
|
|
1138
|
+
const index = gate.waiting.indexOf(queued);
|
|
1139
|
+
if (index === -1) return;
|
|
1140
|
+
gate.waiting.splice(index, 1);
|
|
1141
|
+
deferred.reject(new DOMException("The operation was aborted.", "AbortError"));
|
|
1142
|
+
}, { once: true });
|
|
1143
|
+
try {
|
|
1144
|
+
await deferred.promise;
|
|
1145
|
+
} catch (error) {
|
|
1146
|
+
if (isAbortError(error)) return;
|
|
1147
|
+
throw error;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
function isAbortError(error) {
|
|
1151
|
+
return error instanceof Error && error.name === "AbortError";
|
|
1152
|
+
}
|
|
1153
|
+
function payloadFromAddEvent(event) {
|
|
1154
|
+
return {
|
|
1155
|
+
lines: event.lines,
|
|
1156
|
+
products: extractProductDetails(event.detail),
|
|
1157
|
+
...event.detail ? { eventDetail: event.detail } : {}
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
function handleLinesEvent(store, event) {
|
|
1161
|
+
const eventToken = getTransactionEventToken(event.detail);
|
|
1162
|
+
if (event.action === "add") {
|
|
1163
|
+
enqueueTransaction(store, "add_to_cart", payloadFromAddEvent(event), event.promise, void 0, eventToken);
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
if (event.lines.length !== 1) return;
|
|
1167
|
+
const line = event.lines[0];
|
|
1168
|
+
enqueueTransaction(store, "change_line_quantity", {
|
|
1169
|
+
lineId: line.id,
|
|
1170
|
+
quantity: line.quantity
|
|
1171
|
+
}, event.promise, void 0, eventToken);
|
|
1172
|
+
}
|
|
1173
|
+
function handleDiscountEvent(store, event) {
|
|
1174
|
+
enqueueTransaction(store, "set_discount_codes", { discountCodes: event.discountCodes.map((discount) => discount.code) }, event.promise, void 0, getTransactionEventToken(event.detail));
|
|
1175
|
+
}
|
|
1176
|
+
function handleNoteEvent(store, event) {
|
|
1177
|
+
enqueueTransaction(store, "set_note", { note: event.note }, event.promise, void 0, getTransactionEventToken(event.detail));
|
|
1178
|
+
}
|
|
1179
|
+
function handleAttributesEvent(store, event) {
|
|
1180
|
+
enqueueTransaction(store, "set_attributes", { attributes: event.attributes }, event.promise, void 0, getTransactionEventToken(event.detail));
|
|
1181
|
+
}
|
|
1182
|
+
function connectCartStore(store, handlers) {
|
|
1183
|
+
if (typeof document === "undefined") return false;
|
|
1184
|
+
if (store.lifecycleController.signal.aborted) store.lifecycleController = new AbortController();
|
|
1185
|
+
if (store.cartSyncAttached) return true;
|
|
1186
|
+
store.cartSyncAttached = true;
|
|
1187
|
+
connectedCartStores.add(store);
|
|
1188
|
+
attachCartConsentListener();
|
|
1189
|
+
document.addEventListener("shopify:cart:lines-update", handlers.lines);
|
|
1190
|
+
document.addEventListener("shopify:cart:discount-update", handlers.discount);
|
|
1191
|
+
document.addEventListener("shopify:cart:note-update", handlers.note);
|
|
1192
|
+
document.addEventListener("shopify:cart:attributes-update", handlers.attributes);
|
|
1193
|
+
getShopifyStandardActions().catch(() => {});
|
|
1194
|
+
return true;
|
|
1195
|
+
}
|
|
1196
|
+
function cancelCartRevalidation(store) {
|
|
1197
|
+
store.revalidation.active?.controller.abort();
|
|
1198
|
+
store.revalidation.active = null;
|
|
1199
|
+
store.revalidation.requested = false;
|
|
1200
|
+
store.revalidation.visible = false;
|
|
1201
|
+
}
|
|
1202
|
+
function clearPendingTransactions(store) {
|
|
1203
|
+
store.generation += 1;
|
|
1204
|
+
store.lifecycleController.abort();
|
|
1205
|
+
store.lifecycleController = new AbortController();
|
|
1206
|
+
for (const owner of new Set(store.keyedOwners.values())) owner.controller.abort();
|
|
1207
|
+
store.keyedOwners.clear();
|
|
1208
|
+
store.transactions = [];
|
|
1209
|
+
store.projectedErrors = [];
|
|
1210
|
+
store.observedPromises.clear();
|
|
1211
|
+
store.activeMutationTransports.clear();
|
|
1212
|
+
store.expectedEvents = [];
|
|
1213
|
+
store.reservation = null;
|
|
1214
|
+
store.identityTransportGate.active = null;
|
|
1215
|
+
for (const queued of store.identityTransportGate.waiting) queued.deferred.reject(new DOMException("The operation was aborted.", "AbortError"));
|
|
1216
|
+
store.identityTransportGate.waiting = [];
|
|
1217
|
+
cancelCartRevalidation(store);
|
|
1218
|
+
}
|
|
1219
|
+
function destroyCartStore(store, handlers) {
|
|
1220
|
+
clearPendingTransactions(store);
|
|
1221
|
+
if (typeof document !== "undefined" && store.cartSyncAttached) {
|
|
1222
|
+
document.removeEventListener("shopify:cart:lines-update", handlers.lines);
|
|
1223
|
+
document.removeEventListener("shopify:cart:discount-update", handlers.discount);
|
|
1224
|
+
document.removeEventListener("shopify:cart:note-update", handlers.note);
|
|
1225
|
+
document.removeEventListener("shopify:cart:attributes-update", handlers.attributes);
|
|
1226
|
+
}
|
|
1227
|
+
connectedCartStores.delete(store);
|
|
1228
|
+
detachCartConsentListenerIfIdle();
|
|
1229
|
+
store.cartSyncAttached = false;
|
|
1230
|
+
publishVisibleState(store);
|
|
1231
|
+
}
|
|
1232
|
+
function handleVisitorConsentCollected() {
|
|
1233
|
+
revalidateConnectedCartCheckoutUrls();
|
|
1234
|
+
}
|
|
1235
|
+
function attachCartConsentListener() {
|
|
1236
|
+
if (cartConsentListenerAttached) return;
|
|
1237
|
+
document.addEventListener(VISITOR_CONSENT_COLLECTED_EVENT, handleVisitorConsentCollected);
|
|
1238
|
+
cartConsentListenerAttached = true;
|
|
1239
|
+
}
|
|
1240
|
+
function detachCartConsentListenerIfIdle() {
|
|
1241
|
+
if (!cartConsentListenerAttached || connectedCartStores.size > 0) return;
|
|
1242
|
+
document.removeEventListener(VISITOR_CONSENT_COLLECTED_EVENT, handleVisitorConsentCollected);
|
|
1243
|
+
cartConsentListenerAttached = false;
|
|
1244
|
+
}
|
|
1245
|
+
function createCartObservable(initialState, onReadyPromiseRemoved) {
|
|
1246
|
+
const observable = createObservable(initialState);
|
|
1247
|
+
return {
|
|
1248
|
+
get state() {
|
|
1249
|
+
return observable.state;
|
|
1250
|
+
},
|
|
1251
|
+
subscribe: observable.subscribe,
|
|
1252
|
+
setState(next) {
|
|
1253
|
+
observable.setState((prev) => {
|
|
1254
|
+
const nextState = typeof next === "function" ? next(prev) : next;
|
|
1255
|
+
if (Object.is(nextState, prev)) return prev;
|
|
1256
|
+
if (prev.readyPromise) {
|
|
1257
|
+
onReadyPromiseRemoved();
|
|
1258
|
+
return withoutReadyPromise({
|
|
1259
|
+
...nextState,
|
|
1260
|
+
loading: false
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
return withoutReadyPromise(nextState);
|
|
1264
|
+
});
|
|
1265
|
+
},
|
|
1266
|
+
setReadyState(next) {
|
|
1267
|
+
observable.setState(next);
|
|
1268
|
+
},
|
|
1269
|
+
clearReadyState() {
|
|
1270
|
+
observable.setState(withoutReadyPromise(observable.state));
|
|
1271
|
+
}
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
function withoutReadyPromise(state) {
|
|
1275
|
+
if (!state.readyPromise) return state;
|
|
1276
|
+
const nextState = {
|
|
1277
|
+
...state,
|
|
1278
|
+
loading: false
|
|
1279
|
+
};
|
|
1280
|
+
delete nextState.readyPromise;
|
|
1281
|
+
return nextState;
|
|
1282
|
+
}
|
|
1283
|
+
function invalidateActiveCartLoad(store) {
|
|
1284
|
+
const activeCartLoad = store.activeCartLoad;
|
|
1285
|
+
if (!activeCartLoad) return;
|
|
1286
|
+
store.activeCartLoad = null;
|
|
1287
|
+
activeCartLoad.resolveReadyPromise();
|
|
1288
|
+
}
|
|
1289
|
+
function hasLocalCartData(state) {
|
|
1290
|
+
return state.data.id !== null || state.data.totalQuantity > EMPTY_QUANTITY || getLines(state.data).length > 0;
|
|
1291
|
+
}
|
|
1292
|
+
function hydrateCartInStore(store, data) {
|
|
1293
|
+
const current = store.observable.state;
|
|
1294
|
+
invalidateActiveCartLoad(store);
|
|
1295
|
+
if (current.data.id !== null && current.data.id === data.id) {
|
|
1296
|
+
store.observable.clearReadyState();
|
|
1297
|
+
return;
|
|
1298
|
+
}
|
|
1299
|
+
if (store.transactions.length > 0) {
|
|
1300
|
+
store.observable.clearReadyState();
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1303
|
+
cancelCartRevalidation(store);
|
|
1304
|
+
store.settled = createCartState(data);
|
|
1305
|
+
store.projectedErrors = [];
|
|
1306
|
+
publishVisibleState(store);
|
|
1307
|
+
}
|
|
1308
|
+
function resetCartStore(store) {
|
|
1309
|
+
const hadActiveCartLoad = store.activeCartLoad !== null;
|
|
1310
|
+
const hadActiveRevalidation = store.revalidation.active !== null;
|
|
1311
|
+
const shouldReloadAfterReset = store.cartSyncAttached && !hadActiveRevalidation && (hadActiveCartLoad || hasLocalCartData(store.observable.state));
|
|
1312
|
+
clearPendingTransactions(store);
|
|
1313
|
+
invalidateActiveCartLoad(store);
|
|
1314
|
+
cancelCartRevalidation(store);
|
|
1315
|
+
store.lastSnapshotSequence = 0;
|
|
1316
|
+
store.settled = createEmptyCartState();
|
|
1317
|
+
publishVisibleState(store);
|
|
1318
|
+
if (shouldReloadAfterReset) loadCartInStore(store).catch((error) => log.error("cart reset load failed", { error }));
|
|
1319
|
+
}
|
|
1320
|
+
function isCurrentCartLoad(store, request) {
|
|
1321
|
+
return store.activeCartLoad === request && store.observable.state === request.state;
|
|
1322
|
+
}
|
|
1323
|
+
function loadCartInStore(store, cartPromise) {
|
|
1324
|
+
const existing = store.activeCartLoad;
|
|
1325
|
+
if (existing?.state === store.observable.state) return existing.promise;
|
|
1326
|
+
invalidateActiveCartLoad(store);
|
|
1327
|
+
let resolveReadyPromise = NOOP;
|
|
1328
|
+
const readyPromise = new Promise((resolve) => {
|
|
1329
|
+
resolveReadyPromise = resolve;
|
|
1330
|
+
});
|
|
1331
|
+
let request;
|
|
1332
|
+
const state = {
|
|
1333
|
+
...store.observable.state,
|
|
1334
|
+
readyPromise
|
|
1335
|
+
};
|
|
1336
|
+
const promise = Promise.resolve(cartPromise ?? fetchCartData(state.data.id)).then((data) => {
|
|
1337
|
+
if (!isCurrentCartLoad(store, request)) return;
|
|
1338
|
+
if (data) hydrateCartInStore(store, data);
|
|
1339
|
+
if (!data) {
|
|
1340
|
+
store.settled = {
|
|
1341
|
+
...store.settled,
|
|
1342
|
+
loading: false
|
|
1343
|
+
};
|
|
1344
|
+
publishVisibleState(store);
|
|
1345
|
+
}
|
|
1346
|
+
}).catch((error) => {
|
|
1347
|
+
if (isCurrentCartLoad(store, request)) {
|
|
1348
|
+
store.settled = {
|
|
1349
|
+
...store.settled,
|
|
1350
|
+
loading: false
|
|
1351
|
+
};
|
|
1352
|
+
publishVisibleState(store);
|
|
1353
|
+
}
|
|
1354
|
+
throw error;
|
|
1355
|
+
}).finally(() => {
|
|
1356
|
+
if (store.activeCartLoad === request) store.activeCartLoad = null;
|
|
1357
|
+
request.resolveReadyPromise();
|
|
1358
|
+
});
|
|
1359
|
+
request = {
|
|
1360
|
+
state,
|
|
1361
|
+
promise,
|
|
1362
|
+
resolveReadyPromise
|
|
1363
|
+
};
|
|
1364
|
+
store.activeCartLoad = request;
|
|
1365
|
+
store.observable.setReadyState(state);
|
|
1366
|
+
return promise;
|
|
1367
|
+
}
|
|
1368
|
+
function createCartStore(options = {}) {
|
|
1369
|
+
const initialData = options.initialData;
|
|
1370
|
+
const asyncInitialData = isPromiseLike(initialData);
|
|
1371
|
+
const syncInitialData = initialData !== void 0 && !asyncInitialData;
|
|
1372
|
+
const initialCart = syncInitialData ? initialData.cart : null;
|
|
1373
|
+
const settled = initialCart ? createCartState(initialCart) : syncInitialData ? createEmptyCartState({ loading: false }) : createEmptyCartState();
|
|
1374
|
+
let context = null;
|
|
1375
|
+
const store = {
|
|
1376
|
+
observable: createCartObservable(settled, () => {
|
|
1377
|
+
if (context) invalidateActiveCartLoad(context);
|
|
1378
|
+
}),
|
|
1379
|
+
settled,
|
|
1380
|
+
transactions: [],
|
|
1381
|
+
projectedErrors: [],
|
|
1382
|
+
observedPromises: /* @__PURE__ */ new Set(),
|
|
1383
|
+
activeMutationTransports: /* @__PURE__ */ new Set(),
|
|
1384
|
+
expectedEvents: [],
|
|
1385
|
+
nextTransactionId: 1,
|
|
1386
|
+
generation: 0,
|
|
1387
|
+
lifecycleController: new AbortController(),
|
|
1388
|
+
keyedOwners: /* @__PURE__ */ new Map(),
|
|
1389
|
+
activeCartLoad: null,
|
|
1390
|
+
revalidation: {
|
|
1391
|
+
requested: false,
|
|
1392
|
+
active: null,
|
|
1393
|
+
visible: false
|
|
1394
|
+
},
|
|
1395
|
+
mutationRevision: 0,
|
|
1396
|
+
identityTransportGate: {
|
|
1397
|
+
active: null,
|
|
1398
|
+
waiting: []
|
|
1399
|
+
},
|
|
1400
|
+
cartSyncAttached: false,
|
|
1401
|
+
reservation: null,
|
|
1402
|
+
lastSnapshotSequence: 0
|
|
1403
|
+
};
|
|
1404
|
+
context = store;
|
|
1405
|
+
const handlers = {
|
|
1406
|
+
lines: ((event) => handleLinesEvent(store, event)),
|
|
1407
|
+
discount: ((event) => handleDiscountEvent(store, event)),
|
|
1408
|
+
note: ((event) => handleNoteEvent(store, event)),
|
|
1409
|
+
attributes: ((event) => handleAttributesEvent(store, event))
|
|
1410
|
+
};
|
|
1411
|
+
if (asyncInitialData) loadCartInStore(store, Promise.resolve(initialData).then((data) => data.cart)).catch((error) => log.error("cart initial load failed", { error }));
|
|
1412
|
+
let initialCartLoadStarted = syncInitialData || asyncInitialData;
|
|
1413
|
+
return {
|
|
1414
|
+
connect: () => {
|
|
1415
|
+
if (!connectCartStore(store, handlers) || initialCartLoadStarted) return;
|
|
1416
|
+
initialCartLoadStarted = true;
|
|
1417
|
+
loadCartInStore(store).catch((error) => log.error("cart initial load failed", { error }));
|
|
1418
|
+
},
|
|
1419
|
+
destroy: () => destroyCartStore(store, handlers),
|
|
1420
|
+
hydrate: (data) => hydrateCartInStore(store, data),
|
|
1421
|
+
getState: () => store.observable.state,
|
|
1422
|
+
subscribe: (listener) => store.observable.subscribe(listener),
|
|
1423
|
+
fetch: () => loadCartInStore(store),
|
|
1424
|
+
refresh: () => refreshCartInStore(store),
|
|
1425
|
+
reset: () => resetCartStore(store),
|
|
1426
|
+
handleFormSubmit: (event, eventDetail) => handleFormSubmitInStore(store, handlers, event, eventDetail)
|
|
1427
|
+
};
|
|
1428
|
+
}
|
|
1429
|
+
const LINE_INTENTS = new Set([
|
|
1430
|
+
"increase",
|
|
1431
|
+
"decrease",
|
|
1432
|
+
"remove",
|
|
1433
|
+
"set"
|
|
1434
|
+
]);
|
|
1435
|
+
const DISCOUNT_INTENTS = new Set(["discount-apply", "discount-remove"]);
|
|
1436
|
+
function requireFormEvent(event) {
|
|
1437
|
+
if (!(event.target instanceof HTMLFormElement)) throw new TypeError(`Expected event.target to be an HTMLFormElement, got ${event.target}`);
|
|
1438
|
+
if (!(event.submitter instanceof HTMLElement)) throw new TypeError(`Expected event.submitter to be an HTMLElement, got ${event.submitter}`);
|
|
1439
|
+
return {
|
|
1440
|
+
form: event.target,
|
|
1441
|
+
submitter: event.submitter
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1444
|
+
function getLineQuantityPayload(state, intent, lineId, formData) {
|
|
1445
|
+
const line = getLines(state.data).find((candidate) => candidate.id === lineId);
|
|
1446
|
+
const currentQuantity = line?.quantity ?? 0;
|
|
1447
|
+
if (intent === "remove") return {
|
|
1448
|
+
lineId,
|
|
1449
|
+
quantity: 0
|
|
1450
|
+
};
|
|
1451
|
+
if (intent === "increase") return {
|
|
1452
|
+
lineId,
|
|
1453
|
+
quantity: currentQuantity + 1
|
|
1454
|
+
};
|
|
1455
|
+
if (intent === "decrease") return {
|
|
1456
|
+
lineId,
|
|
1457
|
+
quantity: Math.max(0, currentQuantity - 1)
|
|
1458
|
+
};
|
|
1459
|
+
const rawQuantity = Number(formData.get("quantity"));
|
|
1460
|
+
const explicitQuantity = Number.isNaN(rawQuantity) ? 1 : rawQuantity;
|
|
1461
|
+
if (explicitQuantity <= 0) return {
|
|
1462
|
+
lineId,
|
|
1463
|
+
quantity: 0
|
|
1464
|
+
};
|
|
1465
|
+
return {
|
|
1466
|
+
lineId,
|
|
1467
|
+
quantity: sanitizeQuantity(explicitQuantity, {
|
|
1468
|
+
min: 1,
|
|
1469
|
+
max: line?.merchandise?.quantityAvailable ?? void 0
|
|
1470
|
+
})
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1473
|
+
function getAddPayload(formData, eventDetail) {
|
|
1474
|
+
const merchandiseId = formData.get("merchandiseId");
|
|
1475
|
+
if (!merchandiseId) throw new Error("Add intent requires a \"merchandiseId\" field.");
|
|
1476
|
+
const rawQuantity = Number.parseInt(formData.get("quantity"), 10);
|
|
1477
|
+
const quantity = Number.isNaN(rawQuantity) ? DEFAULT_ADD_QUANTITY : Math.max(DEFAULT_ADD_QUANTITY, rawQuantity);
|
|
1478
|
+
const sellingPlanId = formData.get("sellingPlanId") || void 0;
|
|
1479
|
+
return {
|
|
1480
|
+
lines: [{
|
|
1481
|
+
merchandiseId,
|
|
1482
|
+
quantity,
|
|
1483
|
+
...sellingPlanId ? { sellingPlanId } : {}
|
|
1484
|
+
}],
|
|
1485
|
+
products: extractProductDetails(eventDetail),
|
|
1486
|
+
...eventDetail ? { eventDetail } : {}
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
function submitLineIntent(store, intent, formData) {
|
|
1490
|
+
const lineId = formData.get("lineId");
|
|
1491
|
+
if (!lineId) throw new Error("Missing \"lineId\" in form data");
|
|
1492
|
+
return dispatchTransaction(store, "change_line_quantity", getLineQuantityPayload(store.observable.state, intent, lineId, formData));
|
|
1493
|
+
}
|
|
1494
|
+
function submitDiscountIntent(store, intent, formData) {
|
|
1495
|
+
const code = formData.get("discountCode") ?? "";
|
|
1496
|
+
const currentCodes = store.observable.state.data.discountCodes.map((discount) => discount.code);
|
|
1497
|
+
return dispatchTransaction(store, "set_discount_codes", { discountCodes: intent === "discount-apply" ? [...currentCodes, code] : currentCodes.filter((current) => current !== code) });
|
|
1498
|
+
}
|
|
1499
|
+
async function handleFormSubmitInStore(store, handlers, event, eventDetail) {
|
|
1500
|
+
const { form, submitter } = requireFormEvent(event);
|
|
1501
|
+
connectCartStore(store, handlers);
|
|
1502
|
+
const intent = submitter.getAttribute("value") ?? "";
|
|
1503
|
+
const formData = new FormData(form);
|
|
1504
|
+
if (intent === "add" || !intent && formData.has("merchandiseId")) return dispatchTransaction(store, "add_to_cart", getAddPayload(formData, eventDetail));
|
|
1505
|
+
if (LINE_INTENTS.has(intent)) return submitLineIntent(store, intent, formData);
|
|
1506
|
+
if (DISCOUNT_INTENTS.has(intent)) return submitDiscountIntent(store, intent, formData);
|
|
1507
|
+
if (intent === "note-update") return dispatchTransaction(store, "set_note", { note: formData.get("note") ?? "" });
|
|
1508
|
+
if (intent === "attributes-update") return dispatchTransaction(store, "set_attributes", { attributes: getCartAttributeFormEntries(formData).map(({ key, value }) => ({
|
|
1509
|
+
key,
|
|
1510
|
+
value: String(value)
|
|
1511
|
+
})) });
|
|
1512
|
+
throw new Error(`Unknown cart form intent: "${intent}"`);
|
|
1513
|
+
}
|
|
1514
|
+
function configureCartEndpoint(endpoint) {
|
|
1515
|
+
if (configuredCartEndpoint === endpoint) return;
|
|
1516
|
+
if (configuredCartEndpoint !== null) log.warn(`configureCartEndpoint called with "${endpoint}" but already configured with "${configuredCartEndpoint}".`);
|
|
1517
|
+
configuredCartEndpoint = endpoint;
|
|
1518
|
+
}
|
|
1519
|
+
async function postCartUpdateToEndpoint(endpoint, payload, options) {
|
|
1520
|
+
const timeoutSignal = AbortSignal.timeout(STANDARD_ACTION_TIMEOUT_IN_MS);
|
|
1521
|
+
const signal = options?.signal ? AbortSignal.any([options.signal, timeoutSignal]) : timeoutSignal;
|
|
1522
|
+
const response = await fetch(endpoint, {
|
|
1523
|
+
method: "POST",
|
|
1524
|
+
headers: { "content-type": "application/json" },
|
|
1525
|
+
body: JSON.stringify(payload),
|
|
1526
|
+
signal
|
|
1527
|
+
});
|
|
1528
|
+
if (!response.ok) throw new CartNetworkError(response.status);
|
|
1529
|
+
return response.json();
|
|
1530
|
+
}
|
|
1531
|
+
function configureUpdateCartOnce(actions) {
|
|
1532
|
+
if (hasConfiguredUpdateCart) return;
|
|
1533
|
+
if (actions.updateCart.configure({
|
|
1534
|
+
eventTarget: () => document,
|
|
1535
|
+
handler: (defaultHandler, payload, options) => {
|
|
1536
|
+
if (!configuredCartEndpoint || !payload) return defaultHandler();
|
|
1537
|
+
return postCartUpdateToEndpoint(configuredCartEndpoint, payload, options);
|
|
1538
|
+
}
|
|
1539
|
+
}) === false) throw new Error("Standard Actions updateCart could not be configured.");
|
|
1540
|
+
hasConfiguredUpdateCart = true;
|
|
1541
|
+
}
|
|
1542
|
+
function hasShopifyStandardActionsScript() {
|
|
1543
|
+
if (typeof document === "undefined") return false;
|
|
1544
|
+
return document.querySelector(`script[src="${SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT}"]`) !== null;
|
|
1545
|
+
}
|
|
1546
|
+
function getShopifyStandardActions() {
|
|
1547
|
+
return standardActionsPromise ??= new Promise((resolve, reject) => {
|
|
1548
|
+
const configure = () => {
|
|
1549
|
+
const actions = typeof window === "undefined" ? void 0 : window.Shopify?.actions;
|
|
1550
|
+
if (actions?.updateCart) {
|
|
1551
|
+
configureUpdateCartOnce(actions);
|
|
1552
|
+
resolve(actions);
|
|
1553
|
+
return;
|
|
1554
|
+
}
|
|
1555
|
+
const message = hasShopifyStandardActionsScript() ? "Standard Actions not available. Ensure the Shopify script tag has loaded before calling cart actions." : `Standard Actions not available. Add ShopifyScripts to your document head or include ${SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT} before calling cart actions.`;
|
|
1556
|
+
reject(new Error(message));
|
|
1557
|
+
};
|
|
1558
|
+
if (typeof document !== "undefined" && document.readyState === "loading") {
|
|
1559
|
+
document.addEventListener("DOMContentLoaded", configure, { once: true });
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
configure();
|
|
1563
|
+
}).catch((error) => {
|
|
1564
|
+
standardActionsPromise = null;
|
|
1565
|
+
throw error;
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
function extractNoteFromCart(cart) {
|
|
1569
|
+
return cart.note ?? "";
|
|
1570
|
+
}
|
|
1571
|
+
async function fetchCart(cartId, callerSignal) {
|
|
1572
|
+
const timeoutSignal = AbortSignal.timeout(STANDARD_ACTION_TIMEOUT_IN_MS);
|
|
1573
|
+
const signal = callerSignal ? AbortSignal.any([callerSignal, timeoutSignal]) : timeoutSignal;
|
|
1574
|
+
if (configuredCartEndpoint) {
|
|
1575
|
+
const response = await fetch(configuredCartEndpoint, {
|
|
1576
|
+
cache: "no-store",
|
|
1577
|
+
signal
|
|
1578
|
+
});
|
|
1579
|
+
if (!response.ok) throw new CartNetworkError(response.status);
|
|
1580
|
+
return { cart: (await response.json()).cart };
|
|
1581
|
+
}
|
|
1582
|
+
const { getCart } = await getShopifyStandardActions();
|
|
1583
|
+
if (!getCart) throw new Error("Standard Actions not available. Ensure the Shopify script tag is loaded before calling fetchCart.");
|
|
1584
|
+
return { cart: (await getCart(cartId ? { cartId } : void 0, { signal })).cart };
|
|
1585
|
+
}
|
|
1586
|
+
function fetchCartData(cartId, signal) {
|
|
1587
|
+
return fetchCart(cartId, signal).then(({ cart }) => cart ? {
|
|
1588
|
+
...cart,
|
|
1589
|
+
checkoutUrl: cart.checkoutUrl ?? null,
|
|
1590
|
+
note: extractNoteFromCart(cart),
|
|
1591
|
+
attributes: cart.attributes ?? []
|
|
1592
|
+
} : null);
|
|
1593
|
+
}
|
|
1594
|
+
function mergeAuthoritativeCartData(previous, authoritative) {
|
|
1595
|
+
const previousLines = new Map(getLines(previous).map((line) => [line.id, line]));
|
|
1596
|
+
const lines = getLines(authoritative).map((line) => mergeServerLine(previousLines.get(line.id), line));
|
|
1597
|
+
const { checkoutUrl, cost, lines: authoritativeConnection, note, ...authoritativeFields } = authoritative;
|
|
1598
|
+
return {
|
|
1599
|
+
...previous,
|
|
1600
|
+
...authoritativeFields,
|
|
1601
|
+
cost: {
|
|
1602
|
+
...previous.cost,
|
|
1603
|
+
...cost
|
|
1604
|
+
},
|
|
1605
|
+
lines: {
|
|
1606
|
+
...previous.lines,
|
|
1607
|
+
...authoritativeConnection,
|
|
1608
|
+
nodes: lines
|
|
1609
|
+
},
|
|
1610
|
+
...checkoutUrl !== void 0 && { checkoutUrl },
|
|
1611
|
+
...note !== void 0 && { note }
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
function fetchCartRevalidationData(cartId, signal) {
|
|
1615
|
+
return fetchCart(cartId, signal).then(({ cart }) => cart ? cartResponseFromStandardEvent(cart) : null);
|
|
1616
|
+
}
|
|
1617
|
+
function isCurrentCartRevalidationRequest(store, request) {
|
|
1618
|
+
return !request.controller.signal.aborted && store.revalidation.active === request && store.generation === request.generation && store.mutationRevision === request.mutationRevision && store.transactions.length === 0 && store.settled.data.id === request.cartId;
|
|
1619
|
+
}
|
|
1620
|
+
function applyCartRevalidation(store, request, cart) {
|
|
1621
|
+
if (!isCurrentCartRevalidationRequest(store, request)) return;
|
|
1622
|
+
if (request.cartId === null) {
|
|
1623
|
+
if (cart) {
|
|
1624
|
+
hydrateCartInStore(store, cart);
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
store.revalidation.visible = false;
|
|
1628
|
+
publishVisibleState(store);
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
if (!cart) throw new Error(CART_REVALIDATION_ERROR_MESSAGE);
|
|
1632
|
+
if (cart.id !== request.cartId) {
|
|
1633
|
+
hydrateCartInStore(store, cart);
|
|
1634
|
+
return;
|
|
1635
|
+
}
|
|
1636
|
+
store.settled = {
|
|
1637
|
+
...store.settled,
|
|
1638
|
+
data: mergeAuthoritativeCartData(store.settled.data, cart)
|
|
1639
|
+
};
|
|
1640
|
+
store.revalidation.visible = false;
|
|
1641
|
+
publishVisibleState(store);
|
|
1642
|
+
}
|
|
1643
|
+
function refreshCartInStore(store) {
|
|
1644
|
+
const activeCartLoad = store.activeCartLoad;
|
|
1645
|
+
if (activeCartLoad) {
|
|
1646
|
+
const runAfterLoad = () => refreshCartInStore(store);
|
|
1647
|
+
activeCartLoad.promise.then(runAfterLoad, runAfterLoad);
|
|
1648
|
+
return;
|
|
1649
|
+
}
|
|
1650
|
+
requestCartRevalidation(store);
|
|
1651
|
+
publishVisibleState(store);
|
|
1652
|
+
revalidateCartWhenIdle(store);
|
|
1653
|
+
}
|
|
1654
|
+
function revalidateCartWhenIdle(store) {
|
|
1655
|
+
if (!store.revalidation.requested || store.revalidation.active || store.transactions.length > 0 || store.activeMutationTransports.size > 0) return;
|
|
1656
|
+
store.revalidation.requested = false;
|
|
1657
|
+
clearProjectedErrors(store, [REVALIDATION_ERROR_KEY]);
|
|
1658
|
+
publishVisibleState(store);
|
|
1659
|
+
const cartId = store.settled.data.id;
|
|
1660
|
+
const controller = new AbortController();
|
|
1661
|
+
let request;
|
|
1662
|
+
const promise = (cartId ? fetchCartRevalidationData(cartId, controller.signal) : fetchCartData(null, controller.signal)).then((cart) => applyCartRevalidation(store, request, cart)).catch((error) => {
|
|
1663
|
+
if (isAbortError(error) || !isCurrentCartRevalidationRequest(store, request)) return;
|
|
1664
|
+
store.revalidation.visible = false;
|
|
1665
|
+
addProjectedError(store, [REVALIDATION_ERROR_KEY], (state, timestampMs) => writeNetworkError(state, new Error(CART_REVALIDATION_ERROR_MESSAGE), timestampMs));
|
|
1666
|
+
publishVisibleState(store);
|
|
1667
|
+
}).finally(() => {
|
|
1668
|
+
if (store.revalidation.active === request) store.revalidation.active = null;
|
|
1669
|
+
revalidateCartWhenIdle(store);
|
|
1670
|
+
});
|
|
1671
|
+
request = {
|
|
1672
|
+
cartId,
|
|
1673
|
+
controller,
|
|
1674
|
+
generation: store.generation,
|
|
1675
|
+
mutationRevision: store.mutationRevision,
|
|
1676
|
+
promise
|
|
1677
|
+
};
|
|
1678
|
+
store.revalidation.active = request;
|
|
1679
|
+
}
|
|
1680
|
+
async function refreshCheckoutUrl(store) {
|
|
1681
|
+
const { cart } = await fetchCart(store.observable.state.data.id);
|
|
1682
|
+
const current = store.observable.state;
|
|
1683
|
+
if (!cart || current.data.id && current.data.id !== cart.id) return;
|
|
1684
|
+
const checkoutUrl = cart.checkoutUrl ?? null;
|
|
1685
|
+
if (current.data.checkoutUrl === checkoutUrl) return;
|
|
1686
|
+
store.settled = {
|
|
1687
|
+
...store.settled,
|
|
1688
|
+
data: {
|
|
1689
|
+
...store.settled.data,
|
|
1690
|
+
checkoutUrl
|
|
1691
|
+
}
|
|
1692
|
+
};
|
|
1693
|
+
publishVisibleState(store);
|
|
1694
|
+
}
|
|
1695
|
+
/** @internal */
|
|
1696
|
+
function revalidateConnectedCartCheckoutUrls() {
|
|
1697
|
+
if (typeof window === "undefined") return;
|
|
1698
|
+
for (const store of connectedCartStores) {
|
|
1699
|
+
const state = store.observable.state;
|
|
1700
|
+
if (!state.data.checkoutUrl || state.data.totalQuantity === 0) continue;
|
|
1701
|
+
refreshCheckoutUrl(store).catch(() => {});
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
//#endregion
|
|
1706
|
+
export { CartNetworkError, STANDARD_ACTION_TIMEOUT_IN_MS, configureCartEndpoint, createCartStore };
|
|
1707
|
+
//# sourceMappingURL=cart.mjs.map
|