Shopify / js-buy-sdk

The JS Buy SDK is a lightweight library that allows you to build ecommerce into any website. It is based on Shopify's API and provides the ability to retrieve products and collections from your shop, add products to a cart, and checkout.
https://shopify.github.io/js-buy-sdk
MIT License
984 stars 259 forks source link

Plans to support new cart mutations? #862

Open mattrosno opened 2 years ago

mattrosno commented 2 years ago

I see that this SDK upgraded to the Storefront API version 2021-10 recently. Source: https://github.com/Shopify/js-buy-sdk/blob/master/CHANGELOG.md#v2130-october-28-2021

I'm looking to add subscriptions to my headless site. Per the Shopify docs, that requires you to use the new cart workflow instead of the legacy checkout workflow. Source: https://shopify.dev/custom-storefronts/products/subscriptions#limitations-and-considerations

Are there plans to add the new cart mutations like cartCreate, cartLinesUpdate, etc.?

awesome-swagger commented 2 years ago

Hi @mattrosno

you can use this query

cartLinesAdd(lines: $lines, cartId: $cartId) {
      cart {
        id
        checkoutUrl
        createdAt
        updatedAt
        lines(first:10) {
          edges {
            node {
              id
              quantity
              merchandise {
                __typename
                ... on ProductVariant {
                  id
                  product {
                    id
                    productType
                    title
                    vendor
                    variants(first: 10) {
                      edges {
                        node {
                          id
                          title
                          sku
                        }
                      }
                    }
                  }
                }
              }
              sellingPlanAllocation {
                sellingPlan {
                  id
                  name
                }
                priceAdjustments {
                  price {
                    amount
                  }
                  compareAtPrice {
                    amount
                  }
                  perDeliveryPrice {
                    amount
                  }
                }
              }
            }
          }
        }
        estimatedCost {
          totalAmount {
            amount
            currencyCode
          }
          subtotalAmount {
            amount
            currencyCode
          }
          totalTaxAmount {
            amount
            currencyCode
          }
          totalDutyAmount {
            amount
            currencyCode
          }
        }
        buyerIdentity {
          email
          phone
          customer {
            id
          }
          countryCode
        }
      }
      userErrors {
        code
        field
        message
      }
    }
  }
nandorojo commented 2 years ago

Wondering the same thing here.

raRaRa commented 2 years ago

Hi @mattrosno

you can use this query

cartLinesAdd(lines: $lines, cartId: $cartId) {
      cart {
        id
        checkoutUrl
        createdAt
        updatedAt
        lines(first:10) {
          edges {
            node {
              id
              quantity
              merchandise {
                __typename
                ... on ProductVariant {
                  id
                  product {
                    id
                    productType
                    title
                    vendor
                    variants(first: 10) {
                      edges {
                        node {
                          id
                          title
                          sku
                        }
                      }
                    }
                  }
                }
              }
              sellingPlanAllocation {
                sellingPlan {
                  id
                  name
                }
                priceAdjustments {
                  price {
                    amount
                  }
                  compareAtPrice {
                    amount
                  }
                  perDeliveryPrice {
                    amount
                  }
                }
              }
            }
          }
        }
        estimatedCost {
          totalAmount {
            amount
            currencyCode
          }
          subtotalAmount {
            amount
            currencyCode
          }
          totalTaxAmount {
            amount
            currencyCode
          }
          totalDutyAmount {
            amount
            currencyCode
          }
        }
        buyerIdentity {
          email
          phone
          customer {
            id
          }
          countryCode
        }
      }
      userErrors {
        code
        field
        message
      }
    }
  }

Can you use custom queries in the JS Buy SDK, or would you call this with a different client? Also, how would you map it to a ShopifyBuy.Cart?

sshaw commented 2 years ago

Can you use custom queries in the JS Buy SDK, or would you call this with a different client?

You may be able to do it via Buy SDK, but it is not straightforward. I tried to do this for a product's metafields and variants and gave up. Not a clean solution really. Instead I installed graphql-request.

Also, how would you map it to a ShopifyBuy.Cart?

What is the upside to the ShopifyBuy.Cart type? Just call the mutation directly.

The more I use GQL the more I realize all you should be using is something that sends queries and mutations. Really these additional abstractions defeat the purpose of GraphQL by providing a set of default fields.

dmytro-kushnir commented 2 years ago

Probably worth it to contribute to this SKD with the Cart methods: https://shopify.dev/api/storefront/2022-04/objects/Cart#top

So we can omit manual mutations?

raRaRa commented 2 years ago

I ended up writing my own GraphQL queries, this library is too limited for subscriptions.

dmytro-kushnir commented 2 years ago

сan you show how we can accomplish such queries, @raRaRa ? For example for : cartLinesAdd

raRaRa commented 2 years ago

Sure, here's an example:

export async function addCartLines(
  cartId: string,
  lines: ShopifyAddCartLineType[],
): Promise<ICartSession> {
  const res = await sendShopifyStorefrontRequestext({
    query: `
    mutation cartLinesAddMutation($cartId: ID!, $lines: [CartLineInput!]!) {
      cartLinesAdd(cartId: $cartId, lines: $lines) {
        cart {
          ${shopifyCartFields}
        }
        userErrors {
          field
          message
        }
      }
    }
    `,
    variables: {
      cartId,
      lines,
    },
  });

  const { data } = res;
  return data.cartLinesAdd.cart;
}

Please note that ${shopifyCartFields} is basically the fields you want Shopify to return for the cart after adding items to the cart.

And here's how I add subscription to the cart:

await addCartLines(cartId, [
  {
    merchandiseId: selectedVariant.id,
    quantity: quantity,
    sellingPlanId: sellingPlanId,
  },
]);

selectedVariant.id is basically the id of the product variant.

Finally here's how I make a request to Shopify:

export async function sendShopifyStorefrontRequestext({
  query,
  variables,
}: any) {
  try {
    const res = await axios.post(
      `https://${process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN}/api/2022-04/graphql.json`,
      JSON.stringify({ query, variables }),
      {
        headers: {
          "X-Shopify-Storefront-Access-Token":
            process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN || "",
          "Content-Type": "application/json",
        },
      },
    );

    return res.data;
  } catch (err) {
    console.log(err);
    return null;
  }
}

Hope this helps.

dmytro-kushnir commented 2 years ago

yeah, thanks, @raRaRa , I will try it out. Probably it will be easier to create such Proxy client instead of contributing and modifying existent Shopify JS SDK

dmytro-kushnir commented 2 years ago

hello guys. Have anybody experienced the issue that Carts created from Storefront API are not visible in the shop store?

And vice versa, cards that are created in the shop or via AJAX API can't be found by storefront cart API.

vixdug commented 1 year ago

@dmytro-kushnir We are working on the functionality to share carts between Ajax and Storefront API cart. I'd love to learn more about your use case and get you to test it out with our first release if you are interested!

dmytro-kushnir commented 1 year ago

Hey @vixdug We're working on integrating Storefront Cart Api into our site and trying to sync it via a subdomain-less cookie with the main shop site (which uses Ajax as far as I understand), And they can't see each other.

I created a ticket with more details some time ago: https://community.shopify.com/c/storefront-api-and-sdks/shopify-storefront-cart-api-shop-can-t-see-created-carts/td-p/1600948.

We would like to have a demo and test this release, yeah.