Manage a shopping cart with Vercel KV and Grafbase

JosepJosep
Manage a shopping cart with Vercel KV and Grafbase

Resolvers in Grafbase allow you to extend the functionality of your GraphQL API. With resolvers, you can execute custom logic, integrate external services, and manipulate data. In this guide, we will explore how to use Vercel KV, a key-value store provided by Vercel, to store and retrieve an e-commerce cart in Grafbase resolvers.

The shopping cart in an ecommerce fit perfectly the use-case for a key-value database, you can persist the cart between user devices (browser, desktop), without polluting or adding extra load to the database.

Before we begin, ensure that you have the following set up:

  • A Grafbase project with the necessary dependencies installed.
  • An active Vercel account.

To use Vercel KV in your Grafbase project, you need to install the @vercel/kv library. Follow these steps to install the library:

  1. Open your terminal or command prompt.
  2. Navigate to your Grafbase project directory.
  3. Run the following command:
npm install @vercel/kv

The @vercel/kv library is now installed and ready to use in your Grafbase project.

To get started Vercel has a great quick-start, on you have completed the steps, remember to run:

vercel env pull .env

And check that your .env file has the required environment variables defined:

KV_URL
KV_REST_API_URL
KV_REST_API_TOKEN
KV_REST_API_READ_ONLY_TOKEN

Now that you have the Vercel KV created and configured, you can integrate it with your e-commerce app to manage the shopping cart. Here's an example of how you can implement cart retrieval:

  1. Create a new resolver file, e.g., grafbase/resolvers/cart.js, and define the resolver function:
import { createClient } from '@vercel/kv'

export default async function Resolver(_, { userId }) {
  const kv = createClient({
    url: process.env.USERS_REST_API_URL,
    token: process.env.VERCEL_TOKEN,
  })

  const cartKey = 'cart:' + userId

  // Retrieve the cart from Vercel KV
  const cart = await kv.get(cartKey)

  // Manipulate the cart data as needed
  // ...

  return cart
}
  1. Add another resolver file, grafbase/resolvers/update-cart.js, and define the resolver function:
import { createClient } from '@vercel/kv'

export default async function Resolver(_, { userId, items }) {
  const kv = createClient({
    url: process.env.USERS_REST_API_URL,
    token: process.env.VERCEL_TOKEN,
  })

  const cartKey = 'cart:' + userId

  // Store the items object a string
  const cart = await kv.set(cartKey, JSON.stringify(items))

  return cart
}
  1. Create the grafbase/schema.graphql file with the resolvers and the cart type:
extend type Query {
  cart(userId: ID!): Cart! @resolver(name: "cart")
}

extend type Mutation {
  updateCart(userId: ID!, items: [CartItem!]!): Cart!
    @resolver(name: "update-cart")
}

type CartItem {
  productId: String!
  quantity: Int!
}

type Cart {
  items: [CartItem!]!
}
  1. Start the Grafbase development server:
npx grafbase dev

Now you can interact with the GraphQL API and use the cart query and the update-cart mutation to retrieve and update the cart for a specific user.

Here is a React example, leveraging graphql-request, that updates the shopping cart locally and in the KV store:

import React, { useState } from 'react'
import { GraphQLClient, gql } from 'graphql-request'

const endpoint = process.env.GRAFBASE_API_URL

const client = new GraphQLClient(endpoint, {
  headers: {
    'x-api-key': process.env.GRAFBASE_API_KEY,
  },
})

const UPDATE_CART_MUTATION = gql`
  mutation UpdateCart($userId: ID!, $items: [CartItem!]!) {
    updateCart(userId: $userId, items: $items) {
      items {
        productId
        quantity
      }
    }
  }
`

const Cart = ({ userId }) => {
  const [cartItems, setCartItems] = useState([])

  const handleAddToCart = async () => {
    const newItem = {
      productId: 'exampleProductId',
      quantity: 1,
    }

    const updatedItems = [...cartItems, newItem]
    setCartItems(updatedItems)

    try {
      const response = client.request(UPDATE_CART_MUTATION, {
        userId,
        items: updatedItems,
      })

      const updatedCartItems = response.updateCart.items
      setCartItems(updatedCartItems)
    } catch (error) {
      console.error('Failed to update cart:', error)
    }
  }

  return (
    <div>
      <h2>Cart</h2>
      <ul>
        {cartItems.map((item, index) => (
          <li key={index}>
            Product ID: {item.productId} - Quantity: {item.quantity}
          </li>
        ))}
      </ul>
      <button onClick={handleAddToCart}>Add to Cart</button>
    </div>
  )
}

export default Cart

Congratulations! You've learned how to integrate Vercel KV with Grafbase resolvers to store and retrieve an e-commerce cart. By leveraging Vercel KV, you can provide a scalable and persistent storage solution for your e-commerce application. Feel free to explore more features and adapt the cart management logic to suit your specific requirements.

Remember to refer to the Vercel KV documentation for more details on using the library and managing your KV store. Happy coding!

Get Started

Start building your backend of the future now.