4
0
forked from crowetic/commerce

Added handlers for the cart API

This commit is contained in:
Luis Alvarez 2020-10-11 00:58:57 -05:00
parent 1c3714bf51
commit f1b9ea605e
5 changed files with 138 additions and 107 deletions

View File

@ -0,0 +1,37 @@
import parseItem from '../../utils/parse-item'
import getCartCookie from '../../utils/get-cart-cookie'
import type { CartHandlers } from '..'
// Return current cart info
const addItem: CartHandlers['addItem'] = async ({
res,
body: { cartId, item },
config,
}) => {
if (!item) {
return res.status(400).json({
data: null,
errors: [{ message: 'Missing item' }],
})
}
if (!item.quantity) item.quantity = 1
const options = {
method: 'POST',
body: JSON.stringify({
line_items: [parseItem(item)],
}),
}
const { data } = cartId
? await config.storeApiFetch(`/v3/carts/${cartId}/items`, options)
: await config.storeApiFetch('/v3/carts', options)
// Create or update the cart cookie
res.setHeader(
'Set-Cookie',
getCartCookie(config.cartCookie, data.id, config.cartCookieMaxAge)
)
res.status(200).json({ data })
}
export default addItem

View File

@ -0,0 +1,34 @@
import getCartCookie from '../../utils/get-cart-cookie'
import type { CartHandlers } from '..'
// Return current cart info
const removeItem: CartHandlers['removeItem'] = async ({
res,
body: { cartId, itemId },
config,
}) => {
if (!cartId || !itemId) {
return res.status(400).json({
data: null,
errors: [{ message: 'Invalid request' }],
})
}
const result = await config.storeApiFetch<{ data: any } | null>(
`/v3/carts/${cartId}/items/${itemId}`,
{ method: 'DELETE' }
)
const data = result?.data ?? null
res.setHeader(
'Set-Cookie',
data
? // Update the cart cookie
getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge)
: // Remove the cart cookie if the cart was removed (empty items)
getCartCookie(config.cartCookie)
)
res.status(200).json({ data })
}
export default removeItem

View File

@ -0,0 +1,36 @@
import parseItem from '../../utils/parse-item'
import getCartCookie from '../../utils/get-cart-cookie'
import type { CartHandlers } from '..'
// Return current cart info
const updateItem: CartHandlers['updateItem'] = async ({
res,
body: { cartId, itemId, item },
config,
}) => {
if (!cartId || !itemId || !item) {
return res.status(400).json({
data: null,
errors: [{ message: 'Invalid request' }],
})
}
const { data } = await config.storeApiFetch(
`/v3/carts/${cartId}/items/${itemId}`,
{
method: 'PUT',
body: JSON.stringify({
line_item: parseItem(item),
}),
}
)
// Update the cart cookie
res.setHeader(
'Set-Cookie',
getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge)
)
res.status(200).json({ data })
}
export default updateItem

View File

