# createCartHandler Creates an API that can be used to interact with the cart. ```js import { createStorefrontClient, createCartHandler, cartGetIdDefault, cartSetIdDefault, } from '@shopify/hydrogen'; import * as remixBuild from '@remix-run/dev/server-build'; import { createRequestHandler, getStorefrontHeaders, } from '@shopify/remix-oxygen'; export default { async fetch(request, env, executionContext) { const {storefront} = createStorefrontClient({ /* client parameters */ }); // Create a cart api instance. const cart = createCartHandler({ storefront, getCartId: cartGetIdDefault(request.headers), setCartId: cartSetIdDefault(), }); const handleRequest = createRequestHandler({ build: remixBuild, mode: process.env.NODE_ENV, getLoadContext: () => ({ storefront, cart, // Pass the cart api instance to the loader context. }), }); return await handleRequest(request); }, }; ``` ```ts import { createStorefrontClient, createCartHandler, cartGetIdDefault, cartSetIdDefault, } from '@shopify/hydrogen'; import * as remixBuild from '@remix-run/dev/server-build'; import { createRequestHandler, getStorefrontHeaders, } from '@shopify/remix-oxygen'; export default { async fetch( request: Request, env: Record<string, string>, executionContext: ExecutionContext, ): Promise<Response> { const {storefront} = createStorefrontClient({ /* client parameters */ }); // Create a cart api instance. const cart = createCartHandler({ storefront, getCartId: cartGetIdDefault(request.headers), setCartId: cartSetIdDefault(), }); const handleRequest = createRequestHandler({ build: remixBuild, mode: process.env.NODE_ENV, getLoadContext: () => ({ storefront, cart, // Pass the cart api instance to the loader context. }), }); return await handleRequest(request); }, }; ``` ## createCartHandler(options) ### CartHandlerOptionsForDocs ### getCartId value: `() => string` A function that returns the cart id in the form of `gid://shopify/Cart/c1-123`. ### setCartId value: `(cartId: string) => Headers` A function that sets the cart ID. ### storefront value: `Storefront` The storefront client instance created by [`createStorefrontClient`](docs/api/hydrogen/latest/utilities/createstorefrontclient). ### cartMutateFragment value: `string` The cart mutation fragment used in most mutation requests, except for `setMetafields` and `deleteMetafield`. See the [example usage](https://shopify.dev/docs/api/hydrogen/2023-10/utilities/createcarthandler#example-cart-fragments) in the documentation. ### cartQueryFragment value: `string` The cart query fragment used by `cart.get()`. See the [example usage](https://shopify.dev/docs/api/hydrogen/2023-10/utilities/createcarthandler#example-cart-fragments) in the documentation. ### customMethods value: `TCustomMethods` Define custom methods or override existing methods for your cart API instance. See the [example usage](https://shopify.dev/docs/api/hydrogen/2023-10/utilities/createcarthandler#example-custom-methods) in the documentation. ### Storefront Interface to interact with the Storefront API. ### query value: `<OverrideReturnType = any, RawGqlString extends string = string>(query: RawGqlString, ...options: RawGqlString extends never ? IsOptionalVariables<StorefrontQueries[RawGqlString]> extends true ? [StorefrontQuerySecondParam<RawGqlString>?] : [StorefrontQuerySecondParam<RawGqlString>] : [StorefrontQuerySecondParam<string>?]) => Promise<RawGqlString extends never ? StorefrontQueries[RawGqlString]["return"] : OverrideReturnType>` The function to run a query on Storefront API. ### mutate value: `<OverrideReturnType = any, RawGqlString extends string = string>(mutation: RawGqlString, ...options: RawGqlString extends never ? IsOptionalVariables<StorefrontMutations[RawGqlString]> extends true ? [StorefrontMutateSecondParam<RawGqlString>?] : [StorefrontMutateSecondParam<RawGqlString>] : [StorefrontCommonOptions<{ readonly [variable: string]: unknown; }>?]) => Promise<RawGqlString extends never ? StorefrontMutations[RawGqlString]["return"] : OverrideReturnType>` The function to run a mutation on Storefront API. ### cache value: `Cache` The cache instance passed in from the `createStorefrontClient` argument. ### CacheNone value: `() => NoStoreStrategy` Re-export of [`CacheNone`](https://shopify.dev/docs/api/hydrogen/2023-10/utilities/cachenone). ### CacheLong value: `(overrideOptions?: AllCacheOptions) => AllCacheOptions` Re-export of [`CacheLong`](https://shopify.dev/docs/api/hydrogen/2023-10/utilities/cachelong). ### CacheShort value: `(overrideOptions?: AllCacheOptions) => AllCacheOptions` Re-export of [`CacheShort`](https://shopify.dev/docs/api/hydrogen/2023-10/utilities/cacheshort). ### CacheCustom value: `(overrideOptions: AllCacheOptions) => AllCacheOptions` Re-export of [`CacheCustom`](https://shopify.dev/docs/api/hydrogen/2023-10/utilities/cachecustom). ### generateCacheControlHeader value: `(cacheOptions: AllCacheOptions) => string` Re-export of [`generateCacheControlHeader`](https://shopify.dev/docs/api/hydrogen/2023-10/utilities/generatecachecontrolheader). ### getPublicTokenHeaders value: `(props?: Partial<Pick<StorefrontClientProps, "contentType">> & Pick<StorefrontClientProps, "publicStorefrontToken">) => Record<string, string>` Returns an object that contains headers that are needed for each query to Storefront API GraphQL endpoint. See [`getPublicTokenHeaders` in Hydrogen React](https://shopify.dev/docs/api/hydrogen-react/2023-10/utilities/createstorefrontclient#:~:text=%27graphql%27.-,getPublicTokenHeaders,-(props%3F%3A) for more details. ### getPrivateTokenHeaders value: `(props?: Partial<Pick<StorefrontClientProps, "contentType">> & Pick<StorefrontClientProps, "privateStorefrontToken"> & { buyerIp?: string; }) => Record<string, string>` Returns an object that contains headers that are needed for each query to Storefront API GraphQL endpoint for API calls made from a server. See [`getPrivateTokenHeaders` in Hydrogen React](https://shopify.dev/docs/api/hydrogen-react/2023-10/utilities/createstorefrontclient#:~:text=storefrontApiVersion-,getPrivateTokenHeaders,-(props%3F%3A) for more details. ### getShopifyDomain value: `(props?: Partial<Pick<StorefrontClientProps, "storeDomain">>) => string` Creates the fully-qualified URL to your myshopify.com domain. See [`getShopifyDomain` in Hydrogen React](https://shopify.dev/docs/api/hydrogen-react/2023-10/utilities/createstorefrontclient#:~:text=StorefrontClientReturn-,getShopifyDomain,-(props%3F%3A) for more details. ### getApiUrl value: `(props?: Partial<Pick<StorefrontClientProps, "storeDomain" | "storefrontApiVersion">>) => string` Creates the fully-qualified URL to your store's GraphQL endpoint. See [`getStorefrontApiUrl` in Hydrogen React](https://shopify.dev/docs/api/hydrogen-react/2023-10/utilities/createstorefrontclient#:~:text=storeDomain-,getStorefrontApiUrl,-(props%3F%3A) for more details. ### isApiError value: `(error: any) => boolean` Determines if the error is resulted from a Storefront API call. ### i18n value: `TI18n` The `i18n` object passed in from the `createStorefrontClient` argument. ### CachingStrategy Use the `CachingStrategy` to define a custom caching mechanism for your data. Or use one of the pre-defined caching strategies: CacheNone, CacheShort, CacheLong. ### mode value: `string` The caching mode, generally `public`, `private`, or `no-store`. ### maxAge value: `number` The maximum amount of time in seconds that a resource will be considered fresh. See `max-age` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#:~:text=Response%20Directives-,max%2Dage,-The%20max%2Dage). ### staleWhileRevalidate value: `number` Indicate that the cache should serve the stale response in the background while revalidating the cache. See `stale-while-revalidate` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-while-revalidate). ### sMaxAge value: `number` Similar to `maxAge` but specific to shared caches. See `s-maxage` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage). ### staleIfError value: `number` Indicate that the cache should serve the stale response if an error occurs while revalidating the cache. See `stale-if-error` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error). ### NoStoreStrategy ### mode value: `string` ### AllCacheOptions Override options for a cache strategy. ### mode value: `string` The caching mode, generally `public`, `private`, or `no-store`. ### maxAge value: `number` The maximum amount of time in seconds that a resource will be considered fresh. See `max-age` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#:~:text=Response%20Directives-,max%2Dage,-The%20max%2Dage). ### staleWhileRevalidate value: `number` Indicate that the cache should serve the stale response in the background while revalidating the cache. See `stale-while-revalidate` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-while-revalidate). ### sMaxAge value: `number` Similar to `maxAge` but specific to shared caches. See `s-maxage` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage). ### staleIfError value: `number` Indicate that the cache should serve the stale response if an error occurs while revalidating the cache. See `stale-if-error` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error). ## Examples Creates an API that can be used to interact with the cart. ### Cart fragments ```js import { createCartHandler, cartGetIdDefault, cartSetIdDefault, } from '@shopify/hydrogen'; // Override cart fragments const cart = createCartHandler({ storefront, getCartId: cartGetIdDefault(request.headers), setCartId: cartSetIdDefault(), cartQueryFragment: CART_QUERY_FRAGMENT, cartMutateFragment: CART_MUTATE_FRAGMENT, }); // cartQueryFragment requirements: // - Must be named `CartApiQuery` // - Only have access to the following query variables: // - $cartId: ID! // - $country: CountryCode // - $language: LanguageCode // - $numCartLines: Int const CART_QUERY_FRAGMENT = `#graphql fragment CartApiQuery on Cart { id totalQuantity checkoutUrl note } `; // cartMutateFragment requirements: // - Must be named `CartApiMutation` // - Only have access to the following query variables: // - $cartId: ID! // - $country: CountryCode // - $language: LanguageCode const CART_MUTATE_FRAGMENT = `#graphql fragment CartApiMutation on Cart { id totalQuantity checkoutUrl lines(first: 100) { edges { node { id quantity } } } } `; ``` ### Custom methods ```js import { createCartHandler, cartGetIdDefault, cartSetIdDefault, cartLinesAddDefault, cartLinesRemoveDefault, } from '@shopify/hydrogen'; const cartQueryOptions = { storefront, getCartId: cartGetIdDefault(request.headers), }; const getCartId = cartGetIdDefault(request.headers); const cart = createCartHandler({ storefront, getCartId, setCartId: cartSetIdDefault(), customMethods: { editInLine: async (addLines, removeLineIds, optionalParams) => { // Using Hydrogen default cart query methods await cartLinesAddDefault(cartQueryOptions)(addLines, optionalParams); return await cartLinesRemoveDefault(cartQueryOptions)( removeLineIds, optionalParams, ); }, addLines: async (lines, optionalParams) => { // With your own Storefront API graphql query return await storefront.mutate(CART_LINES_ADD_MUTATION, { variables: { id: optionalParams.cartId || getCartId(), lines, }, }); }, }, }); // Use custom method editInLine that delete and add items in one method cart.editInLine( ['123'], [ { merchandiseId: 'gid://shopify/ProductVariant/456789123', quantity: 1, }, ], ); // Use overridden cart.addLines const result = await cart.addLines( [ { merchandiseId: 'gid://shopify/ProductVariant/123456789', quantity: 1, }, ], { cartId: 'c-123', }, ); // Output of result: // { // cartLinesAdd: { // cart: { // id: 'c-123', // totalQuantity: 1 // }, // errors: [] // } // } const CART_LINES_ADD_MUTATION = `#graphql mutation CartLinesAdd( $cartId: ID! $lines: [CartLineInput!]! $country: CountryCode = ZZ $language: LanguageCode ) @inContext(country: $country, language: $language) { cartLinesAdd(cartId: $cartId, lines: $lines) { cart { id totalQuantity } errors: userErrors { message field code } } } `; ``` ### Cart instance usage ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.addLines( [ { merchandiseId: 'gid://shopify/ProductVariant/123456789', quantity: 1, }, ], // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); } // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 1 // }, // errors: [] // } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.create( { lines: [ { merchandiseId: 'gid://shopify/ProductVariant/123456789', quantity: 1, }, ], discountCodes: ['FREE_SHIPPING'], }, // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 1, // discountCodes: [{ code: 'FREE_SHIPPING'}] // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.setMetafields( [ { key: 'custom.gift', type: 'boolean', value: 'true', }, ], // Optional parameters { cartId: '123', // override the cart id }, ); const result2 = await cart.deleteMetafield( 'custom.gift', // Optional parameters { cartId: '123', // override the cart id }, ); } // server.js // To query for metafields, use the `cartQueryFragment` option when creating the cart handler. import { createCartHandler, cartGetIdDefault, cartSetIdDefault, } from '@shopify/hydrogen'; const cart = createCartHandler({ storefront, getCartId: cartGetIdDefault(request.headers), setCartId: cartSetIdDefault(), cartQueryFragment: CART_QUERY_FRAGMENT, }); const CART_QUERY_FRAGMENT = `#graphql fragment CartApiQuery on Cart { id metafields( identifiers: [{ namespace: "custom", key: "gift" ]) { namespace key type value } } `; ``` ```js export async function loader({context}) { const {cart} = context; // Usage const result = await cart.get(); // Optional parameters const result2 = await cart.get({ cartId: '123', // override the cart id numCartLines: 50, //override to return 50 cart lines country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }); } ``` ```js export async function loader({context}) { // Usage context.cart.getCartId(); // 'gid://shopify/Cart/123' } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.removeLines( ['123'], // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 0 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; const result = await cart.addLines([ { merchandiseId: 'gid://shopify/ProductVariant/123456789', quantity: 1, }, ]); // Usage const headers = cart.setCartId(result.cart.id); } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.setMetafields( [ { key: 'custom.gift', type: 'boolean', value: 'true', }, ], // Optional parameters { cartId: '123', // override the cart id }, ); const result2 = await cart.deleteMetafield( 'custom.gift', // Optional parameters { cartId: '123', // override the cart id }, ); } // server.js // To query for metafields, use the `cartQueryFragment` option when creating the cart handler. import { createCartHandler, cartGetIdDefault, cartSetIdDefault, } from '@shopify/hydrogen'; const cart = createCartHandler({ storefront, getCartId: cartGetIdDefault(request.headers), setCartId: cartSetIdDefault(), cartQueryFragment: CART_QUERY_FRAGMENT, }); const CART_QUERY_FRAGMENT = `#graphql fragment CartApiQuery on Cart { id metafields( identifiers: [{ namespace: "custom", key: "gift" ]) { namespace key type value } } `; ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateAttributes( [ { key: 'Somekey', value: '1', }, ], // Optional parameters { cartId: '123', // override the cart id }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 1 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateBuyerIdentity( { customerAccessToken: '123', }, // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 1 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateDiscountCodes( ['FREE_SHIPPING'], // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 1 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateLines( [ { merchandiseId: 'gid://shopify/ProductVariant/123456789', quantity: 2, }, ], // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 2 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateNote( 'Some notes', // Optional parameters { cartId: '123', // override the cart id }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 0 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateSelectedDeliveryOptions( [ { deliveryGroupId: '123', deliveryOptionHandle: 'Canada Post', }, ], // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 2 // }, // errors: [] // } } ``` ## Returns The handler returns the following default methods. Any [custom](https://shopify.dev/docs/api/hydrogen/2023-10/utilities/createcarthandler#example-custom-methods) or overwritten methods will also be available in the returned cart instance. ### HydrogenCartForDocs ### addLines value: `CartLinesAddFunction` Adds items to the cart. If the cart doesn't exist, a new one will be created. ### create value: `CartCreateFunction` Creates a new cart. ### deleteMetafield value: `CartMetafieldDeleteFunction` Removes a custom field (metafield) from the cart. ### get value: `CartGetFunction` Retrieves the cart information. ### getCartId value: `() => string` Retrieves the unique identifier of the cart. By default, it gets the ID from the request cookie. ### removeLines value: `CartLinesRemoveFunction` Removes items from the cart. ### setCartId value: `(cartId: string) => Headers` Sets the unique identifier of the cart. By default, it sets the ID in the header cookie. ### setMetafields value: `CartMetafieldsSetFunction` Adds extra information (metafields) to the cart. If the cart doesn't exist, a new one will be created. ### updateAttributes value: `CartAttributesUpdateFunction` Updates additional information (attributes) in the cart. ### updateBuyerIdentity value: `CartBuyerIdentityUpdateFunction` Updates the buyer's information in the cart. If the cart doesn't exist, a new one will be created. ### updateDiscountCodes value: `CartDiscountCodesUpdateFunction` Updates discount codes in the cart. ### updateLines value: `CartLinesUpdateFunction` Updates items in the cart. ### updateNote value: `CartNoteUpdateFunction` Updates the note in the cart. If the cart doesn't exist, a new one will be created. ### updateSelectedDeliveryOption value: `CartSelectedDeliveryOptionsUpdateFunction` Updates the selected delivery options in the cart. Only available for carts associated with a customer access token. ### CartLinesAddFunction #### Returns: Promise<CartQueryData> #### Params: - lines: CartLineInput[] - optionalParams: CartOptionalInput export type CartLinesAddFunction = ( lines: CartLineInput[], optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ### CartOptionalInput ### cartId value: `string` The cart id. ### country value: `CountryCode` The country code. ### language value: `LanguageCode` The language code. ### CartQueryData ### cart value: `Cart` ### errors value: `CartUserError[] | MetafieldsSetUserError[] | MetafieldDeleteUserError[]` ### CartCreateFunction #### Returns: Promise<CartQueryData> #### Params: - input: CartInput - optionalParams: CartOptionalInput export type CartCreateFunction = ( input: CartInput, optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ### CartMetafieldDeleteFunction #### Returns: Promise<CartQueryData> #### Params: - key: string - optionalParams: CartOptionalInput export type CartMetafieldDeleteFunction = ( key: Scalars['String']['input'], optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ### CartGetFunction #### Returns: Promise<Cart | null> #### Params: - cartInput: CartGetProps export type CartGetFunction = ( cartInput?: CartGetProps, ) => Promise<Cart | null>; ### CartGetProps ### cartId value: `string` The cart ID. ### country value: `CountryCode` The country code. ### language value: `LanguageCode` The language code. ### numCartLines value: `number` The number of cart lines to be returned. ### CartLinesRemoveFunction #### Returns: Promise<CartQueryData> #### Params: - lineIds: string[] - optionalParams: CartOptionalInput export type CartLinesRemoveFunction = ( lineIds: string[], optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ### CartMetafieldsSetFunction #### Returns: Promise<CartQueryData> #### Params: - metafields: MetafieldWithoutOwnerId[] - optionalParams: CartOptionalInput export type CartMetafieldsSetFunction = ( metafields: MetafieldWithoutOwnerId[], optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ### CartAttributesUpdateFunction #### Returns: Promise<CartQueryData> #### Params: - attributes: AttributeInput[] - optionalParams: CartOptionalInput export type CartAttributesUpdateFunction = ( attributes: AttributeInput[], optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ### CartBuyerIdentityUpdateFunction #### Returns: Promise<CartQueryData> #### Params: - buyerIdentity: CartBuyerIdentityInput - optionalParams: CartOptionalInput export type CartBuyerIdentityUpdateFunction = ( buyerIdentity: CartBuyerIdentityInput, optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ### CartDiscountCodesUpdateFunction #### Returns: Promise<CartQueryData> #### Params: - discountCodes: string[] - optionalParams: CartOptionalInput export type CartDiscountCodesUpdateFunction = ( discountCodes: string[], optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ### CartLinesUpdateFunction #### Returns: Promise<CartQueryData> #### Params: - lines: CartLineUpdateInput[] - optionalParams: CartOptionalInput export type CartLinesUpdateFunction = ( lines: CartLineUpdateInput[], optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ### CartNoteUpdateFunction #### Returns: Promise<CartQueryData> #### Params: - note: string - optionalParams: CartOptionalInput export type CartNoteUpdateFunction = ( note: string, optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ### CartSelectedDeliveryOptionsUpdateFunction #### Returns: Promise<CartQueryData> #### Params: - selectedDeliveryOptions: CartSelectedDeliveryOptionInput[] - optionalParams: CartOptionalInput export type CartSelectedDeliveryOptionsUpdateFunction = ( selectedDeliveryOptions: CartSelectedDeliveryOptionInput[], optionalParams?: CartOptionalInput, ) => Promise<CartQueryData>; ## Examples Creates an API that can be used to interact with the cart. ### Cart fragments ```js import { createCartHandler, cartGetIdDefault, cartSetIdDefault, } from '@shopify/hydrogen'; // Override cart fragments const cart = createCartHandler({ storefront, getCartId: cartGetIdDefault(request.headers), setCartId: cartSetIdDefault(), cartQueryFragment: CART_QUERY_FRAGMENT, cartMutateFragment: CART_MUTATE_FRAGMENT, }); // cartQueryFragment requirements: // - Must be named `CartApiQuery` // - Only have access to the following query variables: // - $cartId: ID! // - $country: CountryCode // - $language: LanguageCode // - $numCartLines: Int const CART_QUERY_FRAGMENT = `#graphql fragment CartApiQuery on Cart { id totalQuantity checkoutUrl note } `; // cartMutateFragment requirements: // - Must be named `CartApiMutation` // - Only have access to the following query variables: // - $cartId: ID! // - $country: CountryCode // - $language: LanguageCode const CART_MUTATE_FRAGMENT = `#graphql fragment CartApiMutation on Cart { id totalQuantity checkoutUrl lines(first: 100) { edges { node { id quantity } } } } `; ``` ### Custom methods ```js import { createCartHandler, cartGetIdDefault, cartSetIdDefault, cartLinesAddDefault, cartLinesRemoveDefault, } from '@shopify/hydrogen'; const cartQueryOptions = { storefront, getCartId: cartGetIdDefault(request.headers), }; const getCartId = cartGetIdDefault(request.headers); const cart = createCartHandler({ storefront, getCartId, setCartId: cartSetIdDefault(), customMethods: { editInLine: async (addLines, removeLineIds, optionalParams) => { // Using Hydrogen default cart query methods await cartLinesAddDefault(cartQueryOptions)(addLines, optionalParams); return await cartLinesRemoveDefault(cartQueryOptions)( removeLineIds, optionalParams, ); }, addLines: async (lines, optionalParams) => { // With your own Storefront API graphql query return await storefront.mutate(CART_LINES_ADD_MUTATION, { variables: { id: optionalParams.cartId || getCartId(), lines, }, }); }, }, }); // Use custom method editInLine that delete and add items in one method cart.editInLine( ['123'], [ { merchandiseId: 'gid://shopify/ProductVariant/456789123', quantity: 1, }, ], ); // Use overridden cart.addLines const result = await cart.addLines( [ { merchandiseId: 'gid://shopify/ProductVariant/123456789', quantity: 1, }, ], { cartId: 'c-123', }, ); // Output of result: // { // cartLinesAdd: { // cart: { // id: 'c-123', // totalQuantity: 1 // }, // errors: [] // } // } const CART_LINES_ADD_MUTATION = `#graphql mutation CartLinesAdd( $cartId: ID! $lines: [CartLineInput!]! $country: CountryCode = ZZ $language: LanguageCode ) @inContext(country: $country, language: $language) { cartLinesAdd(cartId: $cartId, lines: $lines) { cart { id totalQuantity } errors: userErrors { message field code } } } `; ``` ### Cart instance usage ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.addLines( [ { merchandiseId: 'gid://shopify/ProductVariant/123456789', quantity: 1, }, ], // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); } // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 1 // }, // errors: [] // } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.create( { lines: [ { merchandiseId: 'gid://shopify/ProductVariant/123456789', quantity: 1, }, ], discountCodes: ['FREE_SHIPPING'], }, // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 1, // discountCodes: [{ code: 'FREE_SHIPPING'}] // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.setMetafields( [ { key: 'custom.gift', type: 'boolean', value: 'true', }, ], // Optional parameters { cartId: '123', // override the cart id }, ); const result2 = await cart.deleteMetafield( 'custom.gift', // Optional parameters { cartId: '123', // override the cart id }, ); } // server.js // To query for metafields, use the `cartQueryFragment` option when creating the cart handler. import { createCartHandler, cartGetIdDefault, cartSetIdDefault, } from '@shopify/hydrogen'; const cart = createCartHandler({ storefront, getCartId: cartGetIdDefault(request.headers), setCartId: cartSetIdDefault(), cartQueryFragment: CART_QUERY_FRAGMENT, }); const CART_QUERY_FRAGMENT = `#graphql fragment CartApiQuery on Cart { id metafields( identifiers: [{ namespace: "custom", key: "gift" ]) { namespace key type value } } `; ``` ```js export async function loader({context}) { const {cart} = context; // Usage const result = await cart.get(); // Optional parameters const result2 = await cart.get({ cartId: '123', // override the cart id numCartLines: 50, //override to return 50 cart lines country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }); } ``` ```js export async function loader({context}) { // Usage context.cart.getCartId(); // 'gid://shopify/Cart/123' } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.removeLines( ['123'], // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 0 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; const result = await cart.addLines([ { merchandiseId: 'gid://shopify/ProductVariant/123456789', quantity: 1, }, ]); // Usage const headers = cart.setCartId(result.cart.id); } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.setMetafields( [ { key: 'custom.gift', type: 'boolean', value: 'true', }, ], // Optional parameters { cartId: '123', // override the cart id }, ); const result2 = await cart.deleteMetafield( 'custom.gift', // Optional parameters { cartId: '123', // override the cart id }, ); } // server.js // To query for metafields, use the `cartQueryFragment` option when creating the cart handler. import { createCartHandler, cartGetIdDefault, cartSetIdDefault, } from '@shopify/hydrogen'; const cart = createCartHandler({ storefront, getCartId: cartGetIdDefault(request.headers), setCartId: cartSetIdDefault(), cartQueryFragment: CART_QUERY_FRAGMENT, }); const CART_QUERY_FRAGMENT = `#graphql fragment CartApiQuery on Cart { id metafields( identifiers: [{ namespace: "custom", key: "gift" ]) { namespace key type value } } `; ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateAttributes( [ { key: 'Somekey', value: '1', }, ], // Optional parameters { cartId: '123', // override the cart id }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 1 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateBuyerIdentity( { customerAccessToken: '123', }, // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 1 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateDiscountCodes( ['FREE_SHIPPING'], // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 1 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateLines( [ { merchandiseId: 'gid://shopify/ProductVariant/123456789', quantity: 2, }, ], // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 2 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateNote( 'Some notes', // Optional parameters { cartId: '123', // override the cart id }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 0 // }, // errors: [] // } } ``` ```js export async function action({context}) { const {cart} = context; // Usage const result = await cart.updateSelectedDeliveryOptions( [ { deliveryGroupId: '123', deliveryOptionHandle: 'Canada Post', }, ], // Optional parameters { cartId: '123', // override the cart id country: 'US', // override the country code to 'US' language: 'EN', // override the language code to 'EN' }, ); // Output of result: // { // cart: { // id: 'c1-123', // totalQuantity: 2 // }, // errors: [] // } } ```