mirror of
https://github.com/vercel/commerce.git
synced 2025-07-04 04:01:21 +00:00
Start to replace Checkout with Cart API
This commit is contained in:
parent
0e7e7b7d5f
commit
c5e3d82202
@ -19,7 +19,7 @@ const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({
|
|||||||
try {
|
try {
|
||||||
await config.fetch(associateCustomerWithCheckoutMutation, {
|
await config.fetch(associateCustomerWithCheckoutMutation, {
|
||||||
variables: {
|
variables: {
|
||||||
checkoutId: cookies[SHOPIFY_CHECKOUT_ID_COOKIE],
|
cartId: cookies[SHOPIFY_CHECKOUT_ID_COOKIE],
|
||||||
customerAccessToken: cookies[SHOPIFY_CUSTOMER_TOKEN_COOKIE],
|
customerAccessToken: cookies[SHOPIFY_CUSTOMER_TOKEN_COOKIE],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -3,9 +3,9 @@ import type { OperationContext } from '@commerce/api/operations'
|
|||||||
import type { LoginOperation } from '../../types/login'
|
import type { LoginOperation } from '../../types/login'
|
||||||
import type { ShopifyConfig, Provider } from '..'
|
import type { ShopifyConfig, Provider } from '..'
|
||||||
import {
|
import {
|
||||||
customerAccessTokenCreateMutation,
|
|
||||||
setCustomerToken,
|
setCustomerToken,
|
||||||
throwUserErrors,
|
throwUserErrors,
|
||||||
|
customerAccessTokenCreateMutation,
|
||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
import { CustomerAccessTokenCreateMutation } from '../../schema'
|
import { CustomerAccessTokenCreateMutation } from '../../schema'
|
||||||
|
|
||||||
|
@ -4,19 +4,19 @@ import { CommerceError } from '@commerce/utils/errors'
|
|||||||
import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item'
|
import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item'
|
||||||
import type { AddItemHook } from '../types/cart'
|
import type { AddItemHook } from '../types/cart'
|
||||||
import useCart from './use-cart'
|
import useCart from './use-cart'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkoutLineItemAddMutation,
|
getCartId,
|
||||||
getCheckoutId,
|
normalizeCart,
|
||||||
checkoutToCart,
|
throwUserErrors,
|
||||||
|
cartLineItemAddMutation,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { Mutation, MutationCheckoutLineItemsAddArgs } from '../schema'
|
import { CartLinesAddMutation, CartLinesAddMutationVariables } from '../schema'
|
||||||
|
|
||||||
export default useAddItem as UseAddItem<typeof handler>
|
export default useAddItem as UseAddItem<typeof handler>
|
||||||
|
|
||||||
export const handler: MutationHook<AddItemHook> = {
|
export const handler: MutationHook<AddItemHook> = {
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
query: checkoutLineItemAddMutation,
|
query: cartLineItemAddMutation,
|
||||||
},
|
},
|
||||||
async fetcher({ input: item, options, fetch }) {
|
async fetcher({ input: item, options, fetch }) {
|
||||||
if (
|
if (
|
||||||
@ -28,13 +28,13 @@ export const handler: MutationHook<AddItemHook> = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const { checkoutLineItemsAdd } = await fetch<
|
const { cartLinesAdd } = await fetch<
|
||||||
Mutation,
|
CartLinesAddMutation,
|
||||||
MutationCheckoutLineItemsAddArgs
|
CartLinesAddMutationVariables
|
||||||
>({
|
>({
|
||||||
...options,
|
...options,
|
||||||
variables: {
|
variables: {
|
||||||
checkoutId: getCheckoutId(),
|
checkoutId: getCartId(),
|
||||||
lineItems: [
|
lineItems: [
|
||||||
{
|
{
|
||||||
variantId: item.variantId,
|
variantId: item.variantId,
|
||||||
@ -44,9 +44,17 @@ export const handler: MutationHook<AddItemHook> = {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return checkoutToCart(checkoutLineItemsAdd)
|
throwUserErrors(cartLinesAdd?.userErrors)
|
||||||
|
|
||||||
|
if (!cartLinesAdd?.cart) {
|
||||||
|
throw new CommerceError({ message: 'Missing cart from response' })
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizeCart(cartLinesAdd?.cart)
|
||||||
},
|
},
|
||||||
useHook: ({ fetch }) => () => {
|
useHook:
|
||||||
|
({ fetch }) =>
|
||||||
|
() => {
|
||||||
const { mutate } = useCart()
|
const { mutate } = useCart()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
|
@ -2,42 +2,21 @@ import { useMemo } from 'react'
|
|||||||
import useCommerceCart, { UseCart } from '@commerce/cart/use-cart'
|
import useCommerceCart, { UseCart } from '@commerce/cart/use-cart'
|
||||||
|
|
||||||
import { SWRHook } from '@commerce/utils/types'
|
import { SWRHook } from '@commerce/utils/types'
|
||||||
import { checkoutCreate, checkoutToCart } from '../utils'
|
import getCartQuery from '../utils/queries/get-cart-query'
|
||||||
import getCheckoutQuery from '../utils/queries/get-checkout-query'
|
|
||||||
import { GetCartHook } from '../types/cart'
|
import { GetCartHook } from '../types/cart'
|
||||||
|
|
||||||
import {
|
|
||||||
GetCheckoutQuery,
|
|
||||||
GetCheckoutQueryVariables,
|
|
||||||
CheckoutDetailsFragment,
|
|
||||||
} from '../schema'
|
|
||||||
|
|
||||||
export default useCommerceCart as UseCart<typeof handler>
|
export default useCommerceCart as UseCart<typeof handler>
|
||||||
|
|
||||||
export const handler: SWRHook<GetCartHook> = {
|
export const handler: SWRHook<GetCartHook> = {
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
query: getCheckoutQuery,
|
query: getCartQuery,
|
||||||
},
|
},
|
||||||
async fetcher({ input: { cartId: checkoutId }, options, fetch }) {
|
async fetcher({ input: { cartId }, options, fetch }) {
|
||||||
let checkout
|
return cartId ? await fetch(options) : null
|
||||||
|
|
||||||
if (checkoutId) {
|
|
||||||
const data = await fetch({
|
|
||||||
...options,
|
|
||||||
variables: {
|
|
||||||
checkoutId: checkoutId,
|
|
||||||
},
|
},
|
||||||
})
|
useHook:
|
||||||
checkout = data.node
|
({ useData }) =>
|
||||||
}
|
(input) => {
|
||||||
|
|
||||||
if (checkout?.completedAt || !checkoutId) {
|
|
||||||
checkout = await checkoutCreate(fetch)
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkoutToCart({ checkout })
|
|
||||||
},
|
|
||||||
useHook: ({ useData }) => (input) => {
|
|
||||||
const response = useData({
|
const response = useData({
|
||||||
swrOptions: { revalidateOnFocus: false, ...input?.swrOptions },
|
swrOptions: { revalidateOnFocus: false, ...input?.swrOptions },
|
||||||
})
|
})
|
||||||
|
@ -18,34 +18,38 @@ export type RemoveItemActionInput<T = any> = T extends LineItem
|
|||||||
|
|
||||||
export default useRemoveItem as UseRemoveItem<typeof handler>
|
export default useRemoveItem as UseRemoveItem<typeof handler>
|
||||||
|
|
||||||
import {
|
import { getCartId, normalizeCart, throwUserErrors } from '../utils'
|
||||||
checkoutLineItemRemoveMutation,
|
import cartLineItemRemoveMutation from '../utils/mutations/cart-line-item-remove'
|
||||||
getCheckoutId,
|
|
||||||
checkoutToCart,
|
|
||||||
} from '../utils'
|
|
||||||
|
|
||||||
import { Mutation, MutationCheckoutLineItemsRemoveArgs } from '../schema'
|
import {
|
||||||
|
CartLinesRemoveMutation,
|
||||||
|
CartLinesRemoveMutationVariables,
|
||||||
|
} from '../schema'
|
||||||
|
|
||||||
export const handler = {
|
export const handler = {
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
query: checkoutLineItemRemoveMutation,
|
query: cartLineItemRemoveMutation,
|
||||||
},
|
},
|
||||||
async fetcher({
|
async fetcher({
|
||||||
input: { itemId },
|
input: { itemId },
|
||||||
options,
|
options,
|
||||||
fetch,
|
fetch,
|
||||||
}: HookFetcherContext<RemoveItemHook>) {
|
}: HookFetcherContext<RemoveItemHook>) {
|
||||||
const data = await fetch<Mutation, MutationCheckoutLineItemsRemoveArgs>({
|
const data = await fetch<
|
||||||
|
CartLinesRemoveMutation,
|
||||||
|
CartLinesRemoveMutationVariables
|
||||||
|
>({
|
||||||
...options,
|
...options,
|
||||||
variables: { checkoutId: getCheckoutId(), lineItemIds: [itemId] },
|
variables: { cartId: getCartId(), lineItemIds: [itemId] },
|
||||||
})
|
})
|
||||||
return checkoutToCart(data.checkoutLineItemsRemove)
|
|
||||||
|
throwUserErrors(data.cartLinesRemove?.userErrors)
|
||||||
|
|
||||||
|
return normalizeCart(data.cartLinesRemove?.cart)
|
||||||
},
|
},
|
||||||
useHook: ({ fetch }: MutationHookContext<RemoveItemHook>) => <
|
useHook:
|
||||||
T extends LineItem | undefined = undefined
|
({ fetch }: MutationHookContext<RemoveItemHook>) =>
|
||||||
>(
|
<T extends LineItem | undefined = undefined>(ctx: { item?: T } = {}) => {
|
||||||
ctx: { item?: T } = {}
|
|
||||||
) => {
|
|
||||||
const { item } = ctx
|
const { item } = ctx
|
||||||
const { mutate } = useCart()
|
const { mutate } = useCart()
|
||||||
const removeItem: RemoveItemFn<LineItem> = async (input) => {
|
const removeItem: RemoveItemFn<LineItem> = async (input) => {
|
||||||
|
@ -10,12 +10,14 @@ import useUpdateItem, { UseUpdateItem } from '@commerce/cart/use-update-item'
|
|||||||
import useCart from './use-cart'
|
import useCart from './use-cart'
|
||||||
import { handler as removeItemHandler } from './use-remove-item'
|
import { handler as removeItemHandler } from './use-remove-item'
|
||||||
import type { UpdateItemHook, LineItem } from '../types/cart'
|
import type { UpdateItemHook, LineItem } from '../types/cart'
|
||||||
|
import { getCartId, normalizeCart } from '../utils'
|
||||||
import {
|
import {
|
||||||
getCheckoutId,
|
CartLinesUpdateMutation,
|
||||||
checkoutLineItemUpdateMutation,
|
CartLinesUpdateMutationVariables,
|
||||||
checkoutToCart,
|
Mutation,
|
||||||
} from '../utils'
|
MutationCheckoutLineItemsUpdateArgs,
|
||||||
import { Mutation, MutationCheckoutLineItemsUpdateArgs } from '../schema'
|
} from '../schema'
|
||||||
|
import cartLineItemUpdateMutation from '../utils/mutations/cart-line-item-update'
|
||||||
|
|
||||||
export type UpdateItemActionInput<T = any> = T extends LineItem
|
export type UpdateItemActionInput<T = any> = T extends LineItem
|
||||||
? Partial<UpdateItemHook['actionInput']>
|
? Partial<UpdateItemHook['actionInput']>
|
||||||
@ -25,7 +27,7 @@ export default useUpdateItem as UseUpdateItem<typeof handler>
|
|||||||
|
|
||||||
export const handler = {
|
export const handler = {
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
query: checkoutLineItemUpdateMutation,
|
query: cartLineItemUpdateMutation,
|
||||||
},
|
},
|
||||||
async fetcher({
|
async fetcher({
|
||||||
input: { itemId, item },
|
input: { itemId, item },
|
||||||
@ -46,13 +48,13 @@ export const handler = {
|
|||||||
message: 'The item quantity has to be a valid integer',
|
message: 'The item quantity has to be a valid integer',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const { checkoutLineItemsUpdate } = await fetch<
|
const { cartLinesUpdate } = await fetch<
|
||||||
Mutation,
|
CartLinesUpdateMutation,
|
||||||
MutationCheckoutLineItemsUpdateArgs
|
CartLinesUpdateMutationVariables
|
||||||
>({
|
>({
|
||||||
...options,
|
...options,
|
||||||
variables: {
|
variables: {
|
||||||
checkoutId: getCheckoutId(),
|
checkoutId: getCartId(),
|
||||||
lineItems: [
|
lineItems: [
|
||||||
{
|
{
|
||||||
id: itemId,
|
id: itemId,
|
||||||
@ -62,11 +64,11 @@ export const handler = {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return checkoutToCart(checkoutLineItemsUpdate)
|
return normalizeCart(cartLinesUpdate?.cart)
|
||||||
},
|
},
|
||||||
useHook: ({ fetch }: MutationHookContext<UpdateItemHook>) => <
|
useHook:
|
||||||
T extends LineItem | undefined = undefined
|
({ fetch }: MutationHookContext<UpdateItemHook>) =>
|
||||||
>(
|
<T extends LineItem | undefined = undefined>(
|
||||||
ctx: {
|
ctx: {
|
||||||
item?: T
|
item?: T
|
||||||
wait?: number
|
wait?: number
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schema": {
|
"schema": {
|
||||||
"https://${NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN}/api/2021-07/graphql.json": {
|
"https://${NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN}/api/unstable/graphql.json": {
|
||||||
"headers": {
|
"headers": {
|
||||||
"X-Shopify-Storefront-Access-Token": "${NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN}"
|
"X-Shopify-Storefront-Access-Token": "${NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN}"
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ export const STORE_DOMAIN = process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN
|
|||||||
|
|
||||||
export const SHOPIFY_COOKIE_EXPIRE = 30
|
export const SHOPIFY_COOKIE_EXPIRE = 30
|
||||||
|
|
||||||
export const API_URL = `https://${STORE_DOMAIN}/api/2021-01/graphql.json`
|
export const API_URL = `https://${STORE_DOMAIN}/api/unstable/graphql.json`
|
||||||
|
|
||||||
export const API_TOKEN = process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN
|
export const API_TOKEN = process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN
|
||||||
|
|
||||||
|
export const SHOPIFY_CART_ID_COOKIE = 'shopify_cartId'
|
||||||
|
@ -9,14 +9,14 @@ import {
|
|||||||
|
|
||||||
import { shopifyProvider } from './provider'
|
import { shopifyProvider } from './provider'
|
||||||
import type { ShopifyProvider } from './provider'
|
import type { ShopifyProvider } from './provider'
|
||||||
import { SHOPIFY_CHECKOUT_ID_COOKIE } from './const'
|
import { SHOPIFY_CART_ID_COOKIE } from './const'
|
||||||
|
|
||||||
export { shopifyProvider }
|
export { shopifyProvider }
|
||||||
export type { ShopifyProvider }
|
export type { ShopifyProvider }
|
||||||
|
|
||||||
export const shopifyConfig: CommerceConfig = {
|
export const shopifyConfig: CommerceConfig = {
|
||||||
locale: 'en-us',
|
locale: 'en-us',
|
||||||
cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE,
|
cartCookie: SHOPIFY_CART_ID_COOKIE,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShopifyConfig = Partial<CommerceConfig>
|
export type ShopifyConfig = Partial<CommerceConfig>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { SHOPIFY_CHECKOUT_ID_COOKIE } from './const'
|
import { SHOPIFY_CART_ID_COOKIE } from './const'
|
||||||
|
|
||||||
import { handler as useCart } from './cart/use-cart'
|
import { handler as useCart } from './cart/use-cart'
|
||||||
import { handler as useAddItem } from './cart/use-add-item'
|
import { handler as useAddItem } from './cart/use-add-item'
|
||||||
@ -16,7 +16,7 @@ import fetcher from './fetcher'
|
|||||||
|
|
||||||
export const shopifyProvider = {
|
export const shopifyProvider = {
|
||||||
locale: 'en-us',
|
locale: 'en-us',
|
||||||
cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE,
|
cartCookie: SHOPIFY_CART_ID_COOKIE,
|
||||||
fetcher,
|
fetcher,
|
||||||
cart: { useCart, useAddItem, useUpdateItem, useRemoveItem },
|
cart: { useCart, useAddItem, useUpdateItem, useRemoveItem },
|
||||||
customer: { useCustomer },
|
customer: { useCustomer },
|
||||||
|
1476
framework/shopify/schema.d.ts
vendored
1476
framework/shopify/schema.d.ts
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
46
framework/shopify/utils/cart-create.ts
Normal file
46
framework/shopify/utils/cart-create.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import Cookies from 'js-cookie'
|
||||||
|
|
||||||
|
import { SHOPIFY_CART_ID_COOKIE, SHOPIFY_COOKIE_EXPIRE } from '../const'
|
||||||
|
|
||||||
|
import cartCreateMutation from './mutations/cart-create'
|
||||||
|
|
||||||
|
import {
|
||||||
|
CartCreateMutation,
|
||||||
|
CartCreateMutationVariables,
|
||||||
|
CartDetailsFragment,
|
||||||
|
} from '../schema'
|
||||||
|
import { FetcherOptions } from '@commerce/utils/types'
|
||||||
|
import { FetcherError } from '@commerce/utils/errors'
|
||||||
|
|
||||||
|
export const cartCreate = async (
|
||||||
|
fetch: <T = any, B = Body>(options: FetcherOptions<B>) => Promise<T>
|
||||||
|
): Promise<{ node: CartDetailsFragment }> => {
|
||||||
|
const { cartCreate } = await fetch<
|
||||||
|
CartCreateMutation,
|
||||||
|
CartCreateMutationVariables
|
||||||
|
>({
|
||||||
|
query: cartCreateMutation,
|
||||||
|
})
|
||||||
|
|
||||||
|
const cart = cartCreate?.cart
|
||||||
|
|
||||||
|
if (!cart) {
|
||||||
|
throw new FetcherError({
|
||||||
|
status: 500,
|
||||||
|
errors: cartCreate?.userErrors?.map((e) => ({
|
||||||
|
message: e.message,
|
||||||
|
})) ?? [{ message: 'Could not create cart' }],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cart?.id) {
|
||||||
|
const options = {
|
||||||
|
expires: SHOPIFY_COOKIE_EXPIRE,
|
||||||
|
}
|
||||||
|
Cookies.set(SHOPIFY_CART_ID_COOKIE, cart.id, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
return { node: cart }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default cartCreate
|
@ -1,42 +0,0 @@
|
|||||||
import type { Cart } from '../types/cart'
|
|
||||||
import { CommerceError } from '@commerce/utils/errors'
|
|
||||||
|
|
||||||
import {
|
|
||||||
CheckoutLineItemsAddPayload,
|
|
||||||
CheckoutLineItemsRemovePayload,
|
|
||||||
CheckoutLineItemsUpdatePayload,
|
|
||||||
CheckoutCreatePayload,
|
|
||||||
CheckoutUserError,
|
|
||||||
Checkout,
|
|
||||||
Maybe,
|
|
||||||
} from '../schema'
|
|
||||||
|
|
||||||
import { normalizeCart } from './normalize'
|
|
||||||
import throwUserErrors from './throw-user-errors'
|
|
||||||
|
|
||||||
export type CheckoutQuery = {
|
|
||||||
checkout: Checkout
|
|
||||||
checkoutUserErrors?: Array<CheckoutUserError>
|
|
||||||
}
|
|
||||||
|
|
||||||
export type CheckoutPayload =
|
|
||||||
| CheckoutLineItemsAddPayload
|
|
||||||
| CheckoutLineItemsUpdatePayload
|
|
||||||
| CheckoutLineItemsRemovePayload
|
|
||||||
| CheckoutCreatePayload
|
|
||||||
| CheckoutQuery
|
|
||||||
|
|
||||||
const checkoutToCart = (checkoutPayload?: Maybe<CheckoutPayload>): Cart => {
|
|
||||||
const checkout = checkoutPayload?.checkout
|
|
||||||
throwUserErrors(checkoutPayload?.checkoutUserErrors)
|
|
||||||
|
|
||||||
if (!checkout) {
|
|
||||||
throw new CommerceError({
|
|
||||||
message: 'Missing checkout object from response',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return normalizeCart(checkout)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default checkoutToCart
|
|
8
framework/shopify/utils/get-cart-id.ts
Normal file
8
framework/shopify/utils/get-cart-id.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import Cookies from 'js-cookie'
|
||||||
|
import { SHOPIFY_CART_ID_COOKIE } from '../const'
|
||||||
|
|
||||||
|
const getCartId = (id?: string) => {
|
||||||
|
return id ?? Cookies.get(SHOPIFY_CART_ID_COOKIE)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getCartId
|
@ -1,8 +0,0 @@
|
|||||||
import Cookies from 'js-cookie'
|
|
||||||
import { SHOPIFY_CHECKOUT_ID_COOKIE } from '../const'
|
|
||||||
|
|
||||||
const getCheckoutId = (id?: string) => {
|
|
||||||
return id ?? Cookies.get(SHOPIFY_CHECKOUT_ID_COOKIE)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default getCheckoutId
|
|
@ -3,12 +3,12 @@ export { default as getSearchVariables } from './get-search-variables'
|
|||||||
export { default as getSortVariables } from './get-sort-variables'
|
export { default as getSortVariables } from './get-sort-variables'
|
||||||
export { default as getBrands } from './get-brands'
|
export { default as getBrands } from './get-brands'
|
||||||
export { default as getCategories } from './get-categories'
|
export { default as getCategories } from './get-categories'
|
||||||
export { default as getCheckoutId } from './get-checkout-id'
|
export { default as getCartId } from './get-cart-id'
|
||||||
export { default as checkoutCreate } from './checkout-create'
|
export { default as cartCreate } from './cart-create'
|
||||||
export { default as checkoutToCart } from './checkout-to-cart'
|
|
||||||
export { default as handleLogin, handleAutomaticLogin } from './handle-login'
|
export { default as handleLogin, handleAutomaticLogin } from './handle-login'
|
||||||
export { default as handleAccountActivation } from './handle-account-activation'
|
export { default as handleAccountActivation } from './handle-account-activation'
|
||||||
export { default as throwUserErrors } from './throw-user-errors'
|
export { default as throwUserErrors } from './throw-user-errors'
|
||||||
|
|
||||||
export * from './queries'
|
export * from './queries'
|
||||||
export * from './mutations'
|
export * from './mutations'
|
||||||
export * from './normalize'
|
export * from './normalize'
|
||||||
|
18
framework/shopify/utils/mutations/cart-create.ts
Normal file
18
framework/shopify/utils/mutations/cart-create.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { cartDetailsFragment } from '../queries/get-cart-query'
|
||||||
|
|
||||||
|
const cartCreateMutation = /* GraphQL */ `
|
||||||
|
mutation cartCreate {
|
||||||
|
cartCreate {
|
||||||
|
cart {
|
||||||
|
...cartDetails
|
||||||
|
}
|
||||||
|
userErrors {
|
||||||
|
code
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${cartDetailsFragment}
|
||||||
|
`
|
||||||
|
export default cartCreateMutation
|
18
framework/shopify/utils/mutations/cart-line-item-add.ts
Normal file
18
framework/shopify/utils/mutations/cart-line-item-add.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { cartDetailsFragment } from '../queries/get-cart-query'
|
||||||
|
|
||||||
|
const cartLinesAddMutation = /* GraphQL */ `
|
||||||
|
mutation cartLinesAdd($lines: [CartLineInput!]!, $cartId: ID!) {
|
||||||
|
cartLinesAdd(lines: $lines, cartId: $cartId) {
|
||||||
|
cart {
|
||||||
|
...cartDetails
|
||||||
|
}
|
||||||
|
userErrors {
|
||||||
|
code
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${cartDetailsFragment}
|
||||||
|
`
|
||||||
|
export default cartLinesAddMutation
|
18
framework/shopify/utils/mutations/cart-line-item-remove.ts
Normal file
18
framework/shopify/utils/mutations/cart-line-item-remove.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { cartDetailsFragment } from '../queries/get-cart-query'
|
||||||
|
|
||||||
|
const cartLinesAddMutation = /* GraphQL */ `
|
||||||
|
mutation cartLinesRemove($cartId: ID!, $lineIds: [ID!]!) {
|
||||||
|
cartLinesRemove(cartId: $cartId, lineIds: $lineIds) {
|
||||||
|
cart {
|
||||||
|
...cartDetails
|
||||||
|
}
|
||||||
|
userErrors {
|
||||||
|
code
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${cartDetailsFragment}
|
||||||
|
`
|
||||||
|
export default cartLinesAddMutation
|
18
framework/shopify/utils/mutations/cart-line-item-update.ts
Normal file
18
framework/shopify/utils/mutations/cart-line-item-update.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { cartDetailsFragment } from '../queries/get-cart-query'
|
||||||
|
|
||||||
|
const cartLinesAddMutation = /* GraphQL */ `
|
||||||
|
mutation cartLinesUpdate($cartId: ID!, $lines: [CartLineUpdateInput!]!) {
|
||||||
|
cartLinesUpdate(cartId: $cartId, lines: $lines) {
|
||||||
|
cart {
|
||||||
|
...cartDetails
|
||||||
|
}
|
||||||
|
userErrors {
|
||||||
|
code
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${cartDetailsFragment}
|
||||||
|
`
|
||||||
|
export default cartLinesAddMutation
|
@ -1,19 +0,0 @@
|
|||||||
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
|
|
||||||
|
|
||||||
const checkoutCreateMutation = /* GraphQL */ `
|
|
||||||
mutation checkoutCreate($input: CheckoutCreateInput = {}) {
|
|
||||||
checkoutCreate(input: $input) {
|
|
||||||
checkoutUserErrors {
|
|
||||||
code
|
|
||||||
field
|
|
||||||
message
|
|
||||||
}
|
|
||||||
checkout {
|
|
||||||
...checkoutDetails
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
${checkoutDetailsFragment}
|
|
||||||
`
|
|
||||||
export default checkoutCreateMutation
|
|
@ -1,22 +0,0 @@
|
|||||||
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
|
|
||||||
|
|
||||||
const checkoutLineItemAddMutation = /* GraphQL */ `
|
|
||||||
mutation checkoutLineItemAdd(
|
|
||||||
$checkoutId: ID!
|
|
||||||
$lineItems: [CheckoutLineItemInput!]!
|
|
||||||
) {
|
|
||||||
checkoutLineItemsAdd(checkoutId: $checkoutId, lineItems: $lineItems) {
|
|
||||||
checkoutUserErrors {
|
|
||||||
code
|
|
||||||
field
|
|
||||||
message
|
|
||||||
}
|
|
||||||
checkout {
|
|
||||||
...checkoutDetails
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
${checkoutDetailsFragment}
|
|
||||||
`
|
|
||||||
export default checkoutLineItemAddMutation
|
|
@ -1,21 +0,0 @@
|
|||||||
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
|
|
||||||
|
|
||||||
const checkoutLineItemRemoveMutation = /* GraphQL */ `
|
|
||||||
mutation checkoutLineItemRemove($checkoutId: ID!, $lineItemIds: [ID!]!) {
|
|
||||||
checkoutLineItemsRemove(
|
|
||||||
checkoutId: $checkoutId
|
|
||||||
lineItemIds: $lineItemIds
|
|
||||||
) {
|
|
||||||
checkoutUserErrors {
|
|
||||||
code
|
|
||||||
field
|
|
||||||
message
|
|
||||||
}
|
|
||||||
checkout {
|
|
||||||
...checkoutDetails
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
${checkoutDetailsFragment}
|
|
||||||
`
|
|
||||||
export default checkoutLineItemRemoveMutation
|
|
@ -1,22 +0,0 @@
|
|||||||
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
|
|
||||||
|
|
||||||
const checkoutLineItemUpdateMutation = /* GraphQL */ `
|
|
||||||
mutation checkoutLineItemUpdate(
|
|
||||||
$checkoutId: ID!
|
|
||||||
$lineItems: [CheckoutLineItemUpdateInput!]!
|
|
||||||
) {
|
|
||||||
checkoutLineItemsUpdate(checkoutId: $checkoutId, lineItems: $lineItems) {
|
|
||||||
checkoutUserErrors {
|
|
||||||
code
|
|
||||||
field
|
|
||||||
message
|
|
||||||
}
|
|
||||||
checkout {
|
|
||||||
...checkoutDetails
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
${checkoutDetailsFragment}
|
|
||||||
`
|
|
||||||
export default checkoutLineItemUpdateMutation
|
|
@ -1,8 +1,8 @@
|
|||||||
export { default as customerCreateMutation } from './customer-create'
|
export { default as customerCreateMutation } from './customer-create'
|
||||||
export { default as checkoutCreateMutation } from './checkout-create'
|
export { default as cartCreateMutation } from './cart-create'
|
||||||
export { default as checkoutLineItemAddMutation } from './checkout-line-item-add'
|
export { default as cartLineItemAddMutation } from './cart-line-item-add'
|
||||||
export { default as checkoutLineItemUpdateMutation } from './checkout-line-item-update'
|
export { default as cartLineItemUpdateMutation } from './cart-line-item-update'
|
||||||
export { default as checkoutLineItemRemoveMutation } from './checkout-line-item-remove'
|
export { default as cartLineItemRemoveMutation } from './cart-line-item-remove'
|
||||||
export { default as customerAccessTokenCreateMutation } from './customer-access-token-create'
|
export { default as customerAccessTokenCreateMutation } from './customer-access-token-create'
|
||||||
export { default as customerAccessTokenDeleteMutation } from './customer-access-token-delete'
|
export { default as customerAccessTokenDeleteMutation } from './customer-access-token-delete'
|
||||||
export { default as customerActivateMutation } from './customer-activate'
|
export { default as customerActivateMutation } from './customer-activate'
|
||||||
|
@ -5,18 +5,18 @@ import type { Category } from '../types/site'
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Product as ShopifyProduct,
|
Product as ShopifyProduct,
|
||||||
Checkout,
|
|
||||||
CheckoutLineItemEdge,
|
|
||||||
SelectedOption,
|
SelectedOption,
|
||||||
ImageConnection,
|
ImageConnection,
|
||||||
ProductVariantConnection,
|
|
||||||
MoneyV2,
|
MoneyV2,
|
||||||
ProductOption,
|
ProductOption,
|
||||||
Page as ShopifyPage,
|
Page as ShopifyPage,
|
||||||
PageEdge,
|
PageEdge,
|
||||||
Collection,
|
Collection,
|
||||||
|
CartDetailsFragment,
|
||||||
|
ProductVariantConnection,
|
||||||
} from '../schema'
|
} from '../schema'
|
||||||
import { colorMap } from '@lib/colors'
|
import { colorMap } from '@lib/colors'
|
||||||
|
import { CommerceError } from '@commerce/utils/errors'
|
||||||
|
|
||||||
const money = ({ amount, currencyCode }: MoneyV2) => {
|
const money = ({ amount, currencyCode }: MoneyV2) => {
|
||||||
return {
|
return {
|
||||||
@ -128,34 +128,41 @@ export function normalizeProduct({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizeCart(checkout: Checkout): Cart {
|
export function normalizeCart(
|
||||||
|
cart: CartDetailsFragment | undefined | null
|
||||||
|
): Cart {
|
||||||
|
if (!cart) {
|
||||||
|
throw new CommerceError({ message: 'Missing cart details' })
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: checkout.id,
|
id: cart.id,
|
||||||
url: checkout.webUrl,
|
customerId: cart.buyerIdentity?.customer?.id,
|
||||||
customerId: '',
|
email: cart.buyerIdentity?.email ?? '',
|
||||||
email: '',
|
createdAt: cart.createdAt,
|
||||||
createdAt: checkout.createdAt,
|
|
||||||
currency: {
|
currency: {
|
||||||
code: checkout.totalPriceV2?.currencyCode,
|
code: cart.estimatedCost?.totalAmount?.currencyCode,
|
||||||
},
|
},
|
||||||
taxesIncluded: checkout.taxesIncluded,
|
taxesIncluded: !!cart.estimatedCost?.totalTaxAmount,
|
||||||
lineItems: checkout.lineItems?.edges.map(normalizeLineItem),
|
lineItems: cart.lines?.edges?.map(normalizeLineItem) ?? [],
|
||||||
lineItemsSubtotalPrice: +checkout.subtotalPriceV2?.amount,
|
lineItemsSubtotalPrice: +cart.estimatedCost?.totalAmount,
|
||||||
subtotalPrice: +checkout.subtotalPriceV2?.amount,
|
subtotalPrice: +cart.estimatedCost?.subtotalAmount,
|
||||||
totalPrice: checkout.totalPriceV2?.amount,
|
totalPrice: +cart.estimatedCost?.totalAmount,
|
||||||
discounts: [],
|
discounts: [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeLineItem({
|
function normalizeLineItem({
|
||||||
node: { id, title, variant, quantity },
|
node: { id, merchandise: variant, quantity },
|
||||||
}: CheckoutLineItemEdge): LineItem {
|
}: {
|
||||||
|
node: any
|
||||||
|
}): LineItem {
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
variantId: String(variant?.id),
|
variantId: String(variant?.id),
|
||||||
productId: String(variant?.id),
|
productId: String(variant?.id),
|
||||||
name: `${title}`,
|
name: `${variant?.title}`,
|
||||||
quantity,
|
quantity: quantity ?? 0,
|
||||||
variant: {
|
variant: {
|
||||||
id: String(variant?.id),
|
id: String(variant?.id),
|
||||||
sku: variant?.sku ?? '',
|
sku: variant?.sku ?? '',
|
||||||
|
58
framework/shopify/utils/queries/get-cart-query.ts
Normal file
58
framework/shopify/utils/queries/get-cart-query.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
export const cartDetailsFragment = /* GraphQL */ `
|
||||||
|
fragment cartDetails on Cart {
|
||||||
|
id
|
||||||
|
checkoutUrl
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
lines(first: 10) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
merchandise {
|
||||||
|
... on ProductVariant {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attributes {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
|
buyerIdentity {
|
||||||
|
email
|
||||||
|
customer {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
estimatedCost {
|
||||||
|
totalAmount {
|
||||||
|
amount
|
||||||
|
currencyCode
|
||||||
|
}
|
||||||
|
subtotalAmount {
|
||||||
|
amount
|
||||||
|
currencyCode
|
||||||
|
}
|
||||||
|
totalTaxAmount {
|
||||||
|
amount
|
||||||
|
currencyCode
|
||||||
|
}
|
||||||
|
totalDutyAmount {
|
||||||
|
amount
|
||||||
|
currencyCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const getCartQuery = /* GraphQL */ `
|
||||||
|
query getCart($cartId: ID!) {
|
||||||
|
node(id: $cartId) {
|
||||||
|
...cartDetails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${cartDetailsFragment}
|
||||||
|
`
|
||||||
|
export default getCartQuery
|
@ -1,70 +0,0 @@
|
|||||||
export const checkoutDetailsFragment = /* GraphQL */ `
|
|
||||||
fragment checkoutDetails on Checkout {
|
|
||||||
id
|
|
||||||
webUrl
|
|
||||||
subtotalPriceV2 {
|
|
||||||
amount
|
|
||||||
currencyCode
|
|
||||||
}
|
|
||||||
totalTaxV2 {
|
|
||||||
amount
|
|
||||||
currencyCode
|
|
||||||
}
|
|
||||||
totalPriceV2 {
|
|
||||||
amount
|
|
||||||
currencyCode
|
|
||||||
}
|
|
||||||
completedAt
|
|
||||||
createdAt
|
|
||||||
taxesIncluded
|
|
||||||
lineItems(first: 250) {
|
|
||||||
pageInfo {
|
|
||||||
hasNextPage
|
|
||||||
hasPreviousPage
|
|
||||||
}
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
variant {
|
|
||||||
id
|
|
||||||
sku
|
|
||||||
title
|
|
||||||
selectedOptions {
|
|
||||||
name
|
|
||||||
value
|
|
||||||
}
|
|
||||||
image {
|
|
||||||
originalSrc
|
|
||||||
altText
|
|
||||||
width
|
|
||||||
height
|
|
||||||
}
|
|
||||||
priceV2 {
|
|
||||||
amount
|
|
||||||
currencyCode
|
|
||||||
}
|
|
||||||
compareAtPriceV2 {
|
|
||||||
amount
|
|
||||||
currencyCode
|
|
||||||
}
|
|
||||||
product {
|
|
||||||
handle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
quantity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const getCheckoutQuery = /* GraphQL */ `
|
|
||||||
query getCheckout($checkoutId: ID!) {
|
|
||||||
node(id: $checkoutId) {
|
|
||||||
...checkoutDetails
|
|
||||||
}
|
|
||||||
}
|
|
||||||
${checkoutDetailsFragment}
|
|
||||||
`
|
|
||||||
export default getCheckoutQuery
|
|
@ -4,7 +4,7 @@ export { default as getAllProductsQuery } from './get-all-products-query'
|
|||||||
export { default as getAllProductsPathtsQuery } from './get-all-products-paths-query'
|
export { default as getAllProductsPathtsQuery } from './get-all-products-paths-query'
|
||||||
export { default as getAllProductVendors } from './get-all-product-vendors-query'
|
export { default as getAllProductVendors } from './get-all-product-vendors-query'
|
||||||
export { default as getCollectionProductsQuery } from './get-collection-products-query'
|
export { default as getCollectionProductsQuery } from './get-collection-products-query'
|
||||||
export { default as getCheckoutQuery } from './get-checkout-query'
|
export { default as getCartQuery } from './get-cart-query'
|
||||||
export { default as getAllPagesQuery } from './get-all-pages-query'
|
export { default as getAllPagesQuery } from './get-all-pages-query'
|
||||||
export { default as getPageQuery } from './get-page-query'
|
export { default as getPageQuery } from './get-page-query'
|
||||||
export { default as getCustomerQuery } from './get-customer-query'
|
export { default as getCustomerQuery } from './get-customer-query'
|
||||||
|
@ -5,13 +5,18 @@ import {
|
|||||||
CheckoutUserError,
|
CheckoutUserError,
|
||||||
CustomerErrorCode,
|
CustomerErrorCode,
|
||||||
CustomerUserError,
|
CustomerUserError,
|
||||||
|
CartUserError,
|
||||||
|
CartErrorCode,
|
||||||
} from '../schema'
|
} from '../schema'
|
||||||
|
|
||||||
export type UserErrors = Array<CheckoutUserError | CustomerUserError>
|
export type UserErrors = Array<
|
||||||
|
CheckoutUserError | CustomerUserError | CartUserError
|
||||||
|
>
|
||||||
|
|
||||||
export type UserErrorCode =
|
export type UserErrorCode =
|
||||||
| CustomerErrorCode
|
| CustomerErrorCode
|
||||||
| CheckoutErrorCode
|
| CheckoutErrorCode
|
||||||
|
| CartErrorCode
|
||||||
| null
|
| null
|
||||||
| undefined
|
| undefined
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
"@components/*": ["components/*"],
|
"@components/*": ["components/*"],
|
||||||
"@commerce": ["framework/commerce"],
|
"@commerce": ["framework/commerce"],
|
||||||
"@commerce/*": ["framework/commerce/*"],
|
"@commerce/*": ["framework/commerce/*"],
|
||||||
"@framework": ["framework/local"],
|
"@framework": ["framework/shopify"],
|
||||||
"@framework/*": ["framework/local/*"]
|
"@framework/*": ["framework/shopify/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"],
|
"include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user