Add checkout endpoint parser & update errors

This commit is contained in:
Catalin Pinte 2022-10-05 14:07:56 +03:00
parent 4bd20ddf0f
commit fa9fe72a68
9 changed files with 34 additions and 64 deletions

View File

@ -13,10 +13,12 @@ const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({
const { cookies } = req
const cartId = cookies[config.cartCookie]
const customerToken = cookies[config.customerCookie]
if (!cartId) {
res.redirect('/cart')
return
}
const { data } = await config.storeApiFetch<any>(
`/v3/carts/${cartId}/redirect_urls`,
{

View File

@ -1,6 +1,11 @@
import type { GetAPISchema } from '..'
import type { CheckoutSchema } from '../../types/checkout'
import {
getCheckoutBodySchema,
submitCheckoutBodySchema,
} from '../../schemas/checkout'
import validateHandlers from '../utils/validate-handlers'
const checkoutEndpoint: GetAPISchema<
@ -19,13 +24,13 @@ const checkoutEndpoint: GetAPISchema<
// Get checkout
if (req.method === 'GET') {
const body = { ...req.body, cartId }
const body = getCheckoutBodySchema.parse({ ...req.body, cartId })
return handlers['getCheckout']({ ...ctx, body })
}
// Create checkout
if (req.method === 'POST' && handlers['submitCheckout']) {
const body = { ...req.body, cartId }
const body = submitCheckoutBodySchema.parse({ ...req.body, cartId })
return handlers['submitCheckout']({ ...ctx, body })
}
}

View File

@ -51,7 +51,7 @@ export default function createEndpoints<P extends APIProvider>(
const data = await handlers[path](req, res)
// 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({
data,
})

View File

@ -25,26 +25,19 @@ export class CommerceNetworkError extends Error {
}
export const normalizeZodIssues = (issues: ZodError['issues']) =>
issues.map((e, index) => ({
message: `Error #${index + 1} ${
e.path.length > 0 ? `Path: ${e.path.join('.')}, ` : ''
}Code: ${e.code}, Message: ${e.message}`,
}))
issues.map(({ path, message }) => `${message} at "${path.join('.')}"`)
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` +
normalizeZodIssues(error.issues)
.map((e) => e.message)
.join('\n'),
`Validation ${
error.issues.length === 1 ? 'error' : 'errors'
} at "${operation}" operation: \n` +
normalizeZodIssues(error.issues).join('\n'),
})
}
return error
}
@ -63,7 +56,7 @@ export const normalizeError = (error: unknown) => {
return {
status: 400,
data: null,
errors: normalizeZodIssues(error.issues),
errors: normalizeZodIssues(error.issues).map((message) => ({ message })),
}
}

View 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,
}),
})

View File

@ -69,7 +69,7 @@ export type CheckoutHooks = {
}
export type GetCheckoutHandler = GetCheckoutHook & {
body: { cartId: string }
body: { cartId?: string }
}
export type SubmitCheckoutHandler = SubmitCheckoutHook & {

View File

@ -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

View File

@ -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

View File

@ -23,8 +23,8 @@
"@components/*": ["components/*"],
"@commerce": ["../packages/commerce/src"],
"@commerce/*": ["../packages/commerce/src/*"],
"@framework": ["../packages/local/src"],
"@framework/*": ["../packages/local/src/*"]
"@framework": ["../packages/shopify/src"],
"@framework/*": ["../packages/shopify/src/*"]
}
},
"include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"],