mirror of
https://github.com/vercel/commerce.git
synced 2025-05-17 15:06:59 +00:00
Add checkout endpoint parser & update errors
This commit is contained in:
parent
4bd20ddf0f
commit
fa9fe72a68
@ -13,10 +13,12 @@ const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({
|
|||||||
const { cookies } = req
|
const { cookies } = req
|
||||||
const cartId = cookies[config.cartCookie]
|
const cartId = cookies[config.cartCookie]
|
||||||
const customerToken = cookies[config.customerCookie]
|
const customerToken = cookies[config.customerCookie]
|
||||||
|
|
||||||
if (!cartId) {
|
if (!cartId) {
|
||||||
res.redirect('/cart')
|
res.redirect('/cart')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = await config.storeApiFetch<any>(
|
const { data } = await config.storeApiFetch<any>(
|
||||||
`/v3/carts/${cartId}/redirect_urls`,
|
`/v3/carts/${cartId}/redirect_urls`,
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import type { GetAPISchema } from '..'
|
import type { GetAPISchema } from '..'
|
||||||
import type { CheckoutSchema } from '../../types/checkout'
|
import type { CheckoutSchema } from '../../types/checkout'
|
||||||
|
|
||||||
|
import {
|
||||||
|
getCheckoutBodySchema,
|
||||||
|
submitCheckoutBodySchema,
|
||||||
|
} from '../../schemas/checkout'
|
||||||
|
|
||||||
import validateHandlers from '../utils/validate-handlers'
|
import validateHandlers from '../utils/validate-handlers'
|
||||||
|
|
||||||
const checkoutEndpoint: GetAPISchema<
|
const checkoutEndpoint: GetAPISchema<
|
||||||
@ -19,13 +24,13 @@ const checkoutEndpoint: GetAPISchema<
|
|||||||
|
|
||||||
// Get checkout
|
// Get checkout
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
const body = { ...req.body, cartId }
|
const body = getCheckoutBodySchema.parse({ ...req.body, cartId })
|
||||||
return handlers['getCheckout']({ ...ctx, body })
|
return handlers['getCheckout']({ ...ctx, body })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create checkout
|
// Create checkout
|
||||||
if (req.method === 'POST' && handlers['submitCheckout']) {
|
if (req.method === 'POST' && handlers['submitCheckout']) {
|
||||||
const body = { ...req.body, cartId }
|
const body = submitCheckoutBodySchema.parse({ ...req.body, cartId })
|
||||||
return handlers['submitCheckout']({ ...ctx, body })
|
return handlers['submitCheckout']({ ...ctx, body })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ export default function createEndpoints<P extends APIProvider>(
|
|||||||
|
|
||||||
const data = await handlers[path](req, res)
|
const data = await handlers[path](req, res)
|
||||||
// If the handler returns a value but the response hasn't been sent yet, send it
|
// If the handler returns a value but the response hasn't been sent yet, send it
|
||||||
if (!res.headersSent) {
|
if (!res.headersSent && data) {
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
|
@ -25,26 +25,19 @@ export class CommerceNetworkError extends Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const normalizeZodIssues = (issues: ZodError['issues']) =>
|
export const normalizeZodIssues = (issues: ZodError['issues']) =>
|
||||||
issues.map((e, index) => ({
|
issues.map(({ path, message }) => `${message} at "${path.join('.')}"`)
|
||||||
message: `Error #${index + 1} ${
|
|
||||||
e.path.length > 0 ? `Path: ${e.path.join('.')}, ` : ''
|
|
||||||
}Code: ${e.code}, Message: ${e.message}`,
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const getOperationError = (operation: string, error: unknown) => {
|
export const getOperationError = (operation: string, error: unknown) => {
|
||||||
if (error instanceof ZodError) {
|
if (error instanceof ZodError) {
|
||||||
return new CommerceError({
|
return new CommerceError({
|
||||||
code: 'SCHEMA_VALIDATION_ERROR',
|
code: 'SCHEMA_VALIDATION_ERROR',
|
||||||
message:
|
message:
|
||||||
`The ${operation} operation returned invalid data and has ${
|
`Validation ${
|
||||||
error.issues.length
|
error.issues.length === 1 ? 'error' : 'errors'
|
||||||
} parse ${error.issues.length === 1 ? 'error' : 'errors'}: \n` +
|
} at "${operation}" operation: \n` +
|
||||||
normalizeZodIssues(error.issues)
|
normalizeZodIssues(error.issues).join('\n'),
|
||||||
.map((e) => e.message)
|
|
||||||
.join('\n'),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return error
|
return error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +56,7 @@ export const normalizeError = (error: unknown) => {
|
|||||||
return {
|
return {
|
||||||
status: 400,
|
status: 400,
|
||||||
data: null,
|
data: null,
|
||||||
errors: normalizeZodIssues(error.issues),
|
errors: normalizeZodIssues(error.issues).map((message) => ({ message })),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
packages/commerce/src/schemas/checkout.ts
Normal file
15
packages/commerce/src/schemas/checkout.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { z } from 'zod'
|
||||||
|
import { addressFieldsSchema, cardFieldsSchema } from './customer'
|
||||||
|
|
||||||
|
export const getCheckoutBodySchema = z.object({
|
||||||
|
cartId: z.string().optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const submitCheckoutBodySchema = z.object({
|
||||||
|
cartId: z.string(),
|
||||||
|
item: z.object({
|
||||||
|
cartId: z.string().optional(),
|
||||||
|
card: cardFieldsSchema,
|
||||||
|
address: addressFieldsSchema,
|
||||||
|
}),
|
||||||
|
})
|
@ -69,7 +69,7 @@ export type CheckoutHooks = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type GetCheckoutHandler = GetCheckoutHook & {
|
export type GetCheckoutHandler = GetCheckoutHook & {
|
||||||
body: { cartId: string }
|
body: { cartId?: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SubmitCheckoutHandler = SubmitCheckoutHook & {
|
export type SubmitCheckoutHandler = SubmitCheckoutHook & {
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
import { ProductsEndpoint } from '.'
|
|
||||||
|
|
||||||
const SORT: { [key: string]: string | undefined } = {
|
|
||||||
latest: 'id',
|
|
||||||
trending: 'total_sold',
|
|
||||||
price: 'price',
|
|
||||||
}
|
|
||||||
|
|
||||||
const LIMIT = 12
|
|
||||||
|
|
||||||
// Return current cart info
|
|
||||||
const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
|
|
||||||
res,
|
|
||||||
body: { search, categoryId, brandId, sort },
|
|
||||||
config,
|
|
||||||
commerce,
|
|
||||||
}) => {
|
|
||||||
res.status(200).json({
|
|
||||||
data: {
|
|
||||||
products: [],
|
|
||||||
found: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default getProducts
|
|
@ -1,19 +0,0 @@
|
|||||||
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
|
|
||||||
import productsEndpoint from '@vercel/commerce/api/endpoints/catalog/products'
|
|
||||||
import type { ProductsSchema } from '@vercel/commerce/types/product'
|
|
||||||
import type { ShopifyAPI } from '../../..'
|
|
||||||
|
|
||||||
import getProducts from './get-products'
|
|
||||||
|
|
||||||
export type ProductsAPI = GetAPISchema<ShopifyAPI, ProductsSchema>
|
|
||||||
|
|
||||||
export type ProductsEndpoint = ProductsAPI['endpoint']
|
|
||||||
|
|
||||||
export const handlers: ProductsEndpoint['handlers'] = { getProducts }
|
|
||||||
|
|
||||||
const productsApi = createEndpoint<ProductsAPI>({
|
|
||||||
handler: productsEndpoint,
|
|
||||||
handlers,
|
|
||||||
})
|
|
||||||
|
|
||||||
export default productsApi
|
|
@ -23,8 +23,8 @@
|
|||||||
"@components/*": ["components/*"],
|
"@components/*": ["components/*"],
|
||||||
"@commerce": ["../packages/commerce/src"],
|
"@commerce": ["../packages/commerce/src"],
|
||||||
"@commerce/*": ["../packages/commerce/src/*"],
|
"@commerce/*": ["../packages/commerce/src/*"],
|
||||||
"@framework": ["../packages/local/src"],
|
"@framework": ["../packages/shopify/src"],
|
||||||
"@framework/*": ["../packages/local/src/*"]
|
"@framework/*": ["../packages/shopify/src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"],
|
"include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user