From 6af5794ac525e34c86e66f181c1f838e6467c916 Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Sat, 22 May 2021 22:52:21 -0500 Subject: [PATCH] Moved wishlist --- .../api/endpoints/wishlist/add-item.ts | 56 ++++++++++++++++++ .../api/endpoints/wishlist/get-wishlist.ts | 38 ++++++++++++ .../api/endpoints/wishlist/index.ts | 12 ++++ .../api/endpoints/wishlist/remove-item.ts | 38 ++++++++++++ .../wishlist/utils}/get-customer-id.ts | 8 +-- framework/bigcommerce/api/index.ts | 2 + .../api/wishlist/handlers/add-item.ts | 2 +- .../api/wishlist/handlers/get-wishlist.ts | 2 +- .../api/wishlist/handlers/remove-item.ts | 2 +- framework/bigcommerce/types/wishlist.ts | 22 +++++++ framework/commerce/api/endpoints/wishlist.ts | 58 +++++++++++++++++++ framework/commerce/api/index.ts | 4 +- framework/commerce/types/wishlist.ts | 32 ++++++++++ pages/api/bigcommerce/wishlist.ts | 3 - pages/api/wishlist.ts | 8 +++ 15 files changed, 275 insertions(+), 12 deletions(-) create mode 100644 framework/bigcommerce/api/endpoints/wishlist/add-item.ts create mode 100644 framework/bigcommerce/api/endpoints/wishlist/get-wishlist.ts create mode 100644 framework/bigcommerce/api/endpoints/wishlist/index.ts create mode 100644 framework/bigcommerce/api/endpoints/wishlist/remove-item.ts rename framework/bigcommerce/{customer => api/endpoints/wishlist/utils}/get-customer-id.ts (76%) create mode 100644 framework/bigcommerce/types/wishlist.ts create mode 100644 framework/commerce/api/endpoints/wishlist.ts create mode 100644 framework/commerce/types/wishlist.ts delete mode 100644 pages/api/bigcommerce/wishlist.ts create mode 100644 pages/api/wishlist.ts diff --git a/framework/bigcommerce/api/endpoints/wishlist/add-item.ts b/framework/bigcommerce/api/endpoints/wishlist/add-item.ts new file mode 100644 index 000000000..c2fdd9eff --- /dev/null +++ b/framework/bigcommerce/api/endpoints/wishlist/add-item.ts @@ -0,0 +1,56 @@ +import getCustomerWishlist from '../../../customer/get-customer-wishlist' +import { parseWishlistItem } from '../../utils/parse-item' +import getCustomerId from './utils/get-customer-id' +import type { WishlistEndpoint } from '.' + +// Return wishlist info +const addItem: WishlistEndpoint['handlers']['addItem'] = async ({ + res, + body: { customerToken, item }, + config, +}) => { + if (!item) { + return res.status(400).json({ + data: null, + errors: [{ message: 'Missing item' }], + }) + } + + const customerId = + customerToken && (await getCustomerId({ customerToken, config })) + + if (!customerId) { + return res.status(400).json({ + data: null, + errors: [{ message: 'Invalid request' }], + }) + } + + const { wishlist } = await getCustomerWishlist({ + variables: { customerId }, + config, + }) + const options = { + method: 'POST', + body: JSON.stringify( + wishlist + ? { + items: [parseWishlistItem(item)], + } + : { + name: 'Wishlist', + customer_id: customerId, + items: [parseWishlistItem(item)], + is_public: false, + } + ), + } + + const { data } = wishlist + ? await config.storeApiFetch(`/v3/wishlists/${wishlist.id}/items`, options) + : await config.storeApiFetch('/v3/wishlists', options) + + res.status(200).json({ data }) +} + +export default addItem diff --git a/framework/bigcommerce/api/endpoints/wishlist/get-wishlist.ts b/framework/bigcommerce/api/endpoints/wishlist/get-wishlist.ts new file mode 100644 index 000000000..43dcc0bfb --- /dev/null +++ b/framework/bigcommerce/api/endpoints/wishlist/get-wishlist.ts @@ -0,0 +1,38 @@ +import type { Wishlist } from '../../../types/wishlist' +import type { WishlistEndpoint } from '.' +import getCustomerId from './utils/get-customer-id' +import getCustomerWishlist from '../../../customer/get-customer-wishlist' + +// Return wishlist info +const getWishlist: WishlistEndpoint['handlers']['getWishlist'] = async ({ + res, + body: { customerToken, includeProducts }, + config, +}) => { + let result: { data?: Wishlist } = {} + + if (customerToken) { + const customerId = + customerToken && (await getCustomerId({ customerToken, config })) + + if (!customerId) { + // If the customerToken is invalid, then this request is too + return res.status(404).json({ + data: null, + errors: [{ message: 'Wishlist not found' }], + }) + } + + const { wishlist } = await getCustomerWishlist({ + variables: { customerId }, + includeProducts, + config, + }) + + result = { data: wishlist } + } + + res.status(200).json({ data: result.data ?? null }) +} + +export default getWishlist diff --git a/framework/bigcommerce/api/endpoints/wishlist/index.ts b/framework/bigcommerce/api/endpoints/wishlist/index.ts new file mode 100644 index 000000000..78bf8f738 --- /dev/null +++ b/framework/bigcommerce/api/endpoints/wishlist/index.ts @@ -0,0 +1,12 @@ +import type { GetAPISchema } from '@commerce/api' +import type { WishlistSchema } from '../../../types/wishlist' +import type { BigcommerceAPI } from '../..' +import getWishlist from './get-wishlist' +import addItem from './add-item' +import removeItem from './remove-item' + +export type WishlistAPI = GetAPISchema + +export type WishlistEndpoint = WishlistAPI['endpoint'] + +export const handlers = { getWishlist, addItem, removeItem } diff --git a/framework/bigcommerce/api/endpoints/wishlist/remove-item.ts b/framework/bigcommerce/api/endpoints/wishlist/remove-item.ts new file mode 100644 index 000000000..7a243b322 --- /dev/null +++ b/framework/bigcommerce/api/endpoints/wishlist/remove-item.ts @@ -0,0 +1,38 @@ +import type { Wishlist } from '../../../types/wishlist' +import getCustomerWishlist from '../../../customer/get-customer-wishlist' +import getCustomerId from './utils/get-customer-id' +import type { WishlistEndpoint } from '.' + +// Return wishlist info +const removeItem: WishlistEndpoint['handlers']['removeItem'] = async ({ + res, + body: { customerToken, itemId }, + config, +}) => { + const customerId = + customerToken && (await getCustomerId({ customerToken, config })) + const { wishlist } = + (customerId && + (await getCustomerWishlist({ + variables: { customerId }, + config, + }))) || + {} + + if (!wishlist || !itemId) { + return res.status(400).json({ + data: null, + errors: [{ message: 'Invalid request' }], + }) + } + + const result = await config.storeApiFetch<{ data: Wishlist } | null>( + `/v3/wishlists/${wishlist.id}/items/${itemId}`, + { method: 'DELETE' } + ) + const data = result?.data ?? null + + res.status(200).json({ data }) +} + +export default removeItem diff --git a/framework/bigcommerce/customer/get-customer-id.ts b/framework/bigcommerce/api/endpoints/wishlist/utils/get-customer-id.ts similarity index 76% rename from framework/bigcommerce/customer/get-customer-id.ts rename to framework/bigcommerce/api/endpoints/wishlist/utils/get-customer-id.ts index 65ce5a6a8..5f9fc49df 100644 --- a/framework/bigcommerce/customer/get-customer-id.ts +++ b/framework/bigcommerce/api/endpoints/wishlist/utils/get-customer-id.ts @@ -1,5 +1,5 @@ -import { GetCustomerIdQuery } from '../schema' -import { BigcommerceConfig, getConfig } from '../api' +import type { GetCustomerIdQuery } from '../../../../schema' +import type { BigcommerceConfig } from '../../..' export const getCustomerIdQuery = /* GraphQL */ ` query getCustomerId { @@ -14,10 +14,8 @@ async function getCustomerId({ config, }: { customerToken: string - config?: BigcommerceConfig + config: BigcommerceConfig }): Promise { - config = getConfig(config) - const { data } = await config.fetch( getCustomerIdQuery, undefined, diff --git a/framework/bigcommerce/api/index.ts b/framework/bigcommerce/api/index.ts index 2dcd31d4f..c53165966 100644 --- a/framework/bigcommerce/api/index.ts +++ b/framework/bigcommerce/api/index.ts @@ -15,6 +15,7 @@ import type { LoginAPI } from './endpoints/login' import type { LogoutAPI } from './endpoints/logout' import type { SignupAPI } from './endpoints/signup' import type { ProductsAPI } from './endpoints/catalog/products' +import type { WishlistAPI } from './endpoints/wishlist' import login from './operations/login' import getAllPages from './operations/get-all-pages' @@ -127,6 +128,7 @@ export type APIs = | LogoutAPI | SignupAPI | ProductsAPI + | WishlistAPI export type BigcommerceAPI

