diff --git a/.changeset/wicked-schools-reflect.md b/.changeset/wicked-schools-reflect.md new file mode 100644 index 0000000000..8fd1a43a28 --- /dev/null +++ b/.changeset/wicked-schools-reflect.md @@ -0,0 +1,7 @@ +--- +'@shopify/hydrogen': patch +--- + +Update all cart mutation methods from `createCartHandler` to return cart warnings. + +As of API version 2024-10, inventory errors about stock levels will no longer be included in the `userErrors` of cart mutations. Inventory errors will now be available in a new return field `warnings` and will contain explicit code values of `MERCHANDISE_NOT_ENOUGH_STOCK`` or MERCHANDISE_OUT_OF_STOCK`. Reference: https://shopify.dev/changelog/cart-warnings-in-storefront-api-cart diff --git a/packages/hydrogen/src/cart/queries/cart-fragments.ts b/packages/hydrogen/src/cart/queries/cart-fragments.ts index 6c6f2a4a47..4ae48c7be4 100644 --- a/packages/hydrogen/src/cart/queries/cart-fragments.ts +++ b/packages/hydrogen/src/cart/queries/cart-fragments.ts @@ -13,3 +13,11 @@ export const MINIMAL_CART_FRAGMENT = `#graphql checkoutUrl } `; + +export const CART_WARNING_FRAGMENT = `#graphql + fragment CartApiWarning on CartWarning { + code + message + target + } +`; diff --git a/packages/hydrogen/src/cart/queries/cart-types.ts b/packages/hydrogen/src/cart/queries/cart-types.ts index 27bd49197d..ce5bdd07e1 100644 --- a/packages/hydrogen/src/cart/queries/cart-types.ts +++ b/packages/hydrogen/src/cart/queries/cart-types.ts @@ -7,6 +7,7 @@ import type { CartUserError, MetafieldsSetUserError, MetafieldDeleteUserError, + CartWarning, } from '@shopify/hydrogen-react/storefront-api-types'; import type {StorefrontApiErrors, Storefront} from '../../storefront'; import {CustomerAccount} from '../../customer/types'; @@ -60,6 +61,7 @@ export type CartQueryData = { | CartUserError[] | MetafieldsSetUserError[] | MetafieldDeleteUserError[]; + warnings?: CartWarning[]; }; export type CartQueryDataReturn = CartQueryData & { diff --git a/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts index 3cc8fa70cf..4bd821e262 100644 --- a/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts @@ -1,5 +1,9 @@ import {StorefrontApiErrors, formatAPIResult} from '../../storefront'; -import {MINIMAL_CART_FRAGMENT, USER_ERROR_FRAGMENT} from './cart-fragments'; +import { + CART_WARNING_FRAGMENT, + MINIMAL_CART_FRAGMENT, + USER_ERROR_FRAGMENT, +} from './cart-fragments'; import type { CartOptionalInput, CartQueryData, @@ -44,8 +48,12 @@ export const CART_ATTRIBUTES_UPDATE_MUTATION = ( userErrors { ...CartApiError } + warnings { + ...CartApiWarning + } } } ${cartFragment} ${USER_ERROR_FRAGMENT} + ${CART_WARNING_FRAGMENT} `; diff --git a/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts index 0321723f5d..2104c81fa6 100644 --- a/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts @@ -1,5 +1,9 @@ import {StorefrontApiErrors, formatAPIResult} from '../../storefront'; -import {MINIMAL_CART_FRAGMENT, USER_ERROR_FRAGMENT} from './cart-fragments'; +import { + CART_WARNING_FRAGMENT, + MINIMAL_CART_FRAGMENT, + USER_ERROR_FRAGMENT, +} from './cart-fragments'; import type { CartOptionalInput, CartQueryData, @@ -61,8 +65,12 @@ export const CART_BUYER_IDENTITY_UPDATE_MUTATION = ( userErrors { ...CartApiError } + warnings { + ...CartApiWarning + } } } ${cartFragment} ${USER_ERROR_FRAGMENT} + ${CART_WARNING_FRAGMENT} `; diff --git a/packages/hydrogen/src/cart/queries/cartCreateDefault.ts b/packages/hydrogen/src/cart/queries/cartCreateDefault.ts index 78a57efe60..2968f30605 100644 --- a/packages/hydrogen/src/cart/queries/cartCreateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartCreateDefault.ts @@ -1,5 +1,9 @@ import {StorefrontApiErrors, formatAPIResult} from '../../storefront'; -import {MINIMAL_CART_FRAGMENT, USER_ERROR_FRAGMENT} from './cart-fragments'; +import { + CART_WARNING_FRAGMENT, + MINIMAL_CART_FRAGMENT, + USER_ERROR_FRAGMENT, +} from './cart-fragments'; import type { CartQueryData, CartQueryOptions, @@ -58,8 +62,12 @@ export const CART_CREATE_MUTATION = ( userErrors { ...CartApiError } + warnings { + ...CartApiWarning + } } } ${cartFragment} ${USER_ERROR_FRAGMENT} + ${CART_WARNING_FRAGMENT} `; diff --git a/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts index 4d8bd578e0..68976207fb 100644 --- a/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts @@ -1,5 +1,9 @@ import {StorefrontApiErrors, formatAPIResult} from '../../storefront'; -import {MINIMAL_CART_FRAGMENT, USER_ERROR_FRAGMENT} from './cart-fragments'; +import { + CART_WARNING_FRAGMENT, + MINIMAL_CART_FRAGMENT, + USER_ERROR_FRAGMENT, +} from './cart-fragments'; import type { CartOptionalInput, CartQueryData, @@ -52,8 +56,12 @@ export const CART_DISCOUNT_CODE_UPDATE_MUTATION = ( userErrors { ...CartApiError } + warnings { + ...CartApiWarning + } } } ${cartFragment} ${USER_ERROR_FRAGMENT} + ${CART_WARNING_FRAGMENT} `; diff --git a/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts index 60bdd6cf90..7a51b88c64 100644 --- a/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts @@ -1,5 +1,9 @@ import {StorefrontApiErrors, formatAPIResult} from '../../storefront'; -import {MINIMAL_CART_FRAGMENT, USER_ERROR_FRAGMENT} from './cart-fragments'; +import { + CART_WARNING_FRAGMENT, + MINIMAL_CART_FRAGMENT, + USER_ERROR_FRAGMENT, +} from './cart-fragments'; import type { CartOptionalInput, CartQueryData, @@ -52,8 +56,12 @@ export const CART_GIFT_CARD_CODE_UPDATE_MUTATION = ( userErrors { ...CartApiError } + warnings { + ...CartApiWarning + } } } ${cartFragment} ${USER_ERROR_FRAGMENT} + ${CART_WARNING_FRAGMENT} `; diff --git a/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts b/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts index 19fc13d053..0bca0be04b 100644 --- a/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts @@ -1,6 +1,10 @@ import type {CartLineInput} from '@shopify/hydrogen-react/storefront-api-types'; import {StorefrontApiErrors, formatAPIResult} from '../../storefront'; -import {MINIMAL_CART_FRAGMENT, USER_ERROR_FRAGMENT} from './cart-fragments'; +import { + CART_WARNING_FRAGMENT, + MINIMAL_CART_FRAGMENT, + USER_ERROR_FRAGMENT, +} from './cart-fragments'; import type { CartOptionalInput, CartQueryData, @@ -49,9 +53,12 @@ export const CART_LINES_ADD_MUTATION = ( userErrors { ...CartApiError } + warnings { + ...CartApiWarning + } } } - ${cartFragment} ${USER_ERROR_FRAGMENT} + ${CART_WARNING_FRAGMENT} `; diff --git a/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts b/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts index 334cdf04d2..9cd146ad5d 100644 --- a/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts @@ -1,6 +1,10 @@ import {StorefrontApiErrors, formatAPIResult} from '../../storefront'; import {throwIfLinesAreOptimistic} from '../optimistic/optimistic-cart.helper'; -import {MINIMAL_CART_FRAGMENT, USER_ERROR_FRAGMENT} from './cart-fragments'; +import { + CART_WARNING_FRAGMENT, + MINIMAL_CART_FRAGMENT, + USER_ERROR_FRAGMENT, +} from './cart-fragments'; import type { CartOptionalInput, CartQueryData, @@ -50,9 +54,12 @@ export const CART_LINES_REMOVE_MUTATION = ( userErrors { ...CartApiError } + warnings { + ...CartApiWarning + } } } - ${cartFragment} ${USER_ERROR_FRAGMENT} + ${CART_WARNING_FRAGMENT} `; diff --git a/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts index dc66daca17..b9f28ed5e7 100644 --- a/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts @@ -1,6 +1,10 @@ import {StorefrontApiErrors, formatAPIResult} from '../../storefront'; import {throwIfLinesAreOptimistic} from '../optimistic/optimistic-cart.helper'; -import {MINIMAL_CART_FRAGMENT, USER_ERROR_FRAGMENT} from './cart-fragments'; +import { + CART_WARNING_FRAGMENT, + MINIMAL_CART_FRAGMENT, + USER_ERROR_FRAGMENT, +} from './cart-fragments'; import type { CartOptionalInput, CartQueryData, @@ -51,9 +55,12 @@ export const CART_LINES_UPDATE_MUTATION = ( userErrors { ...CartApiError } + warnings { + ...CartApiWarning + } } } - ${cartFragment} ${USER_ERROR_FRAGMENT} + ${CART_WARNING_FRAGMENT} `; diff --git a/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts index b4e1170d92..6c653d9b73 100644 --- a/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts @@ -1,5 +1,9 @@ import {StorefrontApiErrors, formatAPIResult} from '../../storefront'; -import {MINIMAL_CART_FRAGMENT, USER_ERROR_FRAGMENT} from './cart-fragments'; +import { + CART_WARNING_FRAGMENT, + MINIMAL_CART_FRAGMENT, + USER_ERROR_FRAGMENT, +} from './cart-fragments'; import type { CartOptionalInput, CartQueryData, @@ -47,8 +51,12 @@ export const CART_NOTE_UPDATE_MUTATION = ( userErrors { ...CartApiError } + warnings { + ...CartApiWarning + } } } ${cartFragment} ${USER_ERROR_FRAGMENT} + ${CART_WARNING_FRAGMENT} `; diff --git a/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts index d85132d426..04c4b8ff43 100644 --- a/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts @@ -1,5 +1,9 @@ import {StorefrontApiErrors, formatAPIResult} from '../../storefront'; -import {MINIMAL_CART_FRAGMENT, USER_ERROR_FRAGMENT} from './cart-fragments'; +import { + CART_WARNING_FRAGMENT, + MINIMAL_CART_FRAGMENT, + USER_ERROR_FRAGMENT, +} from './cart-fragments'; import type { CartOptionalInput, CartQueryData, @@ -49,8 +53,12 @@ export const CART_SELECTED_DELIVERY_OPTIONS_UPDATE_MUTATION = ( userErrors { ...CartApiError } + warnings { + ...CartApiWarning + } } } ${cartFragment} ${USER_ERROR_FRAGMENT} + ${CART_WARNING_FRAGMENT} `; diff --git a/templates/skeleton/app/routes/cart.tsx b/templates/skeleton/app/routes/cart.tsx index 341667b1f9..61d0a0ea00 100644 --- a/templates/skeleton/app/routes/cart.tsx +++ b/templates/skeleton/app/routes/cart.tsx @@ -74,7 +74,7 @@ export async function action({request, context}: ActionFunctionArgs) { const cartId = result?.cart?.id; const headers = cartId ? cart.setCartId(result.cart.id) : new Headers(); - const {cart: cartResult, errors} = result; + const {cart: cartResult, errors, warnings} = result; const redirectTo = formData.get('redirectTo') ?? null; if (typeof redirectTo === 'string') { @@ -86,6 +86,7 @@ export async function action({request, context}: ActionFunctionArgs) { { cart: cartResult, errors, + warnings, analytics: { cartId, },