Shopify / hydrogen

Hydrogen lets you build faster headless storefronts in less time, on Shopify.
https://hydrogen.shop
MIT License
1.44k stars 273 forks source link

`cartQueryFragment` returns metafield-referenced product variants that are not in Hydrogen channel #2177

Open cmhnk opened 5 months ago

cmhnk commented 5 months ago

What is the location of your example repository?

No response

Which package or tool is having this issue?

Hydrogen

What version of that package or tool are you using?

2024.04

What version of Remix are you using?

2.9.2

Steps to Reproduce

  1. In the Shopify admin, create a metafield on a ProductVariant which references a list of ProductVariants. In this example, it's called custom.worn-with.
image
  1. Set up two products, Product A and Product B, each with a single ProductVariant. Product A is in the Hydrogen channel; Product B is not in the Hydrogen channel.

  2. Go to Product A's variant, and add Product B's variant to the worn-with metafield.

  3. Use the createCartHandler function with the cartQueryFragment to retrieve the worn-with metafield for every line item in cart.

server.ts


   ...

export const WORN_WITH_METAFIELD = `
  metafield(namespace: "custom", key: "worn_with") {
    references(first: 10) {
      edges {
        node {
          ... on ProductVariant {
            id
            selectedOptions {
              name
              value
            }
            product {
              id
              variants(first: 100) {
                nodes {
                  id
                  availableForSale
                  selectedOptions {
                    name
                    value
                  }
                }
              }
            }
          }
        }
      }
    }
  }
`

const CART_QUERY_FRAGMENT = `#graphql
  fragment CartApiQuery on Cart {
    id
    checkoutUrl
    totalQuantity
    buyerIdentity {
      countryCode
      customer {
        id
      }
    }
    lines(first: $numCartLines) {
      edges {
        node {
          id
          quantity
          merchandise {
            ... on ProductVariant {
              id
              product {
                handle
                title
                id
                variants(first: 100) {
                  nodes {
                    ...WornWithVariants
                  }
                }
              }
              selectedOptions {
                name
                value
              }
            }
          }
        }
      }
    }
  ${WORN_WITH_VARIANTS_FRAGMENT}
`;

export const WORN_WITH_VARIANTS_FRAGMENT = `#graphql
  fragment WornWithVariants on ProductVariant {
    ${WORN_WITH_METAFIELD}
  }
`;

/**
 * Create Cart
 */
const cart = createCartHandler({
  storefront,
  getCartId: cartGetIdDefault(request.headers),
  setCartId: cartSetIdDefault({
    maxage: 60 * 60 * 24 * 365, // 1 year expiry
  }),
  cartQueryFragment: CART_QUERY_FRAGMENT
});
  1. Add Product A's variant to cart.

Expected Behavior

Product B's variant should not be returned when calling cart.get() because it is not in the Hydrogen channel.

Actual Behavior

Product B's variant is being returned when calling cart.get(), even though it is not in the Hydrogen channel.

wizardlyhel commented 5 months ago

If you didn't have Product B published to Hydrogen Channel, you shouldn't even able to get the product as part of any products / collection query.

Double check the access token you are using to make the storefront query and make sure that it is indeed the token assigned by the Hydrogen channel (you can see the value of PUBLIC_STOREFRONT_API_TOKEN in the Hydrogen storefront environment variable section)