Adding more migration changes

This commit is contained in:
Luis Alvarez 2021-03-18 20:16:35 -06:00
parent 90fb763602
commit df07a55740
6 changed files with 104 additions and 60 deletions

View File

@ -0,0 +1,46 @@
import { parseCartItem } from '../utils/parse-item'
import getCartCookie from '../utils/get-cart-cookie'
import type { CartHandlers } from '.'
import { normalizeCart } from '@framework/lib/normalize'
const addItem: CartHandlers['addItem'] = async ({
res,
body: { cartId, item },
config,
}) => {
if (!item) {
return res.status(400).json({
data: null,
errors: [{ message: 'Missing item' }],
})
}
if (!item.quantity) item.quantity = 1
const options = {
method: 'POST',
body: JSON.stringify({
line_items: [parseCartItem(item)],
...(!cartId && config.storeChannelId
? { channel_id: config.storeChannelId }
: {}),
}),
}
const { data } = cartId
? await config.storeApiFetch(
`/v3/carts/${cartId}/items?include=line_items.physical_items.options`,
options
)
: await config.storeApiFetch(
'/v3/carts?include=line_items.physical_items.options',
options
)
// Create or update the cart cookie
res.setHeader(
'Set-Cookie',
getCartCookie(config.cartCookie, data.id, config.cartCookieMaxAge)
)
res.status(200).json({ data: normalizeCart(data) })
}
export default addItem

View File

@ -1,7 +1,7 @@
import { CartHandlers as CartHandlersCore } from '@commerce/api'
import isAllowedMethod from '../utils/is-allowed-method' import isAllowedMethod from '../utils/is-allowed-method'
import createApiHandler, { import createApiHandler, {
BigcommerceApiHandler, BigcommerceApiHandler,
BigcommerceHandler,
} from '../utils/create-api-handler' } from '../utils/create-api-handler'
import { BigcommerceApiError } from '../utils/errors' import { BigcommerceApiError } from '../utils/errors'
import getCart from './handlers/get-cart' import getCart from './handlers/get-cart'
@ -14,14 +14,22 @@ import type {
AddCartItemHandlerBody, AddCartItemHandlerBody,
UpdateCartItemHandlerBody, UpdateCartItemHandlerBody,
RemoveCartItemHandlerBody, RemoveCartItemHandlerBody,
Cart,
} from '../../types' } from '../../types'
import { APIHandler } from '@commerce/api/utils/types'
import { CommerceAPI } from '..'
export type CartHandlers = { export type CartHandlers<
getCart: BigcommerceHandler<BigcommerceCart, GetCartHandlerBody> C extends CommerceAPI = CommerceAPI
addItem: BigcommerceHandler<BigcommerceCart, AddCartItemHandlerBody> > = CartHandlersCore<
updateItem: BigcommerceHandler<BigcommerceCart, UpdateCartItemHandlerBody> C,
removeItem: BigcommerceHandler<BigcommerceCart, RemoveCartItemHandlerBody> {
getCart: APIHandler<C, CartHandlers<C>, Cart | null, GetCartHandlerBody>
addItem: APIHandler<C, CartHandlers<C>, Cart, AddCartItemHandlerBody>
updateItem: APIHandler<C, CartHandlers<C>, Cart, UpdateCartItemHandlerBody>
removeItem: APIHandler<C, CartHandlers<C>, Cart, RemoveCartItemHandlerBody>
} }
>
const METHODS = ['GET', 'POST', 'PUT', 'DELETE'] const METHODS = ['GET', 'POST', 'PUT', 'DELETE']

View File

