mirror of
https://github.com/vercel/commerce.git
synced 2025-05-17 23:16:59 +00:00
Add cart endpoints/handlers
Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
parent
50f99e907a
commit
1b2904ac1f
66
packages/opencommerce/src/api/endpoints/cart/add-item.ts
Normal file
66
packages/opencommerce/src/api/endpoints/cart/add-item.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { normalizeCart } from '../../../utils/normalize'
|
||||||
|
import getCartCookie from '../../utils/get-cart-cookie'
|
||||||
|
import addCartItemsMutation from '../../mutations/add-cart-item'
|
||||||
|
import createCartMutation from '../../mutations/create-cart'
|
||||||
|
|
||||||
|
import type { CartEndpoint } from '.'
|
||||||
|
import { CreateCartPayload } from '../../../../schema'
|
||||||
|
|
||||||
|
const addItem: CartEndpoint['handlers']['addItem'] = async ({
|
||||||
|
res,
|
||||||
|
body: { cartId, item },
|
||||||
|
config,
|
||||||
|
req: { cookies },
|
||||||
|
}) => {
|
||||||
|
if (!item) {
|
||||||
|
return res.status(400).json({
|
||||||
|
data: null,
|
||||||
|
errors: [{ message: 'Missing item' }],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (!item.quantity) item.quantity = 1
|
||||||
|
|
||||||
|
const variables = {
|
||||||
|
input: {
|
||||||
|
shopId: config.shopId,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
productConfiguration: {
|
||||||
|
productId: item.productId,
|
||||||
|
productVariantId: item.variantId,
|
||||||
|
},
|
||||||
|
quantity: item.quantity,
|
||||||
|
price: item.price,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cartId) {
|
||||||
|
const { data } = await config.fetch(createCartMutation, { variables })
|
||||||
|
res.setHeader('Set-Cookie', [
|
||||||
|
getCartCookie(config.cartCookie, data.cart._id, config.cartCookieMaxAge),
|
||||||
|
getCartCookie(
|
||||||
|
config.anonymousCartTokenCookie,
|
||||||
|
data.token,
|
||||||
|
config.cartCookieMaxAge
|
||||||
|
),
|
||||||
|
])
|
||||||
|
|
||||||
|
return res.status(200).json({ data: normalizeCart(data.cart) })
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await config.fetch(addCartItemsMutation, {
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
items: variables.input.items,
|
||||||
|
cartId,
|
||||||
|
cartToken: cookies[config.anonymousCartTokenCookie],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return res.status(200).json({ data: normalizeCart(data.cart) })
|
||||||
|
}
|
||||||
|
|
||||||
|
export default addItem
|
31
packages/opencommerce/src/api/endpoints/cart/get-cart.ts
Normal file
31
packages/opencommerce/src/api/endpoints/cart/get-cart.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { normalizeCart } from '../../../utils/normalize'
|
||||||
|
import getCartCookie from '../../utils/get-cart-cookie'
|
||||||
|
import getAnonymousCart from '../../queries/get-anonymous-cart'
|
||||||
|
import type { CartEndpoint } from '.'
|
||||||
|
|
||||||
|
// Return current cart info
|
||||||
|
const getCart: CartEndpoint['handlers']['getCart'] = async ({
|
||||||
|
res,
|
||||||
|
req: { cookies },
|
||||||
|
body: { cartId },
|
||||||
|
config,
|
||||||
|
}) => {
|
||||||
|
if (cartId && cookies[config.anonymousCartTokenCookie]) {
|
||||||
|
const { data } = await config.fetch(getAnonymousCart, {
|
||||||
|
variables: {
|
||||||
|
cartId,
|
||||||
|
cartToken: cookies[config.anonymousCartTokenCookie],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
data: normalizeCart(data),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
data: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getCart
|
@ -1 +1,26 @@
|
|||||||
export default function noopApi(...args: any[]): void {}
|
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||||
|
import cartEndpoint from '@vercel/commerce/api/endpoints/cart'
|
||||||
|
import type { CartSchema } from '../../../types/cart'
|
||||||
|
import type { OpenCommerceAPI } from '../../index'
|
||||||
|
import getCart from './get-cart'
|
||||||
|
import addItem from './add-item'
|
||||||
|
import updateItem from './update-item'
|
||||||
|
import removeItem from './remove-item'
|
||||||
|
|
||||||
|
export type CartAPI = GetAPISchema<OpenCommerceAPI, CartSchema>
|
||||||
|
|
||||||
|
export type CartEndpoint = CartAPI['endpoint']
|
||||||
|
|
||||||
|
export const handlers: CartEndpoint['handlers'] = {
|
||||||
|
addItem,
|
||||||
|
getCart,
|
||||||
|
updateItem,
|
||||||
|
removeItem,
|
||||||
|
}
|
||||||
|
|
||||||
|
const cartApi = createEndpoint<CartAPI>({
|
||||||
|
handler: cartEndpoint,
|
||||||
|
handlers,
|
||||||
|
})
|
||||||
|
|
||||||
|
export default cartApi
|
||||||
|
37
packages/opencommerce/src/api/endpoints/cart/remove-item.ts
Normal file
37
packages/opencommerce/src/api/endpoints/cart/remove-item.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { normalizeCart } from '../../../utils/normalize'
|
||||||
|
import getCartCookie from '../../utils/get-cart-cookie'
|
||||||
|
import removeCartItemsMutation from '../../mutations/remove-cart-item'
|
||||||
|
import type { CartEndpoint } from '.'
|
||||||
|
|
||||||
|
const removeItem: CartEndpoint['handlers']['removeItem'] = async ({
|
||||||
|
res,
|
||||||
|
body: { cartId, itemId },
|
||||||
|
config,
|
||||||
|
req: { cookies },
|
||||||
|
}) => {
|
||||||
|
if (!cartId || !itemId) {
|
||||||
|
return res.status(400).json({
|
||||||
|
data: null,
|
||||||
|
errors: [{ message: 'Invalid request' }],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await config.fetch(removeCartItemsMutation, {
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
cartId,
|
||||||
|
cartItemIds: [itemId],
|
||||||
|
cartToken: cookies[config.anonymousCartTokenCookie],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
res.setHeader(
|
||||||
|
'Set-Cookie',
|
||||||
|
getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge)
|
||||||
|
)
|
||||||
|
|
||||||
|
res.status(200).json({ data: normalizeCart(data.cart) })
|
||||||
|
}
|
||||||
|
|
||||||
|
export default removeItem
|
37
packages/opencommerce/src/api/endpoints/cart/update-item.ts
Normal file
37
packages/opencommerce/src/api/endpoints/cart/update-item.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { normalizeCart } from '../../../utils/normalize'
|
||||||
|
import getCartCookie from '../../utils/get-cart-cookie'
|
||||||
|
import updateCartItemsQuantityMutation from '../../mutations/update-cart-item-quantity'
|
||||||
|
import type { CartEndpoint } from '.'
|
||||||
|
|
||||||
|
const updateItem: CartEndpoint['handlers']['updateItem'] = async ({
|
||||||
|
res,
|
||||||
|
body: { cartId, itemId, item },
|
||||||
|
config,
|
||||||
|
req: { cookies },
|
||||||
|
}) => {
|
||||||
|
if (!cartId || !itemId || !item) {
|
||||||
|
return res.status(400).json({
|
||||||
|
data: null,
|
||||||
|
errors: [{ message: 'Invalid request' }],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await config.fetch(updateCartItemsQuantityMutation, {
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
cartId,
|
||||||
|
cartToken: cookies[config.anonymousCartTokenCookie],
|
||||||
|
items: [{ cartItemId: itemId, quantity: item.quantity }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Update the cart cookie
|
||||||
|
res.setHeader(
|
||||||
|
'Set-Cookie',
|
||||||
|
getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge)
|
||||||
|
)
|
||||||
|
res.status(200).json({ data: normalizeCart(data.cart) })
|
||||||
|
}
|
||||||
|
|
||||||
|
export default updateItem
|
@ -18,6 +18,7 @@ if (!API_URL) {
|
|||||||
|
|
||||||
export interface OpenCommerceConfig extends CommerceAPIConfig {
|
export interface OpenCommerceConfig extends CommerceAPIConfig {
|
||||||
shopId: string
|
shopId: string
|
||||||
|
anonymousCartTokenCookie: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const ONE_DAY = 60 * 60 * 24
|
const ONE_DAY = 60 * 60 * 24
|
||||||
@ -29,6 +30,7 @@ const config: OpenCommerceConfig = {
|
|||||||
customerCookie: 'opencommerce_customerToken',
|
customerCookie: 'opencommerce_customerToken',
|
||||||
cartCookie: 'opencommerce_cartId',
|
cartCookie: 'opencommerce_cartId',
|
||||||
cartCookieMaxAge: ONE_DAY * 30,
|
cartCookieMaxAge: ONE_DAY * 30,
|
||||||
|
anonymousCartTokenCookie: 'opencommerce_anonymousCartToken',
|
||||||
fetch: createFetchGraphqlApi(() => getCommerceApi().getConfig()),
|
fetch: createFetchGraphqlApi(() => getCommerceApi().getConfig()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
packages/opencommerce/src/api/mutations/add-cart-item.ts
Normal file
24
packages/opencommerce/src/api/mutations/add-cart-item.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import {
|
||||||
|
cartPayloadFragment,
|
||||||
|
incorrectPriceFailureDetailsFragment,
|
||||||
|
minOrderQuantityFailureDetailsFragment,
|
||||||
|
} from '../queries/get-cart-query'
|
||||||
|
|
||||||
|
const addCartItemsMutation = /* GraphQL */ `
|
||||||
|
mutation addCartItemsMutation($input: AddCartItemsInput!) {
|
||||||
|
addCartItems(input: $input) {
|
||||||
|
cart {
|
||||||
|
${cartPayloadFragment}
|
||||||
|
}
|
||||||
|
incorrectPriceFailures {
|
||||||
|
${incorrectPriceFailureDetailsFragment}
|
||||||
|
}
|
||||||
|
minOrderQuantityFailures {
|
||||||
|
${minOrderQuantityFailureDetailsFragment}
|
||||||
|
}
|
||||||
|
clientMutationId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default addCartItemsMutation
|
24
packages/opencommerce/src/api/mutations/create-cart.ts
Normal file
24
packages/opencommerce/src/api/mutations/create-cart.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import {
|
||||||
|
cartPayloadFragment,
|
||||||
|
incorrectPriceFailureDetailsFragment,
|
||||||
|
minOrderQuantityFailureDetailsFragment,
|
||||||
|
} from '../queries/get-cart-query'
|
||||||
|
|
||||||
|
const createCartMutation = /* GraphQL */ `
|
||||||
|
mutation createCartMutation($input: CreateCartInput!) {
|
||||||
|
createCart(input: $input) {
|
||||||
|
cart {
|
||||||
|
${cartPayloadFragment}
|
||||||
|
}
|
||||||
|
incorrectPriceFailures {
|
||||||
|
${incorrectPriceFailureDetailsFragment}
|
||||||
|
}
|
||||||
|
minOrderQuantityFailures {
|
||||||
|
${minOrderQuantityFailureDetailsFragment}
|
||||||
|
}
|
||||||
|
clientMutationId
|
||||||
|
token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
export default createCartMutation
|
13
packages/opencommerce/src/api/mutations/remove-cart-item.ts
Normal file
13
packages/opencommerce/src/api/mutations/remove-cart-item.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { cartPayloadFragment } from '../queries/get-cart-query'
|
||||||
|
|
||||||
|
const removeCartItemsMutation = `
|
||||||
|
mutation removeCartItemsMutation($input: RemoveCartItemsInput!) {
|
||||||
|
removeCartItems(input: $input) {
|
||||||
|
cart {
|
||||||
|
${cartPayloadFragment}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default removeCartItemsMutation
|
@ -0,0 +1,13 @@
|
|||||||
|
import { cartPayloadFragment } from '../queries/get-cart-query'
|
||||||
|
|
||||||
|
const updateCartItemsQuantityMutation = `
|
||||||
|
mutation updateCartItemsQuantity($updateCartItemsQuantityInput: UpdateCartItemsQuantityInput!) {
|
||||||
|
updateCartItemsQuantity(input: $updateCartItemsQuantityInput) {
|
||||||
|
cart {
|
||||||
|
${cartPayloadFragment}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default updateCartItemsQuantityMutation
|
11
packages/opencommerce/src/api/queries/get-anonymous-cart.ts
Normal file
11
packages/opencommerce/src/api/queries/get-anonymous-cart.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { cartQueryFragment } from './get-cart-query'
|
||||||
|
|
||||||
|
export const getAnonymousCart = /* GraphQL */ `
|
||||||
|
query anonymousCartByCartIdQuery($cartId: ID!, $cartToken: String!) {
|
||||||
|
cart: anonymousCartByCartId(cartId: $cartId, cartToken: $cartToken) {
|
||||||
|
${cartQueryFragment}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default getAnonymousCart
|
@ -0,0 +1,11 @@
|
|||||||
|
import { cartQueryFragment } from './get-cart-query'
|
||||||
|
|
||||||
|
const accountCartByAccountIdQuery = `
|
||||||
|
query accountCartByAccountIdQuery($accountId: ID!, $shopId: ID!, $itemsAfterCursor: ConnectionCursor) {
|
||||||
|
cart: accountCartByAccountId(accountId: $accountId, shopId: $shopId) {
|
||||||
|
${cartQueryFragment}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default accountCartByAccountIdQuery
|
241
packages/opencommerce/src/api/queries/get-cart-query.ts
Normal file
241
packages/opencommerce/src/api/queries/get-cart-query.ts
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
export const cartCommon = `
|
||||||
|
_id
|
||||||
|
createdAt
|
||||||
|
account {
|
||||||
|
_id
|
||||||
|
emailRecords {
|
||||||
|
address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shop {
|
||||||
|
_id
|
||||||
|
currency {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
email
|
||||||
|
updatedAt
|
||||||
|
expiresAt
|
||||||
|
checkout {
|
||||||
|
fulfillmentGroups {
|
||||||
|
_id
|
||||||
|
type
|
||||||
|
data {
|
||||||
|
shippingAddress {
|
||||||
|
address1
|
||||||
|
address2
|
||||||
|
city
|
||||||
|
company
|
||||||
|
country
|
||||||
|
fullName
|
||||||
|
isBillingDefault
|
||||||
|
isCommercial
|
||||||
|
isShippingDefault
|
||||||
|
phone
|
||||||
|
postal
|
||||||
|
region
|
||||||
|
}
|
||||||
|
}
|
||||||
|
availableFulfillmentOptions {
|
||||||
|
price {
|
||||||
|
amount
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
fulfillmentMethod {
|
||||||
|
_id
|
||||||
|
name
|
||||||
|
displayName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectedFulfillmentOption {
|
||||||
|
fulfillmentMethod {
|
||||||
|
_id
|
||||||
|
name
|
||||||
|
displayName
|
||||||
|
}
|
||||||
|
price {
|
||||||
|
amount
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
handlingPrice {
|
||||||
|
amount
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shop {
|
||||||
|
_id
|
||||||
|
}
|
||||||
|
shippingAddress {
|
||||||
|
address1
|
||||||
|
address2
|
||||||
|
city
|
||||||
|
company
|
||||||
|
country
|
||||||
|
fullName
|
||||||
|
isBillingDefault
|
||||||
|
isCommercial
|
||||||
|
isShippingDefault
|
||||||
|
phone
|
||||||
|
postal
|
||||||
|
region
|
||||||
|
}
|
||||||
|
}
|
||||||
|
summary {
|
||||||
|
fulfillmentTotal {
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
itemTotal {
|
||||||
|
amount
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
surchargeTotal {
|
||||||
|
amount
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
taxTotal {
|
||||||
|
amount
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
total {
|
||||||
|
amount
|
||||||
|
currency {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalItemQuantity
|
||||||
|
`
|
||||||
|
|
||||||
|
const cartItemConnectionFragment = `
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
|
}
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
_id
|
||||||
|
productConfiguration {
|
||||||
|
productId
|
||||||
|
productVariantId
|
||||||
|
}
|
||||||
|
addedAt
|
||||||
|
attributes {
|
||||||
|
label
|
||||||
|
value
|
||||||
|
}
|
||||||
|
createdAt
|
||||||
|
isBackorder
|
||||||
|
isLowQuantity
|
||||||
|
isSoldOut
|
||||||
|
imageURLs {
|
||||||
|
large
|
||||||
|
small
|
||||||
|
original
|
||||||
|
medium
|
||||||
|
thumbnail
|
||||||
|
}
|
||||||
|
metafields {
|
||||||
|
value
|
||||||
|
key
|
||||||
|
}
|
||||||
|
parcel {
|
||||||
|
length
|
||||||
|
width
|
||||||
|
weight
|
||||||
|
height
|
||||||
|
}
|
||||||
|
price {
|
||||||
|
amount
|
||||||
|
displayAmount
|
||||||
|
currency {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
priceWhenAdded {
|
||||||
|
amount
|
||||||
|
displayAmount
|
||||||
|
currency {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
productSlug
|
||||||
|
productType
|
||||||
|
quantity
|
||||||
|
shop {
|
||||||
|
_id
|
||||||
|
}
|
||||||
|
subtotal {
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
title
|
||||||
|
productTags {
|
||||||
|
nodes {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
productVendor
|
||||||
|
variantTitle
|
||||||
|
optionTitle
|
||||||
|
updatedAt
|
||||||
|
inventoryAvailableToSell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export const cartPayloadFragment = `
|
||||||
|
${cartCommon}
|
||||||
|
items {
|
||||||
|
${cartItemConnectionFragment}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export const incorrectPriceFailureDetailsFragment = `
|
||||||
|
currentPrice {
|
||||||
|
amount
|
||||||
|
currency {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
productConfiguration {
|
||||||
|
productId
|
||||||
|
productVariantId
|
||||||
|
}
|
||||||
|
providedPrice {
|
||||||
|
amount
|
||||||
|
currency {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
displayAmount
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export const minOrderQuantityFailureDetailsFragment = `
|
||||||
|
minOrderQuantity
|
||||||
|
productConfiguration {
|
||||||
|
productId
|
||||||
|
productVariantId
|
||||||
|
}
|
||||||
|
quantity
|
||||||
|
`
|
||||||
|
|
||||||
|
const getCartQuery = /* GraphQL */ `
|
||||||
|
query($checkoutId: ID!) {
|
||||||
|
node(id: $checkoutId) {
|
||||||
|
... on Checkout {
|
||||||
|
${cartCommon}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export const cartQueryFragment = `
|
||||||
|
${cartCommon}
|
||||||
|
items(first: 20, after: $itemsAfterCursor) {
|
||||||
|
${cartItemConnectionFragment}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default getCartQuery
|
20
packages/opencommerce/src/api/utils/get-cart-cookie.ts
Normal file
20
packages/opencommerce/src/api/utils/get-cart-cookie.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { serialize, CookieSerializeOptions } from 'cookie'
|
||||||
|
|
||||||
|
export default 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
|
||||||
|
|
||||||
|
return serialize(name, cartId || '', options)
|
||||||
|
}
|
23
packages/opencommerce/src/types/cart.ts
Normal file
23
packages/opencommerce/src/types/cart.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import * as Core from '@vercel/commerce/types/cart'
|
||||||
|
|
||||||
|
export * from '@vercel/commerce/types/cart'
|
||||||
|
|
||||||
|
export type Cart = Core.Cart & {
|
||||||
|
lineItems: Core.LineItem[]
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CartItemBody = Core.CartItemBody & {
|
||||||
|
price: {
|
||||||
|
amount: number
|
||||||
|
currency: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CartTypes = {
|
||||||
|
cart: Cart
|
||||||
|
item: Core.LineItem
|
||||||
|
itemBody: CartItemBody
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CartSchema = Core.CartSchema<CartTypes>
|
@ -10,7 +10,11 @@ import {
|
|||||||
CatalogProduct,
|
CatalogProduct,
|
||||||
CatalogProductVariant,
|
CatalogProductVariant,
|
||||||
ImageInfo,
|
ImageInfo,
|
||||||
|
Cart as OCCart,
|
||||||
|
CartItemEdge,
|
||||||
|
CartItem,
|
||||||
} from '../../schema'
|
} from '../../schema'
|
||||||
|
import { Cart, LineItem } from '../types/cart'
|
||||||
|
|
||||||
const normalizeProductImages = (images: ImageInfo[], name: string) =>
|
const normalizeProductImages = (images: ImageInfo[], name: string) =>
|
||||||
images.map((image) => ({
|
images.map((image) => ({
|
||||||
@ -227,3 +231,74 @@ export function normalizeVendors({ name }: OCVendor): Vendor {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function normalizeCart(cart: OCCart): Cart {
|
||||||
|
return {
|
||||||
|
id: cart._id,
|
||||||
|
customerId: cart.account?._id ?? '',
|
||||||
|
email:
|
||||||
|
(cart.account?.emailRecords && cart.account?.emailRecords[0]?.address) ??
|
||||||
|
'',
|
||||||
|
|
||||||
|
createdAt: cart.createdAt,
|
||||||
|
currency: {
|
||||||
|
code: cart.checkout?.summary?.total?.currency.code ?? '',
|
||||||
|
},
|
||||||
|
lineItems:
|
||||||
|
cart.items?.edges?.map((cartItem) =>
|
||||||
|
normalizeLineItem(<CartItemEdge>cartItem)
|
||||||
|
) ?? [],
|
||||||
|
lineItemsSubtotalPrice: +(cart.checkout?.summary?.itemTotal?.amount ?? 0),
|
||||||
|
subtotalPrice: +(cart.checkout?.summary?.itemTotal?.amount ?? 0),
|
||||||
|
totalPrice: cart.checkout?.summary?.total?.amount ?? 0,
|
||||||
|
discounts: [],
|
||||||
|
taxesIncluded: !!cart.checkout?.summary?.taxTotal?.amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLineItem(cartItemEdge: CartItemEdge): LineItem {
|
||||||
|
const cartItem = cartItemEdge.node
|
||||||
|
|
||||||
|
if (!cartItem) {
|
||||||
|
return <LineItem>{}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
_id,
|
||||||
|
compareAtPrice,
|
||||||
|
imageURLs,
|
||||||
|
title,
|
||||||
|
productConfiguration,
|
||||||
|
priceWhenAdded,
|
||||||
|
optionTitle,
|
||||||
|
variantTitle,
|
||||||
|
quantity,
|
||||||
|
} = <CartItem>cartItem
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: _id,
|
||||||
|
variantId: String(productConfiguration?.productVariantId),
|
||||||
|
productId: String(productConfiguration?.productId),
|
||||||
|
name: `${title}`,
|
||||||
|
quantity,
|
||||||
|
variant: {
|
||||||
|
id: String(productConfiguration?.productVariantId),
|
||||||
|
sku: String(productConfiguration?.productVariantId),
|
||||||
|
name: String(optionTitle || variantTitle),
|
||||||
|
image: {
|
||||||
|
url: imageURLs?.thumbnail ?? '/product-img-placeholder.svg',
|
||||||
|
},
|
||||||
|
requiresShipping: true,
|
||||||
|
price: priceWhenAdded?.amount,
|
||||||
|
listPrice: compareAtPrice?.amount ?? 0,
|
||||||
|
},
|
||||||
|
path: '',
|
||||||
|
discounts: [],
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: String(optionTitle || variantTitle),
|
||||||
|
name: String(optionTitle || variantTitle),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user