forked from crowetic/commerce
Merge branch 'agnostic' of github.com:vercel/commerce into agnostic
This commit is contained in:
commit
b037cc0596
@ -5,6 +5,7 @@ import Link from 'next/link'
|
|||||||
import s from './CartItem.module.css'
|
import s from './CartItem.module.css'
|
||||||
import { Trash, Plus, Minus } from '@components/icons'
|
import { Trash, Plus, Minus } from '@components/icons'
|
||||||
import { useUI } from '@components/ui/context'
|
import { useUI } from '@components/ui/context'
|
||||||
|
import type { LineItem } from '@framework/types'
|
||||||
import usePrice from '@framework/product/use-price'
|
import usePrice from '@framework/product/use-price'
|
||||||
import useUpdateItem from '@framework/cart/use-update-item'
|
import useUpdateItem from '@framework/cart/use-update-item'
|
||||||
import useRemoveItem from '@framework/cart/use-remove-item'
|
import useRemoveItem from '@framework/cart/use-remove-item'
|
||||||
|
@ -14,6 +14,9 @@ const updateItem: CartHandlers['updateItem'] = async ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('ITEM', item)
|
||||||
|
console.log('AFTER', parseCartItem(item))
|
||||||
|
|
||||||
const { data } = await config.storeApiFetch(
|
const { data } = await config.storeApiFetch(
|
||||||
`/v3/carts/${cartId}/items/${itemId}`,
|
`/v3/carts/${cartId}/items/${itemId}`,
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@ import getCart from './handlers/get-cart'
|
|||||||
import addItem from './handlers/add-item'
|
import addItem from './handlers/add-item'
|
||||||
import updateItem from './handlers/update-item'
|
import updateItem from './handlers/update-item'
|
||||||
import removeItem from './handlers/remove-item'
|
import removeItem from './handlers/remove-item'
|
||||||
|
import type { Cart, UpdateCartItemHandlerBody } from '../../types'
|
||||||
|
|
||||||
type OptionSelections = {
|
type OptionSelections = {
|
||||||
option_id: Number
|
option_id: Number
|
||||||
@ -23,40 +24,12 @@ export type ItemBody = {
|
|||||||
|
|
||||||
export type AddItemBody = { item: ItemBody }
|
export type AddItemBody = { item: ItemBody }
|
||||||
|
|
||||||
export type UpdateItemBody = { itemId: string; item: ItemBody }
|
|
||||||
|
|
||||||
export type RemoveItemBody = { itemId: string }
|
export type RemoveItemBody = { itemId: string }
|
||||||
|
|
||||||
// TODO: this type should match:
|
|
||||||
// https://developer.bigcommerce.com/api-reference/cart-checkout/server-server-cart-api/cart/getacart#responses
|
|
||||||
export type Cart = {
|
|
||||||
id: string
|
|
||||||
parent_id?: string
|
|
||||||
customer_id: number
|
|
||||||
email: string
|
|
||||||
currency: { code: string }
|
|
||||||
tax_included: boolean
|
|
||||||
base_amount: number
|
|
||||||
discount_amount: number
|
|
||||||
cart_amount: number
|
|
||||||
line_items: {
|
|
||||||
custom_items: any[]
|
|
||||||
digital_items: any[]
|
|
||||||
gift_certificates: any[]
|
|
||||||
physical_items: any[]
|
|
||||||
}
|
|
||||||
created_time: string
|
|
||||||
discounts?: { id: number; discounted_amount: number }[]
|
|
||||||
// TODO: add missing fields
|
|
||||||
}
|
|
||||||
|
|
||||||
export type CartHandlers = {
|
export type CartHandlers = {
|
||||||
getCart: BigcommerceHandler<Cart, { cartId?: string }>
|
getCart: BigcommerceHandler<Cart, { cartId?: string }>
|
||||||
addItem: BigcommerceHandler<Cart, { cartId?: string } & Partial<AddItemBody>>
|
addItem: BigcommerceHandler<Cart, { cartId?: string } & Partial<AddItemBody>>
|
||||||
updateItem: BigcommerceHandler<
|
updateItem: BigcommerceHandler<Cart, UpdateCartItemHandlerBody>
|
||||||
Cart,
|
|
||||||
{ cartId?: string } & Partial<UpdateItemBody>
|
|
||||||
>
|
|
||||||
removeItem: BigcommerceHandler<
|
removeItem: BigcommerceHandler<
|
||||||
Cart,
|
Cart,
|
||||||
{ cartId?: string } & Partial<RemoveItemBody>
|
{ cartId?: string } & Partial<RemoveItemBody>
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
import type { ItemBody as WishlistItemBody } from '../wishlist'
|
import type { ItemBody as WishlistItemBody } from '../wishlist'
|
||||||
import type { ItemBody } from '../cart'
|
import type { CartItemBody, OptionSelections } from '../../types'
|
||||||
|
|
||||||
|
type BCCartItemBody = {
|
||||||
|
product_id: number
|
||||||
|
variant_id: number
|
||||||
|
quantity?: number
|
||||||
|
option_selections?: OptionSelections
|
||||||
|
}
|
||||||
|
|
||||||
export const parseWishlistItem = (item: WishlistItemBody) => ({
|
export const parseWishlistItem = (item: WishlistItemBody) => ({
|
||||||
product_id: item.productId,
|
product_id: item.productId,
|
||||||
variant_id: item.variantId,
|
variant_id: item.variantId,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const parseCartItem = (item: ItemBody) => ({
|
export const parseCartItem = (item: CartItemBody): BCCartItemBody => ({
|
||||||
quantity: item.quantity,
|
quantity: item.quantity,
|
||||||
product_id: item.productId,
|
product_id: Number(item.productId),
|
||||||
variant_id: item.variantId,
|
variant_id: Number(item.variantId),
|
||||||
option_selections: item.optionSelections,
|
option_selections: item.optionSelections,
|
||||||
})
|
})
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
import type { HookFetcher } from '@commerce/utils/types'
|
import type { HookFetcher } from '@commerce/utils/types'
|
||||||
import { CommerceError } from '@commerce/utils/errors'
|
import { ValidationError } from '@commerce/utils/errors'
|
||||||
import useCartUpdateItem from '@commerce/cart/use-update-item'
|
import useCartUpdateItem from '@commerce/cart/use-update-item'
|
||||||
import { normalizeCart } from '../lib/normalize'
|
import { normalizeCart } from '../lib/normalize'
|
||||||
import type {
|
import type {
|
||||||
ItemBody,
|
UpdateCartItemBody,
|
||||||
UpdateItemBody,
|
UpdateCartItemInput,
|
||||||
Cart as BigcommerceCart,
|
Cart,
|
||||||
} from '../api/cart'
|
BigcommerceCart,
|
||||||
|
LineItem,
|
||||||
|
} from '../types'
|
||||||
import { fetcher as removeFetcher } from './use-remove-item'
|
import { fetcher as removeFetcher } from './use-remove-item'
|
||||||
import useCart from './use-cart'
|
import useCart from './use-cart'
|
||||||
|
|
||||||
@ -17,9 +19,7 @@ const defaultOpts = {
|
|||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UpdateItemInput = Partial<{ id: string } & ItemBody>
|
export const fetcher: HookFetcher<Cart | null, UpdateCartItemBody> = async (
|
||||||
|
|
||||||
export const fetcher: HookFetcher<Cart | null, UpdateItemBody> = async (
|
|
||||||
options,
|
options,
|
||||||
{ itemId, item },
|
{ itemId, item },
|
||||||
fetch
|
fetch
|
||||||
@ -30,12 +30,12 @@ export const fetcher: HookFetcher<Cart | null, UpdateItemBody> = async (
|
|||||||
return removeFetcher(null, { itemId }, fetch)
|
return removeFetcher(null, { itemId }, fetch)
|
||||||
}
|
}
|
||||||
} else if (item.quantity) {
|
} else if (item.quantity) {
|
||||||
throw new CommerceError({
|
throw new ValidationError({
|
||||||
message: 'The item quantity has to be a valid integer',
|
message: 'The item quantity has to be a valid integer',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await fetch<BigcommerceCart>({
|
const data = await fetch<BigcommerceCart, UpdateCartItemBody>({
|
||||||
...defaultOpts,
|
...defaultOpts,
|
||||||
...options,
|
...options,
|
||||||
body: { itemId, item },
|
body: { itemId, item },
|
||||||
@ -45,26 +45,41 @@ export const fetcher: HookFetcher<Cart | null, UpdateItemBody> = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
function extendHook(customFetcher: typeof fetcher, cfg?: { wait?: number }) {
|
function extendHook(customFetcher: typeof fetcher, cfg?: { wait?: number }) {
|
||||||
const useUpdateItem = (item?: any) => {
|
const useUpdateItem = <T extends LineItem | undefined = undefined>(
|
||||||
|
item?: T
|
||||||
|
) => {
|
||||||
const { mutate } = useCart()
|
const { mutate } = useCart()
|
||||||
const fn = useCartUpdateItem<Cart | null, UpdateItemBody>(
|
const fn = useCartUpdateItem<Cart | null, UpdateCartItemBody>(
|
||||||
defaultOpts,
|
defaultOpts,
|
||||||
customFetcher
|
customFetcher
|
||||||
)
|
)
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
debounce(async (input: UpdateItemInput) => {
|
debounce(
|
||||||
const data = await fn({
|
async (
|
||||||
itemId: input.id ?? item?.id,
|
input: T extends LineItem
|
||||||
item: {
|
? Partial<UpdateCartItemInput>
|
||||||
productId: input.productId ?? item?.product_id,
|
: UpdateCartItemInput
|
||||||
variantId: input.productId ?? item?.variant_id,
|
) => {
|
||||||
quantity: input.quantity,
|
const itemId = input.id ?? item?.id
|
||||||
},
|
const productId = input.productId ?? item?.productId
|
||||||
})
|
const variantId = input.productId ?? item?.variantId
|
||||||
await mutate(data, false)
|
|
||||||
return data
|
if (!itemId || !productId || !variantId) {
|
||||||
}, cfg?.wait ?? 500),
|
throw new ValidationError({
|
||||||
|
message: 'Invalid input used for this operation',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await fn({
|
||||||
|
itemId,
|
||||||
|
item: { productId, variantId, quantity: input.quantity },
|
||||||
|
})
|
||||||
|
await mutate(data, false)
|
||||||
|
return data
|
||||||
|
},
|
||||||
|
cfg?.wait ?? 500
|
||||||
|
),
|
||||||
[fn, mutate]
|
[fn, mutate]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { Cart as BigcommerceCart } from '../api/cart'
|
import type { Cart, BigcommerceCart, LineItem } from '../types'
|
||||||
import update from './immutability'
|
import update from './immutability'
|
||||||
|
|
||||||
function normalizeProductOption(productOption: any) {
|
function normalizeProductOption(productOption: any) {
|
||||||
@ -90,6 +90,7 @@ function normalizeLineItem(item: any): LineItem {
|
|||||||
return {
|
return {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
variantId: String(item.variant_id),
|
variantId: String(item.variant_id),
|
||||||
|
productId: String(item.product_id),
|
||||||
name: item.name,
|
name: item.name,
|
||||||
quantity: item.quantity,
|
quantity: item.quantity,
|
||||||
variant: {
|
variant: {
|
||||||
|
5
framework/bigcommerce/types.d.ts
vendored
5
framework/bigcommerce/types.d.ts
vendored
@ -1,5 +0,0 @@
|
|||||||
interface Cart extends BaseCart {
|
|
||||||
lineItems: LineItem[]
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LineItem extends BaseLineItem {}
|
|
54
framework/bigcommerce/types.ts
Normal file
54
framework/bigcommerce/types.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import * as Core from '@commerce/types'
|
||||||
|
|
||||||
|
// TODO: this type should match:
|
||||||
|
// https://developer.bigcommerce.com/api-reference/cart-checkout/server-server-cart-api/cart/getacart#responses
|
||||||
|
export type BigcommerceCart = {
|
||||||
|
id: string
|
||||||
|
parent_id?: string
|
||||||
|
customer_id: number
|
||||||
|
email: string
|
||||||
|
currency: { code: string }
|
||||||
|
tax_included: boolean
|
||||||
|
base_amount: number
|
||||||
|
discount_amount: number
|
||||||
|
cart_amount: number
|
||||||
|
line_items: {
|
||||||
|
custom_items: any[]
|
||||||
|
digital_items: any[]
|
||||||
|
gift_certificates: any[]
|
||||||
|
physical_items: any[]
|
||||||
|
}
|
||||||
|
created_time: string
|
||||||
|
discounts?: { id: number; discounted_amount: number }[]
|
||||||
|
// TODO: add missing fields
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Cart extends Core.Cart {
|
||||||
|
lineItems: LineItem[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LineItem extends Core.LineItem {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cart mutations
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type OptionSelections = {
|
||||||
|
option_id: number
|
||||||
|
option_value: number | string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CartItemBody extends Core.CartItemBody {
|
||||||
|
productId: string // The product id is always required for BC
|
||||||
|
optionSelections?: OptionSelections
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateCartItemBody extends Core.UpdateCartItemBody {
|
||||||
|
item: CartItemBody
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateCartItemInput
|
||||||
|
extends Core.UpdateCartItemInput<CartItemBody> {}
|
||||||
|
|
||||||
|
export interface UpdateCartItemHandlerBody
|
||||||
|
extends Core.UpdateCartItemHandlerBody {}
|
@ -1,15 +1,16 @@
|
|||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
import type { HookInput, HookFetcher, HookFetcherOptions } from '../utils/types'
|
import type { HookInput, HookFetcher, HookFetcherOptions } from '../utils/types'
|
||||||
import useData, { ResponseState, SwrOptions } from '../utils/use-data'
|
import useData, { ResponseState, SwrOptions } from '../utils/use-data'
|
||||||
|
import type { Cart } from '../types'
|
||||||
import { useCommerce } from '..'
|
import { useCommerce } from '..'
|
||||||
|
|
||||||
export type CartResponse<Data> = ResponseState<Data> & { isEmpty?: boolean }
|
export type CartResponse<Data> = ResponseState<Data> & { isEmpty?: boolean }
|
||||||
|
|
||||||
export type CartInput = {
|
export type CartInput = {
|
||||||
cartId?: BaseCart['id']
|
cartId?: Cart['id']
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function useCart<Data extends BaseCart | null>(
|
export default function useCart<Data extends Cart | null>(
|
||||||
options: HookFetcherOptions,
|
options: HookFetcherOptions,
|
||||||
input: HookInput,
|
input: HookInput,
|
||||||
fetcherFn: HookFetcher<Data, CartInput>,
|
fetcherFn: HookFetcher<Data, CartInput>,
|
||||||
|
99
framework/commerce/types.d.ts
vendored
99
framework/commerce/types.d.ts
vendored
@ -45,105 +45,6 @@ interface ProductPrice {
|
|||||||
extendedListPrice?: number
|
extendedListPrice?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DiscountBase {
|
|
||||||
// The value of the discount, can be an amount or percentage
|
|
||||||
value: number
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BaseLineItem {
|
|
||||||
id: string
|
|
||||||
variantId: string
|
|
||||||
name: string
|
|
||||||
quantity: number
|
|
||||||
discounts: DiscountBase[]
|
|
||||||
// A human-friendly unique string automatically generated from the product’s name
|
|
||||||
path: string
|
|
||||||
variant: BaseProductVariant
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Measurement {
|
|
||||||
value: number
|
|
||||||
unit: 'KILOGRAMS' | 'GRAMS' | 'POUNDS' | 'OUNCES'
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Image {
|
|
||||||
url: string
|
|
||||||
altText?: string
|
|
||||||
width?: number
|
|
||||||
height?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BaseProductVariant {
|
|
||||||
id: string
|
|
||||||
// The SKU (stock keeping unit) associated with the product variant.
|
|
||||||
sku: string
|
|
||||||
// The product variant’s title, or the product's name.
|
|
||||||
name: string
|
|
||||||
// Whether a customer needs to provide a shipping address when placing
|
|
||||||
// an order for the product variant.
|
|
||||||
requiresShipping: boolean
|
|
||||||
// The product variant’s price after all discounts are applied.
|
|
||||||
price: number
|
|
||||||
// Product variant’s price, as quoted by the manufacturer/distributor.
|
|
||||||
listPrice: number
|
|
||||||
// Image associated with the product variant. Falls back to the product image
|
|
||||||
// if no image is available.
|
|
||||||
image?: Image
|
|
||||||
// Indicates whether this product variant is in stock.
|
|
||||||
isInStock?: boolean
|
|
||||||
// Indicates if the product variant is available for sale.
|
|
||||||
availableForSale?: boolean
|
|
||||||
// The variant's weight. If a weight was not explicitly specified on the
|
|
||||||
// variant this will be the product's weight.
|
|
||||||
weight?: Measurement
|
|
||||||
// The variant's height. If a height was not explicitly specified on the
|
|
||||||
// variant, this will be the product's height.
|
|
||||||
height?: Measurement
|
|
||||||
// The variant's width. If a width was not explicitly specified on the
|
|
||||||
// variant, this will be the product's width.
|
|
||||||
width?: Measurement
|
|
||||||
// The variant's depth. If a depth was not explicitly specified on the
|
|
||||||
// variant, this will be the product's depth.
|
|
||||||
depth?: Measurement
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shopping cart, a.k.a Checkout
|
|
||||||
interface BaseCart {
|
|
||||||
id: string
|
|
||||||
// ID of the customer to which the cart belongs.
|
|
||||||
customerId?: string
|
|
||||||
// The email assigned to this cart
|
|
||||||
email?: string
|
|
||||||
// The date and time when the cart was created.
|
|
||||||
createdAt: string
|
|
||||||
// The currency used for this cart
|
|
||||||
currency: { code: string }
|
|
||||||
// Specifies if taxes are included in the line items.
|
|
||||||
taxesIncluded: boolean
|
|
||||||
lineItems: BaseLineItem[]
|
|
||||||
// The sum of all the prices of all the items in the cart.
|
|
||||||
// Duties, taxes, shipping and discounts excluded.
|
|
||||||
lineItemsSubtotalPrice: number
|
|
||||||
// Price of the cart before duties, shipping and taxes.
|
|
||||||
subtotalPrice: number
|
|
||||||
// The sum of all the prices of all the items in the cart.
|
|
||||||
// Duties, taxes and discounts included.
|
|
||||||
totalPrice: number
|
|
||||||
// Discounts that have been applied on the cart.
|
|
||||||
discounts?: DiscountBase[]
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Remove this type in favor of BaseCart
|
|
||||||
interface Cart2 extends Entity {
|
|
||||||
id: string | undefined
|
|
||||||
currency: { code: string }
|
|
||||||
taxIncluded?: boolean
|
|
||||||
items: Pick<Product, 'id' | 'name' | 'prices'> & CartItem[]
|
|
||||||
subTotal: number | string
|
|
||||||
total: number | string
|
|
||||||
customerId: Customer['id']
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CartItem extends Entity {
|
interface CartItem extends Entity {
|
||||||
quantity: number
|
quantity: number
|
||||||
productId: Product['id']
|
productId: Product['id']
|
||||||
|
111
framework/commerce/types.ts
Normal file
111
framework/commerce/types.ts
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
export interface Discount {
|
||||||
|
// The value of the discount, can be an amount or percentage
|
||||||
|
value: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LineItem {
|
||||||
|
id: string
|
||||||
|
variantId: string
|
||||||
|
productId: string
|
||||||
|
name: string
|
||||||
|
quantity: number
|
||||||
|
discounts: Discount[]
|
||||||
|
// A human-friendly unique string automatically generated from the product’s name
|
||||||
|
path: string
|
||||||
|
variant: ProductVariant
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Measurement {
|
||||||
|
value: number
|
||||||
|
unit: 'KILOGRAMS' | 'GRAMS' | 'POUNDS' | 'OUNCES'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Image {
|
||||||
|
url: string
|
||||||
|
altText?: string
|
||||||
|
width?: number
|
||||||
|
height?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProductVariant {
|
||||||
|
id: string
|
||||||
|
// The SKU (stock keeping unit) associated with the product variant.
|
||||||
|
sku: string
|
||||||
|
// The product variant’s title, or the product's name.
|
||||||
|
name: string
|
||||||
|
// Whether a customer needs to provide a shipping address when placing
|
||||||
|
// an order for the product variant.
|
||||||
|
requiresShipping: boolean
|
||||||
|
// The product variant’s price after all discounts are applied.
|
||||||
|
price: number
|
||||||
|
// Product variant’s price, as quoted by the manufacturer/distributor.
|
||||||
|
listPrice: number
|
||||||
|
// Image associated with the product variant. Falls back to the product image
|
||||||
|
// if no image is available.
|
||||||
|
image?: Image
|
||||||
|
// Indicates whether this product variant is in stock.
|
||||||
|
isInStock?: boolean
|
||||||
|
// Indicates if the product variant is available for sale.
|
||||||
|
availableForSale?: boolean
|
||||||
|
// The variant's weight. If a weight was not explicitly specified on the
|
||||||
|
// variant this will be the product's weight.
|
||||||
|
weight?: Measurement
|
||||||
|
// The variant's height. If a height was not explicitly specified on the
|
||||||
|
// variant, this will be the product's height.
|
||||||
|
height?: Measurement
|
||||||
|
// The variant's width. If a width was not explicitly specified on the
|
||||||
|
// variant, this will be the product's width.
|
||||||
|
width?: Measurement
|
||||||
|
// The variant's depth. If a depth was not explicitly specified on the
|
||||||
|
// variant, this will be the product's depth.
|
||||||
|
depth?: Measurement
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shopping cart, a.k.a Checkout
|
||||||
|
export interface Cart {
|
||||||
|
id: string
|
||||||
|
// ID of the customer to which the cart belongs.
|
||||||
|
customerId?: string
|
||||||
|
// The email assigned to this cart
|
||||||
|
email?: string
|
||||||
|
// The date and time when the cart was created.
|
||||||
|
createdAt: string
|
||||||
|
// The currency used for this cart
|
||||||
|
currency: { code: string }
|
||||||
|
// Specifies if taxes are included in the line items.
|
||||||
|
taxesIncluded: boolean
|
||||||
|
lineItems: LineItem[]
|
||||||
|
// The sum of all the prices of all the items in the cart.
|
||||||
|
// Duties, taxes, shipping and discounts excluded.
|
||||||
|
lineItemsSubtotalPrice: number
|
||||||
|
// Price of the cart before duties, shipping and taxes.
|
||||||
|
subtotalPrice: number
|
||||||
|
// The sum of all the prices of all the items in the cart.
|
||||||
|
// Duties, taxes and discounts included.
|
||||||
|
totalPrice: number
|
||||||
|
// Discounts that have been applied on the cart.
|
||||||
|
discounts?: Discount[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base cart item body used for cart mutations
|
||||||
|
export interface CartItemBody {
|
||||||
|
variantId: string
|
||||||
|
productId?: string
|
||||||
|
quantity?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
// Body by the update operation
|
||||||
|
export interface UpdateCartItemBody {
|
||||||
|
itemId: string
|
||||||
|
item: CartItemBody
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input expected by the `useUpdateItem` hook
|
||||||
|
export type UpdateCartItemInput<T extends CartItemBody> = T & {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Body expected by the update operation handler
|
||||||
|
export interface UpdateCartItemHandlerBody extends Partial<UpdateCartItemBody> {
|
||||||
|
cartId?: string
|
||||||
|
}
|
@ -26,6 +26,14 @@ export class CommerceError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used for errors that come from a bad implementation of the hooks
|
||||||
|
export class ValidationError extends CommerceError {
|
||||||
|
constructor(options: ErrorProps) {
|
||||||
|
super(options)
|
||||||
|
this.code = 'validation_error'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class FetcherError extends CommerceError {
|
export class FetcherError extends CommerceError {
|
||||||
status: number
|
status: number
|
||||||
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
// Core fetcher added by CommerceProvider
|
// Core fetcher added by CommerceProvider
|
||||||
export type Fetcher<T> = (options: FetcherOptions) => T | Promise<T>
|
export type Fetcher<T> = (options: FetcherOptions) => T | Promise<T>
|
||||||
|
|
||||||
export type FetcherOptions = {
|
export type FetcherOptions<Body = any> = {
|
||||||
url?: string
|
url?: string
|
||||||
query?: string
|
query?: string
|
||||||
method?: string
|
method?: string
|
||||||
variables?: any
|
variables?: any
|
||||||
body?: any
|
body?: Body
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HookFetcher<Data, Input = null, Result = any> = (
|
export type HookFetcher<Data, Input = null, Result = any> = (
|
||||||
options: HookFetcherOptions | null,
|
options: HookFetcherOptions | null,
|
||||||
input: Input,
|
input: Input,
|
||||||
fetch: <T = Result>(options: FetcherOptions) => Promise<T>
|
fetch: <T = Result, Body = any>(options: FetcherOptions<Body>) => Promise<T>
|
||||||
) => Data | Promise<Data>
|
) => Data | Promise<Data>
|
||||||
|
|
||||||
export type HookFetcherOptions = {
|
export type HookFetcherOptions = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user