@shopify/hydrogen 2026.10.0-preview.4 → 2026.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.mjs +23 -12
- package/dist/client/client.d.mts +18 -15
- package/dist/client/client.mjs +8 -3
- package/dist/client/client.mjs.map +1 -1
- package/dist/client/errors.d.mts +35 -13
- package/dist/client/errors.mjs +23 -13
- package/dist/client/errors.mjs.map +1 -1
- package/dist/client/types.d.mts +140 -90
- package/dist/core/analytics/cart-tracker.d.mts +19 -10
- package/dist/core/analytics/cart-tracker.mjs +18 -10
- package/dist/core/analytics/cart-tracker.mjs.map +1 -1
- package/dist/core/analytics/events.d.mts +17 -11
- package/dist/core/analytics/events.mjs +13 -4
- package/dist/core/analytics/events.mjs.map +1 -1
- package/dist/core/analytics/types.d.mts +207 -118
- package/dist/core/analytics/utils/flatten-connection.d.mts +11 -9
- package/dist/core/analytics/utils/flatten-connection.mjs +7 -6
- package/dist/core/analytics/utils/flatten-connection.mjs.map +1 -1
- package/dist/core/cache/fetch-with-cache.d.mts +24 -4
- package/dist/core/cache/fetch-with-cache.mjs +17 -2
- package/dist/core/cache/fetch-with-cache.mjs.map +1 -1
- package/dist/core/cache/key.d.mts +2 -0
- package/dist/core/cache/key.mjs.map +1 -1
- package/dist/core/cache/run-with-cache.d.mts +56 -8
- package/dist/core/cache/run-with-cache.mjs +17 -6
- package/dist/core/cache/run-with-cache.mjs.map +1 -1
- package/dist/core/cache/store.d.mts +8 -6
- package/dist/core/cache/store.mjs.map +1 -1
- package/dist/core/cache/strategies.d.mts +27 -2
- package/dist/core/cache/strategies.mjs +6 -0
- package/dist/core/cache/strategies.mjs.map +1 -1
- package/dist/core/cart/actions.d.mts +37 -30
- package/dist/core/cart/actions.mjs +21 -9
- package/dist/core/cart/actions.mjs.map +1 -1
- package/dist/core/cart/attach-quantity-input.d.mts +8 -7
- package/dist/core/cart/attach-quantity-input.mjs +8 -7
- package/dist/core/cart/attach-quantity-input.mjs.map +1 -1
- package/dist/core/cart/buyer-identity-sync.d.mts +7 -6
- package/dist/core/cart/buyer-identity-sync.mjs.map +1 -1
- package/dist/core/cart/cart.d.mts +59 -46
- package/dist/core/cart/cart.mjs +46 -29
- package/dist/core/cart/cart.mjs.map +1 -1
- package/dist/core/cart/cookie.d.mts +8 -4
- package/dist/core/cart/cookie.mjs +8 -4
- package/dist/core/cart/cookie.mjs.map +1 -1
- package/dist/core/cart/form.d.mts +34 -20
- package/dist/core/cart/form.mjs +6 -4
- package/dist/core/cart/form.mjs.map +1 -1
- package/dist/core/cart/get-cart.d.mts +27 -15
- package/dist/core/cart/get-cart.mjs +13 -8
- package/dist/core/cart/get-cart.mjs.map +1 -1
- package/dist/core/cart/quantity.d.mts +16 -5
- package/dist/core/cart/quantity.mjs +16 -5
- package/dist/core/cart/quantity.mjs.map +1 -1
- package/dist/core/cart/queries.d.mts +25 -19
- package/dist/core/cart/queries.mjs +15 -1
- package/dist/core/cart/queries.mjs.map +1 -1
- package/dist/core/cart/server-handlers.d.mts +82 -45
- package/dist/core/cart/server-handlers.mjs +4 -0
- package/dist/core/cart/server-handlers.mjs.map +1 -1
- package/dist/core/cart/state.d.mts +110 -64
- package/dist/core/cart/state.mjs +24 -6
- package/dist/core/cart/state.mjs.map +1 -1
- package/dist/core/collection/collection.d.mts +52 -53
- package/dist/core/collection/collection.mjs +5 -3
- package/dist/core/collection/collection.mjs.map +1 -1
- package/dist/core/collection/reconciler.d.mts +23 -16
- package/dist/core/collection/reconciler.mjs +8 -4
- package/dist/core/collection/reconciler.mjs.map +1 -1
- package/dist/core/collection/state.d.mts +31 -26
- package/dist/core/collection/state.mjs +4 -3
- package/dist/core/collection/state.mjs.map +1 -1
- package/dist/core/collection/url.d.mts +70 -29
- package/dist/core/collection/url.mjs +63 -25
- package/dist/core/collection/url.mjs.map +1 -1
- package/dist/core/constants.d.mts +1 -0
- package/dist/core/constants.mjs +1 -0
- package/dist/core/constants.mjs.map +1 -1
- package/dist/core/logging/logging.d.mts +14 -8
- package/dist/core/logging/logging.mjs +15 -10
- package/dist/core/logging/logging.mjs.map +1 -1
- package/dist/core/logging/types.d.mts +28 -11
- package/dist/core/logging/types.mjs.map +1 -1
- package/dist/core/money/format.d.mts +6 -4
- package/dist/core/money/format.mjs +19 -9
- package/dist/core/money/format.mjs.map +1 -1
- package/dist/core/money/types.d.mts +41 -25
- package/dist/core/predictive-search/form.d.mts +37 -7
- package/dist/core/predictive-search/form.mjs +21 -3
- package/dist/core/predictive-search/form.mjs.map +1 -1
- package/dist/core/predictive-search/queries.d.mts +18 -30
- package/dist/core/predictive-search/queries.mjs +7 -3
- package/dist/core/predictive-search/queries.mjs.map +1 -1
- package/dist/core/predictive-search/search.d.mts +25 -27
- package/dist/core/predictive-search/search.mjs +20 -19
- package/dist/core/predictive-search/search.mjs.map +1 -1
- package/dist/core/predictive-search/server-handlers.d.mts +25 -26
- package/dist/core/predictive-search/server-handlers.mjs +4 -0
- package/dist/core/predictive-search/server-handlers.mjs.map +1 -1
- package/dist/core/predictive-search/store.d.mts +65 -24
- package/dist/core/predictive-search/store.mjs +12 -1
- package/dist/core/predictive-search/store.mjs.map +1 -1
- package/dist/core/predictive-search/url.d.mts +36 -37
- package/dist/core/predictive-search/url.mjs +14 -6
- package/dist/core/predictive-search/url.mjs.map +1 -1
- package/dist/core/product/form.d.mts +63 -16
- package/dist/core/product/form.mjs +8 -2
- package/dist/core/product/form.mjs.map +1 -1
- package/dist/core/product/options.d.mts +8 -10
- package/dist/core/product/options.mjs +8 -10
- package/dist/core/product/options.mjs.map +1 -1
- package/dist/core/product/product-form.d.mts +77 -29
- package/dist/core/product/product-form.mjs +32 -10
- package/dist/core/product/product-form.mjs.map +1 -1
- package/dist/core/product/state.d.mts +55 -32
- package/dist/core/product/url.d.mts +19 -13
- package/dist/core/product/url.mjs +10 -10
- package/dist/core/product/url.mjs.map +1 -1
- package/dist/core/request-context.d.mts +77 -19
- package/dist/core/request-context.mjs +5 -1
- package/dist/core/request-context.mjs.map +1 -1
- package/dist/core/request-routing/handle-shopify-redirects.d.mts +12 -4
- package/dist/core/request-routing/handle-shopify-redirects.mjs +9 -2
- package/dist/core/request-routing/handle-shopify-redirects.mjs.map +1 -1
- package/dist/core/request-routing/handle-shopify-routes.d.mts +5 -5
- package/dist/core/request-routing/handle-shopify-routes.mjs +7 -5
- package/dist/core/request-routing/handle-shopify-routes.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/proxy.mjs +79 -43
- package/dist/core/request-routing/interceptors/proxy.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/ucp-profile-proxy.mjs +69 -0
- package/dist/core/request-routing/interceptors/ucp-profile-proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/url-redirects.mjs +6 -1
- package/dist/core/request-routing/interceptors/url-redirects.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/well-known.mjs +1 -1
- package/dist/core/request-routing/interceptors/well-known.mjs.map +1 -1
- package/dist/core/request-routing/registered-routes.d.mts +12 -0
- package/dist/core/request-routing/registered-routes.mjs +12 -0
- package/dist/core/request-routing/registered-routes.mjs.map +1 -1
- package/dist/core/request-routing/route-types.d.mts +43 -18
- package/dist/core/shop-pay/shop-pay.d.mts +71 -35
- package/dist/core/shop-pay/shop-pay.mjs +36 -10
- package/dist/core/shop-pay/shop-pay.mjs.map +1 -1
- package/dist/core/shopify-scripts/index.d.mts +15 -5
- package/dist/core/shopify-scripts/index.mjs +15 -5
- package/dist/core/shopify-scripts/index.mjs.map +1 -1
- package/dist/core/shopify-scripts/initialize.d.mts +12 -4
- package/dist/core/shopify-scripts/initialize.mjs +12 -4
- package/dist/core/shopify-scripts/initialize.mjs.map +1 -1
- package/dist/core/shopify-scripts/types.d.mts +58 -25
- package/dist/core/standard-routes/build.d.mts +11 -12
- package/dist/core/standard-routes/build.mjs +11 -12
- package/dist/core/standard-routes/build.mjs.map +1 -1
- package/dist/core/standard-routes/types.d.mts +30 -24
- package/dist/core/url.mjs +2 -1
- package/dist/core/url.mjs.map +1 -1
- package/dist/customer-account/client.d.mts +36 -69
- package/dist/customer-account/client.mjs +7 -8
- package/dist/customer-account/client.mjs.map +1 -1
- package/dist/customer-account/errors.d.mts +45 -36
- package/dist/customer-account/errors.mjs +21 -36
- package/dist/customer-account/errors.mjs.map +1 -1
- package/dist/customer-account/graphql.d.mts +11 -23
- package/dist/customer-account/graphql.mjs +3 -9
- package/dist/customer-account/graphql.mjs.map +1 -1
- package/dist/customer-account/session.d.mts +130 -100
- package/dist/customer-account/session.mjs +32 -10
- package/dist/customer-account/session.mjs.map +1 -1
- package/dist/customer-account/type-resolver.d.mts +7 -8
- package/dist/development/client/client.d.mts +18 -15
- package/dist/development/client/client.mjs +8 -3
- package/dist/development/client/client.mjs.map +1 -1
- package/dist/development/client/errors.d.mts +35 -13
- package/dist/development/client/errors.mjs +23 -13
- package/dist/development/client/errors.mjs.map +1 -1
- package/dist/development/client/types.d.mts +140 -90
- package/dist/development/core/analytics/cart-tracker.d.mts +19 -10
- package/dist/development/core/analytics/cart-tracker.mjs +18 -10
- package/dist/development/core/analytics/cart-tracker.mjs.map +1 -1
- package/dist/development/core/analytics/events.d.mts +17 -11
- package/dist/development/core/analytics/events.mjs +13 -4
- package/dist/development/core/analytics/events.mjs.map +1 -1
- package/dist/development/core/analytics/types.d.mts +207 -118
- package/dist/development/core/analytics/utils/flatten-connection.d.mts +11 -9
- package/dist/development/core/analytics/utils/flatten-connection.mjs +7 -6
- package/dist/development/core/analytics/utils/flatten-connection.mjs.map +1 -1
- package/dist/development/core/cache/fetch-with-cache.d.mts +24 -4
- package/dist/development/core/cache/fetch-with-cache.mjs +17 -2
- package/dist/development/core/cache/fetch-with-cache.mjs.map +1 -1
- package/dist/development/core/cache/key.d.mts +2 -0
- package/dist/development/core/cache/key.mjs.map +1 -1
- package/dist/development/core/cache/run-with-cache.d.mts +56 -8
- package/dist/development/core/cache/run-with-cache.mjs +17 -6
- package/dist/development/core/cache/run-with-cache.mjs.map +1 -1
- package/dist/development/core/cache/store.d.mts +8 -6
- package/dist/development/core/cache/store.mjs.map +1 -1
- package/dist/development/core/cache/strategies.d.mts +27 -2
- package/dist/development/core/cache/strategies.mjs +6 -0
- package/dist/development/core/cache/strategies.mjs.map +1 -1
- package/dist/development/core/cart/actions.d.mts +37 -30
- package/dist/development/core/cart/actions.mjs +21 -9
- package/dist/development/core/cart/actions.mjs.map +1 -1
- package/dist/development/core/cart/attach-quantity-input.d.mts +8 -7
- package/dist/development/core/cart/attach-quantity-input.mjs +8 -7
- package/dist/development/core/cart/attach-quantity-input.mjs.map +1 -1
- package/dist/development/core/cart/buyer-identity-sync.d.mts +6 -5
- package/dist/development/core/cart/buyer-identity-sync.mjs.map +1 -1
- package/dist/development/core/cart/cart.d.mts +59 -46
- package/dist/development/core/cart/cart.mjs +46 -29
- package/dist/development/core/cart/cart.mjs.map +1 -1
- package/dist/development/core/cart/cookie.d.mts +8 -4
- package/dist/development/core/cart/cookie.mjs +8 -4
- package/dist/development/core/cart/cookie.mjs.map +1 -1
- package/dist/development/core/cart/form.d.mts +34 -20
- package/dist/development/core/cart/form.mjs +6 -4
- package/dist/development/core/cart/form.mjs.map +1 -1
- package/dist/development/core/cart/get-cart.d.mts +27 -15
- package/dist/development/core/cart/get-cart.mjs +13 -8
- package/dist/development/core/cart/get-cart.mjs.map +1 -1
- package/dist/development/core/cart/quantity.d.mts +16 -5
- package/dist/development/core/cart/quantity.mjs +16 -5
- package/dist/development/core/cart/quantity.mjs.map +1 -1
- package/dist/development/core/cart/queries.d.mts +25 -19
- package/dist/development/core/cart/queries.mjs +15 -1
- package/dist/development/core/cart/queries.mjs.map +1 -1
- package/dist/development/core/cart/server-handlers.d.mts +82 -45
- package/dist/development/core/cart/server-handlers.mjs +4 -0
- package/dist/development/core/cart/server-handlers.mjs.map +1 -1
- package/dist/development/core/cart/state.d.mts +110 -64
- package/dist/development/core/cart/state.mjs +24 -6
- package/dist/development/core/cart/state.mjs.map +1 -1
- package/dist/development/core/collection/collection.d.mts +52 -53
- package/dist/development/core/collection/collection.mjs +5 -3
- package/dist/development/core/collection/collection.mjs.map +1 -1
- package/dist/development/core/collection/reconciler.d.mts +23 -16
- package/dist/development/core/collection/reconciler.mjs +8 -4
- package/dist/development/core/collection/reconciler.mjs.map +1 -1
- package/dist/development/core/collection/state.d.mts +31 -26
- package/dist/development/core/collection/state.mjs +4 -3
- package/dist/development/core/collection/state.mjs.map +1 -1
- package/dist/development/core/collection/url.d.mts +70 -29
- package/dist/development/core/collection/url.mjs +63 -25
- package/dist/development/core/collection/url.mjs.map +1 -1
- package/dist/development/core/constants.mjs.map +1 -1
- package/dist/development/core/logging/logging.d.mts +14 -8
- package/dist/development/core/logging/logging.mjs +15 -10
- package/dist/development/core/logging/logging.mjs.map +1 -1
- package/dist/development/core/logging/types.d.mts +28 -11
- package/dist/development/core/logging/types.mjs.map +1 -1
- package/dist/development/core/money/format.d.mts +6 -4
- package/dist/development/core/money/format.mjs +19 -9
- package/dist/development/core/money/format.mjs.map +1 -1
- package/dist/development/core/money/types.d.mts +41 -25
- package/dist/development/core/predictive-search/form.d.mts +37 -7
- package/dist/development/core/predictive-search/form.mjs +21 -3
- package/dist/development/core/predictive-search/form.mjs.map +1 -1
- package/dist/development/core/predictive-search/queries.d.mts +18 -30
- package/dist/development/core/predictive-search/queries.mjs +7 -3
- package/dist/development/core/predictive-search/queries.mjs.map +1 -1
- package/dist/development/core/predictive-search/search.d.mts +25 -27
- package/dist/development/core/predictive-search/search.mjs +20 -19
- package/dist/development/core/predictive-search/search.mjs.map +1 -1
- package/dist/development/core/predictive-search/server-handlers.d.mts +25 -26
- package/dist/development/core/predictive-search/server-handlers.mjs +4 -0
- package/dist/development/core/predictive-search/server-handlers.mjs.map +1 -1
- package/dist/development/core/predictive-search/store.d.mts +65 -24
- package/dist/development/core/predictive-search/store.mjs +12 -1
- package/dist/development/core/predictive-search/store.mjs.map +1 -1
- package/dist/development/core/predictive-search/url.d.mts +36 -37
- package/dist/development/core/predictive-search/url.mjs +14 -6
- package/dist/development/core/predictive-search/url.mjs.map +1 -1
- package/dist/development/core/product/form.d.mts +63 -16
- package/dist/development/core/product/form.mjs +8 -2
- package/dist/development/core/product/form.mjs.map +1 -1
- package/dist/development/core/product/options.d.mts +8 -10
- package/dist/development/core/product/options.mjs +8 -10
- package/dist/development/core/product/options.mjs.map +1 -1
- package/dist/development/core/product/product-form.d.mts +77 -29
- package/dist/development/core/product/product-form.mjs +32 -10
- package/dist/development/core/product/product-form.mjs.map +1 -1
- package/dist/development/core/product/state.d.mts +55 -32
- package/dist/development/core/product/url.d.mts +19 -13
- package/dist/development/core/product/url.mjs +10 -10
- package/dist/development/core/product/url.mjs.map +1 -1
- package/dist/development/core/request-context.d.mts +77 -19
- package/dist/development/core/request-context.mjs +5 -1
- package/dist/development/core/request-context.mjs.map +1 -1
- package/dist/development/core/request-routing/handle-shopify-redirects.d.mts +12 -4
- package/dist/development/core/request-routing/handle-shopify-redirects.mjs +9 -2
- package/dist/development/core/request-routing/handle-shopify-redirects.mjs.map +1 -1
- package/dist/development/core/request-routing/handle-shopify-routes.development.d.mts +9 -1
- package/dist/development/core/request-routing/handle-shopify-routes.development.mjs +7 -0
- package/dist/development/core/request-routing/handle-shopify-routes.development.mjs.map +1 -1
- package/dist/development/core/request-routing/handle-shopify-routes.mjs +7 -5
- package/dist/development/core/request-routing/handle-shopify-routes.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/proxy.mjs +79 -43
- package/dist/development/core/request-routing/interceptors/proxy.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/ucp-profile-proxy.mjs +69 -0
- package/dist/development/core/request-routing/interceptors/ucp-profile-proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/url-redirects.mjs +6 -1
- package/dist/development/core/request-routing/interceptors/url-redirects.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/well-known.mjs +1 -1
- package/dist/development/core/request-routing/interceptors/well-known.mjs.map +1 -1
- package/dist/development/core/request-routing/registered-routes.d.mts +12 -0
- package/dist/development/core/request-routing/registered-routes.mjs +12 -0
- package/dist/development/core/request-routing/registered-routes.mjs.map +1 -1
- package/dist/development/core/request-routing/route-types.d.mts +43 -18
- package/dist/development/core/shop-pay/shop-pay.d.mts +71 -35
- package/dist/development/core/shop-pay/shop-pay.mjs +36 -10
- package/dist/development/core/shop-pay/shop-pay.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/index.d.mts +15 -5
- package/dist/development/core/shopify-scripts/index.mjs +15 -5
- package/dist/development/core/shopify-scripts/index.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/initialize.d.mts +12 -4
- package/dist/development/core/shopify-scripts/initialize.mjs +12 -4
- package/dist/development/core/shopify-scripts/initialize.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/types.d.mts +58 -25
- package/dist/development/core/standard-routes/build.d.mts +11 -12
- package/dist/development/core/standard-routes/build.mjs +11 -12
- package/dist/development/core/standard-routes/build.mjs.map +1 -1
- package/dist/development/core/standard-routes/types.d.mts +30 -24
- package/dist/development/core/url.mjs +2 -1
- package/dist/development/core/url.mjs.map +1 -1
- package/dist/development/customer-account/session.d.mts +45 -54
- package/dist/development/customer-account/session.mjs +20 -4
- package/dist/development/customer-account/session.mjs.map +1 -1
- package/dist/development/globals.d.mts +20 -11
- package/dist/development/graphql/generated/storefront-api-types.d.mts +127 -1
- package/dist/development/graphql/graphql.d.mts +17 -16
- package/dist/development/graphql/graphql.mjs +7 -8
- package/dist/development/graphql/graphql.mjs.map +1 -1
- package/dist/development/graphql/type-resolver.d.mts +15 -8
- package/dist/development/react/cart.d.mts +78 -32
- package/dist/development/react/cart.mjs +56 -29
- package/dist/development/react/cart.mjs.map +1 -1
- package/dist/development/react/collection.d.mts +40 -22
- package/dist/development/react/collection.mjs +27 -7
- package/dist/development/react/collection.mjs.map +1 -1
- package/dist/development/react/predictive-search.d.mts +65 -50
- package/dist/development/react/predictive-search.mjs +23 -21
- package/dist/development/react/predictive-search.mjs.map +1 -1
- package/dist/development/react/product.d.mts +45 -16
- package/dist/development/react/product.mjs +13 -11
- package/dist/development/react/product.mjs.map +1 -1
- package/dist/development/react/shop-pay.d.mts +15 -0
- package/dist/development/react/shop-pay.mjs +9 -0
- package/dist/development/react/shop-pay.mjs.map +1 -1
- package/dist/development/react/shopify-scripts.d.mts +23 -2
- package/dist/development/react/shopify-scripts.mjs +9 -0
- package/dist/development/react/shopify-scripts.mjs.map +1 -1
- package/dist/development/vue/cart.d.mts +28 -23
- package/dist/development/vue/cart.mjs +42 -25
- package/dist/development/vue/cart.mjs.map +1 -1
- package/dist/development/vue/collection.d.mts +20 -12
- package/dist/development/vue/collection.mjs +15 -7
- package/dist/development/vue/collection.mjs.map +1 -1
- package/dist/development/vue/index.d.mts +2 -2
- package/dist/development/vue/index.mjs +2 -2
- package/dist/development/vue/predictive-search.d.mts +31 -36
- package/dist/development/vue/predictive-search.mjs +16 -22
- package/dist/development/vue/predictive-search.mjs.map +1 -1
- package/dist/development/vue/product.d.mts +16 -15
- package/dist/development/vue/product.mjs +11 -11
- package/dist/development/vue/product.mjs.map +1 -1
- package/dist/development/vue/shop-pay.d.mts +14 -17
- package/dist/development/vue/shop-pay.mjs +8 -0
- package/dist/development/vue/shop-pay.mjs.map +1 -1
- package/dist/development/vue/shopify-scripts.d.mts +11 -0
- package/dist/development/vue/shopify-scripts.mjs +6 -0
- package/dist/development/vue/shopify-scripts.mjs.map +1 -1
- package/dist/globals.d.mts +20 -11
- package/dist/graphql/generated/storefront-api-types.d.mts +127 -1
- package/dist/graphql/graphql.d.mts +17 -16
- package/dist/graphql/graphql.mjs +7 -8
- package/dist/graphql/graphql.mjs.map +1 -1
- package/dist/graphql/type-resolver.d.mts +15 -8
- package/dist/react/cart.d.mts +78 -32
- package/dist/react/cart.mjs +56 -29
- package/dist/react/cart.mjs.map +1 -1
- package/dist/react/collection.d.mts +40 -22
- package/dist/react/collection.mjs +27 -7
- package/dist/react/collection.mjs.map +1 -1
- package/dist/react/predictive-search.d.mts +65 -50
- package/dist/react/predictive-search.mjs +23 -21
- package/dist/react/predictive-search.mjs.map +1 -1
- package/dist/react/product.d.mts +45 -16
- package/dist/react/product.mjs +13 -11
- package/dist/react/product.mjs.map +1 -1
- package/dist/react/shop-pay.d.mts +15 -0
- package/dist/react/shop-pay.mjs +9 -0
- package/dist/react/shop-pay.mjs.map +1 -1
- package/dist/react/shopify-scripts.d.mts +23 -2
- package/dist/react/shopify-scripts.mjs +9 -0
- package/dist/react/shopify-scripts.mjs.map +1 -1
- package/dist/ts-plugin/index.cjs +6 -0
- package/dist/ts-plugin/index.cjs.map +1 -1
- package/dist/ts-plugin/index.d.cts +6 -0
- package/dist/vite/local-https.d.mts +51 -17
- package/dist/vite/local-https.mjs +26 -5
- package/dist/vite/local-https.mjs.map +1 -1
- package/dist/vue/cart.d.mts +28 -23
- package/dist/vue/cart.mjs +42 -25
- package/dist/vue/cart.mjs.map +1 -1
- package/dist/vue/collection.d.mts +20 -12
- package/dist/vue/collection.mjs +15 -7
- package/dist/vue/collection.mjs.map +1 -1
- package/dist/vue/index.d.mts +2 -2
- package/dist/vue/index.mjs +2 -2
- package/dist/vue/predictive-search.d.mts +31 -36
- package/dist/vue/predictive-search.mjs +16 -22
- package/dist/vue/predictive-search.mjs.map +1 -1
- package/dist/vue/product.d.mts +16 -15
- package/dist/vue/product.mjs +11 -11
- package/dist/vue/product.mjs.map +1 -1
- package/dist/vue/shop-pay.d.mts +14 -17
- package/dist/vue/shop-pay.mjs +8 -0
- package/dist/vue/shop-pay.mjs.map +1 -1
- package/dist/vue/shopify-scripts.d.mts +11 -0
- package/dist/vue/shopify-scripts.mjs +6 -0
- package/dist/vue/shopify-scripts.mjs.map +1 -1
- package/package.json +3 -1
- package/skills/hydrogen-analytics/SKILL.md +1 -1
- package/skills/hydrogen-cart-ui/SKILL.md +28 -2
- package/skills/hydrogen-collection-browser/SKILL.md +9 -1
- package/skills/hydrogen-collection-browser/references/nextjs.md +1 -1
- package/skills/hydrogen-collection-browser/references/nuxt.md +1 -1
- package/skills/hydrogen-collection-browser/references/react.md +151 -32
- package/skills/hydrogen-customer-account/SKILL.md +2 -0
- package/skills/hydrogen-request-handlers/SKILL.md +21 -11
- package/skills/hydrogen-setup/references/analytics.md +14 -8
- package/skills/hydrogen-setup/steps/1-inspect-app.md +2 -2
- package/skills/hydrogen-setup/steps/6-product-detail-page.md +21 -11
- package/skills/hydrogen-storefront-client/SKILL.md +1 -1
- package/skills/hydrogen-storefront-client/references/caching.md +2 -0
- package/skills/hydrogen-variant-form/SKILL.md +25 -7
- package/skills/hydrogen-variant-form/references/nextjs.md +39 -4
- package/skills/hydrogen-variant-form/references/nuxt.md +83 -42
- package/skills/hydrogen-variant-form/references/react.md +45 -9
|
@@ -13,72 +13,103 @@ declare const CART_API_PATH: "/api/cart";
|
|
|
13
13
|
declare const CART_GET_METHOD: "GET";
|
|
14
14
|
declare const CART_POST_METHOD: "POST";
|
|
15
15
|
declare const cartServerHandlersCartQuery: unique symbol;
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* The response body that the cart GET handler returns.
|
|
18
|
+
*
|
|
19
|
+
* @publicDocs
|
|
20
|
+
*/
|
|
17
21
|
type CartGetData<TCart = CartData> = {
|
|
18
|
-
cart: TCart | null;
|
|
22
|
+
/** The cart, or `null` when the request has no cart ID, the cart doesn't exist, or the cart query returns GraphQL errors. */cart: TCart | null; /** GraphQL errors from the cart query. The handler also logs the errors on the server. */
|
|
19
23
|
errors?: Array<{
|
|
20
24
|
message: string;
|
|
21
25
|
}>;
|
|
22
26
|
};
|
|
23
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* The JSON result that the cart GET handler returns. The handler sets private cache headers that keep CDNs and shared caches from storing the cart.
|
|
29
|
+
*
|
|
30
|
+
* @publicDocs
|
|
31
|
+
*/
|
|
24
32
|
type CartGetResult<TCart = CartData> = ShopifyRouteJsonResult<CartGetData<TCart>>;
|
|
25
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Error codes that the cart POST handler returns. The handler returns `invalid_cart_request` when it can't parse a JSON request, and `missing_cart` when a JSON request changes the cart but has no cart ID. With `customerSession`, the handler returns `cart_mutation_failed` when a mutation fails after the handler refreshes the customer's access token.
|
|
35
|
+
*/
|
|
26
36
|
type CartErrorCode = "invalid_cart_request" | "missing_cart" | "cart_mutation_failed";
|
|
27
|
-
/**
|
|
28
|
-
|
|
37
|
+
/**
|
|
38
|
+
* An error that the cart POST handler returns, with a code that identifies the failure.
|
|
39
|
+
*
|
|
40
|
+
* @publicDocs
|
|
41
|
+
*/
|
|
42
|
+
interface CartError extends ShopifyRouteError {
|
|
43
|
+
/** The code that identifies the failure. */
|
|
29
44
|
code: CartErrorCode;
|
|
30
|
-
}
|
|
45
|
+
}
|
|
31
46
|
/**
|
|
32
|
-
*
|
|
33
|
-
* - JSON
|
|
34
|
-
* - 303 redirect
|
|
35
|
-
* -
|
|
47
|
+
* The route result that the cart POST handler returns. Check `type` to tell the results apart:
|
|
48
|
+
* - `json` answers a JSON request. The result's `data` holds the mutation's `cart`, `userErrors`, and `warnings`.
|
|
49
|
+
* - `redirect` answers a form submission with a `303` redirect to the referring page.
|
|
50
|
+
* - `error` holds a cart error with a code that identifies the failure.
|
|
51
|
+
*
|
|
52
|
+
* @publicDocs
|
|
36
53
|
*/
|
|
37
54
|
type CartPostResult = ShopifyRouteJsonResult<Record<string, unknown>> | ShopifyRouteRedirectResult | ShopifyRouteErrorResult<CartError>;
|
|
55
|
+
/** The context that you pass to the cart GET handler. */
|
|
38
56
|
type CartGetHandlerContext = {
|
|
39
|
-
storefrontClient: StorefrontClient;
|
|
57
|
+
/** The Storefront API client that runs the cart query. */storefrontClient: StorefrontClient; /** The incoming request. Omit the request to read the cart ID from the Storefront API client's request context. */
|
|
40
58
|
request?: Request;
|
|
41
59
|
};
|
|
60
|
+
/** The context that you pass to the cart POST handler. */
|
|
42
61
|
type CartPostHandlerContext = {
|
|
43
|
-
request: Request;
|
|
62
|
+
/** The cart request, with a JSON, URL-encoded form, or multipart form body. */request: Request; /** The Storefront API client that runs the cart mutation. */
|
|
44
63
|
storefrontClient: StorefrontClient;
|
|
45
64
|
};
|
|
65
|
+
/** The extra context that the GET handler needs when you create the handlers with `customerSession`. */
|
|
46
66
|
type CartCustomerSessionReadContext = {
|
|
47
|
-
sessionManager: ReadonlyCustomerSessionManager;
|
|
67
|
+
/** The session storage that holds the customer's tokens. */sessionManager: ReadonlyCustomerSessionManager; /** The current request's context, for checking the customer's login state. */
|
|
48
68
|
requestContext: ShopifyRequestContext;
|
|
49
69
|
};
|
|
70
|
+
/** The extra context that the POST handler needs when you create the handlers with `customerSession`. */
|
|
50
71
|
type CartCustomerSessionWriteContext = {
|
|
51
|
-
sessionManager: WritableCustomerSessionManager;
|
|
72
|
+
/** The session storage that holds the customer's tokens. After a token refresh, the handler commits the session and adds its `Set-Cookie` headers to the response. */sessionManager: WritableCustomerSessionManager; /** The current request's context, for reading or refreshing the customer's access token. */
|
|
52
73
|
requestContext: ShopifyRequestContext;
|
|
53
74
|
};
|
|
75
|
+
/** The customer session from `createCustomerSession`. The cart handlers read the customer's login state and access token from the session. */
|
|
54
76
|
type CartCustomerSession = CustomerSession;
|
|
55
|
-
/** GET
|
|
77
|
+
/** Handles GET requests to `/api/cart` and returns the current cart. */
|
|
56
78
|
type CartGetHandler<TCart = CartData, TContext extends CartGetHandlerContext = CartGetHandlerContext> = CallableRouteHandler<TContext, CartGetResult<TCart>, typeof CART_API_PATH, typeof CART_GET_METHOD>;
|
|
57
|
-
/** POST
|
|
79
|
+
/** Handles POST requests to `/api/cart` and runs the cart change that the request body describes. */
|
|
58
80
|
type CartPostHandler<TContext extends CartPostHandlerContext = CartPostHandlerContext> = CallableRouteHandler<TContext, CartPostResult, typeof CART_API_PATH, typeof CART_POST_METHOD>;
|
|
59
81
|
/**
|
|
60
|
-
*
|
|
82
|
+
* The cart route handlers that `createCartServerHandlers` returns.
|
|
61
83
|
*
|
|
62
|
-
*
|
|
63
|
-
* framework's router so the client cart store can communicate with the
|
|
64
|
-
* Storefront API.
|
|
84
|
+
* Register the handlers with `handleShopifyRoutes` to serve the `/api/cart` route that the cart store calls.
|
|
65
85
|
*/
|
|
66
86
|
type CartServerHandlers<TCartQuery extends AnyStorefrontQueryString = typeof cartQueries.cart, TCart extends CartData = CartDataFromQuery<TCartQuery>> = {
|
|
67
|
-
readonly [cartServerHandlersCartQuery]: TCartQuery | undefined;
|
|
87
|
+
/** The cart query document that the handlers run. */readonly [cartServerHandlersCartQuery]: TCartQuery | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Returns the current cart. The handler reads the cart ID from the request's `cartId` search parameter or `cart` cookie. Without a request, the handler reads the cart ID from the Storefront API client's request context.
|
|
90
|
+
*
|
|
91
|
+
* GraphQL errors return a `null` cart with the errors in the response body. The handler throws when the Storefront API request fails.
|
|
92
|
+
*/
|
|
68
93
|
get: CartGetHandler<TCart>;
|
|
94
|
+
/**
|
|
95
|
+
* Runs the cart change that the request describes and returns the updated cart. An add without a cart creates a cart and sets the `cart` cookie. Other changes without a cart return a `missing_cart` error for a JSON request and a redirect for a form submission.
|
|
96
|
+
*
|
|
97
|
+
* When a JSON body names a cart other than the cookie's cart, the handler leaves the cookie unchanged. The handler throws GraphQL and network errors from the mutation.
|
|
98
|
+
*/
|
|
69
99
|
post: CartPostHandler;
|
|
70
100
|
};
|
|
71
101
|
/**
|
|
72
|
-
*
|
|
73
|
-
* identity with a customer session — the handler contexts require a session
|
|
74
|
-
* manager and request context.
|
|
102
|
+
* The cart route handlers that `createCartServerHandlers` returns when you pass `customerSession`. The handlers connect carts to the logged-in customer.
|
|
75
103
|
*
|
|
76
|
-
*
|
|
104
|
+
* Pass `sessionManager` and `requestContext` in each handler's context. A handler throws when it reads the customer session and either value is missing.
|
|
77
105
|
*/
|
|
78
106
|
type CartServerHandlersWithCustomerSession<TCartQuery extends AnyStorefrontQueryString = typeof cartQueries.cart, TCart extends CartData = CartDataFromQuery<TCartQuery>> = {
|
|
79
|
-
readonly [cartServerHandlersCartQuery]: TCartQuery | undefined;
|
|
80
|
-
readonly [cartBuyerIdentitySync]: CartBuyerIdentitySync;
|
|
107
|
+
/** The cart query document that the handlers run. */readonly [cartServerHandlersCartQuery]: TCartQuery | undefined;
|
|
108
|
+
readonly [cartBuyerIdentitySync]: CartBuyerIdentitySync; /** Returns the cart like the GET handler in `CartServerHandlers`. For a logged-in customer, the handler adds `logged_in=true` to the checkout URL. */
|
|
81
109
|
get: CartGetHandler<TCart, CartGetHandlerContext & CartCustomerSessionReadContext>;
|
|
110
|
+
/**
|
|
111
|
+
* Runs cart changes like the POST handler in `CartServerHandlers`. When an add creates a cart for a logged-in customer, the handler attaches the customer to the new cart. When the handler refreshes the customer's access token and the mutation then fails, the handler returns a `cart_mutation_failed` error with status `500`.
|
|
112
|
+
*/
|
|
82
113
|
post: CartPostHandler<CartPostHandlerContext & CartCustomerSessionWriteContext>;
|
|
83
114
|
};
|
|
84
115
|
type AsyncHandlerResult<THandler> = THandler extends ((...args: infer _Args) => Promise<infer TResult>) ? TResult : never;
|
|
@@ -91,10 +122,9 @@ type CartDataFromHandlerResult<TResult> = [TResult] extends [never] ? never : TR
|
|
|
91
122
|
};
|
|
92
123
|
} ? NonNullable<TCart> extends CartData ? NonNullable<TCart> : CartData : CartData;
|
|
93
124
|
/**
|
|
94
|
-
*
|
|
125
|
+
* Gets the cart data type from the type of your cart server handlers, including the fields from your custom cart fragment.
|
|
95
126
|
*
|
|
96
|
-
*
|
|
97
|
-
* handler's custom cart query without repeating the generic parameter.
|
|
127
|
+
* Pass `typeof cartHandlers` to type cart data in your own components and functions.
|
|
98
128
|
*
|
|
99
129
|
* @example
|
|
100
130
|
* ```ts
|
|
@@ -102,31 +132,37 @@ type CartDataFromHandlerResult<TResult> = [TResult] extends [never] ? never : TR
|
|
|
102
132
|
* ```
|
|
103
133
|
*/
|
|
104
134
|
type CartDataFromHandlers<THandlers> = CartDataFromHandlerResult<CartGetHandlerResult<THandlers>>;
|
|
105
|
-
/**
|
|
106
|
-
|
|
135
|
+
/** The cart fragment option for cart server handlers. */
|
|
136
|
+
interface CartServerHandlersBaseOptions<TCartFragment extends AnyStorefrontQueryString = AnyStorefrontQueryString> {
|
|
107
137
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
138
|
+
* A cart fragment that adds fields to the cart in every cart query and mutation response.
|
|
139
|
+
* Name the fragment `CartFragment` on the `Cart` type.
|
|
140
|
+
*
|
|
141
|
+
* `createCartServerHandlers` throws for any other fragment name or type.
|
|
110
142
|
*/
|
|
111
143
|
readonly fragment?: TCartFragment;
|
|
112
|
-
}
|
|
144
|
+
}
|
|
145
|
+
/** Options for cart server handlers that attach the logged-in customer to new carts. */
|
|
146
|
+
interface CartServerHandlersOptionsWithCustomerSession<TCartFragment extends AnyStorefrontQueryString = AnyStorefrontQueryString> extends CartServerHandlersBaseOptions<TCartFragment> {
|
|
147
|
+
/** The customer session from `createCustomerSession`. Pass the session to attach the logged-in customer to new carts. */
|
|
113
148
|
readonly customerSession: CartCustomerSession;
|
|
114
|
-
}
|
|
149
|
+
}
|
|
150
|
+
/** Options for cart server handlers without a customer session. */
|
|
151
|
+
interface CartServerHandlersOptionsWithoutCustomerSession<TCartFragment extends AnyStorefrontQueryString = AnyStorefrontQueryString> extends CartServerHandlersBaseOptions<TCartFragment> {
|
|
152
|
+
/** Leave the option out to create carts without a customer. */
|
|
115
153
|
readonly customerSession?: undefined;
|
|
116
|
-
}
|
|
154
|
+
}
|
|
155
|
+
/** Options for creating cart server handlers. */
|
|
156
|
+
type CreateCartServerHandlersOptions<TCartFragment extends AnyStorefrontQueryString = AnyStorefrontQueryString> = CartServerHandlersOptionsWithCustomerSession<TCartFragment> | CartServerHandlersOptionsWithoutCustomerSession<TCartFragment>;
|
|
117
157
|
type CartServerHandlersForOptions<TOptions> = TOptions extends {
|
|
118
158
|
readonly customerSession: CartCustomerSession;
|
|
119
159
|
} ? CartServerHandlersWithCustomerSession<CartQueriesForOptions<TOptions>["cart"], CartDataForOptions<TOptions>> : CartServerHandlers<CartQueriesForOptions<TOptions>["cart"], CartDataForOptions<TOptions>>;
|
|
120
160
|
/**
|
|
121
|
-
* Creates
|
|
161
|
+
* Creates the handlers for the `/api/cart` route, which loads and changes the customer's cart.
|
|
122
162
|
*
|
|
123
|
-
* The handlers
|
|
124
|
-
* identity from a cookie, execute the matching Storefront API mutation, and
|
|
125
|
-
* return either JSON (programmatic clients) or a 303 redirect (form submissions).
|
|
163
|
+
* The handlers read the cart ID from the `cart` cookie and set the cookie when they create a cart. A JSON request gets a JSON response, and a form submission gets a `303` redirect to the referring page.
|
|
126
164
|
*
|
|
127
|
-
* Pass `customerSession` to
|
|
128
|
-
* the logged-in customer — the returned handlers then require a session manager
|
|
129
|
-
* in their context.
|
|
165
|
+
* Pass `customerSession` to connect carts to the logged-in customer. The handlers then need `sessionManager` and `requestContext` in their context.
|
|
130
166
|
*
|
|
131
167
|
* @example
|
|
132
168
|
* ```ts
|
|
@@ -143,6 +179,7 @@ type CartServerHandlersForOptions<TOptions> = TOptions extends {
|
|
|
143
179
|
* customerSession,
|
|
144
180
|
* });
|
|
145
181
|
* ```
|
|
182
|
+
* @publicDocs
|
|
146
183
|
*/
|
|
147
184
|
declare function createCartServerHandlers(): CartServerHandlers<typeof cartQueries.cart>;
|
|
148
185
|
declare function createCartServerHandlers<const TOptions extends CreateCartServerHandlersOptions>(options: TOptions): CartServerHandlersForOptions<TOptions>;
|
|
@@ -18,6 +18,10 @@ const CART_POST_METHOD = "POST";
|
|
|
18
18
|
const CART_MUTATION_FAILED_STATUS = 500;
|
|
19
19
|
const CART_MUTATION_FAILED_MESSAGE = "Cart mutation failed. Please try again.";
|
|
20
20
|
const cartServerHandlersCartQuery = Symbol("hydrogen.cartQuery");
|
|
21
|
+
/**
|
|
22
|
+
* @param options A custom cart fragment and the customer session.
|
|
23
|
+
* @returns The GET and POST handlers to register with `handleShopifyRoutes`.
|
|
24
|
+
*/
|
|
21
25
|
function createCartServerHandlers(options) {
|
|
22
26
|
const queries = options?.fragment ? makeCartQueries({ fragment: options.fragment }) : cartQueries;
|
|
23
27
|
const runtimeQueries = queries;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-handlers.mjs","names":["_exhaustive"],"sources":["../../../src/core/cart/server-handlers.ts"],"sourcesContent":["import type { GraphQLFormattedError, StorefrontClient } from \"../../client\";\nimport type {\n CustomerSession,\n ReadonlyCustomerSessionManager,\n WritableCustomerSessionManager,\n} from \"../../customer-account/session\";\nimport { getCustomerSessionRefreshResult } from \"../../customer-account/session\";\nimport type { AnyStorefrontQueryString } from \"../../graphql\";\nimport { applyPrivateResponseCacheHeaders } from \"../headers\";\nimport { getLogger } from \"../logging\";\nimport type { ShopifyRequestContext } from \"../request-context\";\nimport { createProxyResponseHeaders } from \"../request-routing/interceptors/proxy\";\nimport type {\n CallableRouteHandler,\n ShopifyRouteError,\n ShopifyRouteErrorResult,\n ShopifyRouteJsonResult,\n ShopifyRouteRedirectResult,\n} from \"../request-routing/registered-routes\";\nimport { createCallableRouteHandler } from \"../request-routing/registered-routes\";\nimport { getSameOriginPath } from \"../url\";\nimport { parseCartRequest } from \"./actions\";\nimport type { CartAction, CartLineAddInput } from \"./actions\";\nimport {\n cartBuyerIdentitySync,\n type CartBuyerIdentitySync,\n type CartBuyerIdentitySyncContext,\n} from \"./buyer-identity-sync\";\nimport { getCartIdFromCookie, createCartCookie, createExpiredCartCookie } from \"./cookie\";\nimport { getCart, getCartId, type CartDataFromQuery } from \"./get-cart\";\nimport {\n cartBuyerIdentityUpdateMutation,\n cartQueries,\n makeCartQueries,\n type CartDataForOptions,\n type CartQueriesForOptions,\n type CreateCartQueriesOptions,\n} from \"./queries\";\nimport type { CartData } from \"./state\";\nconst log = getLogger(\"cart-api\");\n\nconst CART_API_PATH = \"/api/cart\" as const;\nconst CART_GET_METHOD = \"GET\" as const;\nconst CART_POST_METHOD = \"POST\" as const;\nconst CART_MUTATION_FAILED_STATUS = 500;\nconst CART_MUTATION_FAILED_MESSAGE = \"Cart mutation failed. Please try again.\";\nconst cartServerHandlersCartQuery: unique symbol = Symbol(\"hydrogen.cartQuery\");\n\n/** Response shape from the cart GET handler — the fetched cart plus any GraphQL errors. */\nexport type CartGetData<TCart = CartData> = {\n cart: TCart | null;\n errors?: Array<{ message: string }>;\n};\n\n/** Full route result from the cart GET handler — JSON with {@link CartGetData} payload and response headers. */\nexport type CartGetResult<TCart = CartData> = ShopifyRouteJsonResult<CartGetData<TCart>>;\n\n/** Machine-readable error codes returned by the cart POST handler. */\nexport type CartErrorCode = \"invalid_cart_request\" | \"missing_cart\" | \"cart_mutation_failed\";\n\n/** A cart route error carrying a {@link CartErrorCode} for programmatic handling. */\nexport type CartError = ShopifyRouteError & {\n code: CartErrorCode;\n};\n\n/**\n * Result from the cart POST handler — one of:\n * - JSON with the mutation payload (programmatic clients)\n * - 303 redirect back to the referrer (HTML form submissions)\n * - An error with a {@link CartErrorCode}\n */\nexport type CartPostResult =\n | ShopifyRouteJsonResult<Record<string, unknown>>\n | ShopifyRouteRedirectResult\n | ShopifyRouteErrorResult<CartError>;\n\ntype CartCustomerAccessTokenResult = {\n accessToken?: string;\n commitSession: boolean;\n};\n\ntype ParsedCartRequestResult =\n | { type: \"action\"; action: CartAction; bodyCartId: string | null }\n | { type: \"response\"; response: CartPostResult };\n\ntype CartGetHandlerContext = {\n storefrontClient: StorefrontClient;\n request?: Request;\n};\n\ntype CartPostHandlerContext = {\n request: Request;\n storefrontClient: StorefrontClient;\n};\n\ntype CartCustomerSessionReadContext = {\n sessionManager: ReadonlyCustomerSessionManager;\n requestContext: ShopifyRequestContext;\n};\n\ntype CartCustomerSessionWriteContext = {\n sessionManager: WritableCustomerSessionManager;\n requestContext: ShopifyRequestContext;\n};\n\ntype CartCustomerSession = CustomerSession;\n\n/** GET handler for the `/api/cart` route — fetches the current cart from the Storefront API. */\nexport type CartGetHandler<\n TCart = CartData,\n TContext extends CartGetHandlerContext = CartGetHandlerContext,\n> = CallableRouteHandler<\n TContext,\n CartGetResult<TCart>,\n typeof CART_API_PATH,\n typeof CART_GET_METHOD\n>;\n\n/** POST handler for the `/api/cart` route — processes cart mutations from JSON or FormData bodies. */\nexport type CartPostHandler<TContext extends CartPostHandlerContext = CartPostHandlerContext> =\n CallableRouteHandler<TContext, CartPostResult, typeof CART_API_PATH, typeof CART_POST_METHOD>;\n\n/**\n * GET and POST handlers for the `/api/cart` route.\n *\n * Created by {@link createCartServerHandlers}. Register these with your\n * framework's router so the client cart store can communicate with the\n * Storefront API.\n */\nexport type CartServerHandlers<\n TCartQuery extends AnyStorefrontQueryString = typeof cartQueries.cart,\n TCart extends CartData = CartDataFromQuery<TCartQuery>,\n> = {\n readonly [cartServerHandlersCartQuery]: TCartQuery | undefined;\n get: CartGetHandler<TCart>;\n post: CartPostHandler;\n};\n\n/**\n * {@link CartServerHandlers} variant that additionally syncs the cart's buyer\n * identity with a customer session — the handler contexts require a session\n * manager and request context.\n *\n * Created by passing `customerSession` to {@link createCartServerHandlers}.\n */\nexport type CartServerHandlersWithCustomerSession<\n TCartQuery extends AnyStorefrontQueryString = typeof cartQueries.cart,\n TCart extends CartData = CartDataFromQuery<TCartQuery>,\n> = {\n readonly [cartServerHandlersCartQuery]: TCartQuery | undefined;\n readonly [cartBuyerIdentitySync]: CartBuyerIdentitySync;\n get: CartGetHandler<TCart, CartGetHandlerContext & CartCustomerSessionReadContext>;\n post: CartPostHandler<CartPostHandlerContext & CartCustomerSessionWriteContext>;\n};\n\ntype AsyncHandlerResult<THandler> = THandler extends (\n ...args: infer _Args\n) => Promise<infer TResult>\n ? TResult\n : never;\n\ntype CartGetHandlerResult<THandlers> = THandlers extends { get: infer THandler }\n ? AsyncHandlerResult<THandler>\n : never;\n\ntype CartDataFromHandlerResult<TResult> = [TResult] extends [never]\n ? never\n : TResult extends { data: { cart: infer TCart } }\n ? NonNullable<TCart> extends CartData\n ? NonNullable<TCart>\n : CartData\n : CartData;\n\n/**\n * Infers the {@link CartData} shape from a {@link CartServerHandlers} instance.\n *\n * Use this to type framework components and hooks so they match the server\n * handler's custom cart query without repeating the generic parameter.\n *\n * @example\n * ```ts\n * type MyCartData = CartDataFromHandlers<typeof cartHandlers>;\n * ```\n */\nexport type CartDataFromHandlers<THandlers> = CartDataFromHandlerResult<\n CartGetHandlerResult<THandlers>\n>;\n\n/** Options for {@link createCartServerHandlers}. */\nexport type CreateCartServerHandlersOptions<\n TCartFragment extends AnyStorefrontQueryString = AnyStorefrontQueryString,\n> = {\n /**\n * Custom cart GraphQL fragment spread into every query and mutation response.\n * The fragment must be named `CartFragment` and target `Cart`.\n */\n readonly fragment?: TCartFragment;\n} & ({ readonly customerSession: CartCustomerSession } | { readonly customerSession?: undefined });\n\ntype CartServerHandlersForOptions<TOptions> = TOptions extends {\n readonly customerSession: CartCustomerSession;\n}\n ? CartServerHandlersWithCustomerSession<\n CartQueriesForOptions<TOptions>[\"cart\"],\n CartDataForOptions<TOptions>\n >\n : CartServerHandlers<CartQueriesForOptions<TOptions>[\"cart\"], CartDataForOptions<TOptions>>;\n\n/**\n * Creates GET and POST handlers for the `/api/cart` route.\n *\n * The handlers parse incoming requests (JSON or FormData), resolve the cart\n * identity from a cookie, execute the matching Storefront API mutation, and\n * return either JSON (programmatic clients) or a 303 redirect (form submissions).\n *\n * Pass `customerSession` to additionally sync the cart's buyer identity with\n * the logged-in customer — the returned handlers then require a session manager\n * in their context.\n *\n * @example\n * ```ts\n * // Basic setup\n * const cartHandlers = createCartServerHandlers();\n *\n * // With a custom cart fragment\n * const cartHandlers = createCartServerHandlers({\n * fragment: CART_FRAGMENT,\n * });\n *\n * // With customer session for buyer identity sync\n * const cartHandlers = createCartServerHandlers({\n * customerSession,\n * });\n * ```\n */\nexport function createCartServerHandlers(): CartServerHandlers<typeof cartQueries.cart>;\nexport function createCartServerHandlers<const TOptions extends CreateCartServerHandlersOptions>(\n options: TOptions,\n): CartServerHandlersForOptions<TOptions>;\nexport function createCartServerHandlers(\n options?: CreateCartServerHandlersOptions,\n): CartServerHandlers | CartServerHandlersWithCustomerSession {\n const queries = options?.fragment\n ? makeCartQueries({ fragment: options.fragment } as CreateCartQueriesOptions)\n : cartQueries;\n const runtimeQueries = queries as RuntimeCartQueries;\n const customerSession = options?.customerSession;\n\n const handlers = {\n get: createCallableRouteHandler(\n CART_API_PATH,\n CART_GET_METHOD,\n (context: CartGetHandlerContext & Partial<CartCustomerSessionReadContext>) =>\n handleGet(context, runtimeQueries, customerSession),\n ),\n post: createCallableRouteHandler(\n CART_API_PATH,\n CART_POST_METHOD,\n (context: CartPostHandlerContext & Partial<CartCustomerSessionWriteContext>) =>\n handlePost(context, runtimeQueries, customerSession),\n ),\n };\n\n Object.defineProperty(handlers, cartServerHandlersCartQuery, { value: queries.cart });\n if (customerSession) {\n // Symbol-keyed and non-enumerable so the capability never registers as a\n // route in handleShopifyRoutes and stays uncallable outside Hydrogen wiring.\n Object.defineProperty(handlers, cartBuyerIdentitySync, {\n value: createCartBuyerIdentitySync(),\n });\n }\n return handlers as CartServerHandlers | CartServerHandlersWithCustomerSession;\n}\n\nfunction createCartBuyerIdentitySync(): CartBuyerIdentitySync {\n return {\n updateBuyerIdentity: updateCartBuyerIdentity,\n expiredCartCookie: createExpiredCartCookie(),\n };\n}\n\nasync function updateCartBuyerIdentity(\n context: CartBuyerIdentitySyncContext,\n customerAccessToken: string | null,\n): Promise<void> {\n const cartId = getCartIdFromCookie(context.request);\n if (!cartId) return;\n\n const result = await context.storefrontClient.graphql(cartBuyerIdentityUpdateMutation, {\n variables: { cartId, buyerIdentity: { customerAccessToken } },\n });\n const { userErrors } = assertMutationData(result, \"cartBuyerIdentityUpdate\");\n if (userErrors.length > 0) {\n throw new Error(userErrors.map(({ message }) => message).join(\"\\n\"));\n }\n}\n\ntype RuntimeCartQueries = typeof cartQueries;\n\nasync function handleGet(\n context: CartGetHandlerContext & Partial<CartCustomerSessionReadContext>,\n queries: RuntimeCartQueries,\n customerSession?: CartCustomerSession,\n): Promise<CartGetResult> {\n const { request, storefrontClient } = context;\n const cartIdSource = request ?? storefrontClient.requestContext;\n const result = await getCart(getCartId(cartIdSource), storefrontClient, queries.cart);\n logCartErrors(result.errors);\n const cart = await addLoggedInCheckoutParam(result.cart, context, customerSession);\n const data = { cart, ...(result.errors && { errors: result.errors }) };\n const headers = createProxyResponseHeaders(result.headers);\n applyPrivateResponseCacheHeaders(headers);\n\n return {\n type: \"json\",\n data,\n headers,\n };\n}\n\nfunction logCartErrors(errors: CartGetData[\"errors\"]): void {\n if (!errors?.length) return;\n log.error(errors.map(({ message }) => message).join(\"\\n\"));\n}\n\nasync function handlePost(\n context: CartPostHandlerContext & Partial<CartCustomerSessionWriteContext>,\n queries: RuntimeCartQueries,\n customerSession?: CartCustomerSession,\n): Promise<CartPostResult> {\n const { request, storefrontClient } = context;\n const isFormRequest = !request.headers.get(\"content-type\")?.includes(\"application/json\");\n const redirectTarget = safeRedirectTarget(request);\n\n const parsedCartRequest = await parseCartAction(request, isFormRequest, redirectTarget);\n if (parsedCartRequest.type === \"response\") return parsedCartRequest.response;\n\n const cookieCartId = getCartIdFromCookie(request);\n const cartId = parsedCartRequest.bodyCartId ?? cookieCartId;\n const missingCartResponse = getMissingCartResponse(\n parsedCartRequest.action,\n cartId,\n isFormRequest,\n redirectTarget,\n );\n if (missingCartResponse) return missingCartResponse;\n\n const { action } = parsedCartRequest;\n const customerAccess = await getCartCreateCustomerAccess(\n parsedCartRequest.action,\n cartId,\n context,\n customerSession,\n );\n const customerSessionHeaders = customerAccess.commitSession\n ? await getCustomerSessionHeaders(context)\n : undefined;\n const result = await executeCartMutation(\n action,\n cartId,\n storefrontClient,\n queries,\n customerAccess.accessToken,\n customerSessionHeaders,\n );\n if (result.type !== \"mutation\") return result.response;\n\n const headers = createProxyResponseHeaders(result.headers);\n appendHeaders(headers, customerSessionHeaders);\n\n // Only persist carts the browser already owns, including newly-created carts.\n if (cartId === cookieCartId && result.cartId !== null && result.cartId !== cookieCartId) {\n headers.append(\"set-cookie\", createCartCookie(result.cartId));\n }\n\n if (isFormRequest) return redirectResult(redirectTarget, headers);\n return jsonResult(result.data, headers);\n}\n\nasync function parseCartAction(\n request: Request,\n isFormRequest: boolean,\n redirectTarget: string,\n): Promise<ParsedCartRequestResult> {\n try {\n const { action, cartId: bodyCartId } = await parseCartRequest(request);\n return { type: \"action\", action, bodyCartId };\n } catch (error) {\n if (isFormRequest) return { type: \"response\", response: redirectResult(redirectTarget) };\n return {\n type: \"response\",\n response: errorResult(\"invalid_cart_request\", getErrorMessage(error, \"Bad Request\")),\n };\n }\n}\n\nfunction getMissingCartResponse(\n action: CartAction,\n cartId: string | null,\n isFormRequest: boolean,\n redirectTarget: string,\n): CartPostResult | undefined {\n if (action.intent === \"add\" || cartId) return undefined;\n if (isFormRequest) return redirectResult(redirectTarget);\n return errorResult(\"missing_cart\", \"No cart exists. Add an item first.\");\n}\n\nasync function executeCartMutation(\n action: CartAction,\n cartId: string | null,\n storefrontClient: StorefrontClient,\n queries: RuntimeCartQueries,\n customerAccessToken: string | undefined,\n customerSessionHeaders: Headers | undefined,\n): Promise<\n ({ type: \"mutation\" } & MutationResult) | { type: \"response\"; response: CartPostResult }\n> {\n try {\n return {\n type: \"mutation\",\n ...(await executeMutation(action, cartId, storefrontClient, queries, customerAccessToken)),\n };\n } catch (error) {\n if (!customerSessionHeaders) throw error;\n log.error(\"cart mutation failed\", { error });\n return {\n type: \"response\",\n response: errorResult(\n \"cart_mutation_failed\",\n CART_MUTATION_FAILED_MESSAGE,\n customerSessionHeaders,\n CART_MUTATION_FAILED_STATUS,\n ),\n };\n }\n}\n\nasync function getCustomerSessionHeaders(\n context: Partial<CartCustomerSessionWriteContext>,\n): Promise<Headers | undefined> {\n assertCustomerSessionWriteContext(context);\n const sessionHeaders = await context.sessionManager.commit?.();\n if (!sessionHeaders) return undefined;\n return new Headers(sessionHeaders);\n}\n\nfunction appendHeaders(headers: Headers, headersToAppend: Headers | undefined) {\n if (!headersToAppend) return;\n for (const [key, value] of headersToAppend) {\n if (key !== \"set-cookie\") headers.append(key, value);\n }\n for (const setCookie of headersToAppend.getSetCookie()) {\n headers.append(\"set-cookie\", setCookie);\n }\n}\n\nfunction safeRedirectTarget(request: Request): string {\n return getSameOriginPath(request.headers.get(\"referer\"), new URL(request.url).origin) ?? \"/\";\n}\n\ntype MutationResult = {\n data: Record<string, unknown>;\n cartId: string | null;\n headers: Headers;\n};\n\ntype GraphQLResult<D> = {\n data: D | null;\n errors?: GraphQLFormattedError[];\n headers: Headers;\n};\n\nfunction assertGraphQLData<D>(result: GraphQLResult<D>): NonNullable<D> {\n if (result.errors || !result.data) {\n const message = result.errors?.[0]?.message ?? \"GraphQL error\";\n throw new Error(message);\n }\n return result.data as NonNullable<D>;\n}\n\nfunction assertMutationData<D, K extends keyof NonNullable<D>>(\n result: GraphQLResult<D>,\n key: K,\n): NonNullable<NonNullable<D>[K]> {\n const data = assertGraphQLData(result);\n const payload = data[key];\n if (payload == null) {\n throw new Error(`Missing ${String(key)} in mutation response`);\n }\n return payload as NonNullable<NonNullable<D>[K]>;\n}\n\nfunction createMutationResult(\n cart: unknown,\n userErrors: unknown,\n warnings: unknown,\n headers: Headers,\n): MutationResult {\n const storefrontCart = (cart ?? null) as Record<string, unknown> | null;\n\n return {\n data: { cart: storefrontCart, userErrors, warnings },\n cartId: typeof storefrontCart?.id === \"string\" ? storefrontCart.id : null,\n headers,\n };\n}\n\ntype CartMutationClient = Pick<StorefrontClient, \"graphql\">;\n\nasync function executeMutation(\n action: CartAction,\n cartId: string | null,\n storefront: CartMutationClient,\n queries: RuntimeCartQueries,\n customerAccessToken?: string,\n): Promise<MutationResult> {\n if (action.intent === \"add\") {\n return executeAdd(action.lines, cartId, storefront, queries, customerAccessToken);\n }\n\n if (!cartId) {\n throw new Error(\"cartId is required for non-add mutations\");\n }\n\n switch (action.intent) {\n case \"update\": {\n const result = await storefront.graphql(queries.cartLinesUpdate, {\n variables: { cartId, lines: action.lines },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartLinesUpdate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n case \"remove\": {\n const result = await storefront.graphql(queries.cartLinesRemove, {\n variables: { cartId, lineIds: action.lineIds },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartLinesRemove\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n case \"discount-update\": {\n const result = await storefront.graphql(queries.cartDiscountCodesUpdate, {\n variables: { cartId, discountCodes: action.discountCodes },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartDiscountCodesUpdate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n case \"discount-apply\":\n return executeDiscountModify(cartId, \"apply\", action.code, storefront, queries);\n case \"discount-remove\":\n return executeDiscountModify(cartId, \"remove\", action.code, storefront, queries);\n case \"note-update\": {\n const result = await storefront.graphql(queries.cartNoteUpdate, {\n variables: { cartId, note: action.note },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartNoteUpdate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n case \"attributes-update\": {\n const result = await storefront.graphql(queries.cartAttributesUpdate, {\n variables: { cartId, attributes: action.attributes },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartAttributesUpdate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n default: {\n const _exhaustive: never = action;\n throw new Error(`Unhandled cart action intent: ${(_exhaustive as CartAction).intent}`);\n }\n }\n}\n\nasync function executeAdd(\n lines: CartLineAddInput[],\n cartId: string | null,\n storefront: CartMutationClient,\n queries: RuntimeCartQueries,\n customerAccessToken?: string,\n): Promise<MutationResult> {\n if (cartId) {\n const result = await storefront.graphql(queries.cartLinesAdd, {\n variables: { cartId, lines },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartLinesAdd\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n\n const result = await storefront.graphql(queries.cartCreate, {\n variables: {\n input: {\n lines,\n ...(customerAccessToken && { buyerIdentity: { customerAccessToken } }),\n },\n },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartCreate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n}\n\nasync function getCartCreateCustomerAccess(\n action: CartAction,\n cartId: string | null,\n context: Partial<CartCustomerSessionWriteContext>,\n customerSession?: CartCustomerSession,\n): Promise<CartCustomerAccessTokenResult> {\n if (action.intent !== \"add\" || cartId || !customerSession) {\n return { commitSession: false };\n }\n\n assertCustomerSessionWriteContext(context);\n const accessToken = await customerSession.getAccessToken(\n context.sessionManager,\n context.requestContext,\n );\n if (accessToken) return { accessToken, commitSession: false };\n\n const isLoggedIn = await customerSession.isLoggedIn(\n context.sessionManager,\n context.requestContext,\n );\n if (!isLoggedIn) return { commitSession: false };\n\n const refreshResult = await getCustomerSessionRefreshResult(\n customerSession,\n context.sessionManager,\n context.requestContext,\n );\n if (refreshResult) {\n return {\n accessToken: refreshResult.accessToken,\n commitSession: refreshResult.status !== \"transient\",\n };\n }\n\n const refreshedAccessToken = await customerSession.getOrRefreshAccessToken(\n context.sessionManager,\n context.requestContext,\n );\n return {\n accessToken: refreshedAccessToken,\n commitSession: true,\n };\n}\n\nasync function addLoggedInCheckoutParam<TCart extends CartData>(\n cart: TCart | null,\n context: Partial<CartCustomerSessionReadContext>,\n customerSession?: CartCustomerSession,\n): Promise<TCart | null> {\n if (!cart || !customerSession) return cart;\n assertCustomerSessionReadContext(context);\n if (!(await customerSession.isLoggedIn(context.sessionManager, context.requestContext)))\n return cart;\n if (!cart.checkoutUrl) return cart;\n\n const checkoutUrl = new URL(cart.checkoutUrl);\n checkoutUrl.searchParams.set(\"logged_in\", \"true\");\n return { ...cart, checkoutUrl: checkoutUrl.toString() };\n}\n\nfunction assertCustomerSessionContext(\n context: Partial<CartCustomerSessionReadContext | CartCustomerSessionWriteContext>,\n): void {\n if (context.sessionManager && context.requestContext) return;\n throw new Error(\n \"Cart handlers configured with customerSession require sessionManager and requestContext.\",\n );\n}\n\nfunction assertCustomerSessionReadContext(\n context: Partial<CartCustomerSessionReadContext>,\n): asserts context is CartCustomerSessionReadContext {\n assertCustomerSessionContext(context);\n}\n\nfunction assertCustomerSessionWriteContext(\n context: Partial<CartCustomerSessionWriteContext>,\n): asserts context is CartCustomerSessionWriteContext {\n assertCustomerSessionContext(context);\n}\n\nasync function executeDiscountModify(\n cartId: string,\n mode: \"apply\" | \"remove\",\n code: string,\n storefront: CartMutationClient,\n queries: RuntimeCartQueries,\n): Promise<MutationResult> {\n // Read-then-write: SFAPI has no atomic discount modify endpoint, so concurrent\n // requests can overwrite each other's discount codes.\n const cartResult = await storefront.graphql(queries.cart, {\n variables: { id: cartId },\n });\n const cartData = assertGraphQLData(cartResult);\n\n const currentCodes: string[] = (cartData.cart?.discountCodes ?? []).map((dc) => dc.code);\n\n const updatedCodes =\n mode === \"apply\" ? [...currentCodes, code] : currentCodes.filter((c) => c !== code);\n\n const result = await storefront.graphql(queries.cartDiscountCodesUpdate, {\n variables: { cartId, discountCodes: updatedCodes },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartDiscountCodesUpdate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n}\n\nfunction jsonResult<TData>(data: TData, headers: HeadersInit = {}): ShopifyRouteJsonResult<TData> {\n return { type: \"json\", data, headers };\n}\n\nfunction redirectResult(location: string, headers: HeadersInit = {}): ShopifyRouteRedirectResult {\n return { type: \"redirect\", location, headers };\n}\n\nfunction errorResult(\n code: CartErrorCode,\n message: string,\n headers?: HeadersInit,\n status?: number,\n): ShopifyRouteErrorResult<CartError> {\n return {\n type: \"error\",\n error: { code, message },\n ...(headers && { headers }),\n ...(status !== undefined && { status }),\n };\n}\n\nfunction getErrorMessage(error: unknown, fallback: string): string {\n if (error instanceof Error) return error.message;\n return fallback;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server-handlers.mjs","names":["_exhaustive"],"sources":["../../../src/core/cart/server-handlers.ts"],"sourcesContent":["import type { GraphQLFormattedError, StorefrontClient } from \"../../client\";\nimport type {\n CustomerSession,\n ReadonlyCustomerSessionManager,\n WritableCustomerSessionManager,\n} from \"../../customer-account/session\";\nimport { getCustomerSessionRefreshResult } from \"../../customer-account/session\";\nimport type { AnyStorefrontQueryString } from \"../../graphql\";\nimport { applyPrivateResponseCacheHeaders } from \"../headers\";\nimport { getLogger } from \"../logging\";\nimport type { ShopifyRequestContext } from \"../request-context\";\nimport { createProxyResponseHeaders } from \"../request-routing/interceptors/proxy\";\nimport type {\n CallableRouteHandler,\n ShopifyRouteError,\n ShopifyRouteErrorResult,\n ShopifyRouteJsonResult,\n ShopifyRouteRedirectResult,\n} from \"../request-routing/registered-routes\";\nimport { createCallableRouteHandler } from \"../request-routing/registered-routes\";\nimport { getSameOriginPath } from \"../url\";\nimport { parseCartRequest } from \"./actions\";\nimport type { CartAction, CartLineAddInput } from \"./actions\";\nimport {\n cartBuyerIdentitySync,\n type CartBuyerIdentitySync,\n type CartBuyerIdentitySyncContext,\n} from \"./buyer-identity-sync\";\nimport { getCartIdFromCookie, createCartCookie, createExpiredCartCookie } from \"./cookie\";\nimport { getCart, getCartId, type CartDataFromQuery } from \"./get-cart\";\nimport {\n cartBuyerIdentityUpdateMutation,\n cartQueries,\n makeCartQueries,\n type CartDataForOptions,\n type CartQueriesForOptions,\n type CreateCartQueriesOptions,\n} from \"./queries\";\nimport type { CartData } from \"./state\";\nconst log = getLogger(\"cart-api\");\n\nconst CART_API_PATH = \"/api/cart\" as const;\nconst CART_GET_METHOD = \"GET\" as const;\nconst CART_POST_METHOD = \"POST\" as const;\nconst CART_MUTATION_FAILED_STATUS = 500;\nconst CART_MUTATION_FAILED_MESSAGE = \"Cart mutation failed. Please try again.\";\nconst cartServerHandlersCartQuery: unique symbol = Symbol(\"hydrogen.cartQuery\");\n\n/**\n * The response body that the cart GET handler returns.\n *\n * @publicDocs\n */\nexport type CartGetData<TCart = CartData> = {\n /** The cart, or `null` when the request has no cart ID, the cart doesn't exist, or the cart query returns GraphQL errors. */\n cart: TCart | null;\n /** GraphQL errors from the cart query. The handler also logs the errors on the server. */\n errors?: Array<{ message: string }>;\n};\n\n/**\n * The JSON result that the cart GET handler returns. The handler sets private cache headers that keep CDNs and shared caches from storing the cart.\n *\n * @publicDocs\n */\nexport type CartGetResult<TCart = CartData> = ShopifyRouteJsonResult<CartGetData<TCart>>;\n\n/**\n * Error codes that the cart POST handler returns. The handler returns `invalid_cart_request` when it can't parse a JSON request, and `missing_cart` when a JSON request changes the cart but has no cart ID. With `customerSession`, the handler returns `cart_mutation_failed` when a mutation fails after the handler refreshes the customer's access token.\n */\nexport type CartErrorCode = \"invalid_cart_request\" | \"missing_cart\" | \"cart_mutation_failed\";\n\n/**\n * An error that the cart POST handler returns, with a code that identifies the failure.\n *\n * @publicDocs\n */\nexport interface CartError extends ShopifyRouteError {\n /** The code that identifies the failure. */\n code: CartErrorCode;\n}\n\n/**\n * The route result that the cart POST handler returns. Check `type` to tell the results apart:\n * - `json` answers a JSON request. The result's `data` holds the mutation's `cart`, `userErrors`, and `warnings`.\n * - `redirect` answers a form submission with a `303` redirect to the referring page.\n * - `error` holds a cart error with a code that identifies the failure.\n *\n * @publicDocs\n */\nexport type CartPostResult =\n | ShopifyRouteJsonResult<Record<string, unknown>>\n | ShopifyRouteRedirectResult\n | ShopifyRouteErrorResult<CartError>;\n\ntype CartCustomerAccessTokenResult = {\n accessToken?: string;\n commitSession: boolean;\n};\n\ntype ParsedCartRequestResult =\n | { type: \"action\"; action: CartAction; bodyCartId: string | null }\n | { type: \"response\"; response: CartPostResult };\n\n/** The context that you pass to the cart GET handler. */\ntype CartGetHandlerContext = {\n /** The Storefront API client that runs the cart query. */\n storefrontClient: StorefrontClient;\n /** The incoming request. Omit the request to read the cart ID from the Storefront API client's request context. */\n request?: Request;\n};\n\n/** The context that you pass to the cart POST handler. */\ntype CartPostHandlerContext = {\n /** The cart request, with a JSON, URL-encoded form, or multipart form body. */\n request: Request;\n /** The Storefront API client that runs the cart mutation. */\n storefrontClient: StorefrontClient;\n};\n\n/** The extra context that the GET handler needs when you create the handlers with `customerSession`. */\ntype CartCustomerSessionReadContext = {\n /** The session storage that holds the customer's tokens. */\n sessionManager: ReadonlyCustomerSessionManager;\n /** The current request's context, for checking the customer's login state. */\n requestContext: ShopifyRequestContext;\n};\n\n/** The extra context that the POST handler needs when you create the handlers with `customerSession`. */\ntype CartCustomerSessionWriteContext = {\n /** The session storage that holds the customer's tokens. After a token refresh, the handler commits the session and adds its `Set-Cookie` headers to the response. */\n sessionManager: WritableCustomerSessionManager;\n /** The current request's context, for reading or refreshing the customer's access token. */\n requestContext: ShopifyRequestContext;\n};\n\n/** The customer session from `createCustomerSession`. The cart handlers read the customer's login state and access token from the session. */\ntype CartCustomerSession = CustomerSession;\n\n/** Handles GET requests to `/api/cart` and returns the current cart. */\nexport type CartGetHandler<\n TCart = CartData,\n TContext extends CartGetHandlerContext = CartGetHandlerContext,\n> = CallableRouteHandler<\n TContext,\n CartGetResult<TCart>,\n typeof CART_API_PATH,\n typeof CART_GET_METHOD\n>;\n\n/** Handles POST requests to `/api/cart` and runs the cart change that the request body describes. */\nexport type CartPostHandler<TContext extends CartPostHandlerContext = CartPostHandlerContext> =\n CallableRouteHandler<TContext, CartPostResult, typeof CART_API_PATH, typeof CART_POST_METHOD>;\n\n/**\n * The cart route handlers that `createCartServerHandlers` returns.\n *\n * Register the handlers with `handleShopifyRoutes` to serve the `/api/cart` route that the cart store calls.\n */\nexport type CartServerHandlers<\n TCartQuery extends AnyStorefrontQueryString = typeof cartQueries.cart,\n TCart extends CartData = CartDataFromQuery<TCartQuery>,\n> = {\n /** The cart query document that the handlers run. */\n readonly [cartServerHandlersCartQuery]: TCartQuery | undefined;\n /**\n * Returns the current cart. The handler reads the cart ID from the request's `cartId` search parameter or `cart` cookie. Without a request, the handler reads the cart ID from the Storefront API client's request context.\n *\n * GraphQL errors return a `null` cart with the errors in the response body. The handler throws when the Storefront API request fails.\n */\n get: CartGetHandler<TCart>;\n /**\n * Runs the cart change that the request describes and returns the updated cart. An add without a cart creates a cart and sets the `cart` cookie. Other changes without a cart return a `missing_cart` error for a JSON request and a redirect for a form submission.\n *\n * When a JSON body names a cart other than the cookie's cart, the handler leaves the cookie unchanged. The handler throws GraphQL and network errors from the mutation.\n */\n post: CartPostHandler;\n};\n\n/**\n * The cart route handlers that `createCartServerHandlers` returns when you pass `customerSession`. The handlers connect carts to the logged-in customer.\n *\n * Pass `sessionManager` and `requestContext` in each handler's context. A handler throws when it reads the customer session and either value is missing.\n */\nexport type CartServerHandlersWithCustomerSession<\n TCartQuery extends AnyStorefrontQueryString = typeof cartQueries.cart,\n TCart extends CartData = CartDataFromQuery<TCartQuery>,\n> = {\n /** The cart query document that the handlers run. */\n readonly [cartServerHandlersCartQuery]: TCartQuery | undefined;\n readonly [cartBuyerIdentitySync]: CartBuyerIdentitySync;\n /** Returns the cart like the GET handler in `CartServerHandlers`. For a logged-in customer, the handler adds `logged_in=true` to the checkout URL. */\n get: CartGetHandler<TCart, CartGetHandlerContext & CartCustomerSessionReadContext>;\n /**\n * Runs cart changes like the POST handler in `CartServerHandlers`. When an add creates a cart for a logged-in customer, the handler attaches the customer to the new cart. When the handler refreshes the customer's access token and the mutation then fails, the handler returns a `cart_mutation_failed` error with status `500`.\n */\n post: CartPostHandler<CartPostHandlerContext & CartCustomerSessionWriteContext>;\n};\n\ntype AsyncHandlerResult<THandler> = THandler extends (\n ...args: infer _Args\n) => Promise<infer TResult>\n ? TResult\n : never;\n\ntype CartGetHandlerResult<THandlers> = THandlers extends { get: infer THandler }\n ? AsyncHandlerResult<THandler>\n : never;\n\ntype CartDataFromHandlerResult<TResult> = [TResult] extends [never]\n ? never\n : TResult extends { data: { cart: infer TCart } }\n ? NonNullable<TCart> extends CartData\n ? NonNullable<TCart>\n : CartData\n : CartData;\n\n/**\n * Gets the cart data type from the type of your cart server handlers, including the fields from your custom cart fragment.\n *\n * Pass `typeof cartHandlers` to type cart data in your own components and functions.\n *\n * @example\n * ```ts\n * type MyCartData = CartDataFromHandlers<typeof cartHandlers>;\n * ```\n */\nexport type CartDataFromHandlers<THandlers> = CartDataFromHandlerResult<\n CartGetHandlerResult<THandlers>\n>;\n\n/** The cart fragment option for cart server handlers. */\ninterface CartServerHandlersBaseOptions<\n TCartFragment extends AnyStorefrontQueryString = AnyStorefrontQueryString,\n> {\n /**\n * A cart fragment that adds fields to the cart in every cart query and mutation response.\n * Name the fragment `CartFragment` on the `Cart` type.\n *\n * `createCartServerHandlers` throws for any other fragment name or type.\n */\n readonly fragment?: TCartFragment;\n}\n\n/** Options for cart server handlers that attach the logged-in customer to new carts. */\ninterface CartServerHandlersOptionsWithCustomerSession<\n TCartFragment extends AnyStorefrontQueryString = AnyStorefrontQueryString,\n> extends CartServerHandlersBaseOptions<TCartFragment> {\n /** The customer session from `createCustomerSession`. Pass the session to attach the logged-in customer to new carts. */\n readonly customerSession: CartCustomerSession;\n}\n\n/** Options for cart server handlers without a customer session. */\ninterface CartServerHandlersOptionsWithoutCustomerSession<\n TCartFragment extends AnyStorefrontQueryString = AnyStorefrontQueryString,\n> extends CartServerHandlersBaseOptions<TCartFragment> {\n /** Leave the option out to create carts without a customer. */\n readonly customerSession?: undefined;\n}\n\n/** Options for creating cart server handlers. */\nexport type CreateCartServerHandlersOptions<\n TCartFragment extends AnyStorefrontQueryString = AnyStorefrontQueryString,\n> =\n | CartServerHandlersOptionsWithCustomerSession<TCartFragment>\n | CartServerHandlersOptionsWithoutCustomerSession<TCartFragment>;\n\ntype CartServerHandlersForOptions<TOptions> = TOptions extends {\n readonly customerSession: CartCustomerSession;\n}\n ? CartServerHandlersWithCustomerSession<\n CartQueriesForOptions<TOptions>[\"cart\"],\n CartDataForOptions<TOptions>\n >\n : CartServerHandlers<CartQueriesForOptions<TOptions>[\"cart\"], CartDataForOptions<TOptions>>;\n\n/**\n * Creates the handlers for the `/api/cart` route, which loads and changes the customer's cart.\n *\n * The handlers read the cart ID from the `cart` cookie and set the cookie when they create a cart. A JSON request gets a JSON response, and a form submission gets a `303` redirect to the referring page.\n *\n * Pass `customerSession` to connect carts to the logged-in customer. The handlers then need `sessionManager` and `requestContext` in their context.\n *\n * @example\n * ```ts\n * // Basic setup\n * const cartHandlers = createCartServerHandlers();\n *\n * // With a custom cart fragment\n * const cartHandlers = createCartServerHandlers({\n * fragment: CART_FRAGMENT,\n * });\n *\n * // With customer session for buyer identity sync\n * const cartHandlers = createCartServerHandlers({\n * customerSession,\n * });\n * ```\n * @publicDocs\n */\nexport function createCartServerHandlers(): CartServerHandlers<typeof cartQueries.cart>;\nexport function createCartServerHandlers<const TOptions extends CreateCartServerHandlersOptions>(\n options: TOptions,\n): CartServerHandlersForOptions<TOptions>;\n/**\n * @param options A custom cart fragment and the customer session.\n * @returns The GET and POST handlers to register with `handleShopifyRoutes`.\n */\nexport function createCartServerHandlers(\n options?: CreateCartServerHandlersOptions,\n): CartServerHandlers | CartServerHandlersWithCustomerSession {\n const queries = options?.fragment\n ? makeCartQueries({ fragment: options.fragment } as CreateCartQueriesOptions)\n : cartQueries;\n const runtimeQueries = queries as RuntimeCartQueries;\n const customerSession = options?.customerSession;\n\n const handlers = {\n get: createCallableRouteHandler(\n CART_API_PATH,\n CART_GET_METHOD,\n (context: CartGetHandlerContext & Partial<CartCustomerSessionReadContext>) =>\n handleGet(context, runtimeQueries, customerSession),\n ),\n post: createCallableRouteHandler(\n CART_API_PATH,\n CART_POST_METHOD,\n (context: CartPostHandlerContext & Partial<CartCustomerSessionWriteContext>) =>\n handlePost(context, runtimeQueries, customerSession),\n ),\n };\n\n Object.defineProperty(handlers, cartServerHandlersCartQuery, { value: queries.cart });\n if (customerSession) {\n // Symbol-keyed and non-enumerable so the capability never registers as a\n // route in handleShopifyRoutes and stays uncallable outside Hydrogen wiring.\n Object.defineProperty(handlers, cartBuyerIdentitySync, {\n value: createCartBuyerIdentitySync(),\n });\n }\n return handlers as CartServerHandlers | CartServerHandlersWithCustomerSession;\n}\n\nfunction createCartBuyerIdentitySync(): CartBuyerIdentitySync {\n return {\n updateBuyerIdentity: updateCartBuyerIdentity,\n expiredCartCookie: createExpiredCartCookie(),\n };\n}\n\nasync function updateCartBuyerIdentity(\n context: CartBuyerIdentitySyncContext,\n customerAccessToken: string | null,\n): Promise<void> {\n const cartId = getCartIdFromCookie(context.request);\n if (!cartId) return;\n\n const result = await context.storefrontClient.graphql(cartBuyerIdentityUpdateMutation, {\n variables: { cartId, buyerIdentity: { customerAccessToken } },\n });\n const { userErrors } = assertMutationData(result, \"cartBuyerIdentityUpdate\");\n if (userErrors.length > 0) {\n throw new Error(userErrors.map(({ message }) => message).join(\"\\n\"));\n }\n}\n\ntype RuntimeCartQueries = typeof cartQueries;\n\nasync function handleGet(\n context: CartGetHandlerContext & Partial<CartCustomerSessionReadContext>,\n queries: RuntimeCartQueries,\n customerSession?: CartCustomerSession,\n): Promise<CartGetResult> {\n const { request, storefrontClient } = context;\n const cartIdSource = request ?? storefrontClient.requestContext;\n const result = await getCart(getCartId(cartIdSource), storefrontClient, queries.cart);\n logCartErrors(result.errors);\n const cart = await addLoggedInCheckoutParam(result.cart, context, customerSession);\n const data = { cart, ...(result.errors && { errors: result.errors }) };\n const headers = createProxyResponseHeaders(result.headers);\n applyPrivateResponseCacheHeaders(headers);\n\n return {\n type: \"json\",\n data,\n headers,\n };\n}\n\nfunction logCartErrors(errors: CartGetData[\"errors\"]): void {\n if (!errors?.length) return;\n log.error(errors.map(({ message }) => message).join(\"\\n\"));\n}\n\nasync function handlePost(\n context: CartPostHandlerContext & Partial<CartCustomerSessionWriteContext>,\n queries: RuntimeCartQueries,\n customerSession?: CartCustomerSession,\n): Promise<CartPostResult> {\n const { request, storefrontClient } = context;\n const isFormRequest = !request.headers.get(\"content-type\")?.includes(\"application/json\");\n const redirectTarget = safeRedirectTarget(request);\n\n const parsedCartRequest = await parseCartAction(request, isFormRequest, redirectTarget);\n if (parsedCartRequest.type === \"response\") return parsedCartRequest.response;\n\n const cookieCartId = getCartIdFromCookie(request);\n const cartId = parsedCartRequest.bodyCartId ?? cookieCartId;\n const missingCartResponse = getMissingCartResponse(\n parsedCartRequest.action,\n cartId,\n isFormRequest,\n redirectTarget,\n );\n if (missingCartResponse) return missingCartResponse;\n\n const { action } = parsedCartRequest;\n const customerAccess = await getCartCreateCustomerAccess(\n parsedCartRequest.action,\n cartId,\n context,\n customerSession,\n );\n const customerSessionHeaders = customerAccess.commitSession\n ? await getCustomerSessionHeaders(context)\n : undefined;\n const result = await executeCartMutation(\n action,\n cartId,\n storefrontClient,\n queries,\n customerAccess.accessToken,\n customerSessionHeaders,\n );\n if (result.type !== \"mutation\") return result.response;\n\n const headers = createProxyResponseHeaders(result.headers);\n appendHeaders(headers, customerSessionHeaders);\n\n // Only persist carts the browser already owns, including newly-created carts.\n if (cartId === cookieCartId && result.cartId !== null && result.cartId !== cookieCartId) {\n headers.append(\"set-cookie\", createCartCookie(result.cartId));\n }\n\n if (isFormRequest) return redirectResult(redirectTarget, headers);\n return jsonResult(result.data, headers);\n}\n\nasync function parseCartAction(\n request: Request,\n isFormRequest: boolean,\n redirectTarget: string,\n): Promise<ParsedCartRequestResult> {\n try {\n const { action, cartId: bodyCartId } = await parseCartRequest(request);\n return { type: \"action\", action, bodyCartId };\n } catch (error) {\n if (isFormRequest) return { type: \"response\", response: redirectResult(redirectTarget) };\n return {\n type: \"response\",\n response: errorResult(\"invalid_cart_request\", getErrorMessage(error, \"Bad Request\")),\n };\n }\n}\n\nfunction getMissingCartResponse(\n action: CartAction,\n cartId: string | null,\n isFormRequest: boolean,\n redirectTarget: string,\n): CartPostResult | undefined {\n if (action.intent === \"add\" || cartId) return undefined;\n if (isFormRequest) return redirectResult(redirectTarget);\n return errorResult(\"missing_cart\", \"No cart exists. Add an item first.\");\n}\n\nasync function executeCartMutation(\n action: CartAction,\n cartId: string | null,\n storefrontClient: StorefrontClient,\n queries: RuntimeCartQueries,\n customerAccessToken: string | undefined,\n customerSessionHeaders: Headers | undefined,\n): Promise<\n ({ type: \"mutation\" } & MutationResult) | { type: \"response\"; response: CartPostResult }\n> {\n try {\n return {\n type: \"mutation\",\n ...(await executeMutation(action, cartId, storefrontClient, queries, customerAccessToken)),\n };\n } catch (error) {\n if (!customerSessionHeaders) throw error;\n log.error(\"cart mutation failed\", { error });\n return {\n type: \"response\",\n response: errorResult(\n \"cart_mutation_failed\",\n CART_MUTATION_FAILED_MESSAGE,\n customerSessionHeaders,\n CART_MUTATION_FAILED_STATUS,\n ),\n };\n }\n}\n\nasync function getCustomerSessionHeaders(\n context: Partial<CartCustomerSessionWriteContext>,\n): Promise<Headers | undefined> {\n assertCustomerSessionWriteContext(context);\n const sessionHeaders = await context.sessionManager.commit?.();\n if (!sessionHeaders) return undefined;\n return new Headers(sessionHeaders);\n}\n\nfunction appendHeaders(headers: Headers, headersToAppend: Headers | undefined) {\n if (!headersToAppend) return;\n for (const [key, value] of headersToAppend) {\n if (key !== \"set-cookie\") headers.append(key, value);\n }\n for (const setCookie of headersToAppend.getSetCookie()) {\n headers.append(\"set-cookie\", setCookie);\n }\n}\n\nfunction safeRedirectTarget(request: Request): string {\n return getSameOriginPath(request.headers.get(\"referer\"), new URL(request.url).origin) ?? \"/\";\n}\n\ntype MutationResult = {\n data: Record<string, unknown>;\n cartId: string | null;\n headers: Headers;\n};\n\ntype GraphQLResult<D> = {\n data: D | null;\n errors?: GraphQLFormattedError[];\n headers: Headers;\n};\n\nfunction assertGraphQLData<D>(result: GraphQLResult<D>): NonNullable<D> {\n if (result.errors || !result.data) {\n const message = result.errors?.[0]?.message ?? \"GraphQL error\";\n throw new Error(message);\n }\n return result.data as NonNullable<D>;\n}\n\nfunction assertMutationData<D, K extends keyof NonNullable<D>>(\n result: GraphQLResult<D>,\n key: K,\n): NonNullable<NonNullable<D>[K]> {\n const data = assertGraphQLData(result);\n const payload = data[key];\n if (payload == null) {\n throw new Error(`Missing ${String(key)} in mutation response`);\n }\n return payload as NonNullable<NonNullable<D>[K]>;\n}\n\nfunction createMutationResult(\n cart: unknown,\n userErrors: unknown,\n warnings: unknown,\n headers: Headers,\n): MutationResult {\n const storefrontCart = (cart ?? null) as Record<string, unknown> | null;\n\n return {\n data: { cart: storefrontCart, userErrors, warnings },\n cartId: typeof storefrontCart?.id === \"string\" ? storefrontCart.id : null,\n headers,\n };\n}\n\ntype CartMutationClient = Pick<StorefrontClient, \"graphql\">;\n\nasync function executeMutation(\n action: CartAction,\n cartId: string | null,\n storefront: CartMutationClient,\n queries: RuntimeCartQueries,\n customerAccessToken?: string,\n): Promise<MutationResult> {\n if (action.intent === \"add\") {\n return executeAdd(action.lines, cartId, storefront, queries, customerAccessToken);\n }\n\n if (!cartId) {\n throw new Error(\"cartId is required for non-add mutations\");\n }\n\n switch (action.intent) {\n case \"update\": {\n const result = await storefront.graphql(queries.cartLinesUpdate, {\n variables: { cartId, lines: action.lines },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartLinesUpdate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n case \"remove\": {\n const result = await storefront.graphql(queries.cartLinesRemove, {\n variables: { cartId, lineIds: action.lineIds },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartLinesRemove\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n case \"discount-update\": {\n const result = await storefront.graphql(queries.cartDiscountCodesUpdate, {\n variables: { cartId, discountCodes: action.discountCodes },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartDiscountCodesUpdate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n case \"discount-apply\":\n return executeDiscountModify(cartId, \"apply\", action.code, storefront, queries);\n case \"discount-remove\":\n return executeDiscountModify(cartId, \"remove\", action.code, storefront, queries);\n case \"note-update\": {\n const result = await storefront.graphql(queries.cartNoteUpdate, {\n variables: { cartId, note: action.note },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartNoteUpdate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n case \"attributes-update\": {\n const result = await storefront.graphql(queries.cartAttributesUpdate, {\n variables: { cartId, attributes: action.attributes },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartAttributesUpdate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n default: {\n const _exhaustive: never = action;\n throw new Error(`Unhandled cart action intent: ${(_exhaustive as CartAction).intent}`);\n }\n }\n}\n\nasync function executeAdd(\n lines: CartLineAddInput[],\n cartId: string | null,\n storefront: CartMutationClient,\n queries: RuntimeCartQueries,\n customerAccessToken?: string,\n): Promise<MutationResult> {\n if (cartId) {\n const result = await storefront.graphql(queries.cartLinesAdd, {\n variables: { cartId, lines },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartLinesAdd\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n }\n\n const result = await storefront.graphql(queries.cartCreate, {\n variables: {\n input: {\n lines,\n ...(customerAccessToken && { buyerIdentity: { customerAccessToken } }),\n },\n },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartCreate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n}\n\nasync function getCartCreateCustomerAccess(\n action: CartAction,\n cartId: string | null,\n context: Partial<CartCustomerSessionWriteContext>,\n customerSession?: CartCustomerSession,\n): Promise<CartCustomerAccessTokenResult> {\n if (action.intent !== \"add\" || cartId || !customerSession) {\n return { commitSession: false };\n }\n\n assertCustomerSessionWriteContext(context);\n const accessToken = await customerSession.getAccessToken(\n context.sessionManager,\n context.requestContext,\n );\n if (accessToken) return { accessToken, commitSession: false };\n\n const isLoggedIn = await customerSession.isLoggedIn(\n context.sessionManager,\n context.requestContext,\n );\n if (!isLoggedIn) return { commitSession: false };\n\n const refreshResult = await getCustomerSessionRefreshResult(\n customerSession,\n context.sessionManager,\n context.requestContext,\n );\n if (refreshResult) {\n return {\n accessToken: refreshResult.accessToken,\n commitSession: refreshResult.status !== \"transient\",\n };\n }\n\n const refreshedAccessToken = await customerSession.getOrRefreshAccessToken(\n context.sessionManager,\n context.requestContext,\n );\n return {\n accessToken: refreshedAccessToken,\n commitSession: true,\n };\n}\n\nasync function addLoggedInCheckoutParam<TCart extends CartData>(\n cart: TCart | null,\n context: Partial<CartCustomerSessionReadContext>,\n customerSession?: CartCustomerSession,\n): Promise<TCart | null> {\n if (!cart || !customerSession) return cart;\n assertCustomerSessionReadContext(context);\n if (!(await customerSession.isLoggedIn(context.sessionManager, context.requestContext)))\n return cart;\n if (!cart.checkoutUrl) return cart;\n\n const checkoutUrl = new URL(cart.checkoutUrl);\n checkoutUrl.searchParams.set(\"logged_in\", \"true\");\n return { ...cart, checkoutUrl: checkoutUrl.toString() };\n}\n\nfunction assertCustomerSessionContext(\n context: Partial<CartCustomerSessionReadContext | CartCustomerSessionWriteContext>,\n): void {\n if (context.sessionManager && context.requestContext) return;\n throw new Error(\n \"Cart handlers configured with customerSession require sessionManager and requestContext.\",\n );\n}\n\nfunction assertCustomerSessionReadContext(\n context: Partial<CartCustomerSessionReadContext>,\n): asserts context is CartCustomerSessionReadContext {\n assertCustomerSessionContext(context);\n}\n\nfunction assertCustomerSessionWriteContext(\n context: Partial<CartCustomerSessionWriteContext>,\n): asserts context is CartCustomerSessionWriteContext {\n assertCustomerSessionContext(context);\n}\n\nasync function executeDiscountModify(\n cartId: string,\n mode: \"apply\" | \"remove\",\n code: string,\n storefront: CartMutationClient,\n queries: RuntimeCartQueries,\n): Promise<MutationResult> {\n // Read-then-write: SFAPI has no atomic discount modify endpoint, so concurrent\n // requests can overwrite each other's discount codes.\n const cartResult = await storefront.graphql(queries.cart, {\n variables: { id: cartId },\n });\n const cartData = assertGraphQLData(cartResult);\n\n const currentCodes: string[] = (cartData.cart?.discountCodes ?? []).map((dc) => dc.code);\n\n const updatedCodes =\n mode === \"apply\" ? [...currentCodes, code] : currentCodes.filter((c) => c !== code);\n\n const result = await storefront.graphql(queries.cartDiscountCodesUpdate, {\n variables: { cartId, discountCodes: updatedCodes },\n });\n const { cart, userErrors, warnings } = assertMutationData(result, \"cartDiscountCodesUpdate\");\n return createMutationResult(cart, userErrors, warnings, result.headers);\n}\n\nfunction jsonResult<TData>(data: TData, headers: HeadersInit = {}): ShopifyRouteJsonResult<TData> {\n return { type: \"json\", data, headers };\n}\n\nfunction redirectResult(location: string, headers: HeadersInit = {}): ShopifyRouteRedirectResult {\n return { type: \"redirect\", location, headers };\n}\n\nfunction errorResult(\n code: CartErrorCode,\n message: string,\n headers?: HeadersInit,\n status?: number,\n): ShopifyRouteErrorResult<CartError> {\n return {\n type: \"error\",\n error: { code, message },\n ...(headers && { headers }),\n ...(status !== undefined && { status }),\n };\n}\n\nfunction getErrorMessage(error: unknown, fallback: string): string {\n if (error instanceof Error) return error.message;\n return fallback;\n}\n"],"mappings":"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"}
|