@ -104,7 +104,9 @@ export const provider = {
export type Provider = typeof provider export type Provider = typeof provider
export class CommerceAPI<P extends Provider> extends CoreCommerceAPI<P> { export class CommerceAPI<
P extends Provider = Provider
> extends CoreCommerceAPI<P> {
constructor(readonly provider: P = provider) { constructor(readonly provider: P = provider) {
super(provider) super(provider)
} }

View File

@ -1,9 +1,9 @@
import type { APIEndpoint } from '../utils/types' import type { APIEndpoint } from '../utils/types'
import { CommerceAPIError } from '../utils/errors' import { CommerceAPIError } from '../utils/errors'
import isAllowedOperation from '../utils/is-allowed-operation' import isAllowedOperation from '../utils/is-allowed-operation'
import type { APIProvider, CartHandlers } from '..' import type { CommerceAPI, CartHandlers } from '..'
const cartApi: APIEndpoint<APIProvider, CartHandlers<any>> = async (ctx) => { const cartApi: APIEndpoint<CommerceAPI, CartHandlers<any>> = async (ctx) => {
const { req, res, handlers, config } = ctx const { req, res, handlers, config } = ctx
if ( if (

View File

@ -1,16 +1,22 @@
import type { NextApiHandler } from 'next' import type { NextApiHandler } from 'next'
import type { RequestInit, Response } from '@vercel/fetch' import type { RequestInit, Response } from '@vercel/fetch'
import type { APIEndpoint, APIHandler } from './utils/types' import type { APIEndpoint, APIHandler } from './utils/types'
import type { Cart } from '../types'
export type CartEndpoint = APIEndpoint<any, any, CartHandlers<any>, any> export type CartEndpoint = APIEndpoint<any, any, CartHandlers<CommerceAPI>, any>
export type CartHandlers<Body extends { cartId: 'string' }> = { export type CartHandlersBase<C> = {
getCart: APIHandler<any, CartHandlers<Body>, any, Body> getCart: APIHandler<any, CartHandlersBase<C>, Cart | null, any>
addItem: APIHandler<any, CartHandlers<Body>, any, Body> addItem: APIHandler<any, CartHandlersBase<C>, Cart, any>
updateItem: APIHandler<any, CartHandlers<Body>, any, Body> updateItem: APIHandler<any, CartHandlersBase<C>, Cart, any>
removeItem: APIHandler<any, CartHandlers<Body>, any, Body> removeItem: APIHandler<any, CartHandlersBase<C>, Cart, any>
} }
export type CartHandlers<
C extends CommerceAPI,
T extends CartHandlersBase<C> = CartHandlersBase<C>
> = T
export type Endpoints = CartEndpoint export type Endpoints = CartEndpoint
export type EndpointHandlers<E> = E extends APIEndpoint<any, any, infer T> export type EndpointHandlers<E> = E extends APIEndpoint<any, any, infer T>
@ -21,17 +27,12 @@ export type EndpointOptions<E> = E extends APIEndpoint<any, any, any, infer T>
? T ? T
: never : never
export type CoreAPIProvider = { export type APIProvider = {
config: CommerceAPIConfig config: CommerceAPIConfig
} }
export type APIProvider<P extends CoreAPIProvider = CoreAPIProvider> = P & {
getConfig(userConfig?: Partial<P['config']>): P['config']
setConfig(newConfig: Partial<P['config']>): void
}
export class CommerceAPI< export class CommerceAPI<
P extends CoreAPIProvider = CoreAPIProvider, P extends APIProvider = APIProvider,
E extends Endpoints = Endpoints E extends Endpoints = Endpoints
> { > {
constructor(readonly provider: P) { constructor(readonly provider: P) {
@ -55,14 +56,14 @@ export class CommerceAPI<
operations: EndpointHandlers<typeof context.handler> operations: EndpointHandlers<typeof context.handler>
options?: EndpointOptions<typeof context.handler> options?: EndpointOptions<typeof context.handler>
}): NextApiHandler { }): NextApiHandler {
const provider = this const commerce = this
const cfg = this.getConfig(context.config) const cfg = this.getConfig(context.config)
return function apiHandler(req, res) { return function apiHandler(req, res) {
return context.handler({ return context.handler({
req, req,
res, res,
provider, commerce,
config: cfg, config: cfg,
handlers: context.operations, handlers: context.operations,
options: context.options, options: context.options,
@ -71,23 +72,6 @@ export class CommerceAPI<
} }
} }
export function createAPIProvider<P extends CoreAPIProvider>(
provider: P
): APIProvider<P> {
return {
...provider,
getConfig(userConfig = {}) {
return Object.entries(userConfig).reduce(
(cfg, [key, value]) => Object.assign(cfg, { [key]: value }),
{ ...this.config }
)
},
setConfig(newConfig) {
Object.assign(this.config, newConfig)
},
}
}
export interface CommerceAPIConfig { export interface CommerceAPIConfig {
locale?: string locale?: string
commerceUrl: string commerceUrl: string

View File

@ -1,21 +1,25 @@
import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' import type { NextApiRequest, NextApiResponse } from 'next'
import type { APIProvider } from '..' import type { CommerceAPI } from '..'
export type APIResponse<Data = any> = { export type ErrorData = { message: string; code?: string }
data: Data
errors?: { message: string; code?: string }[] export type APIResponse<Data = any> =
} | { data: Data; errors?: ErrorData[] }
// If `data` doesn't include `null`, then `null` is only allowed on errors
| (Data extends null
? { data: null; errors?: ErrorData[] }
: { data: null; errors: ErrorData[] })
export type APIHandlerContext< export type APIHandlerContext<
P extends APIProvider, C extends CommerceAPI,
H extends APIHandlers<P, Data> = {}, H extends APIHandlers<C> = {},
Data = any, Data = any,
Options extends {} = {} Options extends {} = {}
> = { > = {
req: NextApiRequest req: NextApiRequest
res: NextApiResponse<APIResponse<Data>> res: NextApiResponse<APIResponse<Data>>
provider: P commerce: C
config: P['config'] config: C['provider']['config']
handlers: H handlers: H
/** /**
* Custom configs that may be used by a particular handler * Custom configs that may be used by a particular handler
@ -24,22 +28,22 @@ export type APIHandlerContext<
} }
export type APIHandler< export type APIHandler<
P extends APIProvider, C extends CommerceAPI,
H extends APIHandlers<P, Data> = {}, H extends APIHandlers<C> = {},
Data = any, Data = any,
Body = any, Body = any,
Options extends {} = {} Options extends {} = {}
> = ( > = (
context: APIHandlerContext<P, H, Data, Options> & { body: Body } context: APIHandlerContext<C, H, Data, Options> & { body: Body }
) => void | Promise<void> ) => void | Promise<void>
export type APIHandlers<P extends APIProvider, Data = any> = { export type APIHandlers<C extends CommerceAPI, Data = any> = {
[k: string]: APIHandler<P, any, Data, any> [k: string]: APIHandler<C, any, Data, any, any>
} }
export type APIEndpoint< export type APIEndpoint<
P extends APIProvider = APIProvider, C extends CommerceAPI = CommerceAPI,
H extends APIHandlers<P, Data> = {}, H extends APIHandlers<C> = {},
Data = any, Data = any,
Options extends {} = {} Options extends {} = {}
> = (context: APIHandlerContext<P, H, Data, Options>) => void | Promise<void> > = (context: APIHandlerContext<C, H, Data, Options>) => void | Promise<void>