forked from crowetic/commerce
Update types (#831)
* Update product types * Cart types progress, add zod & initial schema validator * Update normalize.ts * Update with-schema-parser.ts * Updated types, schemas & providers * Fix providers after schema parse errors * Fix paths * More provider fixes * Fix kibocommerce & commercejs * Add customer updated types & fixes * Add checkout & customer types * Import core types only from commerce * Update tsconfig.json * Convert hooks interfaces to types * Requested changes * Change to relative paths * Move Zod dependency
This commit is contained in:
parent
8398a96215
commit
6c2610584d
15
README.md
15
README.md
@ -23,8 +23,8 @@ Demo live at: [demo.vercel.store](https://demo.vercel.store/)
|
||||
> To run a minimal version of Next.js Commerce you can start with the default local provider `@vercel/commerce-local` that has disabled all features (cart, auth) and use static files for the backend
|
||||
|
||||
```bash
|
||||
pnpm install # run this command in root folder of the mono repo
|
||||
pnpm dev
|
||||
pnpm install & pnpm build # run this commands in root folder of the mono repo
|
||||
pnpm dev # run this commands in the site folder
|
||||
```
|
||||
|
||||
> If you encounter any problems while installing and running for the first time, please see the Troubleshoot section
|
||||
@ -111,10 +111,11 @@ Our commitment to Open Source can be found [here](https://vercel.com/oss).
|
||||
1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device.
|
||||
2. Create a new branch `git checkout -b MY_BRANCH_NAME`
|
||||
3. Install the dependencies: `pnpm install`
|
||||
4. Duplicate `site/.env.template` and rename it to `site/.env.local`
|
||||
5. Add proper store values to `site/.env.local`
|
||||
6. Run `pnpm dev` to build the packages and watch for code changes
|
||||
7. Run `pnpm turbo run build` to check the build after your changes
|
||||
4. Build the packages: `pnpm build`
|
||||
5. Duplicate `site/.env.template` and rename it to `site/.env.local`
|
||||
6. Add proper store values to `site/.env.local`
|
||||
7. Run `cd site` & `pnpm dev` to watch for code changes
|
||||
8. Run `pnpm turbo run build` to check the build after your changes
|
||||
|
||||
## Work in progress
|
||||
|
||||
@ -191,7 +192,7 @@ info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this comm
|
||||
|
||||
The error usually occurs when running `pnpm dev` inside of the `/site/` folder after installing a fresh repository.
|
||||
|
||||
In order to fix this, run `pnpm dev` in the monorepo root folder first.
|
||||
In order to fix this, run `pnpm build` in the monorepo root folder first.
|
||||
|
||||
> Using `pnpm dev` from the root is recommended for developing, which will run watch mode on all packages.
|
||||
|
||||
|
@ -1130,7 +1130,7 @@ export interface definitions {
|
||||
*/
|
||||
search_keywords?: string
|
||||
/**
|
||||
* Image URL used for this category on the storefront. Images can be uploaded via form file post to `/brands/{brandId}/image`, or by providing a publicly accessible URL in this field.
|
||||
* Image URL used for this category on the storefront. Images can be uploaded via form file post to `/{brandId}/image`, or by providing a publicly accessible URL in this field.
|
||||
*/
|
||||
image_url?: string
|
||||
custom_url?: definitions['customUrl_Full']
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { normalizeCart } from '../../../lib/normalize'
|
||||
import { BigcommerceApiError } from '../../utils/errors'
|
||||
import getCartCookie from '../../utils/get-cart-cookie'
|
||||
import type { BigcommerceCart } from '../../../types/cart'
|
||||
import type { BigcommerceCart } from '../../../types'
|
||||
import type { CartEndpoint } from '.'
|
||||
|
||||
// Return current cart info
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||
import cartEndpoint from '@vercel/commerce/api/endpoints/cart'
|
||||
import type { CartSchema } from '../../../types/cart'
|
||||
import type { CartSchema } from '@vercel/commerce/types/cart'
|
||||
import type { BigcommerceAPI } from '../..'
|
||||
import getCart from './get-cart'
|
||||
import addItem from './add-item'
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||
import productsEndpoint from '@vercel/commerce/api/endpoints/catalog/products'
|
||||
import type { ProductsSchema } from '../../../../types/product'
|
||||
import type { ProductsSchema } from '@vercel/commerce/types/product'
|
||||
import type { BigcommerceAPI } from '../../..'
|
||||
import getProducts from './get-products'
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||
import checkoutEndpoint from '@vercel/commerce/api/endpoints/checkout'
|
||||
import type { CheckoutSchema } from '../../../types/checkout'
|
||||
import type { CheckoutSchema } from '@vercel/commerce/types/checkout'
|
||||
import type { BigcommerceAPI } from '../..'
|
||||
import getCheckout from './get-checkout'
|
||||
|
||||
|
@ -47,7 +47,19 @@ const getLoggedInCustomer: CustomerEndpoint['handlers']['getLoggedInCustomer'] =
|
||||
})
|
||||
}
|
||||
|
||||
return res.status(200).json({ data: { customer } })
|
||||
return res.status(200).json({
|
||||
data: {
|
||||
customer: {
|
||||
id: String(customer.entityId),
|
||||
firstName: customer.firstName,
|
||||
lastName: customer.lastName,
|
||||
email: customer.email,
|
||||
company: customer.company,
|
||||
phone: customer.phone,
|
||||
notes: customer.notes,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
res.status(200).json({ data: null })
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||
import customerEndpoint from '@vercel/commerce/api/endpoints/customer'
|
||||
import type { CustomerSchema } from '../../../types/customer'
|
||||
import type { CustomerSchema } from '@vercel/commerce/types/customer'
|
||||
import type { BigcommerceAPI } from '../..'
|
||||
import getLoggedInCustomer from './get-logged-in-customer'
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||
import loginEndpoint from '@vercel/commerce/api/endpoints/login'
|
||||
import type { LoginSchema } from '../../../types/login'
|
||||
import type { LoginSchema } from '@vercel/commerce/types/login'
|
||||
import type { BigcommerceAPI } from '../..'
|
||||
import login from './login'
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||
import logoutEndpoint from '@vercel/commerce/api/endpoints/logout'
|
||||
import type { LogoutSchema } from '../../../types/logout'
|
||||
import type { LogoutSchema } from '@vercel/commerce/types/logout'
|
||||
import type { BigcommerceAPI } from '../..'
|
||||
import logout from './logout'
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||
import signupEndpoint from '@vercel/commerce/api/endpoints/signup'
|
||||
import type { SignupSchema } from '../../../types/signup'
|
||||
import type { SignupSchema } from '@vercel/commerce/types/signup'
|
||||
import type { BigcommerceAPI } from '../..'
|
||||
import signup from './signup'
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type { Wishlist } from '../../../types/wishlist'
|
||||
import type { Wishlist } from '@vercel/commerce/types/wishlist'
|
||||
import type { WishlistEndpoint } from '.'
|
||||
import getCustomerId from '../../utils/get-customer-id'
|
||||
import getCustomerWishlist from '../../operations/get-customer-wishlist'
|
||||
|
||||
// Return wishlist info
|
||||
const getWishlist: WishlistEndpoint['handlers']['getWishlist'] = async ({
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||
import wishlistEndpoint from '@vercel/commerce/api/endpoints/wishlist'
|
||||
import type { WishlistSchema } from '../../../types/wishlist'
|
||||
import type { WishlistSchema } from '@vercel/commerce/types/wishlist'
|
||||
import type { BigcommerceAPI } from '../..'
|
||||
import getWishlist from './get-wishlist'
|
||||
import addItem from './add-item'
|
||||
|
@ -1,5 +1,4 @@
|
||||
import type { Wishlist } from '../../../types/wishlist'
|
||||
import getCustomerWishlist from '../../operations/get-customer-wishlist'
|
||||
import type { Wishlist } from '@vercel/commerce/types/wishlist'
|
||||
import getCustomerId from '../../utils/get-customer-id'
|
||||
import type { WishlistEndpoint } from '.'
|
||||
|
||||
|
@ -2,10 +2,13 @@ import type {
|
||||
OperationContext,
|
||||
OperationOptions,
|
||||
} from '@vercel/commerce/api/operations'
|
||||
import type { Page, GetAllPagesOperation } from '../../types/page'
|
||||
import type { GetAllPagesOperation } from '@vercel/commerce/types/page'
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
|
||||
import { BigcommerceConfig, Provider } from '..'
|
||||
|
||||
import { definitions } from '../definitions/store-content'
|
||||
import { normalizePage } from '../../lib/normalize'
|
||||
|
||||
export default function getAllPagesOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
@ -33,12 +36,14 @@ export default function getAllPagesOperation({
|
||||
// RecursivePartial forces the method to check for every prop in the data, which is
|
||||
// required in case there's a custom `url`
|
||||
const { data } = await cfg.storeApiFetch<
|
||||
RecursivePartial<{ data: Page[] }>
|
||||
RecursivePartial<{ data: definitions['page_Full'][] }>
|
||||
>('/v3/content/pages')
|
||||
const pages = (data as RecursiveRequired<typeof data>) ?? []
|
||||
|
||||
return {
|
||||
pages: preview ? pages : pages.filter((p) => p.is_visible),
|
||||
pages: preview
|
||||
? pages.map(normalizePage)
|
||||
: pages.filter((p) => p.is_visible).map(normalizePage),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ import type {
|
||||
OperationOptions,
|
||||
} from '@vercel/commerce/api/operations'
|
||||
import type { GetAllProductPathsQuery } from '../../../schema'
|
||||
import type { GetAllProductPathsOperation } from '../../types/product'
|
||||
import type { GetAllProductPathsOperation } from '@vercel/commerce/types/product'
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
|
||||
import filterEdges from '../utils/filter-edges'
|
||||
import { BigcommerceConfig, Provider } from '..'
|
||||
|
@ -6,7 +6,7 @@ import type {
|
||||
GetAllProductsQuery,
|
||||
GetAllProductsQueryVariables,
|
||||
} from '../../../schema'
|
||||
import type { GetAllProductsOperation } from '../../types/product'
|
||||
import type { GetAllProductsOperation } from '@vercel/commerce/types/product'
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
|
||||
import filterEdges from '../utils/filter-edges'
|
||||
import setProductLocaleMeta from '../utils/set-product-locale-meta'
|
||||
|
@ -5,7 +5,7 @@ import type {
|
||||
import type {
|
||||
GetCustomerWishlistOperation,
|
||||
Wishlist,
|
||||
} from '../../types/wishlist'
|
||||
} from '@vercel/commerce/types/wishlist'
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
|
||||
import { BigcommerceConfig, Provider } from '..'
|
||||
import getAllProducts, { ProductEdge } from './get-all-products'
|
||||
@ -49,7 +49,7 @@ export default function getCustomerWishlistOperation({
|
||||
|
||||
if (includeProducts && wishlist?.items?.length) {
|
||||
const ids = wishlist.items
|
||||
?.map((item) => (item?.product_id ? String(item?.product_id) : null))
|
||||
?.map((item) => (item?.productId ? String(item?.productId) : null))
|
||||
.filter((id): id is string => !!id)
|
||||
|
||||
if (ids?.length) {
|
||||
@ -66,7 +66,7 @@ export default function getCustomerWishlistOperation({
|
||||
}, {})
|
||||
// Populate the wishlist items with the graphql products
|
||||
wishlist.items.forEach((item) => {
|
||||
const product = item && productsById[item.product_id!]
|
||||
const product = item && productsById[Number(item.productId)]
|
||||
if (item && product) {
|
||||
// @ts-ignore Fix this type when the wishlist type is properly defined
|
||||
item.product = product
|
||||
|
@ -2,7 +2,7 @@ import type {
|
||||
OperationContext,
|
||||
OperationOptions,
|
||||
} from '@vercel/commerce/api/operations'
|
||||
import type { GetPageOperation, Page } from '../../types/page'
|
||||
import type { GetPageOperation, Page } from '@vercel/commerce/types/page'
|
||||
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
|
||||
import type { BigcommerceConfig, Provider } from '..'
|
||||
import { normalizePage } from '../../lib/normalize'
|
||||
|
@ -2,7 +2,7 @@ import type {
|
||||
OperationContext,
|
||||
OperationOptions,
|
||||
} from '@vercel/commerce/api/operations'
|
||||
import type { GetProductOperation } from '../../types/product'
|
||||
import type { GetProductOperation } from '@vercel/commerce/types/product'
|
||||
import type { GetProductQuery, GetProductQueryVariables } from '../../../schema'
|
||||
import setProductLocaleMeta from '../utils/set-product-locale-meta'
|
||||
import { productInfoFragment } from '../fragments/product'
|
||||
@ -100,7 +100,7 @@ export default function getAllProductPathsOperation({
|
||||
const variables: GetProductQueryVariables = {
|
||||
locale,
|
||||
hasLocale: !!locale,
|
||||
path: slug ? `/${slug}/` : vars.path!,
|
||||
path: slug ? `/${slug}` : vars.path!,
|
||||
}
|
||||
const { data } = await config.fetch<GetProductQuery>(query, { variables })
|
||||
const product = data.site?.route?.node
|
||||
|
@ -2,12 +2,12 @@ import type {
|
||||
OperationContext,
|
||||
OperationOptions,
|
||||
} from '@vercel/commerce/api/operations'
|
||||
import type { GetSiteInfoOperation } from '../../types/site'
|
||||
import type { GetSiteInfoOperation } from '@vercel/commerce/types/site'
|
||||
import type { GetSiteInfoQuery } from '../../../schema'
|
||||
import filterEdges from '../utils/filter-edges'
|
||||
import type { BigcommerceConfig, Provider } from '..'
|
||||
import { categoryTreeItemFragment } from '../fragments/category-tree'
|
||||
import { normalizeCategory } from '../../lib/normalize'
|
||||
import { normalizeBrand, normalizeCategory } from '../../lib/normalize'
|
||||
|
||||
// Get 3 levels of categories
|
||||
export const getSiteInfoQuery = /* GraphQL */ `
|
||||
@ -79,7 +79,7 @@ export default function getSiteInfoOperation({
|
||||
|
||||
return {
|
||||
categories: categories ?? [],
|
||||
brands: filterEdges(brands),
|
||||
brands: filterEdges(brands).map(normalizeBrand),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ import type {
|
||||
OperationContext,
|
||||
OperationOptions,
|
||||
} from '@vercel/commerce/api/operations'
|
||||
import type { LoginOperation } from '../../types/login'
|
||||
import type { LoginOperation } from '@vercel/commerce/types/login'
|
||||
import type { LoginMutation } from '../../../schema'
|
||||
import type { RecursivePartial } from '../utils/types'
|
||||
import concatHeader from '../utils/concat-cookie'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { WishlistItemBody } from '../../types/wishlist'
|
||||
import type { CartItemBody, OptionSelections } from '../../types/cart'
|
||||
import type { WishlistItemBody } from '@vercel/commerce/types/wishlist'
|
||||
import type { CartItemBody, SelectedOption } from '@vercel/commerce/types/cart'
|
||||
|
||||
type BCWishlistItemBody = {
|
||||
product_id: number
|
||||
@ -10,7 +10,7 @@ type BCCartItemBody = {
|
||||
product_id: number
|
||||
variant_id: number
|
||||
quantity?: number
|
||||
option_selections?: OptionSelections[]
|
||||
option_selections?: SelectedOption[]
|
||||
}
|
||||
|
||||
export const parseWishlistItem = (
|
||||
@ -24,5 +24,5 @@ export const parseCartItem = (item: CartItemBody): BCCartItemBody => ({
|
||||
quantity: item.quantity,
|
||||
product_id: Number(item.productId),
|
||||
variant_id: Number(item.variantId),
|
||||
option_selections: item.optionSelections,
|
||||
option_selections: item.optionsSelected,
|
||||
})
|
||||
|
@ -2,7 +2,7 @@ import { useCallback } from 'react'
|
||||
import type { MutationHook } from '@vercel/commerce/utils/types'
|
||||
import { CommerceError } from '@vercel/commerce/utils/errors'
|
||||
import useLogin, { UseLogin } from '@vercel/commerce/auth/use-login'
|
||||
import type { LoginHook } from '../types/login'
|
||||
import type { LoginHook } from '@vercel/commerce/types/login'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
|
||||
export default useLogin as UseLogin<typeof handler>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useCallback } from 'react'
|
||||
import type { MutationHook } from '@vercel/commerce/utils/types'
|
||||
import useLogout, { UseLogout } from '@vercel/commerce/auth/use-logout'
|
||||
import type { LogoutHook } from '../types/logout'
|
||||
import type { LogoutHook } from '@vercel/commerce/types/logout'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
|
||||
export default useLogout as UseLogout<typeof handler>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { useCallback } from 'react'
|
||||
import type { MutationHook } from '@vercel/commerce/utils/types'
|
||||
import { CommerceError } from '@vercel/commerce/utils/errors'
|
||||
import useSignup, { UseSignup } from '@vercel/commerce/auth/use-signup'
|
||||
import type { SignupHook } from '../types/signup'
|
||||
import useSignup, { type UseSignup } from '@vercel/commerce/auth/use-signup'
|
||||
import type { SignupHook } from '@vercel/commerce/types/signup'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
|
||||
export default useSignup as UseSignup<typeof handler>
|
||||
|
@ -4,8 +4,14 @@ import type {
|
||||
HookFetcherContext,
|
||||
} from '@vercel/commerce/utils/types'
|
||||
import { ValidationError } from '@vercel/commerce/utils/errors'
|
||||
import useRemoveItem, { UseRemoveItem } from '@vercel/commerce/cart/use-remove-item'
|
||||
import type { Cart, LineItem, RemoveItemHook } from '@vercel/commerce/types/cart'
|
||||
import useRemoveItem, {
|
||||
UseRemoveItem,
|
||||
} from '@vercel/commerce/cart/use-remove-item'
|
||||
import type {
|
||||
Cart,
|
||||
LineItem,
|
||||
RemoveItemHook,
|
||||
} from '@vercel/commerce/types/cart'
|
||||
import useCart from './use-cart'
|
||||
|
||||
export type RemoveItemFn<T = any> = T extends LineItem
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { SWRHook } from '@vercel/commerce/utils/types'
|
||||
import useCustomer, { UseCustomer } from '@vercel/commerce/customer/use-customer'
|
||||
import type { CustomerHook } from '../types/customer'
|
||||
import type { SWRHook } from '@vercel/commerce/utils/types'
|
||||
import useCustomer, {
|
||||
type UseCustomer,
|
||||
} from '@vercel/commerce/customer/use-customer'
|
||||
import type { CustomerHook } from '@vercel/commerce/types/customer'
|
||||
|
||||
export default useCustomer as UseCustomer<typeof handler>
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
import type { Product } from '../types/product'
|
||||
import type { Cart, BigcommerceCart, LineItem } from '../types/cart'
|
||||
import type { Page } from '../types/page'
|
||||
import type { BCCategory, Category } from '../types/site'
|
||||
import type { Page } from '@vercel/commerce/types/page'
|
||||
import type { Product } from '@vercel/commerce/types/product'
|
||||
import type { Cart, LineItem } from '@vercel/commerce/types/cart'
|
||||
import type { Category, Brand } from '@vercel/commerce/types/site'
|
||||
import type { BigcommerceCart, BCCategory, BCBrand } from '../types'
|
||||
|
||||
import { definitions } from '../api/definitions/store-content'
|
||||
import update from './immutability'
|
||||
import getSlug from './get-slug'
|
||||
@ -12,7 +14,7 @@ function normalizeProductOption(productOption: any) {
|
||||
} = productOption
|
||||
|
||||
return {
|
||||
id: entityId,
|
||||
id: String(entityId),
|
||||
values: edges?.map(({ node }: any) => node),
|
||||
...rest,
|
||||
}
|
||||
@ -41,7 +43,7 @@ export function normalizeProduct(productNode: any): Product {
|
||||
variants: {
|
||||
$apply: ({ edges }: any) =>
|
||||
edges?.map(({ node: { entityId, productOptions, ...rest } }: any) => ({
|
||||
id: entityId,
|
||||
id: String(entityId),
|
||||
options: productOptions?.edges
|
||||
? productOptions.edges.map(normalizeProductOption)
|
||||
: [],
|
||||
@ -54,7 +56,7 @@ export function normalizeProduct(productNode: any): Product {
|
||||
: [],
|
||||
},
|
||||
brand: {
|
||||
$apply: (brand: any) => (brand?.entityId ? brand?.entityId : null),
|
||||
$apply: (brand: any) => (brand?.id ? brand.id : null),
|
||||
},
|
||||
slug: {
|
||||
$set: path?.replace(/^\/+|\/+$/g, ''),
|
||||
@ -75,7 +77,8 @@ export function normalizePage(page: definitions['page_Full']): Page {
|
||||
name: page.name,
|
||||
is_visible: page.is_visible,
|
||||
sort_order: page.sort_order,
|
||||
body: page.body,
|
||||
body: page.body ?? '',
|
||||
url: page.url,
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,3 +137,12 @@ export function normalizeCategory(category: BCCategory): Category {
|
||||
path: category.path,
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeBrand(brand: BCBrand): Brand {
|
||||
return {
|
||||
id: `${brand.node.entityId}`,
|
||||
name: brand.node.name,
|
||||
slug: getSlug(brand.node.path),
|
||||
path: brand.node.path,
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { SWRHook } from '@vercel/commerce/utils/types'
|
||||
import useSearch, { UseSearch } from '@vercel/commerce/product/use-search'
|
||||
import type { SearchProductsHook } from '../types/product'
|
||||
import type { SearchProductsHook } from '@vercel/commerce/types/product'
|
||||
|
||||
export default useSearch as UseSearch<typeof handler>
|
||||
|
||||
|
32
packages/bigcommerce/src/types.ts
Normal file
32
packages/bigcommerce/src/types.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import type { GetSiteInfoQuery } from '../schema'
|
||||
|
||||
export type BCCategory = NonNullable<
|
||||
GetSiteInfoQuery['site']['categoryTree']
|
||||
>[0]
|
||||
|
||||
export type BCBrand = NonNullable<
|
||||
NonNullable<GetSiteInfoQuery['site']['brands']['edges']>[0]
|
||||
>
|
||||
|
||||
// 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
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
import * as Core from '@vercel/commerce/types/cart'
|
||||
|
||||
export * from '@vercel/commerce/types/cart'
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend core cart types
|
||||
*/
|
||||
|
||||
export type Cart = Core.Cart & {
|
||||
lineItems: Core.LineItem[]
|
||||
}
|
||||
|
||||
export type OptionSelections = {
|
||||
option_id: number
|
||||
option_value: number | string
|
||||
}
|
||||
|
||||
export type CartItemBody = Core.CartItemBody & {
|
||||
productId: string // The product id is always required for BC
|
||||
optionSelections?: OptionSelections[]
|
||||
}
|
||||
|
||||
export type CartTypes = {
|
||||
cart: Cart
|
||||
item: Core.LineItem
|
||||
itemBody: CartItemBody
|
||||
}
|
||||
|
||||
export type CartHooks = Core.CartHooks<CartTypes>
|
||||
|
||||
export type GetCartHook = CartHooks['getCart']
|
||||
export type AddItemHook = CartHooks['addItem']
|
||||
export type UpdateItemHook = CartHooks['updateItem']
|
||||
export type RemoveItemHook = CartHooks['removeItem']
|
||||
|
||||
export type CartSchema = Core.CartSchema<CartTypes>
|
||||
|
||||
export type CartHandlers = Core.CartHandlers<CartTypes>
|
||||
|
||||
export type GetCartHandler = CartHandlers['getCart']
|
||||
export type AddItemHandler = CartHandlers['addItem']
|
||||
export type UpdateItemHandler = CartHandlers['updateItem']
|
||||
export type RemoveItemHandler = CartHandlers['removeItem']
|
@ -1 +0,0 @@
|
||||
export * from '@vercel/commerce/types/checkout'
|
@ -1 +0,0 @@
|
||||
export * from '@vercel/commerce/types/common'
|
@ -1,5 +0,0 @@
|
||||
import * as Core from '@vercel/commerce/types/customer'
|
||||
|
||||
export * from '@vercel/commerce/types/customer'
|
||||
|
||||
export type CustomerSchema = Core.CustomerSchema
|
@ -1,25 +0,0 @@
|
||||
import * as Cart from './cart'
|
||||
import * as Checkout from './checkout'
|
||||
import * as Common from './common'
|
||||
import * as Customer from './customer'
|
||||
import * as Login from './login'
|
||||
import * as Logout from './logout'
|
||||
import * as Page from './page'
|
||||
import * as Product from './product'
|
||||
import * as Signup from './signup'
|
||||
import * as Site from './site'
|
||||
import * as Wishlist from './wishlist'
|
||||
|
||||
export type {
|
||||
Cart,
|
||||
Checkout,
|
||||
Common,
|
||||
Customer,
|
||||
Login,
|
||||
Logout,
|
||||
Page,
|
||||
Product,
|
||||
Signup,
|
||||
Site,
|
||||
Wishlist,
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
import * as Core from '@vercel/commerce/types/login'
|
||||
import type { LoginMutationVariables } from '../../schema'
|
||||
|
||||
export * from '@vercel/commerce/types/login'
|
||||
|
||||
export type LoginOperation = Core.LoginOperation & {
|
||||
variables: LoginMutationVariables
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from '@vercel/commerce/types/logout'
|
@ -1,11 +0,0 @@
|
||||
import * as Core from '@vercel/commerce/types/page'
|
||||
export * from '@vercel/commerce/types/page'
|
||||
|
||||
export type Page = Core.Page
|
||||
|
||||
export type PageTypes = {
|
||||
page: Page
|
||||
}
|
||||
|
||||
export type GetAllPagesOperation = Core.GetAllPagesOperation<PageTypes>
|
||||
export type GetPageOperation = Core.GetPageOperation<PageTypes>
|
@ -1 +0,0 @@
|
||||
export * from '@vercel/commerce/types/product'
|
@ -1 +0,0 @@
|
||||
export * from '@vercel/commerce/types/signup'
|
@ -1,19 +0,0 @@
|
||||
import * as Core from '@vercel/commerce/types/site'
|
||||
import type { GetSiteInfoQuery, GetSiteInfoQueryVariables } from '../../schema'
|
||||
|
||||
export * from '@vercel/commerce/types/site'
|
||||
|
||||
export type BCCategory = NonNullable<
|
||||
GetSiteInfoQuery['site']['categoryTree']
|
||||
>[0]
|
||||
|
||||
export type Brand = NonNullable<
|
||||
NonNullable<GetSiteInfoQuery['site']['brands']['edges']>[0]
|
||||
>
|
||||
|
||||
export type SiteTypes = {
|
||||
category: Core.Category
|
||||
brand: Brand
|
||||
}
|
||||
|
||||
export type GetSiteInfoOperation = Core.GetSiteInfoOperation<SiteTypes>
|
@ -1,24 +0,0 @@
|
||||
import * as Core from '@vercel/commerce/types/wishlist'
|
||||
import { definitions } from '../api/definitions/wishlist'
|
||||
import type { ProductEdge } from '../api/operations/get-all-products'
|
||||
|
||||
export * from '@vercel/commerce/types/wishlist'
|
||||
|
||||
export type WishlistItem = NonNullable<
|
||||
definitions['wishlist_Full']['items']
|
||||
>[0] & {
|
||||
product?: ProductEdge['node']
|
||||
}
|
||||
|
||||
export type Wishlist = Omit<definitions['wishlist_Full'], 'items'> & {
|
||||
items?: WishlistItem[]
|
||||
}
|
||||
|
||||
export type WishlistTypes = {
|
||||
wishlist: Wishlist
|
||||
itemBody: Core.WishlistItemBody
|
||||
}
|
||||
|
||||
export type WishlistSchema = Core.WishlistSchema<WishlistTypes>
|
||||
export type GetCustomerWishlistOperation =
|
||||
Core.GetCustomerWishlistOperation<WishlistTypes>
|
@ -1,8 +1,10 @@
|
||||
import { useCallback } from 'react'
|
||||
import type { MutationHook } from '@vercel/commerce/utils/types'
|
||||
import { CommerceError } from '@vercel/commerce/utils/errors'
|
||||
import useAddItem, { UseAddItem } from '@vercel/commerce/wishlist/use-add-item'
|
||||
import type { AddItemHook } from '../types/wishlist'
|
||||
import useAddItem, {
|
||||
type UseAddItem,
|
||||
} from '@vercel/commerce/wishlist/use-add-item'
|
||||
import type { AddItemHook } from '@vercel/commerce/types/wishlist'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
import useWishlist from './use-wishlist'
|
||||
|
||||
|
@ -2,9 +2,9 @@ import { useCallback } from 'react'
|
||||
import type { MutationHook } from '@vercel/commerce/utils/types'
|
||||
import { CommerceError } from '@vercel/commerce/utils/errors'
|
||||
import useRemoveItem, {
|
||||
UseRemoveItem,
|
||||
type UseRemoveItem,
|
||||
} from '@vercel/commerce/wishlist/use-remove-item'
|
||||
import type { RemoveItemHook } from '../types/wishlist'
|
||||
import type { RemoveItemHook } from '@vercel/commerce/types/wishlist'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
import useWishlist from './use-wishlist'
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { useMemo } from 'react'
|
||||
import { SWRHook } from '@vercel/commerce/utils/types'
|
||||
import useWishlist, {
|
||||
UseWishlist,
|
||||
type UseWishlist,
|
||||
} from '@vercel/commerce/wishlist/use-wishlist'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
|
||||
import type { GetWishlistHook } from '../types/wishlist'
|
||||
import type { GetWishlistHook } from '@vercel/commerce/types/wishlist'
|
||||
|
||||
export default useWishlist as UseWishlist<typeof handler>
|
||||
export const handler: SWRHook<GetWishlistHook> = {
|
||||
@ -32,7 +32,7 @@ export const handler: SWRHook<GetWishlistHook> = {
|
||||
const { data: customer } = useCustomer()
|
||||
const response = useData({
|
||||
input: [
|
||||
['customerId', customer?.entityId],
|
||||
['customerId', customer?.id],
|
||||
['includeProducts', input?.includeProducts],
|
||||
],
|
||||
swrOptions: {
|
||||
|
@ -52,7 +52,8 @@
|
||||
"import-cwd": "^3.0.0",
|
||||
"js-cookie": "^3.0.1",
|
||||
"swr": "^1.3.0",
|
||||
"node-fetch": "^2.6.7"
|
||||
"node-fetch": "^2.6.7",
|
||||
"zod": "^3.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^12",
|
||||
|
@ -3,58 +3,60 @@ import { CommerceAPIError } from '../utils/errors'
|
||||
import isAllowedOperation from '../utils/is-allowed-operation'
|
||||
import type { GetAPISchema } from '..'
|
||||
|
||||
const cartEndpoint: GetAPISchema<any, CartSchema<any>>['endpoint']['handler'] =
|
||||
async (ctx) => {
|
||||
const { req, res, handlers, config } = ctx
|
||||
const cartEndpoint: GetAPISchema<
|
||||
any,
|
||||
CartSchema
|
||||
>['endpoint']['handler'] = async (ctx) => {
|
||||
const { req, res, handlers, config } = ctx
|
||||
|
||||
if (
|
||||
!isAllowedOperation(req, res, {
|
||||
GET: handlers['getCart'],
|
||||
POST: handlers['addItem'],
|
||||
PUT: handlers['updateItem'],
|
||||
DELETE: handlers['removeItem'],
|
||||
})
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const { cookies } = req
|
||||
const cartId = cookies[config.cartCookie]
|
||||
|
||||
try {
|
||||
// Return current cart info
|
||||
if (req.method === 'GET') {
|
||||
const body = { cartId }
|
||||
return await handlers['getCart']({ ...ctx, body })
|
||||
}
|
||||
|
||||
// Create or add an item to the cart
|
||||
if (req.method === 'POST') {
|
||||
const body = { ...req.body, cartId }
|
||||
return await handlers['addItem']({ ...ctx, body })
|
||||
}
|
||||
|
||||
// Update item in cart
|
||||
if (req.method === 'PUT') {
|
||||
const body = { ...req.body, cartId }
|
||||
return await handlers['updateItem']({ ...ctx, body })
|
||||
}
|
||||
|
||||
// Remove an item from the cart
|
||||
if (req.method === 'DELETE') {
|
||||
const body = { ...req.body, cartId }
|
||||
return await handlers['removeItem']({ ...ctx, body })
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
const message =
|
||||
error instanceof CommerceAPIError
|
||||
? 'An unexpected error ocurred with the Commerce API'
|
||||
: 'An unexpected error ocurred'
|
||||
|
||||
res.status(500).json({ data: null, errors: [{ message }] })
|
||||
}
|
||||
if (
|
||||
!isAllowedOperation(req, res, {
|
||||
GET: handlers['getCart'],
|
||||
POST: handlers['addItem'],
|
||||
PUT: handlers['updateItem'],
|
||||
DELETE: handlers['removeItem'],
|
||||
})
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const { cookies } = req
|
||||
const cartId = cookies[config.cartCookie]
|
||||
|
||||
try {
|
||||
// Return current cart info
|
||||
if (req.method === 'GET') {
|
||||
const body = { cartId }
|
||||
return await handlers['getCart']({ ...ctx, body })
|
||||
}
|
||||
|
||||
// Create or add an item to the cart
|
||||
if (req.method === 'POST') {
|
||||
const body = { ...req.body, cartId }
|
||||
return await handlers['addItem']({ ...ctx, body })
|
||||
}
|
||||
|
||||
// Update item in cart
|
||||
if (req.method === 'PUT') {
|
||||
const body = { ...req.body, cartId }
|
||||
return await handlers['updateItem']({ ...ctx, body })
|
||||
}
|
||||
|
||||
// Remove an item from the cart
|
||||
if (req.method === 'DELETE') {
|
||||
const body = { ...req.body, cartId }
|
||||
return await handlers['removeItem']({ ...ctx, body })
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
const message =
|
||||
error instanceof CommerceAPIError
|
||||
? 'An unexpected error ocurred with the Commerce API'
|
||||
: 'An unexpected error ocurred'
|
||||
|
||||
res.status(500).json({ data: null, errors: [{ message }] })
|
||||
}
|
||||
}
|
||||
|
||||
export default cartEndpoint
|
||||
|
@ -6,7 +6,7 @@ import isAllowedOperation from '../../utils/is-allowed-operation'
|
||||
|
||||
const customerEndpoint: GetAPISchema<
|
||||
any,
|
||||
CustomerSchema<any>
|
||||
CustomerSchema
|
||||
>['endpoint']['handler'] = async (ctx) => {
|
||||
const { req, res, handlers } = ctx
|
||||
|
||||
|
0
packages/commerce/src/api/endpoints/index.ts
Normal file
0
packages/commerce/src/api/endpoints/index.ts
Normal file
@ -5,7 +5,7 @@ import type { GetAPISchema } from '..'
|
||||
|
||||
const loginEndpoint: GetAPISchema<
|
||||
any,
|
||||
LoginSchema<any>
|
||||
LoginSchema
|
||||
>['endpoint']['handler'] = async (ctx) => {
|
||||
const { req, res, handlers } = ctx
|
||||
|
||||
|
@ -5,7 +5,7 @@ import type { GetAPISchema } from '..'
|
||||
|
||||
const wishlistEndpoint: GetAPISchema<
|
||||
any,
|
||||
WishlistSchema<any>
|
||||
WishlistSchema
|
||||
>['endpoint']['handler'] = async (ctx) => {
|
||||
const { req, res, handlers, config } = ctx
|
||||
|
||||
|
@ -11,11 +11,14 @@ import type { WishlistSchema } from '../types/wishlist'
|
||||
import type { CheckoutSchema } from '../types/checkout'
|
||||
import type { CustomerCardSchema } from '../types/customer/card'
|
||||
import type { CustomerAddressSchema } from '../types/customer/address'
|
||||
|
||||
import { withOperationCallback } from './utils/with-operation-callback'
|
||||
|
||||
import {
|
||||
defaultOperations,
|
||||
OPERATIONS,
|
||||
AllOperations,
|
||||
APIOperations,
|
||||
defaultOperations,
|
||||
} from './operations'
|
||||
|
||||
export type APISchemas =
|
||||
@ -106,7 +109,10 @@ export function getCommerceApi<P extends APIProvider>(
|
||||
OPERATIONS.forEach((k) => {
|
||||
const op = ops[k]
|
||||
if (op) {
|
||||
commerce[k] = op({ commerce }) as AllOperations<P>[typeof k]
|
||||
commerce[k] = withOperationCallback(
|
||||
k,
|
||||
op({ commerce })
|
||||
) as AllOperations<P>[typeof k]
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -25,6 +25,13 @@ export const OPERATIONS = [
|
||||
'getProduct',
|
||||
] as const
|
||||
|
||||
export type Operation = {
|
||||
[O in AllowedOperations]: {
|
||||
name: O
|
||||
data: Awaited<ReturnType<Operations<APIProvider>[O]>>
|
||||
}
|
||||
}[AllowedOperations]
|
||||
|
||||
export const defaultOperations = OPERATIONS.reduce((ops, k) => {
|
||||
ops[k] = noop
|
||||
return ops
|
||||
|
@ -1,4 +1,7 @@
|
||||
import { ZodError } from 'zod'
|
||||
|
||||
import type { Response } from '@vercel/fetch'
|
||||
import { CommerceError } from '../../utils/errors'
|
||||
|
||||
export class CommerceAPIError extends Error {
|
||||
status: number
|
||||
@ -20,3 +23,25 @@ export class CommerceNetworkError extends Error {
|
||||
this.name = 'CommerceNetworkError'
|
||||
}
|
||||
}
|
||||
|
||||
export const getOperationError = (operation: string, error: unknown) => {
|
||||
if (error instanceof ZodError) {
|
||||
return new CommerceError({
|
||||
code: 'SCHEMA_VALIDATION_ERROR',
|
||||
message:
|
||||
`The ${operation} operation returned invalid data and has ${
|
||||
error.issues.length
|
||||
} parse ${error.issues.length === 1 ? 'error' : 'errors'}: \n` +
|
||||
error.issues
|
||||
.map(
|
||||
(e, index) =>
|
||||
`Error #${index + 1} ${
|
||||
e.path.length > 0 ? `Path: ${e.path.join('.')}, ` : ''
|
||||
}Code: ${e.code}, Message: ${e.message}`
|
||||
)
|
||||
.join('\n'),
|
||||
})
|
||||
}
|
||||
|
||||
return error
|
||||
}
|
||||
|
42
packages/commerce/src/api/utils/with-operation-callback.ts
Normal file
42
packages/commerce/src/api/utils/with-operation-callback.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import type { AllowedOperations, Operation } from '../operations'
|
||||
|
||||
import { z } from 'zod'
|
||||
import { getOperationError } from './errors'
|
||||
import { pageSchema } from '../../schemas/page'
|
||||
import { siteInfoSchema } from '../../schemas/site'
|
||||
import { productSchema, productsPathsSchema } from '../../schemas/product'
|
||||
|
||||
export const withOperationCallback =
|
||||
(name: AllowedOperations, fn: (...args: any[]) => Promise<any>) =>
|
||||
async (...args: any[]) => {
|
||||
try {
|
||||
const data = await fn(...args)
|
||||
parse({ name, data })
|
||||
return data
|
||||
} catch (error) {
|
||||
throw getOperationError(name, error)
|
||||
}
|
||||
}
|
||||
|
||||
const parse = ({ name, data }: Operation) => {
|
||||
switch (name) {
|
||||
case 'getProduct':
|
||||
productSchema.nullable().parse(data.product)
|
||||
break
|
||||
case 'getAllProducts':
|
||||
z.array(productSchema).parse(data.products)
|
||||
break
|
||||
case 'getAllProductPaths':
|
||||
productsPathsSchema.parse(data.products)
|
||||
break
|
||||
case 'getPage':
|
||||
pageSchema.nullable().parse(data.page)
|
||||
break
|
||||
case 'getAllPages':
|
||||
z.array(pageSchema).parse(data.pages)
|
||||
break
|
||||
case 'getSiteInfo':
|
||||
siteInfoSchema.parse(data)
|
||||
break
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import type { LoginHook } from '../types/login'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseLogin<
|
||||
H extends MutationHook<LoginHook<any>> = MutationHook<LoginHook>
|
||||
H extends MutationHook<LoginHook> = MutationHook<LoginHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<LoginHook> = mutationFetcher
|
||||
|
@ -5,7 +5,7 @@ import type { LogoutHook } from '../types/logout'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseLogout<
|
||||
H extends MutationHook<LogoutHook<any>> = MutationHook<LogoutHook>
|
||||
H extends MutationHook<LogoutHook> = MutationHook<LogoutHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<LogoutHook> = mutationFetcher
|
||||
|
@ -5,7 +5,7 @@ import type { SignupHook } from '../types/signup'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseSignup<
|
||||
H extends MutationHook<SignupHook<any>> = MutationHook<SignupHook>
|
||||
H extends MutationHook<SignupHook> = MutationHook<SignupHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<SignupHook> = mutationFetcher
|
||||
|
@ -5,7 +5,7 @@ import type { AddItemHook } from '../types/cart'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseAddItem<
|
||||
H extends MutationHook<AddItemHook<any>> = MutationHook<AddItemHook>
|
||||
H extends MutationHook<AddItemHook> = MutationHook<AddItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<AddItemHook> = mutationFetcher
|
||||
|
@ -4,9 +4,8 @@ import type { SWRHook, HookFetcherFn } from '../utils/types'
|
||||
import type { GetCartHook } from '../types/cart'
|
||||
import { Provider, useCommerce } from '..'
|
||||
|
||||
export type UseCart<
|
||||
H extends SWRHook<GetCartHook<any>> = SWRHook<GetCartHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
export type UseCart<H extends SWRHook<GetCartHook> = SWRHook<GetCartHook>> =
|
||||
ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<GetCartHook> = async ({
|
||||
options,
|
||||
|
@ -5,7 +5,7 @@ import type { RemoveItemHook } from '../types/cart'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseRemoveItem<
|
||||
H extends MutationHook<RemoveItemHook<any>> = MutationHook<RemoveItemHook>
|
||||
H extends MutationHook<RemoveItemHook> = MutationHook<RemoveItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<RemoveItemHook> = mutationFetcher
|
||||
|
@ -5,7 +5,7 @@ import type { UpdateItemHook } from '../types/cart'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseUpdateItem<
|
||||
H extends MutationHook<UpdateItemHook<any>> = MutationHook<UpdateItemHook>
|
||||
H extends MutationHook<UpdateItemHook> = MutationHook<UpdateItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<UpdateItemHook> = mutationFetcher
|
||||
|
@ -7,7 +7,7 @@ import { useHook, useSWRHook } from '../utils/use-hook'
|
||||
import { Provider, useCommerce } from '..'
|
||||
|
||||
export type UseCheckout<
|
||||
H extends SWRHook<GetCheckoutHook<any>> = SWRHook<GetCheckoutHook>
|
||||
H extends SWRHook<GetCheckoutHook> = SWRHook<GetCheckoutHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<GetCheckoutHook> = async ({
|
||||
|
@ -6,9 +6,7 @@ import { useHook, useMutationHook } from '../utils/use-hook'
|
||||
import { mutationFetcher } from '../utils/default-fetcher'
|
||||
|
||||
export type UseSubmitCheckout<
|
||||
H extends MutationHook<
|
||||
SubmitCheckoutHook<any>
|
||||
> = MutationHook<SubmitCheckoutHook>
|
||||
H extends MutationHook<SubmitCheckoutHook> = MutationHook<SubmitCheckoutHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<SubmitCheckoutHook> = mutationFetcher
|
||||
|
@ -6,7 +6,7 @@ import { useHook, useMutationHook } from '../../utils/use-hook'
|
||||
import { mutationFetcher } from '../../utils/default-fetcher'
|
||||
|
||||
export type UseAddItem<
|
||||
H extends MutationHook<AddItemHook<any>> = MutationHook<AddItemHook>
|
||||
H extends MutationHook<AddItemHook> = MutationHook<AddItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<AddItemHook> = mutationFetcher
|
||||
|
@ -7,7 +7,7 @@ import { useHook, useSWRHook } from '../../utils/use-hook'
|
||||
import { Provider, useCommerce } from '../..'
|
||||
|
||||
export type UseAddresses<
|
||||
H extends SWRHook<GetAddressesHook<any>> = SWRHook<GetAddressesHook>
|
||||
H extends SWRHook<GetAddressesHook> = SWRHook<GetAddressesHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<GetAddressesHook> = async ({
|
||||
|
@ -6,7 +6,7 @@ import { useHook, useMutationHook } from '../../utils/use-hook'
|
||||
import { mutationFetcher } from '../../utils/default-fetcher'
|
||||
|
||||
export type UseRemoveItem<
|
||||
H extends MutationHook<RemoveItemHook<any>> = MutationHook<RemoveItemHook>
|
||||
H extends MutationHook<RemoveItemHook> = MutationHook<RemoveItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<RemoveItemHook> = mutationFetcher
|
||||
|
@ -6,7 +6,7 @@ import { useHook, useMutationHook } from '../../utils/use-hook'
|
||||
import { mutationFetcher } from '../../utils/default-fetcher'
|
||||
|
||||
export type UseUpdateItem<
|
||||
H extends MutationHook<UpdateItemHook<any>> = MutationHook<UpdateItemHook>
|
||||
H extends MutationHook<UpdateItemHook> = MutationHook<UpdateItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<UpdateItemHook> = mutationFetcher
|
||||
|
@ -6,7 +6,7 @@ import { useHook, useMutationHook } from '../../utils/use-hook'
|
||||
import { mutationFetcher } from '../../utils/default-fetcher'
|
||||
|
||||
export type UseAddItem<
|
||||
H extends MutationHook<AddItemHook<any>> = MutationHook<AddItemHook>
|
||||
H extends MutationHook<AddItemHook> = MutationHook<AddItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<AddItemHook> = mutationFetcher
|
||||
|
@ -6,9 +6,8 @@ import Cookies from 'js-cookie'
|
||||
import { useHook, useSWRHook } from '../../utils/use-hook'
|
||||
import { Provider, useCommerce } from '../..'
|
||||
|
||||
export type UseCards<
|
||||
H extends SWRHook<GetCardsHook<any>> = SWRHook<GetCardsHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
export type UseCards<H extends SWRHook<GetCardsHook> = SWRHook<GetCardsHook>> =
|
||||
ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<GetCardsHook> = async ({
|
||||
options,
|
||||
|
@ -6,7 +6,7 @@ import { useHook, useMutationHook } from '../../utils/use-hook'
|
||||
import { mutationFetcher } from '../../utils/default-fetcher'
|
||||
|
||||
export type UseRemoveItem<
|
||||
H extends MutationHook<RemoveItemHook<any>> = MutationHook<RemoveItemHook>
|
||||
H extends MutationHook<RemoveItemHook> = MutationHook<RemoveItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<RemoveItemHook> = mutationFetcher
|
||||
|
@ -6,7 +6,7 @@ import { useHook, useMutationHook } from '../../utils/use-hook'
|
||||
import { mutationFetcher } from '../../utils/default-fetcher'
|
||||
|
||||
export type UseUpdateItem<
|
||||
H extends MutationHook<UpdateItemHook<any>> = MutationHook<UpdateItemHook>
|
||||
H extends MutationHook<UpdateItemHook> = MutationHook<UpdateItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<UpdateItemHook> = mutationFetcher
|
||||
|
@ -5,7 +5,7 @@ import type { HookFetcherFn, SWRHook } from '../utils/types'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseCustomer<
|
||||
H extends SWRHook<CustomerHook<any>> = SWRHook<CustomerHook>
|
||||
H extends SWRHook<CustomerHook> = SWRHook<CustomerHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<CustomerHook> = SWRFetcher
|
||||
|
@ -5,7 +5,7 @@ import type { SearchProductsHook } from '../types/product'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseSearch<
|
||||
H extends SWRHook<SearchProductsHook<any>> = SWRHook<SearchProductsHook>
|
||||
H extends SWRHook<SearchProductsHook> = SWRHook<SearchProductsHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<SearchProductsHook> = SWRFetcher
|
||||
|
18
packages/commerce/src/schemas/page.ts
Normal file
18
packages/commerce/src/schemas/page.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export const pageSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
url: z.string().startsWith('/').optional(),
|
||||
body: z.string(),
|
||||
is_visible: z.boolean().optional(),
|
||||
sort_order: z.number().optional(),
|
||||
})
|
||||
|
||||
export const pagesPathsSchema = z.array(
|
||||
z.object({
|
||||
page: z.object({
|
||||
path: z.string().startsWith('/'),
|
||||
}),
|
||||
})
|
||||
)
|
60
packages/commerce/src/schemas/product.ts
Normal file
60
packages/commerce/src/schemas/product.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export const productPriceSchema = z.object({
|
||||
value: z.number(),
|
||||
currencyCode: z.string().max(3).optional(),
|
||||
retailPrice: z.number().optional(),
|
||||
})
|
||||
|
||||
export const productOptionSchema = z.object({
|
||||
id: z.string(),
|
||||
displayName: z.string(),
|
||||
values: z.array(
|
||||
z.object({
|
||||
label: z.string(),
|
||||
hexColors: z.array(z.string()).optional(),
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
export const productImageSchema = z.object({
|
||||
url: z.string().url().or(z.string().startsWith('/')),
|
||||
alt: z.string().optional(),
|
||||
width: z.number().optional(),
|
||||
height: z.number().optional(),
|
||||
})
|
||||
|
||||
export const productVariantSchema = z.object({
|
||||
id: z.string(),
|
||||
sku: z.string().nullish(),
|
||||
name: z.string().optional(),
|
||||
options: z.array(productOptionSchema),
|
||||
image: productImageSchema.optional(),
|
||||
})
|
||||
|
||||
export const productSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string(),
|
||||
descriptionHtml: z.string().optional(),
|
||||
sku: z.string().nullish(),
|
||||
slug: z.string(),
|
||||
path: z.string().startsWith('/'),
|
||||
images: z.array(productImageSchema),
|
||||
variants: z.array(productVariantSchema),
|
||||
price: productPriceSchema,
|
||||
options: z.array(productOptionSchema),
|
||||
vendor: z.string().optional(),
|
||||
})
|
||||
|
||||
export const productsPathsSchema = z.array(
|
||||
z.object({ path: z.string().startsWith('/') })
|
||||
)
|
||||
|
||||
export const searchProductBodySchema = z.object({
|
||||
search: z.string(),
|
||||
categoryId: z.string(),
|
||||
brandId: z.string().optional(),
|
||||
sort: z.string().optional(),
|
||||
locale: z.string().optional(),
|
||||
})
|
18
packages/commerce/src/schemas/site.ts
Normal file
18
packages/commerce/src/schemas/site.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export const siteInfoSchema = z.object({
|
||||
categories: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
path: z.string().startsWith('/'),
|
||||
})
|
||||
),
|
||||
brands: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
path: z.string().startsWith('/'),
|
||||
})
|
||||
),
|
||||
})
|
@ -1,177 +1,264 @@
|
||||
import type { Discount, Measurement, Image } from './common'
|
||||
import type { Discount, Image, Measurement } from './common'
|
||||
|
||||
export type SelectedOption = {
|
||||
// The option's id.
|
||||
id?: string
|
||||
// The product option’s name.
|
||||
name: string
|
||||
/// The product option’s value.
|
||||
value: string
|
||||
}
|
||||
|
||||
export type LineItem = {
|
||||
// TODO: This should use the same type as the `ProductVariant` type from `product.ts`
|
||||
export interface ProductVariant {
|
||||
/**
|
||||
* The unique identifier for the variant.
|
||||
*/
|
||||
id: string
|
||||
variantId: string
|
||||
productId: string
|
||||
/**
|
||||
* The SKU (stock keeping unit) associated with the product variant.
|
||||
*/
|
||||
sku?: string
|
||||
/**
|
||||
* The product variant’s name, or the product's name.
|
||||
*/
|
||||
name: string
|
||||
quantity: number
|
||||
discounts: Discount[]
|
||||
// A human-friendly unique string automatically generated from the product’s name
|
||||
path: string
|
||||
variant: ProductVariant
|
||||
options?: SelectedOption[]
|
||||
}
|
||||
|
||||
export type 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.
|
||||
/**
|
||||
* The product variant’s price after all discounts are applied.
|
||||
*/
|
||||
price: number
|
||||
// Product variant’s price, as quoted by the manufacturer/distributor.
|
||||
/**
|
||||
* The product variant’s price before discounts are applied.
|
||||
*/
|
||||
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.
|
||||
/**
|
||||
* Indicates if the 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.
|
||||
/**
|
||||
* Whether a customer needs to provide a shipping address when placing
|
||||
* an order for the product variant.
|
||||
*/
|
||||
requiresShipping?: boolean
|
||||
/**
|
||||
* The image associated with the variant.
|
||||
*/
|
||||
image?: Image
|
||||
/**
|
||||
* 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.
|
||||
/**
|
||||
* 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.
|
||||
/**
|
||||
* 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.
|
||||
/**
|
||||
* 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 type Cart = {
|
||||
export interface SelectedOption {
|
||||
/**
|
||||
* The unique identifier for the option.
|
||||
*/
|
||||
id?: string
|
||||
/**
|
||||
* The product option’s name, such as "Color" or "Size".
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* The product option’s value, such as "Red" or "XL".
|
||||
*/
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface LineItem {
|
||||
/**
|
||||
* The unique identifier for the line item.
|
||||
*/
|
||||
id: string
|
||||
// ID of the customer to which the cart belongs.
|
||||
/**
|
||||
* The unique identifier for the product variant.
|
||||
*/
|
||||
variantId: string
|
||||
/**
|
||||
* The unique identifier for the product, if the variant is not provided.
|
||||
*/
|
||||
productId: string
|
||||
/**
|
||||
* This is usually the product's name.
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* The quantity of the product variant in the line item.
|
||||
*/
|
||||
quantity: number
|
||||
/**
|
||||
* List of discounts applied to the line item.
|
||||
*/
|
||||
discounts: Discount[]
|
||||
/**
|
||||
* A human-friendly unique string automatically generated from the product’s name.
|
||||
*/
|
||||
path: string
|
||||
/**
|
||||
* The product variant.
|
||||
*/
|
||||
variant: ProductVariant
|
||||
/**
|
||||
* List of selected options, to be used when displaying the line item, such as Color: Red, Size: XL.
|
||||
*/
|
||||
options?: SelectedOption[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Shopping cart, a.k.a Checkout
|
||||
*/
|
||||
export interface Cart {
|
||||
/**
|
||||
* The unique identifier for the cart.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* ID of the customer to which the cart belongs.
|
||||
*/
|
||||
customerId?: string
|
||||
// The email assigned to this cart
|
||||
/**
|
||||
* The URL of the cart.
|
||||
*/
|
||||
url?: string
|
||||
/**
|
||||
* The email assigned to this cart.
|
||||
*/
|
||||
email?: string
|
||||
// The date and time when the cart was created.
|
||||
/**
|
||||
* The date and time when the cart was created.
|
||||
*/
|
||||
createdAt: string
|
||||
// The currency used for this cart
|
||||
/**
|
||||
* The currency used for this cart */
|
||||
currency: { code: string }
|
||||
// Specifies if taxes are included in the line items.
|
||||
/**
|
||||
* Indicates if taxes are included in the line items.
|
||||
*/
|
||||
taxesIncluded: boolean
|
||||
/**
|
||||
* List of cart line items.
|
||||
*/
|
||||
lineItems: LineItem[]
|
||||
// The sum of all the prices of all the items in the cart.
|
||||
// Duties, taxes, shipping and discounts excluded.
|
||||
/**
|
||||
* The sum of all the pricexs of all the items in the cart.
|
||||
* Duties, taxes, shipping and discounts excluded.
|
||||
*/
|
||||
lineItemsSubtotalPrice: number
|
||||
// Price of the cart before duties, shipping and taxes.
|
||||
/**
|
||||
* 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.
|
||||
/**
|
||||
* 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 that have been applied on the cart.
|
||||
*/
|
||||
discounts?: Discount[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Base cart item body used for cart mutations
|
||||
*/
|
||||
export type CartItemBody = {
|
||||
export interface CartItemBody {
|
||||
/**
|
||||
* The unique identifier for the product variant.
|
||||
*/
|
||||
variantId: string
|
||||
/**
|
||||
* The unique identifier for the product, if the variant is not provided.
|
||||
*/
|
||||
productId?: string
|
||||
/**
|
||||
* The quantity of the product variant.
|
||||
*/
|
||||
quantity?: number
|
||||
|
||||
/**
|
||||
* The product variant's selected options.
|
||||
*/
|
||||
optionsSelected?: SelectedOption[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks schema
|
||||
* Cart Hooks for add, update and remove items from the cart
|
||||
*/
|
||||
|
||||
export type CartTypes = {
|
||||
cart?: Cart
|
||||
item: LineItem
|
||||
itemBody: CartItemBody
|
||||
export type CartHooks = {
|
||||
getCart: GetCartHook
|
||||
addItem: AddItemHook
|
||||
updateItem: UpdateItemHook
|
||||
removeItem: RemoveItemHook
|
||||
}
|
||||
|
||||
export type CartHooks<T extends CartTypes = CartTypes> = {
|
||||
getCart: GetCartHook<T>
|
||||
addItem: AddItemHook<T>
|
||||
updateItem: UpdateItemHook<T>
|
||||
removeItem: RemoveItemHook<T>
|
||||
}
|
||||
|
||||
export type GetCartHook<T extends CartTypes = CartTypes> = {
|
||||
data: T['cart'] | null
|
||||
export type GetCartHook = {
|
||||
data: Cart | null
|
||||
input: {}
|
||||
fetcherInput: { cartId?: string }
|
||||
swrState: { isEmpty: boolean }
|
||||
}
|
||||
|
||||
export type AddItemHook<T extends CartTypes = CartTypes> = {
|
||||
data: T['cart']
|
||||
input?: T['itemBody']
|
||||
fetcherInput: T['itemBody']
|
||||
body: { item: T['itemBody'] }
|
||||
actionInput: T['itemBody']
|
||||
export type AddItemHook = {
|
||||
data: Cart
|
||||
input?: CartItemBody
|
||||
fetcherInput: CartItemBody
|
||||
body: { item: CartItemBody }
|
||||
actionInput: CartItemBody
|
||||
}
|
||||
|
||||
export type UpdateItemHook<T extends CartTypes = CartTypes> = {
|
||||
data: T['cart'] | null
|
||||
input: { item?: T['item']; wait?: number }
|
||||
fetcherInput: { itemId: string; item: T['itemBody'] }
|
||||
body: { itemId: string; item: T['itemBody'] }
|
||||
actionInput: T['itemBody'] & { id: string }
|
||||
export type UpdateItemHook = {
|
||||
data: Cart | null | undefined
|
||||
input: { item?: LineItem; wait?: number }
|
||||
fetcherInput: { itemId: string; item: CartItemBody }
|
||||
body: { itemId: string; item: CartItemBody }
|
||||
actionInput: CartItemBody & { id: string }
|
||||
}
|
||||
|
||||
export type RemoveItemHook<T extends CartTypes = CartTypes> = {
|
||||
data: T['cart'] | null
|
||||
input: { item?: T['item'] }
|
||||
export type RemoveItemHook = {
|
||||
data: Cart | null | undefined
|
||||
input: { item?: LineItem }
|
||||
fetcherInput: { itemId: string }
|
||||
body: { itemId: string }
|
||||
actionInput: { id: string }
|
||||
}
|
||||
|
||||
/**
|
||||
* API Schema
|
||||
* Cart API endpoitns & handlers for add, update and remove items from the cart
|
||||
*/
|
||||
|
||||
export type CartSchema<T extends CartTypes = CartTypes> = {
|
||||
export type CartSchema = {
|
||||
endpoint: {
|
||||
options: {}
|
||||
handlers: CartHandlers<T>
|
||||
handlers: CartHandlers
|
||||
}
|
||||
}
|
||||
|
||||
export type CartHandlers<T extends CartTypes = CartTypes> = {
|
||||
getCart: GetCartHandler<T>
|
||||
addItem: AddItemHandler<T>
|
||||
updateItem: UpdateItemHandler<T>
|
||||
removeItem: RemoveItemHandler<T>
|
||||
export type CartHandlers = {
|
||||
getCart: GetCartHandler
|
||||
addItem: AddItemHandler
|
||||
updateItem: UpdateItemHandler
|
||||
removeItem: RemoveItemHandler
|
||||
}
|
||||
|
||||
export type GetCartHandler<T extends CartTypes = CartTypes> = GetCartHook<T> & {
|
||||
export type GetCartHandler = GetCartHook & {
|
||||
body: { cartId?: string }
|
||||
}
|
||||
|
||||
export type AddItemHandler<T extends CartTypes = CartTypes> = AddItemHook<T> & {
|
||||
export type AddItemHandler = AddItemHook & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type UpdateItemHandler<T extends CartTypes = CartTypes> =
|
||||
UpdateItemHook<T> & {
|
||||
data: T['cart']
|
||||
body: { cartId: string }
|
||||
}
|
||||
export type UpdateItemHandler = UpdateItemHook & {
|
||||
data: Cart
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type RemoveItemHandler<T extends CartTypes = CartTypes> =
|
||||
RemoveItemHook<T> & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
export type RemoveItemHandler = RemoveItemHook & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
@ -1,57 +1,89 @@
|
||||
import type { UseSubmitCheckout } from '../checkout/use-submit-checkout'
|
||||
import type { Address, AddressFields } from './customer/address'
|
||||
import type { AddressFields } from './customer/address'
|
||||
import type { Card, CardFields } from './customer/card'
|
||||
import type { LineItem } from './cart'
|
||||
|
||||
// Index
|
||||
export type Checkout = any
|
||||
|
||||
export type CheckoutTypes = {
|
||||
card?: Card | CardFields
|
||||
address?: Address | AddressFields
|
||||
checkout?: Checkout
|
||||
hasPayment?: boolean
|
||||
hasShipping?: boolean
|
||||
export interface Checkout {
|
||||
/**
|
||||
* Indicates if the checkout has payment iformation collected.
|
||||
*/
|
||||
hasPayment: boolean
|
||||
/**
|
||||
* Indicates if the checkout has shipping information collected.
|
||||
*/
|
||||
hasShipping: boolean
|
||||
/**
|
||||
* The unique identifier for the address that the customer has selected for shipping.
|
||||
*/
|
||||
addressId: string
|
||||
/**
|
||||
* The list of payment cards that the customer has available.
|
||||
*/
|
||||
payments?: Card[]
|
||||
/**
|
||||
* The unique identifier of the card that the customer has selected for payment.
|
||||
*/
|
||||
cardId?: string
|
||||
/**
|
||||
* List of items in the checkout.
|
||||
*/
|
||||
lineItems?: LineItem[]
|
||||
}
|
||||
|
||||
export type SubmitCheckoutHook<T extends CheckoutTypes = CheckoutTypes> = {
|
||||
data: T
|
||||
input?: T
|
||||
fetcherInput: T
|
||||
body: { item: T }
|
||||
actionInput: T
|
||||
export interface CheckoutBody {
|
||||
/**
|
||||
* The unique identifier for the cart.
|
||||
*/
|
||||
cartId?: string
|
||||
/**
|
||||
* The Card information.
|
||||
* @see CardFields
|
||||
*/
|
||||
card: CardFields
|
||||
/**
|
||||
* The Address information.
|
||||
* @see AddressFields
|
||||
*/
|
||||
address: AddressFields
|
||||
}
|
||||
|
||||
export type GetCheckoutHook<T extends CheckoutTypes = CheckoutTypes> = {
|
||||
data: T['checkout'] | null
|
||||
export type SubmitCheckoutHook = {
|
||||
data: Checkout
|
||||
input?: CheckoutBody
|
||||
fetcherInput: CheckoutBody
|
||||
body: { item: CheckoutBody }
|
||||
actionInput: CheckoutBody
|
||||
}
|
||||
|
||||
export type GetCheckoutHook = {
|
||||
data: Checkout | null
|
||||
input: {}
|
||||
fetcherInput: { cartId?: string }
|
||||
swrState: { isEmpty: boolean }
|
||||
mutations: { submit: UseSubmitCheckout }
|
||||
}
|
||||
|
||||
export type CheckoutHooks<T extends CheckoutTypes = CheckoutTypes> = {
|
||||
submitCheckout?: SubmitCheckoutHook<T>
|
||||
getCheckout: GetCheckoutHook<T>
|
||||
export type CheckoutHooks = {
|
||||
submitCheckout?: SubmitCheckoutHook
|
||||
getCheckout: GetCheckoutHook
|
||||
}
|
||||
|
||||
export type GetCheckoutHandler<T extends CheckoutTypes = CheckoutTypes> =
|
||||
GetCheckoutHook<T> & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type SubmitCheckoutHandler<T extends CheckoutTypes = CheckoutTypes> =
|
||||
SubmitCheckoutHook<T> & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type CheckoutHandlers<T extends CheckoutTypes = CheckoutTypes> = {
|
||||
getCheckout: GetCheckoutHandler<T>
|
||||
submitCheckout?: SubmitCheckoutHandler<T>
|
||||
export type GetCheckoutHandler = GetCheckoutHook & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type CheckoutSchema<T extends CheckoutTypes = CheckoutTypes> = {
|
||||
export type SubmitCheckoutHandler = SubmitCheckoutHook & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type CheckoutHandlers = {
|
||||
getCheckout: GetCheckoutHandler
|
||||
submitCheckout?: SubmitCheckoutHandler
|
||||
}
|
||||
|
||||
export type CheckoutSchema = {
|
||||
endpoint: {
|
||||
options: {}
|
||||
handlers: CheckoutHandlers<T>
|
||||
handlers: CheckoutHandlers
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,36 @@
|
||||
export type Discount = {
|
||||
// The value of the discount, can be an amount or percentage
|
||||
export interface Discount {
|
||||
/**
|
||||
* The value of the discount, can be an amount or percentage.
|
||||
*/
|
||||
value: number
|
||||
}
|
||||
|
||||
export type Measurement = {
|
||||
export interface Measurement {
|
||||
/**
|
||||
* The measurement's value.
|
||||
*/
|
||||
value: number
|
||||
/**
|
||||
* The measurement's unit, such as "KILOGRAMS", "GRAMS", "POUNDS" & "OOUNCES".
|
||||
*/
|
||||
unit: 'KILOGRAMS' | 'GRAMS' | 'POUNDS' | 'OUNCES'
|
||||
}
|
||||
|
||||
export type Image = {
|
||||
export interface Image {
|
||||
/**
|
||||
* The URL of the image.
|
||||
*/
|
||||
url: string
|
||||
altText?: string
|
||||
/**
|
||||
* A word or phrase that describes the content of an image.
|
||||
*/
|
||||
alt?: string
|
||||
/**
|
||||
* The image's width.
|
||||
*/
|
||||
width?: number
|
||||
/**
|
||||
* The image's height.
|
||||
*/
|
||||
height?: number
|
||||
}
|
||||
|
@ -1,111 +1,123 @@
|
||||
export interface Address {
|
||||
/**
|
||||
* The unique identifier for the address.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* The customer's first name.
|
||||
*/
|
||||
mask: string
|
||||
}
|
||||
|
||||
export interface AddressFields {
|
||||
/**
|
||||
* The type of address.
|
||||
* @example "billing, shipping"
|
||||
*/
|
||||
type: string
|
||||
/**
|
||||
* The customer's first name.
|
||||
*/
|
||||
firstName: string
|
||||
/**
|
||||
* The customer's last name.
|
||||
*/
|
||||
lastName: string
|
||||
/**
|
||||
* Company name.
|
||||
*/
|
||||
company: string
|
||||
/**
|
||||
* The customer's billing address street number.
|
||||
*/
|
||||
streetNumber: string
|
||||
/**
|
||||
* The customer's billing address apartment number.
|
||||
*/
|
||||
apartments: string
|
||||
/**
|
||||
* The customer's billing address zip code.
|
||||
*/
|
||||
zipCode: string
|
||||
/**
|
||||
* The customer's billing address city.
|
||||
*/
|
||||
city: string
|
||||
/**
|
||||
* The customer's billing address country.
|
||||
*/
|
||||
country: string
|
||||
}
|
||||
|
||||
export type CustomerAddressTypes = {
|
||||
address?: Address
|
||||
fields: AddressFields
|
||||
}
|
||||
/**
|
||||
* Hooks for managing a customer's addresses.
|
||||
*/
|
||||
|
||||
export type GetAddressesHook<
|
||||
T extends CustomerAddressTypes = CustomerAddressTypes
|
||||
> = {
|
||||
data: T['address'][] | null
|
||||
export type GetAddressesHook = {
|
||||
data: Address[] | null
|
||||
input: {}
|
||||
fetcherInput: { cartId?: string }
|
||||
swrState: { isEmpty: boolean }
|
||||
}
|
||||
|
||||
export type AddItemHook<T extends CustomerAddressTypes = CustomerAddressTypes> =
|
||||
{
|
||||
data: T['address']
|
||||
input?: T['fields']
|
||||
fetcherInput: T['fields']
|
||||
body: { item: T['fields'] }
|
||||
actionInput: T['fields']
|
||||
}
|
||||
|
||||
export type UpdateItemHook<
|
||||
T extends CustomerAddressTypes = CustomerAddressTypes
|
||||
> = {
|
||||
data: T['address'] | null
|
||||
input: { item?: T['fields']; wait?: number }
|
||||
fetcherInput: { itemId: string; item: T['fields'] }
|
||||
body: { itemId: string; item: T['fields'] }
|
||||
actionInput: T['fields'] & { id: string }
|
||||
export type AddItemHook = {
|
||||
data: Address
|
||||
input?: AddressFields
|
||||
fetcherInput: AddressFields
|
||||
body: { item: AddressFields }
|
||||
actionInput: AddressFields
|
||||
}
|
||||
|
||||
export type RemoveItemHook<
|
||||
T extends CustomerAddressTypes = CustomerAddressTypes
|
||||
> = {
|
||||
data: T['address'] | null
|
||||
input: { item?: T['address'] }
|
||||
export type UpdateItemHook = {
|
||||
data: Address | null
|
||||
input: { item?: AddressFields; wait?: number }
|
||||
fetcherInput: { itemId: string; item: AddressFields }
|
||||
body: { itemId: string; item: AddressFields }
|
||||
actionInput: AddressFields & { id: string }
|
||||
}
|
||||
|
||||
export type RemoveItemHook = {
|
||||
data: Address | null | undefined
|
||||
input: { item?: Address }
|
||||
fetcherInput: { itemId: string }
|
||||
body: { itemId: string }
|
||||
actionInput: { id: string }
|
||||
}
|
||||
|
||||
export type CustomerAddressHooks<
|
||||
T extends CustomerAddressTypes = CustomerAddressTypes
|
||||
> = {
|
||||
getAddresses: GetAddressesHook<T>
|
||||
addItem: AddItemHook<T>
|
||||
updateItem: UpdateItemHook<T>
|
||||
removeItem: RemoveItemHook<T>
|
||||
export type CustomerAddressHooks = {
|
||||
getAddresses: GetAddressesHook
|
||||
addItem: AddItemHook
|
||||
updateItem: UpdateItemHook
|
||||
removeItem: RemoveItemHook
|
||||
}
|
||||
|
||||
export type AddressHandler<
|
||||
T extends CustomerAddressTypes = CustomerAddressTypes
|
||||
> = GetAddressesHook<T> & {
|
||||
body: { cartId?: string }
|
||||
}
|
||||
/**
|
||||
* API endpoints for managing a customer's addresses.
|
||||
*/
|
||||
|
||||
export type AddItemHandler<
|
||||
T extends CustomerAddressTypes = CustomerAddressTypes
|
||||
> = AddItemHook<T> & {
|
||||
export type AddItemHandler = AddItemHook & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type UpdateItemHandler<
|
||||
T extends CustomerAddressTypes = CustomerAddressTypes
|
||||
> = UpdateItemHook<T> & {
|
||||
data: T['address']
|
||||
export type UpdateItemHandler = UpdateItemHook & {
|
||||
data: Address
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type RemoveItemHandler<
|
||||
T extends CustomerAddressTypes = CustomerAddressTypes
|
||||
> = RemoveItemHook<T> & {
|
||||
export type RemoveItemHandler = RemoveItemHook & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type CustomerAddressHandlers<
|
||||
T extends CustomerAddressTypes = CustomerAddressTypes
|
||||
> = {
|
||||
getAddresses: GetAddressesHook<T>
|
||||
addItem: AddItemHandler<T>
|
||||
updateItem: UpdateItemHandler<T>
|
||||
removeItem: RemoveItemHandler<T>
|
||||
export type CustomerAddressHandlers = {
|
||||
getAddresses: GetAddressesHook
|
||||
addItem: AddItemHandler
|
||||
updateItem: UpdateItemHandler
|
||||
removeItem: RemoveItemHandler
|
||||
}
|
||||
|
||||
export type CustomerAddressSchema<
|
||||
T extends CustomerAddressTypes = CustomerAddressTypes
|
||||
> = {
|
||||
export type CustomerAddressSchema = {
|
||||
endpoint: {
|
||||
options: {}
|
||||
handlers: CustomerAddressHandlers<T>
|
||||
handlers: CustomerAddressHandlers
|
||||
}
|
||||
}
|
||||
|
@ -1,102 +1,139 @@
|
||||
export interface Card {
|
||||
/**
|
||||
* Unique identifier for the card.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* Masked card number. Contains only the last 4 digits.
|
||||
* @example "4242"
|
||||
*/
|
||||
mask: string
|
||||
/**
|
||||
* The card's brand.
|
||||
* @example "Visa, Mastercard, etc."
|
||||
*/
|
||||
provider: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The fields required to create a new card.
|
||||
*/
|
||||
export interface CardFields {
|
||||
/**
|
||||
* Name on the card.
|
||||
*/
|
||||
cardHolder: string
|
||||
/**
|
||||
* The card's number, consisting of 16 digits.
|
||||
*/
|
||||
cardNumber: string
|
||||
/**
|
||||
* The card's expiry month and year, in the format MM/YY.
|
||||
* @example "01/25"
|
||||
*/
|
||||
cardExpireDate: string
|
||||
/**
|
||||
* The card's security code, consisting of 3 digits.
|
||||
*/
|
||||
cardCvc: string
|
||||
/**
|
||||
* The customer's first name.
|
||||
*/
|
||||
firstName: string
|
||||
/**
|
||||
* The customer's last name.
|
||||
*/
|
||||
lastName: string
|
||||
/**
|
||||
* Company name.
|
||||
*/
|
||||
company: string
|
||||
/**
|
||||
* The customer's billing address street number.
|
||||
*/
|
||||
streetNumber: string
|
||||
/**
|
||||
* The customer's billing address zip code.
|
||||
*/
|
||||
zipCode: string
|
||||
/**
|
||||
* The customer's billing address city.
|
||||
*/
|
||||
city: string
|
||||
/**
|
||||
* The customer's billing address country.
|
||||
*/
|
||||
country: string
|
||||
}
|
||||
|
||||
export type CustomerCardTypes = {
|
||||
card?: Card
|
||||
fields: CardFields
|
||||
}
|
||||
/**
|
||||
* Hooks for managing a customer's cards.
|
||||
*/
|
||||
|
||||
export type GetCardsHook<T extends CustomerCardTypes = CustomerCardTypes> = {
|
||||
data: T['card'][] | null
|
||||
export type GetCardsHook = {
|
||||
data: Card[] | null
|
||||
input: {}
|
||||
fetcherInput: { cartId?: string }
|
||||
swrState: { isEmpty: boolean }
|
||||
}
|
||||
|
||||
export type AddItemHook<T extends CustomerCardTypes = CustomerCardTypes> = {
|
||||
data: T['card']
|
||||
input?: T['fields']
|
||||
fetcherInput: T['fields']
|
||||
body: { item: T['fields'] }
|
||||
actionInput: T['fields']
|
||||
export type AddItemHook = {
|
||||
data: Card
|
||||
input?: CardFields
|
||||
fetcherInput: CardFields
|
||||
body: { item: CardFields }
|
||||
actionInput: CardFields
|
||||
}
|
||||
|
||||
export type UpdateItemHook<T extends CustomerCardTypes = CustomerCardTypes> = {
|
||||
data: T['card'] | null
|
||||
input: { item?: T['fields']; wait?: number }
|
||||
fetcherInput: { itemId: string; item: T['fields'] }
|
||||
body: { itemId: string; item: T['fields'] }
|
||||
actionInput: T['fields'] & { id: string }
|
||||
export type UpdateItemHook = {
|
||||
data: Card | null | undefined
|
||||
input: { item?: CardFields; wait?: number }
|
||||
fetcherInput: { itemId: string; item: CardFields }
|
||||
body: { itemId: string; item: CardFields }
|
||||
actionInput: CardFields & { id: string }
|
||||
}
|
||||
|
||||
export type RemoveItemHook<T extends CustomerCardTypes = CustomerCardTypes> = {
|
||||
data: T['card'] | null
|
||||
input: { item?: T['card'] }
|
||||
export type RemoveItemHook = {
|
||||
data: Card | null | undefined
|
||||
input: { item?: Card }
|
||||
fetcherInput: { itemId: string }
|
||||
body: { itemId: string }
|
||||
actionInput: { id: string }
|
||||
}
|
||||
|
||||
export type CustomerCardHooks<T extends CustomerCardTypes = CustomerCardTypes> =
|
||||
{
|
||||
getCards: GetCardsHook<T>
|
||||
addItem: AddItemHook<T>
|
||||
updateItem: UpdateItemHook<T>
|
||||
removeItem: RemoveItemHook<T>
|
||||
}
|
||||
|
||||
export type CardsHandler<T extends CustomerCardTypes = CustomerCardTypes> =
|
||||
GetCardsHook<T> & {
|
||||
body: { cartId?: string }
|
||||
}
|
||||
|
||||
export type AddItemHandler<T extends CustomerCardTypes = CustomerCardTypes> =
|
||||
AddItemHook<T> & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type UpdateItemHandler<T extends CustomerCardTypes = CustomerCardTypes> =
|
||||
UpdateItemHook<T> & {
|
||||
data: T['card']
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type RemoveItemHandler<T extends CustomerCardTypes = CustomerCardTypes> =
|
||||
RemoveItemHook<T> & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type CustomerCardHandlers<
|
||||
T extends CustomerCardTypes = CustomerCardTypes
|
||||
> = {
|
||||
getCards: GetCardsHook<T>
|
||||
addItem: AddItemHandler<T>
|
||||
updateItem: UpdateItemHandler<T>
|
||||
removeItem: RemoveItemHandler<T>
|
||||
export interface CustomerCardHooks {
|
||||
getCards: GetCardsHook
|
||||
addItem: AddItemHook
|
||||
updateItem: UpdateItemHook
|
||||
removeItem: RemoveItemHook
|
||||
}
|
||||
|
||||
export type CustomerCardSchema<
|
||||
T extends CustomerCardTypes = CustomerCardTypes
|
||||
> = {
|
||||
/**
|
||||
* Customer card API handlers.
|
||||
*/
|
||||
export type AddItemHandler = AddItemHook & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type UpdateItemHandler = UpdateItemHook & {
|
||||
data: Card
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type RemoveItemHandler = RemoveItemHook & {
|
||||
body: { cartId: string }
|
||||
}
|
||||
|
||||
export type CustomerCardHandlers = {
|
||||
getCards: GetCardsHook
|
||||
addItem: AddItemHandler
|
||||
updateItem: UpdateItemHandler
|
||||
removeItem: RemoveItemHandler
|
||||
}
|
||||
|
||||
export type CustomerCardSchema = {
|
||||
endpoint: {
|
||||
options: {}
|
||||
handlers: CustomerCardHandlers<T>
|
||||
handlers: CustomerCardHandlers
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,53 @@
|
||||
export * as Card from './card'
|
||||
export * as Address from './address'
|
||||
|
||||
// TODO: define this type
|
||||
export type Customer = any
|
||||
|
||||
export type CustomerTypes = {
|
||||
customer: Customer
|
||||
export interface Customer {
|
||||
/**
|
||||
* The unique identifier for the customer.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* The customer's first name.
|
||||
*/
|
||||
firstName: string
|
||||
/**
|
||||
* The customer's last name.
|
||||
*/
|
||||
lastName: string
|
||||
/**
|
||||
* The customer's email address.
|
||||
*/
|
||||
email?: string
|
||||
/**
|
||||
* The customer's phone number.
|
||||
* @optional
|
||||
*/
|
||||
phone?: string
|
||||
/**
|
||||
* The customer's company name.
|
||||
*/
|
||||
company?: string
|
||||
/**
|
||||
* The customer's notes.
|
||||
*/
|
||||
notes?: string
|
||||
/**
|
||||
* Indicates wathever the customer accepts marketing, such as email newsletters.
|
||||
*/
|
||||
acceptsMarketing?: boolean
|
||||
}
|
||||
|
||||
export type CustomerHook<T extends CustomerTypes = CustomerTypes> = {
|
||||
data: T['customer'] | null
|
||||
fetchData: { customer: T['customer'] } | null
|
||||
export type CustomerHook = {
|
||||
data: Customer | null | undefined
|
||||
fetchData: { customer: Customer } | null
|
||||
}
|
||||
|
||||
export type CustomerSchema<T extends CustomerTypes = CustomerTypes> = {
|
||||
export type CustomerSchema = {
|
||||
endpoint: {
|
||||
options: {}
|
||||
handlers: {
|
||||
getLoggedInCustomer: {
|
||||
data: { customer: T['customer'] } | null
|
||||
data: { customer: Customer } | null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,26 @@
|
||||
export type LoginBody = {
|
||||
export interface LoginBody {
|
||||
/**
|
||||
* The user's email address.
|
||||
*/
|
||||
email: string
|
||||
/**
|
||||
* The user's password.
|
||||
*/
|
||||
password: string
|
||||
}
|
||||
|
||||
export type LoginTypes = {
|
||||
body: LoginBody
|
||||
}
|
||||
|
||||
export type LoginHook<T extends LoginTypes = LoginTypes> = {
|
||||
export type LoginHook = {
|
||||
data: null
|
||||
actionInput: LoginBody
|
||||
fetcherInput: LoginBody
|
||||
body: T['body']
|
||||
body: LoginBody
|
||||
}
|
||||
|
||||
export type LoginSchema<T extends LoginTypes = LoginTypes> = {
|
||||
export type LoginSchema = {
|
||||
endpoint: {
|
||||
options: {}
|
||||
handlers: {
|
||||
login: LoginHook<T>
|
||||
login: LoginHook
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,15 @@
|
||||
export type LogoutTypes = {
|
||||
body: { redirectTo?: string }
|
||||
}
|
||||
|
||||
export type LogoutHook<T extends LogoutTypes = LogoutTypes> = {
|
||||
export type LogoutHook = {
|
||||
data: null
|
||||
body: T['body']
|
||||
body: {
|
||||
redirectTo?: string
|
||||
}
|
||||
}
|
||||
|
||||
export type LogoutSchema<T extends LogoutTypes = LogoutTypes> = {
|
||||
export type LogoutSchema = {
|
||||
endpoint: {
|
||||
options: {}
|
||||
handlers: {
|
||||
logout: LogoutHook<T>
|
||||
logout: LogoutHook
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +1,43 @@
|
||||
// TODO: define this type
|
||||
export type Page = {
|
||||
// ID of the Web page.
|
||||
/**
|
||||
* The unique identifier for the page.
|
||||
*/
|
||||
id: string
|
||||
// Page name, as displayed on the storefront.
|
||||
/**
|
||||
* Page name, as displayed on the storefront.
|
||||
*/
|
||||
name: string
|
||||
// Relative URL on the storefront for this page.
|
||||
/**
|
||||
* Relative URL on the storefront for this page.
|
||||
*/
|
||||
url?: string
|
||||
// HTML or variable that populates this page’s `<body>` element, in default/desktop view. Required in POST if page type is `raw`.
|
||||
/**
|
||||
* HTML or variable that populates this page’s `<body>` element, in default/desktop view. Required in POST if page type is `raw`.
|
||||
*/
|
||||
body: string
|
||||
// If true, this page appears in the storefront’s navigation menu.
|
||||
/**
|
||||
* If true, this page appears in the storefront’s navigation menu.
|
||||
*/
|
||||
is_visible?: boolean
|
||||
// Order in which this page should display on the storefront. (Lower integers specify earlier display.)
|
||||
/**
|
||||
* Order in which this page should display on the storefront. (Lower integers specify earlier display.)
|
||||
*/
|
||||
sort_order?: number
|
||||
}
|
||||
|
||||
export type PageTypes = {
|
||||
page: Page
|
||||
/**
|
||||
* Operation to get all pages.
|
||||
*/
|
||||
export type GetAllPagesOperation = {
|
||||
data: { pages: Page[] }
|
||||
}
|
||||
|
||||
export type GetAllPagesOperation<T extends PageTypes = PageTypes> = {
|
||||
data: { pages: T['page'][] }
|
||||
}
|
||||
|
||||
export type GetPageOperation<T extends PageTypes = PageTypes> = {
|
||||
data: { page?: T['page'] }
|
||||
variables: { id: string }
|
||||
export type GetPageOperation = {
|
||||
data: { page?: Page }
|
||||
variables: {
|
||||
/**
|
||||
* The unique identifier of the page.
|
||||
*/
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
@ -1,91 +1,207 @@
|
||||
export type ProductImage = {
|
||||
url: string
|
||||
alt?: string
|
||||
}
|
||||
import { Image } from './common'
|
||||
|
||||
export type ProductPrice = {
|
||||
export interface ProductPrice {
|
||||
/**
|
||||
* The price after all discounts are applied.
|
||||
*/
|
||||
value: number
|
||||
/**
|
||||
* The currency code for the price. This is a 3-letter ISO 4217 code.
|
||||
* @example USD
|
||||
*/
|
||||
currencyCode?: 'USD' | 'EUR' | 'ARS' | 'GBP' | string
|
||||
/**
|
||||
* The retail price of the product. This can be used to mark a product as on sale, when `retailPrice` is higher than the price a.k.a `value`.
|
||||
*/
|
||||
retailPrice?: number
|
||||
salePrice?: number
|
||||
listPrice?: number
|
||||
extendedSalePrice?: number
|
||||
extendedListPrice?: number
|
||||
}
|
||||
|
||||
export type ProductOption = {
|
||||
export interface ProductOption {
|
||||
__typename?: 'MultipleChoiceOption'
|
||||
/**
|
||||
* The unique identifier for the option.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* The product option’s name.
|
||||
* @example `Color` or `Size`
|
||||
*/
|
||||
displayName: string
|
||||
/**
|
||||
* List of option values.
|
||||
* @example `["Red", "Green", "Blue"]`
|
||||
*/
|
||||
values: ProductOptionValues[]
|
||||
}
|
||||
|
||||
export type ProductOptionValues = {
|
||||
export interface ProductOptionValues {
|
||||
/**
|
||||
* A string that uniquely identifies the option value.
|
||||
*/
|
||||
label: string
|
||||
/**
|
||||
* List of hex colors used to display the actual colors in the swatches instead of the name.
|
||||
*/
|
||||
hexColors?: string[]
|
||||
}
|
||||
|
||||
export type ProductVariant = {
|
||||
id: string | number
|
||||
export interface ProductVariant {
|
||||
/**
|
||||
* The unique identifier for the variant.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* The SKU (stock keeping unit) associated with the product variant.
|
||||
*/
|
||||
sku?: string
|
||||
/**
|
||||
* The product variant’s name, or the product's name.
|
||||
*/
|
||||
name?: string
|
||||
/**
|
||||
* List of product options.
|
||||
*/
|
||||
options: ProductOption[]
|
||||
/**
|
||||
* The product variant’s price after all discounts are applied.
|
||||
*/
|
||||
price?: ProductPrice
|
||||
/**
|
||||
* The retail price of the product. This can be used to mark a product as on sale, when `retailPrice` is higher than the `price`.
|
||||
*/
|
||||
retailPrice?: ProductPrice
|
||||
/**
|
||||
* Indicates if the variant is available for sale.
|
||||
*/
|
||||
availableForSale?: boolean
|
||||
/**
|
||||
* Whether a customer needs to provide a shipping address when placing an order for the product variant.
|
||||
*/
|
||||
requiresShipping?: boolean
|
||||
/**
|
||||
* The image associated with the variant.
|
||||
*/
|
||||
image?: Image
|
||||
}
|
||||
|
||||
export type Product = {
|
||||
export interface Product {
|
||||
/**
|
||||
* The unique identifier for the product.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* The name of the product.
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* Stripped description of the product, single line.
|
||||
*/
|
||||
description: string
|
||||
/**
|
||||
* The description of the product, complete with HTML formatting.
|
||||
*/
|
||||
descriptionHtml?: string
|
||||
/**
|
||||
* The SKU (stock keeping unit) associated with the product.
|
||||
*/
|
||||
sku?: string
|
||||
/**
|
||||
* A human-friendly unique string for the product, automatically generated from its title.
|
||||
*/
|
||||
slug?: string
|
||||
/**
|
||||
* Relative URL on the storefront for the product.
|
||||
*/
|
||||
path?: string
|
||||
images: ProductImage[]
|
||||
/**
|
||||
* List of images associated with the product.
|
||||
*/
|
||||
images: Image[]
|
||||
/**
|
||||
* List of the product’s variants.
|
||||
*/
|
||||
variants: ProductVariant[]
|
||||
/**
|
||||
* The product's base price. Could be the minimum value, or default variant price.
|
||||
*/
|
||||
price: ProductPrice
|
||||
/**
|
||||
* List of product's options.
|
||||
*/
|
||||
options: ProductOption[]
|
||||
/**
|
||||
* The product’s vendor name.
|
||||
*/
|
||||
vendor?: string
|
||||
}
|
||||
|
||||
export type SearchProductsBody = {
|
||||
export interface SearchProductsBody {
|
||||
/**
|
||||
* The search query string to filter the products by.
|
||||
*/
|
||||
search?: string
|
||||
categoryId?: string | number
|
||||
brandId?: string | number
|
||||
/**
|
||||
* The category ID to filter the products by.
|
||||
*/
|
||||
categoryId?: string
|
||||
/**
|
||||
* The brand ID to filter the products by.
|
||||
*/
|
||||
brandId?: string
|
||||
/**
|
||||
* The sort key to sort the products by.
|
||||
* @example 'trending-desc' | 'latest-desc' | 'price-asc' | 'price-desc'
|
||||
*/
|
||||
sort?: string
|
||||
/**
|
||||
* The locale code, used to localize the product data (if the provider supports it).
|
||||
*/
|
||||
locale?: string
|
||||
}
|
||||
|
||||
export type ProductTypes = {
|
||||
product: Product
|
||||
searchBody: SearchProductsBody
|
||||
}
|
||||
|
||||
export type SearchProductsHook<T extends ProductTypes = ProductTypes> = {
|
||||
/**
|
||||
* Fetches a list of products based on the given search criteria.
|
||||
*/
|
||||
export type SearchProductsHook = {
|
||||
data: {
|
||||
products: T['product'][]
|
||||
/**
|
||||
* List of products matching the query.
|
||||
*/
|
||||
products: Product[]
|
||||
/**
|
||||
* Indicates if there are any products matching the query.
|
||||
*/
|
||||
found: boolean
|
||||
}
|
||||
body: T['searchBody']
|
||||
input: T['searchBody']
|
||||
fetcherInput: T['searchBody']
|
||||
body: SearchProductsBody
|
||||
input: SearchProductsBody
|
||||
fetcherInput: SearchProductsBody
|
||||
}
|
||||
|
||||
export type ProductsSchema<T extends ProductTypes = ProductTypes> = {
|
||||
/**
|
||||
* Product API schema
|
||||
*/
|
||||
|
||||
export type ProductsSchema = {
|
||||
endpoint: {
|
||||
options: {}
|
||||
handlers: {
|
||||
getProducts: SearchProductsHook<T>
|
||||
getProducts: SearchProductsHook
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type GetAllProductPathsOperation<T extends ProductTypes = ProductTypes> =
|
||||
{
|
||||
data: { products: Pick<T['product'], 'path'>[] }
|
||||
variables: { first?: number }
|
||||
}
|
||||
/**
|
||||
* Product operations
|
||||
*/
|
||||
|
||||
export type GetAllProductsOperation<T extends ProductTypes = ProductTypes> = {
|
||||
data: { products: T['product'][] }
|
||||
export type GetAllProductPathsOperation = {
|
||||
data: { products: Pick<Product, 'path'>[] }
|
||||
variables: { first?: number }
|
||||
}
|
||||
|
||||
export type GetAllProductsOperation = {
|
||||
data: { products: Product[] }
|
||||
variables: {
|
||||
relevance?: 'featured' | 'best_selling' | 'newest'
|
||||
ids?: string[]
|
||||
@ -93,7 +209,7 @@ export type GetAllProductsOperation<T extends ProductTypes = ProductTypes> = {
|
||||
}
|
||||
}
|
||||
|
||||
export type GetProductOperation<T extends ProductTypes = ProductTypes> = {
|
||||
data: { product?: T['product'] }
|
||||
export type GetProductOperation = {
|
||||
data: { product?: Product }
|
||||
variables: { path: string; slug?: never } | { path?: never; slug: string }
|
||||
}
|
||||
|
@ -1,26 +1,34 @@
|
||||
export type SignupBody = {
|
||||
export interface SignupBody {
|
||||
/**
|
||||
* The user's first name.
|
||||
*/
|
||||
firstName: string
|
||||
/**
|
||||
* The user's last name.
|
||||
*/
|
||||
lastName: string
|
||||
/**
|
||||
* The user's email address.
|
||||
*/
|
||||
email: string
|
||||
/**
|
||||
* The user's password.
|
||||
*/
|
||||
password: string
|
||||
}
|
||||
|
||||
export type SignupTypes = {
|
||||
body: SignupBody
|
||||
}
|
||||
|
||||
export type SignupHook<T extends SignupTypes = SignupTypes> = {
|
||||
export type SignupHook = {
|
||||
data: null
|
||||
body: T['body']
|
||||
actionInput: T['body']
|
||||
fetcherInput: T['body']
|
||||
body: SignupBody
|
||||
actionInput: SignupBody
|
||||
fetcherInput: SignupBody
|
||||
}
|
||||
|
||||
export type SignupSchema<T extends SignupTypes = SignupTypes> = {
|
||||
export type SignupSchema = {
|
||||
endpoint: {
|
||||
options: {}
|
||||
handlers: {
|
||||
signup: SignupHook<T>
|
||||
signup: SignupHook
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,51 @@
|
||||
export type Category = {
|
||||
export interface Category {
|
||||
/**
|
||||
* Unique identifier for the category.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* Name of the category.
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* A human-friendly unique string for the category, automatically generated from its name.
|
||||
* @example "t-shirts"
|
||||
*/
|
||||
slug: string
|
||||
/**
|
||||
* Relative URL on the storefront for the category.
|
||||
* @example /t-shirts
|
||||
*/
|
||||
path: string
|
||||
}
|
||||
|
||||
export type Brand = any
|
||||
|
||||
export type SiteTypes = {
|
||||
category: Category
|
||||
brand: Brand
|
||||
export interface Brand {
|
||||
/**
|
||||
* Unique identifier for the brand.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* Name of the brand.
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* A human-friendly unique string for the category, automatically generated from its name.
|
||||
* @example "acme"
|
||||
*/
|
||||
slug: string
|
||||
/**
|
||||
* Relative URL on the storefront for this brand.
|
||||
* @example "/acme"
|
||||
*/
|
||||
path: string
|
||||
}
|
||||
|
||||
export type GetSiteInfoOperation<T extends SiteTypes = SiteTypes> = {
|
||||
/**
|
||||
* Operation to get site information. This includes categories and brands.
|
||||
*/
|
||||
export type GetSiteInfoOperation = {
|
||||
data: {
|
||||
categories: T['category'][]
|
||||
brands: T['brand'][]
|
||||
categories: Category[]
|
||||
brands: Brand[]
|
||||
}
|
||||
}
|
||||
|
@ -1,60 +1,97 @@
|
||||
// TODO: define this type
|
||||
export type Wishlist = any
|
||||
import { Product } from './product'
|
||||
|
||||
export type WishlistItemBody = {
|
||||
variantId: string | number
|
||||
export interface WishlistItem {
|
||||
/**
|
||||
* The unique identifier for the item.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* The unique identifier for the product associated with the wishlist item.
|
||||
*/
|
||||
productId: string
|
||||
/**
|
||||
* The unique identifier for the product variant associated with the wishlist item.
|
||||
*/
|
||||
variantId: string
|
||||
/**
|
||||
* The product associated with the wishlist item.
|
||||
*/
|
||||
product: Product
|
||||
}
|
||||
|
||||
export type WishlistTypes = {
|
||||
wishlist: Wishlist
|
||||
itemBody: WishlistItemBody
|
||||
export interface Wishlist {
|
||||
/**
|
||||
* The unique identifier for the wishlist.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* List of items in the wishlist.
|
||||
*/
|
||||
items: WishlistItem[]
|
||||
|
||||
/**
|
||||
* Some providers require a token to add an item to a wishlist
|
||||
*/
|
||||
token?: string
|
||||
}
|
||||
|
||||
export type GetWishlistHook<T extends WishlistTypes = WishlistTypes> = {
|
||||
data: T['wishlist'] | null
|
||||
export interface WishlistItemBody {
|
||||
/**
|
||||
* The unique identifier for the product variant to associate with the wishlist.
|
||||
*/
|
||||
variantId: string
|
||||
/**
|
||||
* The unique identifier for the product to associate with the wishlist.
|
||||
*/
|
||||
productId: string
|
||||
/**
|
||||
* Some providers require to provide a token to make a request
|
||||
*/
|
||||
wishlistToken?: string
|
||||
}
|
||||
|
||||
export type GetWishlistHook = {
|
||||
data: Wishlist | null | undefined
|
||||
body: { includeProducts?: boolean }
|
||||
input: { includeProducts?: boolean }
|
||||
fetcherInput: { customerId: string; includeProducts?: boolean }
|
||||
swrState: { isEmpty: boolean }
|
||||
}
|
||||
|
||||
export type AddItemHook<T extends WishlistTypes = WishlistTypes> = {
|
||||
data: T['wishlist']
|
||||
body: { item: T['itemBody'] }
|
||||
fetcherInput: { item: T['itemBody'] }
|
||||
actionInput: T['itemBody']
|
||||
export type AddItemHook = {
|
||||
data: Wishlist | null | undefined
|
||||
body: { item: WishlistItemBody }
|
||||
fetcherInput: { item: WishlistItemBody }
|
||||
actionInput: WishlistItemBody
|
||||
}
|
||||
|
||||
export type RemoveItemHook<T extends WishlistTypes = WishlistTypes> = {
|
||||
data: T['wishlist'] | null
|
||||
body: { itemId: string }
|
||||
fetcherInput: { itemId: string }
|
||||
export type RemoveItemHook = {
|
||||
data: Wishlist | null | undefined
|
||||
body: { itemId: string; wishlistToken?: string }
|
||||
fetcherInput: { itemId: string; wishlistToken?: string }
|
||||
actionInput: { id: string }
|
||||
input: { wishlist?: { includeProducts?: boolean } }
|
||||
}
|
||||
|
||||
export type WishlistSchema<T extends WishlistTypes = WishlistTypes> = {
|
||||
export type WishlistSchema = {
|
||||
endpoint: {
|
||||
options: {}
|
||||
handlers: {
|
||||
getWishlist: GetWishlistHook<T> & {
|
||||
data: T['wishlist'] | null
|
||||
getWishlist: GetWishlistHook & {
|
||||
data: Wishlist | null
|
||||
body: { customerToken?: string }
|
||||
}
|
||||
addItem: AddItemHook<T> & {
|
||||
addItem: AddItemHook & {
|
||||
body: { customerToken?: string }
|
||||
}
|
||||
removeItem: RemoveItemHook<T> & {
|
||||
removeItem: RemoveItemHook & {
|
||||
body: { customerToken?: string }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type GetCustomerWishlistOperation<
|
||||
T extends WishlistTypes = WishlistTypes
|
||||
> = {
|
||||
data: { wishlist?: T['wishlist'] }
|
||||
export type GetCustomerWishlistOperation = {
|
||||
data: { wishlist?: Wishlist }
|
||||
variables: { customerId: string }
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import type { AddItemHook } from '../types/wishlist'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseAddItem<
|
||||
H extends MutationHook<AddItemHook<any>> = MutationHook<AddItemHook>
|
||||
H extends MutationHook<AddItemHook> = MutationHook<AddItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher = mutationFetcher
|
||||
|
@ -5,7 +5,7 @@ import type { RemoveItemHook } from '../types/wishlist'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseRemoveItem<
|
||||
H extends MutationHook<RemoveItemHook<any>> = MutationHook<RemoveItemHook>
|
||||
H extends MutationHook<RemoveItemHook> = MutationHook<RemoveItemHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<RemoveItemHook> = mutationFetcher
|
||||
|
@ -5,7 +5,7 @@ import type { GetWishlistHook } from '../types/wishlist'
|
||||
import type { Provider } from '..'
|
||||
|
||||
export type UseWishlist<
|
||||
H extends SWRHook<GetWishlistHook<any>> = SWRHook<GetWishlistHook>
|
||||
H extends SWRHook<GetWishlistHook> = SWRHook<GetWishlistHook>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<GetWishlistHook> = SWRFetcher
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||
import checkoutEndpoint from '@vercel/commerce/api/endpoints/checkout'
|
||||
import type { CheckoutSchema } from '../../../types/checkout'
|
||||
import type { CheckoutSchema } from '@vercel/commerce/types/checkout'
|
||||
import type { CommercejsAPI } from '../..'
|
||||
|
||||
import submitCheckout from './submit-checkout'
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
||||
import loginEndpoint from '@vercel/commerce/api/endpoints/login'
|
||||
import type { LoginSchema } from '../../../types/login'
|
||||
import type { LoginSchema } from '@vercel/commerce/types/login'
|
||||
import type { CommercejsAPI } from '../..'
|
||||
import login from './login'
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { CommercejsConfig } from '..'
|
||||
import { GetAllPagesOperation } from '../../types/page'
|
||||
import { GetAllPagesOperation } from '@vercel/commerce/types/page'
|
||||
|
||||
export type Page = { url: string }
|
||||
export type GetAllPagesResult = { pages: Page[] }
|
||||
|
@ -1,9 +1,5 @@
|
||||
import type { OperationContext } from '@vercel/commerce/api/operations'
|
||||
import type {
|
||||
GetAllProductPathsOperation,
|
||||
CommercejsProduct,
|
||||
} from '../../types/product'
|
||||
|
||||
import type { GetAllProductPathsOperation } from '@vercel/commerce/types/product'
|
||||
import type { CommercejsConfig, Provider } from '..'
|
||||
|
||||
export type GetAllProductPathsResult = {
|
||||
@ -22,7 +18,7 @@ export default function getAllProductPathsOperation({
|
||||
const { data } = await sdkFetch('products', 'list')
|
||||
|
||||
// Match a path for every product retrieved
|
||||
const productPaths = data.map(({ permalink }: CommercejsProduct) => ({
|
||||
const productPaths = data.map(({ permalink }: { permalink: string }) => ({
|
||||
path: `/${permalink}`,
|
||||
}))
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { OperationContext } from '@vercel/commerce/api/operations'
|
||||
import type { GetAllProductsOperation } from '../../types/product'
|
||||
import type { GetAllProductsOperation } from '@vercel/commerce/types/product'
|
||||
import type { CommercejsConfig, Provider } from '../index'
|
||||
|
||||
import { normalizeProduct } from '../../utils/normalize-product'
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { GetPageOperation } from '../../types/page'
|
||||
import { GetPageOperation } from '@vercel/commerce/types/page'
|
||||
|
||||
export type Page = any
|
||||
export type GetPageResult = { page?: Page }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user