Added the get customer wishlist operation

This commit is contained in:
Luis Alvarez 2021-05-24 12:16:11 -05:00
parent 676b614bf6
commit a1167e46f7
14 changed files with 123 additions and 101 deletions

View File

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

View File

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

View File

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

View File

@ -15,7 +15,7 @@ async function getCustomerId({
}: {
customerToken: string
config: BigcommerceConfig
}): Promise<number | undefined> {
}): Promise<string | undefined> {
const { data } = await config.fetch<GetCustomerIdQuery>(
getCustomerIdQuery,
undefined,
@ -26,7 +26,7 @@ async function getCustomerId({
}
)
return data?.customer?.entityId
return String(data?.customer?.entityId)
}
export default getCustomerId

View File

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

View File

@ -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<Provider>) {
async function getCustomerWishlist<
T extends GetCustomerWishlistOperation
>(opts: {
variables: T['variables']
config?: BigcommerceConfig
includeProducts?: boolean
}): Promise<T['data']>
async function getCustomerWishlist<T extends GetCustomerWishlistOperation>(
opts: {
variables: T['variables']
config?: BigcommerceConfig
includeProducts?: boolean
} & OperationOptions
): Promise<T['data']>
async function getCustomerWishlist<T extends GetCustomerWishlistOperation>({
config,
variables,
includeProducts,
}: {
url?: string
variables: T['variables']
config?: BigcommerceConfig
includeProducts?: boolean
}): Promise<T['data']> {
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<typeof wishlist> }
}
return getCustomerWishlist
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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<definitions['wishlist_Full'], 'items'> & {
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<GetCustomerWishlistResult>
async function getCustomerWishlist<
T extends { wishlist?: any },
V = any
>(opts: {
url: string
variables: V
config?: BigcommerceConfig
includeProducts?: boolean
}): Promise<GetCustomerWishlistResult<T>>
async function getCustomerWishlist({
config,
variables,
includeProducts,
}: {
url?: string
variables: GetCustomerWishlistVariables
config?: BigcommerceConfig
includeProducts?: boolean
}): Promise<GetCustomerWishlistResult> {
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<typeof wishlist> }
}
export default getCustomerWishlist

View File

@ -20,3 +20,4 @@ export type WishlistTypes = {
}
export type WishlistSchema = Core.WishlistSchema<WishlistTypes>
export type GetCustomerWishlistOperation = Core.GetCustomerWishlistOperation<WishlistTypes>

View File

@ -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<P extends APIProvider> = {
} & OperationOptions
): Promise<T['data']>
}
getCustomerWishlist: {
<T extends GetCustomerWishlistOperation>(opts: {
variables: T['variables']
config?: P['config']
includeProducts?: boolean
}): Promise<T['data']>
<T extends GetCustomerWishlistOperation>(
opts: {
variables: T['variables']
config?: P['config']
includeProducts?: boolean
} & OperationOptions
): Promise<T['data']>
}
}
export type APIOperations<P extends APIProvider> = {

View File

@ -30,3 +30,10 @@ export type WishlistSchema<T extends WishlistTypes = WishlistTypes> = {
}
}
}
export type GetCustomerWishlistOperation<
T extends WishlistTypes = WishlistTypes
> = {
data: { wishlist?: T['wishlist'] }
variables: { customerId: string }
}