= CommerceAPI

diff --git a/framework/bigcommerce/api/wishlist/handlers/add-item.ts b/framework/bigcommerce/api/wishlist/handlers/add-item.ts index 00d7b06bd..cbf0ec9d6 100644 --- a/framework/bigcommerce/api/wishlist/handlers/add-item.ts +++ b/framework/bigcommerce/api/wishlist/handlers/add-item.ts @@ -1,5 +1,5 @@ import type { WishlistHandlers } from '..' -import getCustomerId from '../../../customer/get-customer-id' +import getCustomerId from '../../endpoints/wishlist/utils/get-customer-id' import getCustomerWishlist from '../../../customer/get-customer-wishlist' import { parseWishlistItem } from '../../utils/parse-item' diff --git a/framework/bigcommerce/api/wishlist/handlers/get-wishlist.ts b/framework/bigcommerce/api/wishlist/handlers/get-wishlist.ts index 3737c033a..a1c74fb29 100644 --- a/framework/bigcommerce/api/wishlist/handlers/get-wishlist.ts +++ b/framework/bigcommerce/api/wishlist/handlers/get-wishlist.ts @@ -1,4 +1,4 @@ -import getCustomerId from '../../../customer/get-customer-id' +import getCustomerId from '../../endpoints/wishlist/utils/get-customer-id' import getCustomerWishlist from '../../../customer/get-customer-wishlist' import type { Wishlist, WishlistHandlers } from '..' diff --git a/framework/bigcommerce/api/wishlist/handlers/remove-item.ts b/framework/bigcommerce/api/wishlist/handlers/remove-item.ts index a9cfd9db5..ea5764a28 100644 --- a/framework/bigcommerce/api/wishlist/handlers/remove-item.ts +++ b/framework/bigcommerce/api/wishlist/handlers/remove-item.ts @@ -1,4 +1,4 @@ -import getCustomerId from '../../../customer/get-customer-id' +import getCustomerId from '../../endpoints/wishlist/utils/get-customer-id' import getCustomerWishlist, { Wishlist, } from '../../../customer/get-customer-wishlist' diff --git a/framework/bigcommerce/types/wishlist.ts b/framework/bigcommerce/types/wishlist.ts new file mode 100644 index 000000000..9c98a8df4 --- /dev/null +++ b/framework/bigcommerce/types/wishlist.ts @@ -0,0 +1,22 @@ +import * as Core from '@commerce/types/wishlist' +import { definitions } from '../api/definitions/wishlist' +import type { ProductEdge } from '../product/get-all-products' + +export * from '@commerce/types/wishlist' + +export type WishlistItem = NonNullable< + definitions['wishlist_Full']['items'] +>[0] & { + product?: ProductEdge['node'] +} + +export type Wishlist = Omit & { + items?: WishlistItem[] +} + +export type WishlistTypes = { + wishlist: Wishlist + itemBody: Core.WishlistItemBody +} + +export type WishlistSchema = Core.WishlistSchema diff --git a/framework/commerce/api/endpoints/wishlist.ts b/framework/commerce/api/endpoints/wishlist.ts new file mode 100644 index 000000000..688fcd5da --- /dev/null +++ b/framework/commerce/api/endpoints/wishlist.ts @@ -0,0 +1,58 @@ +import type { WishlistSchema } from '../../types/wishlist' +import { CommerceAPIError } from '../utils/errors' +import isAllowedOperation from '../utils/is-allowed-operation' +import type { GetAPISchema } from '..' + +const wishlistEndpoint: GetAPISchema< + any, + WishlistSchema +>['endpoint']['handler'] = async (ctx) => { + const { req, res, handlers, config } = ctx + + if ( + !isAllowedOperation(req, res, { + GET: handlers['getWishlist'], + POST: handlers['addItem'], + DELETE: handlers['removeItem'], + }) + ) { + return + } + + const { cookies } = req + const customerToken = cookies[config.customerCookie] + + try { + // Return current wishlist info + if (req.method === 'GET') { + const body = { + customerToken, + includeProducts: req.query.products === '1', + } + return await handlers['getWishlist']({ ...ctx, body }) + } + + // Add an item to the wishlist + if (req.method === 'POST') { + const body = { ...req.body, customerToken } + return await handlers['addItem']({ ...ctx, body }) + } + + // Remove an item from the wishlist + if (req.method === 'DELETE') { + const body = { ...req.body, customerToken } + 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 wishlistEndpoint diff --git a/framework/commerce/api/index.ts b/framework/commerce/api/index.ts index 6d4c16f2a..60afb7ae2 100644 --- a/framework/commerce/api/index.ts +++ b/framework/commerce/api/index.ts @@ -6,7 +6,8 @@ import type { CustomerSchema } from '../types/customer' import type { LoginSchema } from '../types/login' import type { LogoutSchema } from '../types/logout' import type { SignupSchema } from '../types/signup' -import type { ProductsSchema } from '@commerce/types/product' +import type { ProductsSchema } from '../types/product' +import type { WishlistSchema } from '../types/wishlist' import { defaultOperations, OPERATIONS, @@ -21,6 +22,7 @@ export type APISchemas = | LogoutSchema | SignupSchema | ProductsSchema + | WishlistSchema export type GetAPISchema< C extends CommerceAPI, diff --git a/framework/commerce/types/wishlist.ts b/framework/commerce/types/wishlist.ts new file mode 100644 index 000000000..70f900362 --- /dev/null +++ b/framework/commerce/types/wishlist.ts @@ -0,0 +1,32 @@ +// TODO: define this type +export type Wishlist = any + +export type WishlistItemBody = { + variantId: string + productId: string +} + +export type WishlistTypes = { + wishlist: Wishlist + itemBody: WishlistItemBody +} + +export type WishlistSchema = { + endpoint: { + options: {} + handlers: { + getWishlist: { + data: T['wishlist'] | null + body: { customerToken?: string; includeProducts?: boolean } + } + addItem: { + data: T['wishlist'] + body: { customerToken?: string; item: T['itemBody'] } + } + removeItem: { + data: T['wishlist'] | null + body: { customerToken?: string; itemId: string } + } + } + } +} diff --git a/pages/api/bigcommerce/wishlist.ts b/pages/api/bigcommerce/wishlist.ts deleted file mode 100644 index 0d6a895a5..000000000 --- a/pages/api/bigcommerce/wishlist.ts +++ /dev/null @@ -1,3 +0,0 @@ -import wishlistApi from '@framework/api/wishlist' - -export default wishlistApi() diff --git a/pages/api/wishlist.ts b/pages/api/wishlist.ts new file mode 100644 index 000000000..fe6d2d1c7 --- /dev/null +++ b/pages/api/wishlist.ts @@ -0,0 +1,8 @@ +import wishlist from '@commerce/api/endpoints/wishlist' +import { WishlistAPI, handlers } from '@framework/api/endpoints/wishlist' +import commerce from '@lib/api/commerce' + +export default commerce.endpoint({ + handler: wishlist as WishlistAPI['endpoint']['handler'], + handlers, +})