From a1167e46f7f2f509f9e1c08e7b635dde38c300a4 Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Mon, 24 May 2021 12:16:11 -0500 Subject: [PATCH] Added the get customer wishlist operation --- .../api/endpoints/wishlist/add-item.ts | 5 +- .../api/endpoints/wishlist/get-wishlist.ts | 5 +- .../api/endpoints/wishlist/remove-item.ts | 5 +- .../wishlist/utils/get-customer-id.ts | 4 +- framework/bigcommerce/api/index.ts | 3 +- .../api/operations/get-customer-wishlist.ts | 81 +++++++++++++++++ .../api/wishlist/handlers/add-item.ts | 2 +- .../api/wishlist/handlers/get-wishlist.ts | 2 +- .../api/wishlist/handlers/remove-item.ts | 2 +- framework/bigcommerce/api/wishlist/index.ts | 2 +- .../customer/get-customer-wishlist.ts | 88 ------------------- framework/bigcommerce/types/wishlist.ts | 1 + framework/commerce/api/operations.ts | 17 ++++ framework/commerce/types/wishlist.ts | 7 ++ 14 files changed, 123 insertions(+), 101 deletions(-) create mode 100644 framework/bigcommerce/api/operations/get-customer-wishlist.ts delete mode 100644 framework/bigcommerce/customer/get-customer-wishlist.ts diff --git a/framework/bigcommerce/api/endpoints/wishlist/add-item.ts b/framework/bigcommerce/api/endpoints/wishlist/add-item.ts index c2fdd9eff..4c5970a5d 100644 --- a/framework/bigcommerce/api/endpoints/wishlist/add-item.ts +++ b/framework/bigcommerce/api/endpoints/wishlist/add-item.ts @@ -1,4 +1,4 @@ -import getCustomerWishlist from '../../../customer/get-customer-wishlist' +import getCustomerWishlist from '../../operations/get-customer-wishlist' import { parseWishlistItem } from '../../utils/parse-item' import getCustomerId from './utils/get-customer-id' import type { WishlistEndpoint } from '.' @@ -8,6 +8,7 @@ const addItem: WishlistEndpoint['handlers']['addItem'] = async ({ res, body: { customerToken, item }, config, + commerce, }) => { if (!item) { return res.status(400).json({ @@ -26,7 +27,7 @@ const addItem: WishlistEndpoint['handlers']['addItem'] = async ({ }) } - const { wishlist } = await getCustomerWishlist({ + const { wishlist } = await commerce.getCustomerWishlist({ variables: { customerId }, config, }) diff --git a/framework/bigcommerce/api/endpoints/wishlist/get-wishlist.ts b/framework/bigcommerce/api/endpoints/wishlist/get-wishlist.ts index 43dcc0bfb..21443119c 100644 --- a/framework/bigcommerce/api/endpoints/wishlist/get-wishlist.ts +++ b/framework/bigcommerce/api/endpoints/wishlist/get-wishlist.ts @@ -1,13 +1,14 @@ import type { Wishlist } from '../../../types/wishlist' import type { WishlistEndpoint } from '.' import getCustomerId from './utils/get-customer-id' -import getCustomerWishlist from '../../../customer/get-customer-wishlist' +import getCustomerWishlist from '../../operations/get-customer-wishlist' // Return wishlist info const getWishlist: WishlistEndpoint['handlers']['getWishlist'] = async ({ res, body: { customerToken, includeProducts }, config, + commerce, }) => { let result: { data?: Wishlist } = {} @@ -23,7 +24,7 @@ const getWishlist: WishlistEndpoint['handlers']['getWishlist'] = async ({ }) } - const { wishlist } = await getCustomerWishlist({ + const { wishlist } = await commerce.getCustomerWishlist({ variables: { customerId }, includeProducts, config, diff --git a/framework/bigcommerce/api/endpoints/wishlist/remove-item.ts b/framework/bigcommerce/api/endpoints/wishlist/remove-item.ts index 7a243b322..22ac31cf9 100644 --- a/framework/bigcommerce/api/endpoints/wishlist/remove-item.ts +++ b/framework/bigcommerce/api/endpoints/wishlist/remove-item.ts @@ -1,5 +1,5 @@ import type { Wishlist } from '../../../types/wishlist' -import getCustomerWishlist from '../../../customer/get-customer-wishlist' +import getCustomerWishlist from '../../operations/get-customer-wishlist' import getCustomerId from './utils/get-customer-id' import type { WishlistEndpoint } from '.' @@ -8,12 +8,13 @@ const removeItem: WishlistEndpoint['handlers']['removeItem'] = async ({ res, body: { customerToken, itemId }, config, + commerce, }) => { const customerId = customerToken && (await getCustomerId({ customerToken, config })) const { wishlist } = (customerId && - (await getCustomerWishlist({ + (await commerce.getCustomerWishlist({ variables: { customerId }, config, }))) || diff --git a/framework/bigcommerce/api/endpoints/wishlist/utils/get-customer-id.ts b/framework/bigcommerce/api/endpoints/wishlist/utils/get-customer-id.ts index 5f9fc49df..603f8be2d 100644 --- a/framework/bigcommerce/api/endpoints/wishlist/utils/get-customer-id.ts +++ b/framework/bigcommerce/api/endpoints/wishlist/utils/get-customer-id.ts @@ -15,7 +15,7 @@ async function getCustomerId({ }: { customerToken: string config: BigcommerceConfig -}): Promise { +}): Promise { const { data } = await config.fetch( getCustomerIdQuery, undefined, @@ -26,7 +26,7 @@ async function getCustomerId({ } ) - return data?.customer?.entityId + return String(data?.customer?.entityId) } export default getCustomerId diff --git a/framework/bigcommerce/api/index.ts b/framework/bigcommerce/api/index.ts index 9eeea5b49..d33c5620b 100644 --- a/framework/bigcommerce/api/index.ts +++ b/framework/bigcommerce/api/index.ts @@ -20,6 +20,7 @@ import login from './operations/login' import getAllPages from './operations/get-all-pages' import getPage from './operations/get-page' import getSiteInfo from './operations/get-site-info' +import getCustomerWishlist from './operations/get-customer-wishlist' export interface BigcommerceConfig extends CommerceAPIConfig { // Indicates if the returned metadata with translations should be applied to the @@ -115,7 +116,7 @@ const config2: BigcommerceConfig = { export const provider = { config: config2, - operations: { login, getAllPages, getPage, getSiteInfo }, + operations: { login, getAllPages, getPage, getSiteInfo, getCustomerWishlist }, } export type Provider = typeof provider diff --git a/framework/bigcommerce/api/operations/get-customer-wishlist.ts b/framework/bigcommerce/api/operations/get-customer-wishlist.ts new file mode 100644 index 000000000..f4036ee51 --- /dev/null +++ b/framework/bigcommerce/api/operations/get-customer-wishlist.ts @@ -0,0 +1,81 @@ +import type { + OperationContext, + OperationOptions, +} from '@commerce/api/operations' +import type { + GetCustomerWishlistOperation, + Wishlist, +} from '../../types/wishlist' +import type { RecursivePartial, RecursiveRequired } from '../utils/types' +import { BigcommerceConfig, Provider } from '..' +import getAllProducts, { ProductEdge } from '../../product/get-all-products' + +export default function getCustomerWishlistOperation({ + commerce, +}: OperationContext) { + async function getCustomerWishlist< + T extends GetCustomerWishlistOperation + >(opts: { + variables: T['variables'] + config?: BigcommerceConfig + includeProducts?: boolean + }): Promise + + async function getCustomerWishlist( + opts: { + variables: T['variables'] + config?: BigcommerceConfig + includeProducts?: boolean + } & OperationOptions + ): Promise + + async function getCustomerWishlist({ + config, + variables, + includeProducts, + }: { + url?: string + variables: T['variables'] + config?: BigcommerceConfig + includeProducts?: boolean + }): Promise { + config = commerce.getConfig(config) + + const { data = [] } = await config.storeApiFetch< + RecursivePartial<{ data: Wishlist[] }> + >(`/v3/wishlists?customer_id=${variables.customerId}`) + const wishlist = data[0] + + if (includeProducts && wishlist?.items?.length) { + const entityIds = wishlist.items + ?.map((item) => item?.product_id) + .filter((id): id is number => !!id) + + if (entityIds?.length) { + const graphqlData = await getAllProducts({ + variables: { first: 100, entityIds }, + config, + }) + // Put the products in an object that we can use to get them by id + const productsById = graphqlData.products.reduce<{ + [k: number]: ProductEdge + }>((prods, p) => { + prods[Number(p.id)] = p as any + return prods + }, {}) + // Populate the wishlist items with the graphql products + wishlist.items.forEach((item) => { + const product = item && productsById[item.product_id!] + if (item && product) { + // @ts-ignore Fix this type when the wishlist type is properly defined + item.product = product + } + }) + } + } + + return { wishlist: wishlist as RecursiveRequired } + } + + return getCustomerWishlist +} diff --git a/framework/bigcommerce/api/wishlist/handlers/add-item.ts b/framework/bigcommerce/api/wishlist/handlers/add-item.ts index cbf0ec9d6..aeaac2545 100644 --- a/framework/bigcommerce/api/wishlist/handlers/add-item.ts +++ b/framework/bigcommerce/api/wishlist/handlers/add-item.ts @@ -1,6 +1,6 @@ import type { WishlistHandlers } from '..' import getCustomerId from '../../endpoints/wishlist/utils/get-customer-id' -import getCustomerWishlist from '../../../customer/get-customer-wishlist' +import getCustomerWishlist from '../../operations/get-customer-wishlist' import { parseWishlistItem } from '../../utils/parse-item' // Returns the wishlist of the signed customer diff --git a/framework/bigcommerce/api/wishlist/handlers/get-wishlist.ts b/framework/bigcommerce/api/wishlist/handlers/get-wishlist.ts index a1c74fb29..c5db21243 100644 --- a/framework/bigcommerce/api/wishlist/handlers/get-wishlist.ts +++ b/framework/bigcommerce/api/wishlist/handlers/get-wishlist.ts @@ -1,5 +1,5 @@ import getCustomerId from '../../endpoints/wishlist/utils/get-customer-id' -import getCustomerWishlist from '../../../customer/get-customer-wishlist' +import getCustomerWishlist from '../../operations/get-customer-wishlist' import type { Wishlist, WishlistHandlers } from '..' // Return wishlist info diff --git a/framework/bigcommerce/api/wishlist/handlers/remove-item.ts b/framework/bigcommerce/api/wishlist/handlers/remove-item.ts index ea5764a28..32e612119 100644 --- a/framework/bigcommerce/api/wishlist/handlers/remove-item.ts +++ b/framework/bigcommerce/api/wishlist/handlers/remove-item.ts @@ -1,7 +1,7 @@ import getCustomerId from '../../endpoints/wishlist/utils/get-customer-id' import getCustomerWishlist, { Wishlist, -} from '../../../customer/get-customer-wishlist' +} from '../../operations/get-customer-wishlist' import type { WishlistHandlers } from '..' // Return current wishlist info diff --git a/framework/bigcommerce/api/wishlist/index.ts b/framework/bigcommerce/api/wishlist/index.ts index 7c700689c..c7bef234f 100644 --- a/framework/bigcommerce/api/wishlist/index.ts +++ b/framework/bigcommerce/api/wishlist/index.ts @@ -7,7 +7,7 @@ import { BigcommerceApiError } from '../utils/errors' import type { Wishlist, WishlistItem, -} from '../../customer/get-customer-wishlist' +} from '../operations/get-customer-wishlist' import getWishlist from './handlers/get-wishlist' import addItem from './handlers/add-item' import removeItem from './handlers/remove-item' diff --git a/framework/bigcommerce/customer/get-customer-wishlist.ts b/framework/bigcommerce/customer/get-customer-wishlist.ts deleted file mode 100644 index 97e5654a9..000000000 --- a/framework/bigcommerce/customer/get-customer-wishlist.ts +++ /dev/null @@ -1,88 +0,0 @@ -import type { RecursivePartial, RecursiveRequired } from '../api/utils/types' -import { definitions } from '../api/definitions/wishlist' -import { BigcommerceConfig, getConfig } from '../api' -import getAllProducts, { ProductEdge } from '../product/get-all-products' - -export type Wishlist = Omit & { - items?: WishlistItem[] -} - -export type WishlistItem = NonNullable< - definitions['wishlist_Full']['items'] ->[0] & { - product?: ProductEdge['node'] -} - -export type GetCustomerWishlistResult< - T extends { wishlist?: any } = { wishlist?: Wishlist } -> = T - -export type GetCustomerWishlistVariables = { - customerId: number -} - -async function getCustomerWishlist(opts: { - variables: GetCustomerWishlistVariables - config?: BigcommerceConfig - includeProducts?: boolean -}): Promise - -async function getCustomerWishlist< - T extends { wishlist?: any }, - V = any ->(opts: { - url: string - variables: V - config?: BigcommerceConfig - includeProducts?: boolean -}): Promise> - -async function getCustomerWishlist({ - config, - variables, - includeProducts, -}: { - url?: string - variables: GetCustomerWishlistVariables - config?: BigcommerceConfig - includeProducts?: boolean -}): Promise { - config = getConfig(config) - - const { data = [] } = await config.storeApiFetch< - RecursivePartial<{ data: Wishlist[] }> - >(`/v3/wishlists?customer_id=${variables.customerId}`) - const wishlist = data[0] - - if (includeProducts && wishlist?.items?.length) { - const entityIds = wishlist.items - ?.map((item) => item?.product_id) - .filter((id): id is number => !!id) - - if (entityIds?.length) { - const graphqlData = await getAllProducts({ - variables: { first: 100, entityIds }, - config, - }) - // Put the products in an object that we can use to get them by id - const productsById = graphqlData.products.reduce<{ - [k: number]: ProductEdge - }>((prods, p) => { - prods[Number(p.id)] = p as any - return prods - }, {}) - // Populate the wishlist items with the graphql products - wishlist.items.forEach((item) => { - const product = item && productsById[item.product_id!] - if (item && product) { - // @ts-ignore Fix this type when the wishlist type is properly defined - item.product = product - } - }) - } - } - - return { wishlist: wishlist as RecursiveRequired } -} - -export default getCustomerWishlist diff --git a/framework/bigcommerce/types/wishlist.ts b/framework/bigcommerce/types/wishlist.ts index 9c98a8df4..510299eac 100644 --- a/framework/bigcommerce/types/wishlist.ts +++ b/framework/bigcommerce/types/wishlist.ts @@ -20,3 +20,4 @@ export type WishlistTypes = { } export type WishlistSchema = Core.WishlistSchema +export type GetCustomerWishlistOperation = Core.GetCustomerWishlistOperation diff --git a/framework/commerce/api/operations.ts b/framework/commerce/api/operations.ts index b6529f059..2b8c9b77a 100644 --- a/framework/commerce/api/operations.ts +++ b/framework/commerce/api/operations.ts @@ -2,6 +2,7 @@ import type { ServerResponse } from 'http' import type { LoginOperation } from '../types/login' import type { GetAllPagesOperation, GetPageOperation } from '../types/page' import type { GetSiteInfoOperation } from '../types/site' +import type { GetCustomerWishlistOperation } from '../types/wishlist' import type { APIProvider, CommerceAPI } from '.' const noop = () => { @@ -77,6 +78,22 @@ export type Operations

= { } & OperationOptions ): Promise } + + getCustomerWishlist: { + (opts: { + variables: T['variables'] + config?: P['config'] + includeProducts?: boolean + }): Promise + + ( + opts: { + variables: T['variables'] + config?: P['config'] + includeProducts?: boolean + } & OperationOptions + ): Promise + } } export type APIOperations

= { diff --git a/framework/commerce/types/wishlist.ts b/framework/commerce/types/wishlist.ts index 70f900362..24c0a7c28 100644 --- a/framework/commerce/types/wishlist.ts +++ b/framework/commerce/types/wishlist.ts @@ -30,3 +30,10 @@ export type WishlistSchema = { } } } + +export type GetCustomerWishlistOperation< + T extends WishlistTypes = WishlistTypes +> = { + data: { wishlist?: T['wishlist'] } + variables: { customerId: string } +}