@ -1,4 +1,3 @@
import { serialize, CookieSerializeOptions } from 'cookie'
import isAllowedMethod from '../utils/is-allowed-method'
import createApiHandler, {
BigcommerceApiHandler,
@ -6,6 +5,9 @@ import createApiHandler, {
} from '../utils/create-api-handler'
import { BigcommerceApiError } from '../utils/errors'
import getCart from './handlers/get-cart'
import addItem from './handlers/add-item'
import updateItem from './handlers/update-item'
import removeItem from './handlers/remove-item'
type Body<T> = Partial<T> | undefined
@ -44,6 +46,15 @@ export type Cart = {
export type CartHandlers = {
getCart: BigcommerceHandler<Cart, { cartId?: string }>
addItem: BigcommerceHandler<Cart, { cartId?: string } & Body<AddItemBody>>
updateItem: BigcommerceHandler<
Cart,
{ cartId?: string } & Body<UpdateItemBody>
>
removeItem: BigcommerceHandler<
Cart,
{ cartId?: string } & Body<RemoveItemBody>
>
}
const METHODS = ['GET', 'POST', 'PUT', 'DELETE']
@ -63,97 +74,26 @@ const cartApi: BigcommerceApiHandler<Cart, CartHandlers> = async (
try {
// Return current cart info
if (req.method === 'GET') {
return await handlers['getCart']({ req, res, config, body: { cartId } })
const body = { cartId }
return await handlers['getCart']({ req, res, config, body })
}
// Create or add an item to the cart
if (req.method === 'POST') {
const { item } = (req.body as Body<AddItemBody>) ?? {}
if (!item) {
return res.status(400).json({
data: null,
errors: [{ message: 'Missing item' }],
})
}
if (!item.quantity) item.quantity = 1
const options = {
method: 'POST',
body: JSON.stringify({
line_items: [parseItem(item)],
}),
}
const { data } = cartId
? await config.storeApiFetch(`/v3/carts/${cartId}/items`, options)
: await config.storeApiFetch('/v3/carts', options)
// Create or update the cart cookie
res.setHeader(
'Set-Cookie',
getCartCookie(config.cartCookie, data.id, config.cartCookieMaxAge)
)
return res.status(200).json({ data })
const body = { cartId, ...req.body }
return await handlers['addItem']({ req, res, config, body })
}
// Update item in cart
if (req.method === 'PUT') {
const { itemId, item } = (req.body as Body<UpdateItemBody>) ?? {}
if (!cartId || !itemId || !item) {
return res.status(400).json({
data: null,
errors: [{ message: 'Invalid request' }],
})
}
const { data } = await config.storeApiFetch(
`/v3/carts/${cartId}/items/${itemId}`,
{
method: 'PUT',
body: JSON.stringify({
line_item: parseItem(item),
}),
}
)
// Update the cart cookie
res.setHeader(
'Set-Cookie',
getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge)
)
return res.status(200).json({ data })
const body = { cartId, ...req.body }
return await handlers['updateItem']({ req, res, config, body })
}
// Remove an item from the cart
if (req.method === 'DELETE') {
const { itemId } = (req.body as Body<RemoveItemBody>) ?? {}
if (!cartId || !itemId) {
return res.status(400).json({
data: null,
errors: [{ message: 'Invalid request' }],
})
}
const result = await config.storeApiFetch<{ data: any } | null>(
`/v3/carts/${cartId}/items/${itemId}`,
{ method: 'DELETE' }
)
const data = result?.data ?? null
res.setHeader(
'Set-Cookie',
data
? // Update the cart cookie
getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge)
: // Remove the cart cookie if the cart was removed (empty items)
getCartCookie(config.cartCookie)
)
return res.status(200).json({ data })
const body = { cartId, ...req.body }
return await handlers['removeItem']({ req, res, config, body })
}
} catch (error) {
console.error(error)
@ -167,31 +107,6 @@ const cartApi: BigcommerceApiHandler<Cart, CartHandlers> = async (
}
}
function getCartCookie(name: string, cartId?: string, maxAge?: number) {
const options: CookieSerializeOptions =
cartId && maxAge
? {
maxAge,
expires: new Date(Date.now() + maxAge * 1000),
secure: process.env.NODE_ENV === 'production',
path: '/',
sameSite: 'lax',
}
: { maxAge: -1, path: '/' } // Removes the cookie
export const handlers = { getCart, addItem, updateItem, removeItem }
return serialize(name, cartId || '', options)
}
const parseItem = (item: ItemBody) => ({
quantity: item.quantity,
product_id: item.productId,
variant_id: item.variantId,
})
const handlers = {
getCart,
}
const h = createApiHandler(cartApi, handlers)
export default h
export default createApiHandler(cartApi, handlers)

View File

@ -0,0 +1,9 @@
import type { ItemBody } from '../cart'
const parseItem = (item: ItemBody) => ({
quantity: item.quantity,
product_id: item.productId,
variant_id: item.variantId,
})
export default parseItem