From 336fe88e10a68294541cf6502c045444c49d0031 Mon Sep 17 00:00:00 2001 From: Riley Nowak Date: Tue, 14 Apr 2026 12:45:01 -0300 Subject: [PATCH 1/4] fix(hydrogen): make visitorConsent conditional in cart operations Fixes #3708 Cart operations were unconditionally declaring `$visitorConsent: VisitorConsent` in GraphQL mutations, causing schema validation failures on stores without the VisitorConsent type (older API versions or certain store configurations). The visitorConsent parameter is now only included when explicitly provided via `optionalParams.visitorConsent`. This restores compatibility while preserving the feature for users who need it. Changes: - Add cart-query-helpers.ts with getInContextVariables/getInContextDirective - Update 16 cart mutation files to use conditional inclusion - Add tests verifying conditional behavior Co-Authored-By: Claude Opus 4.5 (1M context) --- .../cart/queries/cart-query-helpers.test.ts | 43 +++++++++++++++++++ .../src/cart/queries/cart-query-helpers.ts | 31 +++++++++++++ .../queries/cartAttributesUpdateDefault.ts | 33 +++++++++----- .../queries/cartBuyerIdentityUpdateDefault.ts | 37 ++++++++++------ .../src/cart/queries/cartCreateDefault.ts | 18 +++++--- .../cartDeliveryAddressesAddDefault.tsx | 33 +++++++++----- .../cartDeliveryAddressesRemoveDefault.tsx | 33 +++++++++----- .../cartDeliveryAddressesUpdateDefault.tsx | 33 +++++++++----- .../queries/cartDiscountCodesUpdateDefault.ts | 33 +++++++++----- .../src/cart/queries/cartGetDefault.ts | 31 +++++++++---- .../queries/cartGiftCardCodeUpdateDefault.ts | 33 +++++++++----- .../queries/cartGiftCardCodesRemoveDefault.ts | 33 +++++++++----- .../src/cart/queries/cartLinesAddDefault.ts | 18 +++++--- .../cart/queries/cartLinesRemoveDefault.ts | 31 ++++++++----- .../cart/queries/cartLinesUpdateDefault.ts | 31 ++++++++----- .../queries/cartMetafieldDeleteDefault.ts | 21 ++++++--- .../queries/cartMetafieldsSetDefault.test.ts | 25 ++++++++++- .../cart/queries/cartMetafieldsSetDefault.ts | 21 ++++++--- .../src/cart/queries/cartNoteUpdateDefault.ts | 31 ++++++++----- ...artSelectedDeliveryOptionsUpdateDefault.ts | 33 +++++++++----- 20 files changed, 448 insertions(+), 154 deletions(-) create mode 100644 packages/hydrogen/src/cart/queries/cart-query-helpers.test.ts create mode 100644 packages/hydrogen/src/cart/queries/cart-query-helpers.ts diff --git a/packages/hydrogen/src/cart/queries/cart-query-helpers.test.ts b/packages/hydrogen/src/cart/queries/cart-query-helpers.test.ts new file mode 100644 index 0000000000..62d2deba8b --- /dev/null +++ b/packages/hydrogen/src/cart/queries/cart-query-helpers.test.ts @@ -0,0 +1,43 @@ +import {describe, it, expect} from 'vitest'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; + +describe('cart-query-helpers', () => { + describe('getInContextVariables', () => { + it('returns base variables without visitorConsent when not included', () => { + const result = getInContextVariables(false); + + expect(result).toContain('$country: CountryCode = ZZ'); + expect(result).toContain('$language: LanguageCode'); + expect(result).not.toContain('visitorConsent'); + expect(result).not.toContain('VisitorConsent'); + }); + + it('returns variables with visitorConsent when included', () => { + const result = getInContextVariables(true); + + expect(result).toContain('$country: CountryCode = ZZ'); + expect(result).toContain('$language: LanguageCode'); + expect(result).toContain('$visitorConsent: VisitorConsent'); + }); + }); + + describe('getInContextDirective', () => { + it('returns directive without visitorConsent when not included', () => { + const result = getInContextDirective(false); + + expect(result).toBe('@inContext(country: $country, language: $language)'); + expect(result).not.toContain('visitorConsent'); + }); + + it('returns directive with visitorConsent when included', () => { + const result = getInContextDirective(true); + + expect(result).toBe( + '@inContext(country: $country, language: $language, visitorConsent: $visitorConsent)', + ); + }); + }); +}); diff --git a/packages/hydrogen/src/cart/queries/cart-query-helpers.ts b/packages/hydrogen/src/cart/queries/cart-query-helpers.ts new file mode 100644 index 0000000000..0bf94aed59 --- /dev/null +++ b/packages/hydrogen/src/cart/queries/cart-query-helpers.ts @@ -0,0 +1,31 @@ +/** + * Helper functions for building cart GraphQL operations with conditional + * @inContext directive support. + * + * The visitorConsent parameter is only included when explicitly provided, + * maintaining compatibility with stores whose API schema doesn't support it. + */ + +/** + * Builds the @inContext directive variable declarations for cart operations. + * Only includes visitorConsent when it's actually being used. + */ +export function getInContextVariables(includeVisitorConsent: boolean): string { + const base = `$country: CountryCode = ZZ + $language: LanguageCode`; + + return includeVisitorConsent + ? `${base} + $visitorConsent: VisitorConsent` + : base; +} + +/** + * Builds the @inContext directive for cart operations. + * Only includes visitorConsent when it's actually being used. + */ +export function getInContextDirective(includeVisitorConsent: boolean): string { + return includeVisitorConsent + ? '@inContext(country: $country, language: $language, visitorConsent: $visitorConsent)' + : '@inContext(country: $country, language: $language)'; +} diff --git a/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts index c40ebce1df..b1c831833c 100644 --- a/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts @@ -11,6 +11,10 @@ import type { CartQueryOptions, } from './cart-types'; import type {AttributeInput} from '@shopify/hydrogen-react/storefront-api-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartAttributesUpdateFunction = ( attributes: AttributeInput[], @@ -21,30 +25,39 @@ export function cartAttributesUpdateDefault( options: CartQueryOptions, ): CartAttributesUpdateFunction { return async (attributes, optionalParams) => { + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartAttributesUpdate, errors} = await options.storefront.mutate<{ cartAttributesUpdate: CartQueryData; errors: StorefrontApiErrors; - }>(CART_ATTRIBUTES_UPDATE_MUTATION(options.cartFragment), { - variables: { - cartId: optionalParams?.cartId || options.getCartId(), - attributes, - ...optionalParams, + }>( + CART_ATTRIBUTES_UPDATE_MUTATION(options.cartFragment, { + includeVisitorConsent, + }), + { + variables: { + cartId: optionalParams?.cartId || options.getCartId(), + attributes, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartAttributesUpdate, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + export const CART_ATTRIBUTES_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartAttributesUpdate( $cartId: ID! $attributes: [AttributeInput!]! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartAttributesUpdate(cartId: $cartId, attributes: $attributes) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts index 2ebead1376..2f17fcf975 100644 --- a/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts @@ -11,6 +11,10 @@ import type { CartQueryOptions, } from './cart-types'; import type {CartBuyerIdentityInput} from '@shopify/hydrogen-react/storefront-api-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartBuyerIdentityUpdateFunction = ( buyerIdentity: CartBuyerIdentityInput, @@ -31,34 +35,43 @@ export function cartBuyerIdentityUpdateDefault( ? await options.customerAccount.getBuyer() : undefined; + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartBuyerIdentityUpdate, errors} = await options.storefront.mutate<{ cartBuyerIdentityUpdate: CartQueryData; errors: StorefrontApiErrors; - }>(CART_BUYER_IDENTITY_UPDATE_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - buyerIdentity: { - ...buyer, - ...buyerIdentity, + }>( + CART_BUYER_IDENTITY_UPDATE_MUTATION(options.cartFragment, { + includeVisitorConsent, + }), + { + variables: { + cartId: options.getCartId(), + buyerIdentity: { + ...buyer, + ...buyerIdentity, + }, + ...optionalParams, }, - ...optionalParams, }, - }); + ); return formatAPIResult(cartBuyerIdentityUpdate, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartBuyerIdentityUpdate export const CART_BUYER_IDENTITY_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartBuyerIdentityUpdate( $cartId: ID! $buyerIdentity: CartBuyerIdentityInput! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartBuyerIdentityUpdate(cartId: $cartId, buyerIdentity: $buyerIdentity) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartCreateDefault.ts b/packages/hydrogen/src/cart/queries/cartCreateDefault.ts index f7dd188c47..4fc976af65 100644 --- a/packages/hydrogen/src/cart/queries/cartCreateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartCreateDefault.ts @@ -11,6 +11,10 @@ import type { CartQueryDataReturn, } from './cart-types'; import type {CartInput} from '@shopify/hydrogen-react/storefront-api-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartCreateFunction = ( input: CartInput, @@ -26,10 +30,11 @@ export function cartCreateDefault( : undefined; const {cartId, ...restOfOptionalParams} = optionalParams || {}; const {buyerIdentity, ...restOfInput} = input; + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartCreate, errors} = await options.storefront.mutate<{ cartCreate: CartQueryData; errors: StorefrontApiErrors; - }>(CART_CREATE_MUTATION(options.cartFragment), { + }>(CART_CREATE_MUTATION(options.cartFragment, {includeVisitorConsent}), { variables: { input: { ...restOfInput, @@ -45,16 +50,19 @@ export function cartCreateDefault( }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartCreate export const CART_CREATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartCreate( $input: CartInput! - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartCreate(input: $input) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesAddDefault.tsx b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesAddDefault.tsx index e6f74a848d..f43bfdfbdf 100644 --- a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesAddDefault.tsx +++ b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesAddDefault.tsx @@ -11,6 +11,10 @@ import type { CartQueryDataReturn, CartQueryOptions, } from './cart-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartDeliveryAddressesAddFunction = ( addresses: Array, @@ -45,32 +49,41 @@ export function cartDeliveryAddressesAddDefault( addresses: Array, optionalParams, ) => { + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartDeliveryAddressesAdd, errors} = await options.storefront.mutate<{ cartDeliveryAddressesAdd: CartQueryData; errors: StorefrontApiErrors; - }>(CART_DELIVERY_ADDRESSES_ADD_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - addresses, - ...optionalParams, + }>( + CART_DELIVERY_ADDRESSES_ADD_MUTATION(options.cartFragment, { + includeVisitorConsent, + }), + { + variables: { + cartId: options.getCartId(), + addresses, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartDeliveryAddressesAdd, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartDeliveryAddressesAdd export const CART_DELIVERY_ADDRESSES_ADD_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartDeliveryAddressesAdd( $cartId: ID! $addresses: [CartSelectableAddressInput!]!, - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartDeliveryAddressesAdd(addresses: $addresses, cartId: $cartId) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesRemoveDefault.tsx b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesRemoveDefault.tsx index baf70f7736..3c8631631e 100644 --- a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesRemoveDefault.tsx +++ b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesRemoveDefault.tsx @@ -11,6 +11,10 @@ import type { CartQueryDataReturn, CartQueryOptions, } from './cart-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartDeliveryAddressesRemoveFunction = ( addressIds: Array | Array, @@ -40,33 +44,42 @@ export function cartDeliveryAddressesRemoveDefault( addressIds: Array | string[], optionalParams, ) => { + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartDeliveryAddressesRemove, errors} = await options.storefront.mutate<{ cartDeliveryAddressesRemove: CartQueryData; errors: StorefrontApiErrors; - }>(CART_DELIVERY_ADDRESSES_REMOVE_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - addressIds, - ...optionalParams, + }>( + CART_DELIVERY_ADDRESSES_REMOVE_MUTATION(options.cartFragment, { + includeVisitorConsent, + }), + { + variables: { + cartId: options.getCartId(), + addressIds, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartDeliveryAddressesRemove, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartDeliveryAddressesRemove export const CART_DELIVERY_ADDRESSES_REMOVE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartDeliveryAddressesRemove( $cartId: ID! $addressIds: [ID!]!, - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartDeliveryAddressesRemove(addressIds: $addressIds, cartId: $cartId) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesUpdateDefault.tsx b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesUpdateDefault.tsx index ee222e89a3..4e9be05bac 100644 --- a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesUpdateDefault.tsx +++ b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesUpdateDefault.tsx @@ -11,6 +11,10 @@ import type { CartQueryDataReturn, CartQueryOptions, } from './cart-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartDeliveryAddressesUpdateFunction = ( addresses: Array, @@ -62,33 +66,42 @@ export function cartDeliveryAddressesUpdateDefault( addresses: Array, optionalParams, ) => { + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartDeliveryAddressesUpdate, errors} = await options.storefront.mutate<{ cartDeliveryAddressesUpdate: CartQueryData; errors: StorefrontApiErrors; - }>(CART_DELIVERY_ADDRESSES_UPDATE_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - addresses, - ...optionalParams, + }>( + CART_DELIVERY_ADDRESSES_UPDATE_MUTATION(options.cartFragment, { + includeVisitorConsent, + }), + { + variables: { + cartId: options.getCartId(), + addresses, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartDeliveryAddressesUpdate, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartDeliveryAddressesUpdate export const CART_DELIVERY_ADDRESSES_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartDeliveryAddressesUpdate( $cartId: ID! $addresses: [CartSelectableAddressUpdateInput!]!, - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartDeliveryAddressesUpdate(addresses: $addresses, cartId: $cartId) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts index 128b79477b..099cd3131c 100644 --- a/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts @@ -10,6 +10,10 @@ import type { CartQueryDataReturn, CartQueryOptions, } from './cart-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartDiscountCodesUpdateFunction = ( discountCodes: string[], @@ -25,31 +29,40 @@ export function cartDiscountCodesUpdateDefault( return array.indexOf(value) === index; }); + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartDiscountCodesUpdate, errors} = await options.storefront.mutate<{ cartDiscountCodesUpdate: CartQueryData; errors: StorefrontApiErrors; - }>(CART_DISCOUNT_CODE_UPDATE_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - discountCodes: uniqueCodes, - ...optionalParams, + }>( + CART_DISCOUNT_CODE_UPDATE_MUTATION(options.cartFragment, { + includeVisitorConsent, + }), + { + variables: { + cartId: options.getCartId(), + discountCodes: uniqueCodes, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartDiscountCodesUpdate, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartDiscountCodesUpdate export const CART_DISCOUNT_CODE_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartDiscountCodesUpdate( $cartId: ID! $discountCodes: [String!]! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartDiscountCodesUpdate(cartId: $cartId, discountCodes: $discountCodes) { ... @defer { cart { diff --git a/packages/hydrogen/src/cart/queries/cartGetDefault.ts b/packages/hydrogen/src/cart/queries/cartGetDefault.ts index 71ddee722b..acbdf0e72a 100644 --- a/packages/hydrogen/src/cart/queries/cartGetDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartGetDefault.ts @@ -7,6 +7,10 @@ import type { LanguageCode, VisitorConsent, } from '@shopify/hydrogen-react/storefront-api-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; type CartGetProps = { /** @@ -67,12 +71,16 @@ export function cartGetDefault({ if (!cartId) return null; + const includeVisitorConsent = cartInput?.visitorConsent !== undefined; const [isCustomerLoggedIn, {cart, errors}] = await Promise.all([ customerAccount ? customerAccount.isLoggedIn() : false, - storefront.query<{cart: Cart | null}>(CART_QUERY(cartFragment), { - variables: {cartId, ...cartInput}, - cache: storefront.CacheNone(), - }), + storefront.query<{cart: Cart | null}>( + CART_QUERY(cartFragment, {includeVisitorConsent}), + { + variables: {cartId, ...cartInput}, + cache: storefront.CacheNone(), + }, + ), ]); if (isCustomerLoggedIn && cart?.checkoutUrl) { @@ -85,15 +93,20 @@ export function cartGetDefault({ }; } +type CartQueryBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see https://shopify.dev/docs/api/storefront/latest/queries/cart -const CART_QUERY = (cartFragment = DEFAULT_CART_FRAGMENT) => `#graphql +const CART_QUERY = ( + cartFragment = DEFAULT_CART_FRAGMENT, + options: CartQueryBuilderOptions = {}, +) => `#graphql query CartQuery( $cartId: ID! $numCartLines: Int = 100 - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cart(id: $cartId) { ...CartApiQuery } diff --git a/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts index 77db16f082..12255ac720 100644 --- a/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts @@ -10,6 +10,10 @@ import type { CartQueryDataReturn, CartQueryOptions, } from './cart-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartGiftCardCodesUpdateFunction = ( giftCardCodes: string[], @@ -32,31 +36,40 @@ export function cartGiftCardCodesUpdateDefault( options: CartQueryOptions, ): CartGiftCardCodesUpdateFunction { return async (giftCardCodes, optionalParams) => { + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartGiftCardCodesUpdate, errors} = await options.storefront.mutate<{ cartGiftCardCodesUpdate: CartQueryData; errors: StorefrontApiErrors; - }>(CART_GIFT_CARD_CODE_UPDATE_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - giftCardCodes, - ...optionalParams, + }>( + CART_GIFT_CARD_CODE_UPDATE_MUTATION(options.cartFragment, { + includeVisitorConsent, + }), + { + variables: { + cartId: options.getCartId(), + giftCardCodes, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartGiftCardCodesUpdate, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartGiftCardCodesUpdate export const CART_GIFT_CARD_CODE_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartGiftCardCodesUpdate( $cartId: ID! $giftCardCodes: [String!]! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartGiftCardCodesUpdate(cartId: $cartId, giftCardCodes: $giftCardCodes) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartGiftCardCodesRemoveDefault.ts b/packages/hydrogen/src/cart/queries/cartGiftCardCodesRemoveDefault.ts index bd2c320f06..f7e205690e 100644 --- a/packages/hydrogen/src/cart/queries/cartGiftCardCodesRemoveDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartGiftCardCodesRemoveDefault.ts @@ -10,6 +10,10 @@ import type { CartQueryDataReturn, CartQueryOptions, } from './cart-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartGiftCardCodesRemoveFunction = ( appliedGiftCardIds: string[], @@ -20,31 +24,40 @@ export function cartGiftCardCodesRemoveDefault( options: CartQueryOptions, ): CartGiftCardCodesRemoveFunction { return async (appliedGiftCardIds, optionalParams) => { + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartGiftCardCodesRemove, errors} = await options.storefront.mutate<{ cartGiftCardCodesRemove: CartQueryData; errors: StorefrontApiErrors; - }>(CART_GIFT_CARD_CODES_REMOVE_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - appliedGiftCardIds, - ...optionalParams, + }>( + CART_GIFT_CARD_CODES_REMOVE_MUTATION(options.cartFragment, { + includeVisitorConsent, + }), + { + variables: { + cartId: options.getCartId(), + appliedGiftCardIds, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartGiftCardCodesRemove, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartGiftCardCodesRemove export const CART_GIFT_CARD_CODES_REMOVE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartGiftCardCodesRemove( $cartId: ID! $appliedGiftCardIds: [ID!]! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartGiftCardCodesRemove(cartId: $cartId, appliedGiftCardIds: $appliedGiftCardIds) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts b/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts index f0b1435589..dcdf9bddbc 100644 --- a/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts @@ -11,6 +11,10 @@ import type { CartQueryDataReturn, CartQueryOptions, } from './cart-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartLinesAddFunction = ( lines: Array, @@ -21,10 +25,11 @@ export function cartLinesAddDefault( options: CartQueryOptions, ): CartLinesAddFunction { return async (lines, optionalParams) => { + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartLinesAdd, errors} = await options.storefront.mutate<{ cartLinesAdd: CartQueryData; errors: StorefrontApiErrors; - }>(CART_LINES_ADD_MUTATION(options.cartFragment), { + }>(CART_LINES_ADD_MUTATION(options.cartFragment, {includeVisitorConsent}), { variables: { cartId: options.getCartId(), lines, @@ -36,17 +41,20 @@ export function cartLinesAddDefault( }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartLinesAdd export const CART_LINES_ADD_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartLinesAdd( $cartId: ID! $lines: [CartLineInput!]! - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartLinesAdd(cartId: $cartId, lines: $lines) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts b/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts index 38b8cc38f1..e27e4e8c21 100644 --- a/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts @@ -11,6 +11,10 @@ import type { CartQueryDataReturn, CartQueryOptions, } from './cart-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartLinesRemoveFunction = ( lineIds: string[], @@ -23,31 +27,38 @@ export function cartLinesRemoveDefault( return async (lineIds, optionalParams) => { throwIfLinesAreOptimistic('removeLines', lineIds); + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartLinesRemove, errors} = await options.storefront.mutate<{ cartLinesRemove: CartQueryData; errors: StorefrontApiErrors; - }>(CART_LINES_REMOVE_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - lineIds, - ...optionalParams, + }>( + CART_LINES_REMOVE_MUTATION(options.cartFragment, {includeVisitorConsent}), + { + variables: { + cartId: options.getCartId(), + lineIds, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartLinesRemove, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartLinesRemove export const CART_LINES_REMOVE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartLinesRemove( $cartId: ID! $lineIds: [ID!]! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartLinesRemove(cartId: $cartId, lineIds: $lineIds) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts index 1f09da4c09..986c4a6d76 100644 --- a/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts @@ -12,6 +12,10 @@ import type { CartQueryOptions, } from './cart-types'; import type {CartLineUpdateInput} from '@shopify/hydrogen-react/storefront-api-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartLinesUpdateFunction = ( lines: CartLineUpdateInput[], @@ -24,31 +28,38 @@ export function cartLinesUpdateDefault( return async (lines, optionalParams) => { throwIfLinesAreOptimistic('updateLines', lines); + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartLinesUpdate, errors} = await options.storefront.mutate<{ cartLinesUpdate: CartQueryData; errors: StorefrontApiErrors; - }>(CART_LINES_UPDATE_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - lines, - ...optionalParams, + }>( + CART_LINES_UPDATE_MUTATION(options.cartFragment, {includeVisitorConsent}), + { + variables: { + cartId: options.getCartId(), + lines, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartLinesUpdate, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartLinesUpdate export const CART_LINES_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartLinesUpdate( $cartId: ID! $lines: [CartLineUpdateInput!]! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartLinesUpdate(cartId: $cartId, lines: $lines) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartMetafieldDeleteDefault.ts b/packages/hydrogen/src/cart/queries/cartMetafieldDeleteDefault.ts index 4cb56f7058..ed52eda888 100644 --- a/packages/hydrogen/src/cart/queries/cartMetafieldDeleteDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartMetafieldDeleteDefault.ts @@ -9,6 +9,10 @@ import type { MetafieldDeleteUserError, Scalars, } from '@shopify/hydrogen-react/storefront-api-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartMetafieldDeleteFunction = ( key: Scalars['String']['input'], @@ -20,12 +24,13 @@ export function cartMetafieldDeleteDefault( ): CartMetafieldDeleteFunction { return async (key, optionalParams) => { const ownerId = optionalParams?.cartId || options.getCartId(); + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartMetafieldDelete, errors} = await options.storefront.mutate<{ cartMetafieldDelete: { userErrors: MetafieldDeleteUserError[]; }; errors: StorefrontApiErrors; - }>(CART_METAFIELD_DELETE_MUTATION(), { + }>(CART_METAFIELD_DELETE_MUTATION({includeVisitorConsent}), { variables: { input: { ownerId, @@ -46,14 +51,18 @@ export function cartMetafieldDeleteDefault( }; } +type CartMutationOptions = { + includeVisitorConsent?: boolean; +}; + //! @see https://shopify.dev/docs/api/storefront/2026-04/mutations/cartMetafieldDelete -export const CART_METAFIELD_DELETE_MUTATION = () => `#graphql +export const CART_METAFIELD_DELETE_MUTATION = ( + options: CartMutationOptions = {}, +) => `#graphql mutation cartMetafieldDelete( $input: CartMetafieldDeleteInput! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartMetafieldDelete(input: $input) { userErrors { code diff --git a/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.test.ts b/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.test.ts index 0f0aeb3c2d..d18a83954e 100644 --- a/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.test.ts +++ b/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.test.ts @@ -1,6 +1,9 @@ import {describe, it, expect} from 'vitest'; import {CART_ID, mockCreateStorefrontClient} from '../cart-test-helper'; -import {cartMetafieldsSetDefault} from './cartMetafieldsSetDefault'; +import { + cartMetafieldsSetDefault, + CART_METAFIELD_SET_MUTATION, +} from './cartMetafieldsSetDefault'; describe('cartMetafieldsSetDefault', () => { it('should return a default cart metafields set implementation', async () => { @@ -27,4 +30,24 @@ describe('cartMetafieldsSetDefault', () => { expect(result.cart).toHaveProperty('id', CART_ID); expect(result.userErrors?.[0]).not.toContain(cartFragment); }); + + describe('mutation structure', () => { + it('should not include visitorConsent by default', () => { + const mutation = CART_METAFIELD_SET_MUTATION(); + + expect(mutation).toContain('@inContext'); + expect(mutation).not.toContain('visitorConsent'); + expect(mutation).not.toContain('VisitorConsent'); + }); + + it('should include visitorConsent when specified', () => { + const mutation = CART_METAFIELD_SET_MUTATION({ + includeVisitorConsent: true, + }); + + expect(mutation).toContain('@inContext'); + expect(mutation).toContain('$visitorConsent: VisitorConsent'); + expect(mutation).toContain('visitorConsent: $visitorConsent'); + }); + }); }); diff --git a/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.ts b/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.ts index e61431a2a2..9c83b85dda 100644 --- a/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.ts @@ -9,6 +9,10 @@ import type { Cart, MetafieldsSetUserError, } from '@shopify/hydrogen-react/storefront-api-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartMetafieldsSetFunction = ( metafields: MetafieldWithoutOwnerId[], @@ -26,12 +30,13 @@ export function cartMetafieldsSetDefault( ownerId, }), ); + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartMetafieldsSet, errors} = await options.storefront.mutate<{ cartMetafieldsSet: { userErrors: MetafieldsSetUserError[]; }; errors: StorefrontApiErrors; - }>(CART_METAFIELD_SET_MUTATION(), { + }>(CART_METAFIELD_SET_MUTATION({includeVisitorConsent}), { variables: {metafields: metafieldsWithOwnerId, ...optionalParams}, }); @@ -47,14 +52,18 @@ export function cartMetafieldsSetDefault( }; } +type CartMutationOptions = { + includeVisitorConsent?: boolean; +}; + //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartMetafieldsSet -export const CART_METAFIELD_SET_MUTATION = () => `#graphql +export const CART_METAFIELD_SET_MUTATION = ( + options: CartMutationOptions = {}, +) => `#graphql mutation cartMetafieldsSet( $metafields: [CartMetafieldsSetInput!]! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartMetafieldsSet(metafields: $metafields) { userErrors { code diff --git a/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts index c4561448ab..0b0a556584 100644 --- a/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts @@ -10,6 +10,10 @@ import type { CartQueryDataReturn, CartQueryOptions, } from './cart-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartNoteUpdateFunction = ( note: string, @@ -20,31 +24,38 @@ export function cartNoteUpdateDefault( options: CartQueryOptions, ): CartNoteUpdateFunction { return async (note, optionalParams) => { + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartNoteUpdate, errors} = await options.storefront.mutate<{ cartNoteUpdate: CartQueryData; errors: StorefrontApiErrors; - }>(CART_NOTE_UPDATE_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - note, - ...optionalParams, + }>( + CART_NOTE_UPDATE_MUTATION(options.cartFragment, {includeVisitorConsent}), + { + variables: { + cartId: options.getCartId(), + note, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartNoteUpdate, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartNoteUpdate export const CART_NOTE_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartNoteUpdate( $cartId: ID! $note: String! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartNoteUpdate(cartId: $cartId, note: $note) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts index fbb324e1d1..5eaba70295 100644 --- a/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts @@ -11,6 +11,10 @@ import type { CartQueryOptions, } from './cart-types'; import type {CartSelectedDeliveryOptionInput} from '@shopify/hydrogen-react/storefront-api-types'; +import { + getInContextVariables, + getInContextDirective, +} from './cart-query-helpers'; export type CartSelectedDeliveryOptionsUpdateFunction = ( selectedDeliveryOptions: CartSelectedDeliveryOptionInput[], @@ -21,32 +25,41 @@ export function cartSelectedDeliveryOptionsUpdateDefault( options: CartQueryOptions, ): CartSelectedDeliveryOptionsUpdateFunction { return async (selectedDeliveryOptions, optionalParams) => { + const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; const {cartSelectedDeliveryOptionsUpdate, errors} = await options.storefront.mutate<{ cartSelectedDeliveryOptionsUpdate: CartQueryData; errors: StorefrontApiErrors; - }>(CART_SELECTED_DELIVERY_OPTIONS_UPDATE_MUTATION(options.cartFragment), { - variables: { - cartId: options.getCartId(), - selectedDeliveryOptions, - ...optionalParams, + }>( + CART_SELECTED_DELIVERY_OPTIONS_UPDATE_MUTATION(options.cartFragment, { + includeVisitorConsent, + }), + { + variables: { + cartId: options.getCartId(), + selectedDeliveryOptions, + ...optionalParams, + }, }, - }); + ); return formatAPIResult(cartSelectedDeliveryOptionsUpdate, errors); }; } +type CartMutationBuilderOptions = { + includeVisitorConsent?: boolean; +}; + //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartSelectedDeliveryOptionsUpdate export const CART_SELECTED_DELIVERY_OPTIONS_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, + options: CartMutationBuilderOptions = {}, ) => `#graphql mutation cartSelectedDeliveryOptionsUpdate( $cartId: ID! $selectedDeliveryOptions: [CartSelectedDeliveryOptionInput!]! - $language: LanguageCode - $country: CountryCode - $visitorConsent: VisitorConsent - ) @inContext(country: $country, language: $language, visitorConsent: $visitorConsent) { + ${getInContextVariables(options.includeVisitorConsent ?? false)} + ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartSelectedDeliveryOptionsUpdate(cartId: $cartId, selectedDeliveryOptions: $selectedDeliveryOptions) { cart { ...CartApiMutation From 83ab81d8ac35b489e8e6ba0467456007945b609d Mon Sep 17 00:00:00 2001 From: Riley Nowak Date: Tue, 14 Apr 2026 12:45:15 -0300 Subject: [PATCH 2/4] fix(hydrogen-react): make visitorConsent conditional in cart queries Same root cause as the hydrogen fix - cart queries were unconditionally declaring `$visitorConsent: VisitorConsent`, causing schema validation failures on stores without that type. Cart query functions now accept an optional second parameter: `{ includeVisitorConsent?: boolean }`. The visitorConsent variable and directive argument are only included when explicitly enabled. Co-Authored-By: Claude Opus 4.5 (1M context) --- .../hydrogen-react/src/cart-queries.test.ts | 56 +++++++ packages/hydrogen-react/src/cart-queries.ts | 150 +++++++++--------- 2 files changed, 128 insertions(+), 78 deletions(-) create mode 100644 packages/hydrogen-react/src/cart-queries.test.ts diff --git a/packages/hydrogen-react/src/cart-queries.test.ts b/packages/hydrogen-react/src/cart-queries.test.ts new file mode 100644 index 0000000000..b60f1422f9 --- /dev/null +++ b/packages/hydrogen-react/src/cart-queries.test.ts @@ -0,0 +1,56 @@ +import {describe, it, expect} from 'vitest'; +import { + CartLineAdd, + CartCreate, + CartLineRemove, + CartLineUpdate, + CartNoteUpdate, + CartBuyerIdentityUpdate, + CartAttributesUpdate, + CartDiscountCodesUpdate, + CartQuery, +} from './cart-queries'; + +const MOCK_FRAGMENT = '...MockFragment'; + +describe('cart-queries', () => { + describe('visitorConsent conditional inclusion', () => { + const queries = [ + {name: 'CartLineAdd', fn: CartLineAdd}, + {name: 'CartCreate', fn: CartCreate}, + {name: 'CartLineRemove', fn: CartLineRemove}, + {name: 'CartLineUpdate', fn: CartLineUpdate}, + {name: 'CartNoteUpdate', fn: CartNoteUpdate}, + {name: 'CartBuyerIdentityUpdate', fn: CartBuyerIdentityUpdate}, + {name: 'CartAttributesUpdate', fn: CartAttributesUpdate}, + {name: 'CartDiscountCodesUpdate', fn: CartDiscountCodesUpdate}, + {name: 'CartQuery', fn: CartQuery}, + ]; + + describe.each(queries)('$name', ({fn}) => { + it('should not include visitorConsent by default', () => { + const query = fn(MOCK_FRAGMENT); + + expect(query).toContain('@inContext'); + expect(query).not.toContain('visitorConsent'); + expect(query).not.toContain('VisitorConsent'); + }); + + it('should not include visitorConsent when explicitly disabled', () => { + const query = fn(MOCK_FRAGMENT, {includeVisitorConsent: false}); + + expect(query).toContain('@inContext'); + expect(query).not.toContain('visitorConsent'); + expect(query).not.toContain('VisitorConsent'); + }); + + it('should include visitorConsent when explicitly enabled', () => { + const query = fn(MOCK_FRAGMENT, {includeVisitorConsent: true}); + + expect(query).toContain('@inContext'); + expect(query).toContain('$visitorConsent: VisitorConsent'); + expect(query).toContain('visitorConsent: $visitorConsent'); + }); + }); + }); +}); diff --git a/packages/hydrogen-react/src/cart-queries.ts b/packages/hydrogen-react/src/cart-queries.ts index 531562349e..9039533111 100644 --- a/packages/hydrogen-react/src/cart-queries.ts +++ b/packages/hydrogen-react/src/cart-queries.ts @@ -1,17 +1,41 @@ -export const CartLineAdd = (cartFragment: string): string => /* GraphQL */ ` +type CartQueryOptions = { + includeVisitorConsent?: boolean; +}; + +function getInContextVariables(includeVisitorConsent: boolean): string { + const base = `$country: CountryCode = ZZ + $language: LanguageCode`; + + return includeVisitorConsent + ? `${base} + $visitorConsent: VisitorConsent` + : base; +} + +function getInContextDirective(includeVisitorConsent: boolean): string { + return includeVisitorConsent + ? `@inContext( + country: $country + language: $language + visitorConsent: $visitorConsent + )` + : `@inContext( + country: $country + language: $language + )`; +} + +export const CartLineAdd = ( + cartFragment: string, + options: CartQueryOptions = {}, +): string => /* GraphQL */ ` mutation CartLineAdd( $cartId: ID! $lines: [CartLineInput!]! $numCartLines: Int = 250 - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent + ${getInContextVariables(options.includeVisitorConsent ?? false)} ) - @inContext( - country: $country - language: $language - visitorConsent: $visitorConsent - ) { + ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartLinesAdd(cartId: $cartId, lines: $lines) { cart { ...CartFragment @@ -22,19 +46,16 @@ export const CartLineAdd = (cartFragment: string): string => /* GraphQL */ ` ${cartFragment} `; -export const CartCreate = (cartFragment: string): string => /* GraphQL */ ` +export const CartCreate = ( + cartFragment: string, + options: CartQueryOptions = {}, +): string => /* GraphQL */ ` mutation CartCreate( $input: CartInput! $numCartLines: Int = 250 - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent + ${getInContextVariables(options.includeVisitorConsent ?? false)} ) - @inContext( - country: $country - language: $language - visitorConsent: $visitorConsent - ) { + ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartCreate(input: $input) { cart { ...CartFragment @@ -45,20 +66,17 @@ export const CartCreate = (cartFragment: string): string => /* GraphQL */ ` ${cartFragment} `; -export const CartLineRemove = (cartFragment: string): string => /* GraphQL */ ` +export const CartLineRemove = ( + cartFragment: string, + options: CartQueryOptions = {}, +): string => /* GraphQL */ ` mutation CartLineRemove( $cartId: ID! $lines: [ID!]! $numCartLines: Int = 250 - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent + ${getInContextVariables(options.includeVisitorConsent ?? false)} ) - @inContext( - country: $country - language: $language - visitorConsent: $visitorConsent - ) { + ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartLinesRemove(cartId: $cartId, lineIds: $lines) { cart { ...CartFragment @@ -69,20 +87,17 @@ export const CartLineRemove = (cartFragment: string): string => /* GraphQL */ ` ${cartFragment} `; -export const CartLineUpdate = (cartFragment: string): string => /* GraphQL */ ` +export const CartLineUpdate = ( + cartFragment: string, + options: CartQueryOptions = {}, +): string => /* GraphQL */ ` mutation CartLineUpdate( $cartId: ID! $lines: [CartLineUpdateInput!]! $numCartLines: Int = 250 - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent + ${getInContextVariables(options.includeVisitorConsent ?? false)} ) - @inContext( - country: $country - language: $language - visitorConsent: $visitorConsent - ) { + ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartLinesUpdate(cartId: $cartId, lines: $lines) { cart { ...CartFragment @@ -93,20 +108,17 @@ export const CartLineUpdate = (cartFragment: string): string => /* GraphQL */ ` ${cartFragment} `; -export const CartNoteUpdate = (cartFragment: string): string => /* GraphQL */ ` +export const CartNoteUpdate = ( + cartFragment: string, + options: CartQueryOptions = {}, +): string => /* GraphQL */ ` mutation CartNoteUpdate( $cartId: ID! $note: String! $numCartLines: Int = 250 - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent + ${getInContextVariables(options.includeVisitorConsent ?? false)} ) - @inContext( - country: $country - language: $language - visitorConsent: $visitorConsent - ) { + ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartNoteUpdate(cartId: $cartId, note: $note) { cart { ...CartFragment @@ -119,20 +131,15 @@ export const CartNoteUpdate = (cartFragment: string): string => /* GraphQL */ ` export const CartBuyerIdentityUpdate = ( cartFragment: string, + options: CartQueryOptions = {}, ): string => /* GraphQL */ ` mutation CartBuyerIdentityUpdate( $cartId: ID! $buyerIdentity: CartBuyerIdentityInput! $numCartLines: Int = 250 - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent + ${getInContextVariables(options.includeVisitorConsent ?? false)} ) - @inContext( - country: $country - language: $language - visitorConsent: $visitorConsent - ) { + ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartBuyerIdentityUpdate(cartId: $cartId, buyerIdentity: $buyerIdentity) { cart { ...CartFragment @@ -145,20 +152,15 @@ export const CartBuyerIdentityUpdate = ( export const CartAttributesUpdate = ( cartFragment: string, + options: CartQueryOptions = {}, ): string => /* GraphQL */ ` mutation CartAttributesUpdate( $attributes: [AttributeInput!]! $cartId: ID! $numCartLines: Int = 250 - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent + ${getInContextVariables(options.includeVisitorConsent ?? false)} ) - @inContext( - country: $country - language: $language - visitorConsent: $visitorConsent - ) { + ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartAttributesUpdate(attributes: $attributes, cartId: $cartId) { cart { ...CartFragment @@ -171,20 +173,15 @@ export const CartAttributesUpdate = ( export const CartDiscountCodesUpdate = ( cartFragment: string, + options: CartQueryOptions = {}, ): string => /* GraphQL */ ` mutation CartDiscountCodesUpdate( $cartId: ID! $discountCodes: [String!]! $numCartLines: Int = 250 - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent + ${getInContextVariables(options.includeVisitorConsent ?? false)} ) - @inContext( - country: $country - language: $language - visitorConsent: $visitorConsent - ) { + ${getInContextDirective(options.includeVisitorConsent ?? false)} { cartDiscountCodesUpdate(cartId: $cartId, discountCodes: $discountCodes) { cart { ...CartFragment @@ -195,19 +192,16 @@ export const CartDiscountCodesUpdate = ( ${cartFragment} `; -export const CartQuery = (cartFragment: string): string => /* GraphQL */ ` +export const CartQuery = ( + cartFragment: string, + options: CartQueryOptions = {}, +): string => /* GraphQL */ ` query CartQuery( $id: ID! $numCartLines: Int = 250 - $country: CountryCode = ZZ - $language: LanguageCode - $visitorConsent: VisitorConsent + ${getInContextVariables(options.includeVisitorConsent ?? false)} ) - @inContext( - country: $country - language: $language - visitorConsent: $visitorConsent - ) { + ${getInContextDirective(options.includeVisitorConsent ?? false)} { cart(id: $id) { ...CartFragment } From bdc1d85ff9b79f438bb4cf71c1ebd1f7ddc43a51 Mon Sep 17 00:00:00 2001 From: Riley Nowak Date: Tue, 14 Apr 2026 12:45:23 -0300 Subject: [PATCH 3/4] chore: add changeset for visitorConsent fix Co-Authored-By: Claude Opus 4.5 (1M context) --- .changeset/fix-visitor-consent-conditional.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/fix-visitor-consent-conditional.md diff --git a/.changeset/fix-visitor-consent-conditional.md b/.changeset/fix-visitor-consent-conditional.md new file mode 100644 index 0000000000..b0fa30d3d5 --- /dev/null +++ b/.changeset/fix-visitor-consent-conditional.md @@ -0,0 +1,10 @@ +--- +'@shopify/hydrogen': patch +'@shopify/hydrogen-react': patch +--- + +Fix cart operations failing on stores without `VisitorConsent` type + +Cart operations (like `cart.setMetafields()`) were unconditionally including the `visitorConsent` parameter in GraphQL operations, even when not being used. This caused failures on stores whose Storefront API schema doesn't include the `VisitorConsent` type (older API versions or certain store configurations). + +The `visitorConsent` parameter is now only included in cart GraphQL operations when explicitly provided. This restores compatibility with stores that don't support the `VisitorConsent` type while preserving the feature for users who need it. From 45c3550661330c466d09ad82682e208572918f7a Mon Sep 17 00:00:00 2001 From: Riley Nowak Date: Wed, 15 Apr 2026 10:47:14 -0300 Subject: [PATCH 4/4] refactor(hydrogen): unify CartBuilderOptions type and pull complexity into helpers Address review feedback on PR #3720. The visitorConsent helpers and type were duplicated across 17 mutation/query files with 3 inconsistent names (CartMutationBuilderOptions, CartMutationOptions, CartQueryBuilderOptions). Callers also repeated the derivation logic and forced ?? false at every call site. - Export CartBuilderOptions from cart-query-helpers.ts as the single source of truth - Add shouldIncludeVisitorConsent() to centralize the visitorConsent detection logic - Make getInContextVariables/getInContextDirective params optional (default false) so callers no longer write options.includeVisitorConsent ?? false at 34 call sites Co-Authored-By: Claude Sonnet 4.6 (1M context) --- .../cart/queries/cart-query-helpers.test.ts | 38 +++++++++++++++++++ .../src/cart/queries/cart-query-helpers.ts | 18 ++++++++- .../queries/cartAttributesUpdateDefault.ts | 14 +++---- .../queries/cartBuyerIdentityUpdateDefault.ts | 14 +++---- .../src/cart/queries/cartCreateDefault.ts | 14 +++---- .../cartDeliveryAddressesAddDefault.tsx | 14 +++---- .../cartDeliveryAddressesRemoveDefault.tsx | 14 +++---- .../cartDeliveryAddressesUpdateDefault.tsx | 14 +++---- .../queries/cartDiscountCodesUpdateDefault.ts | 14 +++---- .../src/cart/queries/cartGetDefault.ts | 14 +++---- .../queries/cartGiftCardCodeUpdateDefault.ts | 14 +++---- .../queries/cartGiftCardCodesRemoveDefault.ts | 14 +++---- .../src/cart/queries/cartLinesAddDefault.ts | 14 +++---- .../cart/queries/cartLinesRemoveDefault.ts | 14 +++---- .../cart/queries/cartLinesUpdateDefault.ts | 14 +++---- .../queries/cartMetafieldDeleteDefault.ts | 14 +++---- .../cart/queries/cartMetafieldsSetDefault.ts | 14 +++---- .../src/cart/queries/cartNoteUpdateDefault.ts | 14 +++---- ...artSelectedDeliveryOptionsUpdateDefault.ts | 14 +++---- 19 files changed, 156 insertions(+), 138 deletions(-) diff --git a/packages/hydrogen/src/cart/queries/cart-query-helpers.test.ts b/packages/hydrogen/src/cart/queries/cart-query-helpers.test.ts index 62d2deba8b..8ea9f145c5 100644 --- a/packages/hydrogen/src/cart/queries/cart-query-helpers.test.ts +++ b/packages/hydrogen/src/cart/queries/cart-query-helpers.test.ts @@ -2,6 +2,7 @@ import {describe, it, expect} from 'vitest'; import { getInContextVariables, getInContextDirective, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; describe('cart-query-helpers', () => { @@ -15,6 +16,13 @@ describe('cart-query-helpers', () => { expect(result).not.toContain('VisitorConsent'); }); + it('defaults to excluding visitorConsent when called with no argument', () => { + const result = getInContextVariables(); + + expect(result).toContain('$country: CountryCode = ZZ'); + expect(result).not.toContain('visitorConsent'); + }); + it('returns variables with visitorConsent when included', () => { const result = getInContextVariables(true); @@ -32,6 +40,12 @@ describe('cart-query-helpers', () => { expect(result).not.toContain('visitorConsent'); }); + it('defaults to excluding visitorConsent when called with no argument', () => { + const result = getInContextDirective(); + + expect(result).toBe('@inContext(country: $country, language: $language)'); + }); + it('returns directive with visitorConsent when included', () => { const result = getInContextDirective(true); @@ -40,4 +54,28 @@ describe('cart-query-helpers', () => { ); }); }); + + describe('shouldIncludeVisitorConsent', () => { + it('returns false when input is undefined', () => { + expect(shouldIncludeVisitorConsent(undefined)).toBe(false); + }); + + it('returns false when input has no visitorConsent key', () => { + expect(shouldIncludeVisitorConsent({})).toBe(false); + }); + + it('returns false when visitorConsent is explicitly undefined', () => { + expect(shouldIncludeVisitorConsent({visitorConsent: undefined})).toBe( + false, + ); + }); + + it('returns true when visitorConsent is provided', () => { + expect( + shouldIncludeVisitorConsent({ + visitorConsent: {saleOfData: 'SALE_OF_DATA_OPTED_OUT'}, + }), + ).toBe(true); + }); + }); }); diff --git a/packages/hydrogen/src/cart/queries/cart-query-helpers.ts b/packages/hydrogen/src/cart/queries/cart-query-helpers.ts index 0bf94aed59..6602ab83ea 100644 --- a/packages/hydrogen/src/cart/queries/cart-query-helpers.ts +++ b/packages/hydrogen/src/cart/queries/cart-query-helpers.ts @@ -6,11 +6,25 @@ * maintaining compatibility with stores whose API schema doesn't support it. */ +export type CartBuilderOptions = { + includeVisitorConsent?: boolean; +}; + +/** + * Returns true when the caller explicitly provides a visitorConsent value, + * indicating the store's Storefront API schema supports the VisitorConsent type. + */ +export function shouldIncludeVisitorConsent(input?: { + visitorConsent?: unknown; +}): boolean { + return input?.visitorConsent !== undefined; +} + /** * Builds the @inContext directive variable declarations for cart operations. * Only includes visitorConsent when it's actually being used. */ -export function getInContextVariables(includeVisitorConsent: boolean): string { +export function getInContextVariables(includeVisitorConsent = false): string { const base = `$country: CountryCode = ZZ $language: LanguageCode`; @@ -24,7 +38,7 @@ export function getInContextVariables(includeVisitorConsent: boolean): string { * Builds the @inContext directive for cart operations. * Only includes visitorConsent when it's actually being used. */ -export function getInContextDirective(includeVisitorConsent: boolean): string { +export function getInContextDirective(includeVisitorConsent = false): string { return includeVisitorConsent ? '@inContext(country: $country, language: $language, visitorConsent: $visitorConsent)' : '@inContext(country: $country, language: $language)'; diff --git a/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts index b1c831833c..d943b1fa00 100644 --- a/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartAttributesUpdateDefault.ts @@ -14,6 +14,8 @@ import type {AttributeInput} from '@shopify/hydrogen-react/storefront-api-types' import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartAttributesUpdateFunction = ( @@ -25,7 +27,7 @@ export function cartAttributesUpdateDefault( options: CartQueryOptions, ): CartAttributesUpdateFunction { return async (attributes, optionalParams) => { - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartAttributesUpdate, errors} = await options.storefront.mutate<{ cartAttributesUpdate: CartQueryData; errors: StorefrontApiErrors; @@ -45,19 +47,15 @@ export function cartAttributesUpdateDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - export const CART_ATTRIBUTES_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartAttributesUpdate( $cartId: ID! $attributes: [AttributeInput!]! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartAttributesUpdate(cartId: $cartId, attributes: $attributes) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts index 2f17fcf975..5b6b2167f0 100644 --- a/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartBuyerIdentityUpdateDefault.ts @@ -14,6 +14,8 @@ import type {CartBuyerIdentityInput} from '@shopify/hydrogen-react/storefront-ap import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartBuyerIdentityUpdateFunction = ( @@ -35,7 +37,7 @@ export function cartBuyerIdentityUpdateDefault( ? await options.customerAccount.getBuyer() : undefined; - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartBuyerIdentityUpdate, errors} = await options.storefront.mutate<{ cartBuyerIdentityUpdate: CartQueryData; errors: StorefrontApiErrors; @@ -58,20 +60,16 @@ export function cartBuyerIdentityUpdateDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartBuyerIdentityUpdate export const CART_BUYER_IDENTITY_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartBuyerIdentityUpdate( $cartId: ID! $buyerIdentity: CartBuyerIdentityInput! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartBuyerIdentityUpdate(cartId: $cartId, buyerIdentity: $buyerIdentity) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartCreateDefault.ts b/packages/hydrogen/src/cart/queries/cartCreateDefault.ts index 4fc976af65..c295590fab 100644 --- a/packages/hydrogen/src/cart/queries/cartCreateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartCreateDefault.ts @@ -14,6 +14,8 @@ import type {CartInput} from '@shopify/hydrogen-react/storefront-api-types'; import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartCreateFunction = ( @@ -30,7 +32,7 @@ export function cartCreateDefault( : undefined; const {cartId, ...restOfOptionalParams} = optionalParams || {}; const {buyerIdentity, ...restOfInput} = input; - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartCreate, errors} = await options.storefront.mutate<{ cartCreate: CartQueryData; errors: StorefrontApiErrors; @@ -50,19 +52,15 @@ export function cartCreateDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartCreate export const CART_CREATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartCreate( $input: CartInput! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartCreate(input: $input) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesAddDefault.tsx b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesAddDefault.tsx index f43bfdfbdf..02c72d05be 100644 --- a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesAddDefault.tsx +++ b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesAddDefault.tsx @@ -14,6 +14,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartDeliveryAddressesAddFunction = ( @@ -49,7 +51,7 @@ export function cartDeliveryAddressesAddDefault( addresses: Array, optionalParams, ) => { - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartDeliveryAddressesAdd, errors} = await options.storefront.mutate<{ cartDeliveryAddressesAdd: CartQueryData; errors: StorefrontApiErrors; @@ -70,20 +72,16 @@ export function cartDeliveryAddressesAddDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartDeliveryAddressesAdd export const CART_DELIVERY_ADDRESSES_ADD_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartDeliveryAddressesAdd( $cartId: ID! $addresses: [CartSelectableAddressInput!]!, - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartDeliveryAddressesAdd(addresses: $addresses, cartId: $cartId) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesRemoveDefault.tsx b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesRemoveDefault.tsx index 3c8631631e..307eb73730 100644 --- a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesRemoveDefault.tsx +++ b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesRemoveDefault.tsx @@ -14,6 +14,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartDeliveryAddressesRemoveFunction = ( @@ -44,7 +46,7 @@ export function cartDeliveryAddressesRemoveDefault( addressIds: Array | string[], optionalParams, ) => { - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartDeliveryAddressesRemove, errors} = await options.storefront.mutate<{ cartDeliveryAddressesRemove: CartQueryData; @@ -66,20 +68,16 @@ export function cartDeliveryAddressesRemoveDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartDeliveryAddressesRemove export const CART_DELIVERY_ADDRESSES_REMOVE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartDeliveryAddressesRemove( $cartId: ID! $addressIds: [ID!]!, - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartDeliveryAddressesRemove(addressIds: $addressIds, cartId: $cartId) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesUpdateDefault.tsx b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesUpdateDefault.tsx index 4e9be05bac..d735b1146a 100644 --- a/packages/hydrogen/src/cart/queries/cartDeliveryAddressesUpdateDefault.tsx +++ b/packages/hydrogen/src/cart/queries/cartDeliveryAddressesUpdateDefault.tsx @@ -14,6 +14,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartDeliveryAddressesUpdateFunction = ( @@ -66,7 +68,7 @@ export function cartDeliveryAddressesUpdateDefault( addresses: Array, optionalParams, ) => { - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartDeliveryAddressesUpdate, errors} = await options.storefront.mutate<{ cartDeliveryAddressesUpdate: CartQueryData; @@ -88,20 +90,16 @@ export function cartDeliveryAddressesUpdateDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartDeliveryAddressesUpdate export const CART_DELIVERY_ADDRESSES_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartDeliveryAddressesUpdate( $cartId: ID! $addresses: [CartSelectableAddressUpdateInput!]!, - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartDeliveryAddressesUpdate(addresses: $addresses, cartId: $cartId) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts index 099cd3131c..ac4f819a91 100644 --- a/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartDiscountCodesUpdateDefault.ts @@ -13,6 +13,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartDiscountCodesUpdateFunction = ( @@ -29,7 +31,7 @@ export function cartDiscountCodesUpdateDefault( return array.indexOf(value) === index; }); - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartDiscountCodesUpdate, errors} = await options.storefront.mutate<{ cartDiscountCodesUpdate: CartQueryData; errors: StorefrontApiErrors; @@ -49,20 +51,16 @@ export function cartDiscountCodesUpdateDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartDiscountCodesUpdate export const CART_DISCOUNT_CODE_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartDiscountCodesUpdate( $cartId: ID! $discountCodes: [String!]! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartDiscountCodesUpdate(cartId: $cartId, discountCodes: $discountCodes) { ... @defer { cart { diff --git a/packages/hydrogen/src/cart/queries/cartGetDefault.ts b/packages/hydrogen/src/cart/queries/cartGetDefault.ts index acbdf0e72a..f5fb885b24 100644 --- a/packages/hydrogen/src/cart/queries/cartGetDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartGetDefault.ts @@ -10,6 +10,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; type CartGetProps = { @@ -71,7 +73,7 @@ export function cartGetDefault({ if (!cartId) return null; - const includeVisitorConsent = cartInput?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(cartInput); const [isCustomerLoggedIn, {cart, errors}] = await Promise.all([ customerAccount ? customerAccount.isLoggedIn() : false, storefront.query<{cart: Cart | null}>( @@ -93,20 +95,16 @@ export function cartGetDefault({ }; } -type CartQueryBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see https://shopify.dev/docs/api/storefront/latest/queries/cart const CART_QUERY = ( cartFragment = DEFAULT_CART_FRAGMENT, - options: CartQueryBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql query CartQuery( $cartId: ID! $numCartLines: Int = 100 - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cart(id: $cartId) { ...CartApiQuery } diff --git a/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts index 12255ac720..04568318b1 100644 --- a/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartGiftCardCodeUpdateDefault.ts @@ -13,6 +13,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartGiftCardCodesUpdateFunction = ( @@ -36,7 +38,7 @@ export function cartGiftCardCodesUpdateDefault( options: CartQueryOptions, ): CartGiftCardCodesUpdateFunction { return async (giftCardCodes, optionalParams) => { - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartGiftCardCodesUpdate, errors} = await options.storefront.mutate<{ cartGiftCardCodesUpdate: CartQueryData; errors: StorefrontApiErrors; @@ -56,20 +58,16 @@ export function cartGiftCardCodesUpdateDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartGiftCardCodesUpdate export const CART_GIFT_CARD_CODE_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartGiftCardCodesUpdate( $cartId: ID! $giftCardCodes: [String!]! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartGiftCardCodesUpdate(cartId: $cartId, giftCardCodes: $giftCardCodes) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartGiftCardCodesRemoveDefault.ts b/packages/hydrogen/src/cart/queries/cartGiftCardCodesRemoveDefault.ts index f7e205690e..08d1259da1 100644 --- a/packages/hydrogen/src/cart/queries/cartGiftCardCodesRemoveDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartGiftCardCodesRemoveDefault.ts @@ -13,6 +13,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartGiftCardCodesRemoveFunction = ( @@ -24,7 +26,7 @@ export function cartGiftCardCodesRemoveDefault( options: CartQueryOptions, ): CartGiftCardCodesRemoveFunction { return async (appliedGiftCardIds, optionalParams) => { - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartGiftCardCodesRemove, errors} = await options.storefront.mutate<{ cartGiftCardCodesRemove: CartQueryData; errors: StorefrontApiErrors; @@ -44,20 +46,16 @@ export function cartGiftCardCodesRemoveDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartGiftCardCodesRemove export const CART_GIFT_CARD_CODES_REMOVE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartGiftCardCodesRemove( $cartId: ID! $appliedGiftCardIds: [ID!]! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartGiftCardCodesRemove(cartId: $cartId, appliedGiftCardIds: $appliedGiftCardIds) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts b/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts index dcdf9bddbc..353c84436f 100644 --- a/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartLinesAddDefault.ts @@ -14,6 +14,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartLinesAddFunction = ( @@ -25,7 +27,7 @@ export function cartLinesAddDefault( options: CartQueryOptions, ): CartLinesAddFunction { return async (lines, optionalParams) => { - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartLinesAdd, errors} = await options.storefront.mutate<{ cartLinesAdd: CartQueryData; errors: StorefrontApiErrors; @@ -41,20 +43,16 @@ export function cartLinesAddDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartLinesAdd export const CART_LINES_ADD_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartLinesAdd( $cartId: ID! $lines: [CartLineInput!]! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartLinesAdd(cartId: $cartId, lines: $lines) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts b/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts index e27e4e8c21..584ab45bcb 100644 --- a/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartLinesRemoveDefault.ts @@ -14,6 +14,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartLinesRemoveFunction = ( @@ -27,7 +29,7 @@ export function cartLinesRemoveDefault( return async (lineIds, optionalParams) => { throwIfLinesAreOptimistic('removeLines', lineIds); - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartLinesRemove, errors} = await options.storefront.mutate<{ cartLinesRemove: CartQueryData; errors: StorefrontApiErrors; @@ -45,20 +47,16 @@ export function cartLinesRemoveDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartLinesRemove export const CART_LINES_REMOVE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartLinesRemove( $cartId: ID! $lineIds: [ID!]! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartLinesRemove(cartId: $cartId, lineIds: $lineIds) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts index 986c4a6d76..f37607e30a 100644 --- a/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartLinesUpdateDefault.ts @@ -15,6 +15,8 @@ import type {CartLineUpdateInput} from '@shopify/hydrogen-react/storefront-api-t import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartLinesUpdateFunction = ( @@ -28,7 +30,7 @@ export function cartLinesUpdateDefault( return async (lines, optionalParams) => { throwIfLinesAreOptimistic('updateLines', lines); - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartLinesUpdate, errors} = await options.storefront.mutate<{ cartLinesUpdate: CartQueryData; errors: StorefrontApiErrors; @@ -46,20 +48,16 @@ export function cartLinesUpdateDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see: https://shopify.dev/docs/api/storefront/latest/mutations/cartLinesUpdate export const CART_LINES_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartLinesUpdate( $cartId: ID! $lines: [CartLineUpdateInput!]! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartLinesUpdate(cartId: $cartId, lines: $lines) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartMetafieldDeleteDefault.ts b/packages/hydrogen/src/cart/queries/cartMetafieldDeleteDefault.ts index ed52eda888..e905e98186 100644 --- a/packages/hydrogen/src/cart/queries/cartMetafieldDeleteDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartMetafieldDeleteDefault.ts @@ -12,6 +12,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartMetafieldDeleteFunction = ( @@ -24,7 +26,7 @@ export function cartMetafieldDeleteDefault( ): CartMetafieldDeleteFunction { return async (key, optionalParams) => { const ownerId = optionalParams?.cartId || options.getCartId(); - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartMetafieldDelete, errors} = await options.storefront.mutate<{ cartMetafieldDelete: { userErrors: MetafieldDeleteUserError[]; @@ -51,18 +53,14 @@ export function cartMetafieldDeleteDefault( }; } -type CartMutationOptions = { - includeVisitorConsent?: boolean; -}; - //! @see https://shopify.dev/docs/api/storefront/2026-04/mutations/cartMetafieldDelete export const CART_METAFIELD_DELETE_MUTATION = ( - options: CartMutationOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartMetafieldDelete( $input: CartMetafieldDeleteInput! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartMetafieldDelete(input: $input) { userErrors { code diff --git a/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.ts b/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.ts index 9c83b85dda..a38f5905b2 100644 --- a/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartMetafieldsSetDefault.ts @@ -12,6 +12,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartMetafieldsSetFunction = ( @@ -30,7 +32,7 @@ export function cartMetafieldsSetDefault( ownerId, }), ); - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartMetafieldsSet, errors} = await options.storefront.mutate<{ cartMetafieldsSet: { userErrors: MetafieldsSetUserError[]; @@ -52,18 +54,14 @@ export function cartMetafieldsSetDefault( }; } -type CartMutationOptions = { - includeVisitorConsent?: boolean; -}; - //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartMetafieldsSet export const CART_METAFIELD_SET_MUTATION = ( - options: CartMutationOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartMetafieldsSet( $metafields: [CartMetafieldsSetInput!]! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartMetafieldsSet(metafields: $metafields) { userErrors { code diff --git a/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts index 0b0a556584..689f11cc76 100644 --- a/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartNoteUpdateDefault.ts @@ -13,6 +13,8 @@ import type { import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartNoteUpdateFunction = ( @@ -24,7 +26,7 @@ export function cartNoteUpdateDefault( options: CartQueryOptions, ): CartNoteUpdateFunction { return async (note, optionalParams) => { - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartNoteUpdate, errors} = await options.storefront.mutate<{ cartNoteUpdate: CartQueryData; errors: StorefrontApiErrors; @@ -42,20 +44,16 @@ export function cartNoteUpdateDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartNoteUpdate export const CART_NOTE_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartNoteUpdate( $cartId: ID! $note: String! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartNoteUpdate(cartId: $cartId, note: $note) { cart { ...CartApiMutation diff --git a/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts b/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts index 5eaba70295..ed3314afc6 100644 --- a/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts +++ b/packages/hydrogen/src/cart/queries/cartSelectedDeliveryOptionsUpdateDefault.ts @@ -14,6 +14,8 @@ import type {CartSelectedDeliveryOptionInput} from '@shopify/hydrogen-react/stor import { getInContextVariables, getInContextDirective, + CartBuilderOptions, + shouldIncludeVisitorConsent, } from './cart-query-helpers'; export type CartSelectedDeliveryOptionsUpdateFunction = ( @@ -25,7 +27,7 @@ export function cartSelectedDeliveryOptionsUpdateDefault( options: CartQueryOptions, ): CartSelectedDeliveryOptionsUpdateFunction { return async (selectedDeliveryOptions, optionalParams) => { - const includeVisitorConsent = optionalParams?.visitorConsent !== undefined; + const includeVisitorConsent = shouldIncludeVisitorConsent(optionalParams); const {cartSelectedDeliveryOptionsUpdate, errors} = await options.storefront.mutate<{ cartSelectedDeliveryOptionsUpdate: CartQueryData; @@ -46,20 +48,16 @@ export function cartSelectedDeliveryOptionsUpdateDefault( }; } -type CartMutationBuilderOptions = { - includeVisitorConsent?: boolean; -}; - //! @see https://shopify.dev/docs/api/storefront/latest/mutations/cartSelectedDeliveryOptionsUpdate export const CART_SELECTED_DELIVERY_OPTIONS_UPDATE_MUTATION = ( cartFragment = MINIMAL_CART_FRAGMENT, - options: CartMutationBuilderOptions = {}, + options: CartBuilderOptions = {}, ) => `#graphql mutation cartSelectedDeliveryOptionsUpdate( $cartId: ID! $selectedDeliveryOptions: [CartSelectedDeliveryOptionInput!]! - ${getInContextVariables(options.includeVisitorConsent ?? false)} - ) ${getInContextDirective(options.includeVisitorConsent ?? false)} { + ${getInContextVariables(options.includeVisitorConsent)} + ) ${getInContextDirective(options.includeVisitorConsent)} { cartSelectedDeliveryOptionsUpdate(cartId: $cartId, selectedDeliveryOptions: $selectedDeliveryOptions) { cart { ...CartApiMutation