From eb2fd80eaded8689cae3589d8cd340cae130e5f9 Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Tue, 18 May 2021 08:39:36 -0500 Subject: [PATCH] Added customer endpoint --- .../api/customer/get-logged-in-customer.ts | 59 +++++++++++++++++++ framework/bigcommerce/api/customer/index.ts | 10 ++++ framework/bigcommerce/api/index.ts | 7 ++- framework/bigcommerce/types/customer.ts | 5 ++ framework/commerce/api/endpoints/cart.ts | 10 ++-- framework/commerce/api/endpoints/customer.ts | 35 +++++++++++ framework/commerce/api/index.ts | 3 +- framework/commerce/types/customer.ts | 23 ++++++++ pages/api/{bigcommerce => }/cart.ts | 0 pages/api/customer.ts | 8 +++ 10 files changed, 151 insertions(+), 9 deletions(-) create mode 100644 framework/bigcommerce/api/customer/get-logged-in-customer.ts create mode 100644 framework/bigcommerce/api/customer/index.ts create mode 100644 framework/bigcommerce/types/customer.ts create mode 100644 framework/commerce/api/endpoints/customer.ts create mode 100644 framework/commerce/types/customer.ts rename pages/api/{bigcommerce => }/cart.ts (100%) create mode 100644 pages/api/customer.ts diff --git a/framework/bigcommerce/api/customer/get-logged-in-customer.ts b/framework/bigcommerce/api/customer/get-logged-in-customer.ts new file mode 100644 index 000000000..f35b2d135 --- /dev/null +++ b/framework/bigcommerce/api/customer/get-logged-in-customer.ts @@ -0,0 +1,59 @@ +import type { GetLoggedInCustomerQuery } from '../../schema' +import type { CustomerEndpoint } from '.' + +export const getLoggedInCustomerQuery = /* GraphQL */ ` + query getLoggedInCustomer { + customer { + entityId + firstName + lastName + email + company + customerGroupId + notes + phone + addressCount + attributeCount + storeCredit { + value + currencyCode + } + } + } +` + +export type Customer = NonNullable + +const getLoggedInCustomer: CustomerEndpoint['operations']['getLoggedInCustomer'] = async ({ + req, + res, + config, +}) => { + const token = req.cookies[config.customerCookie] + + if (token) { + const { data } = await config.fetch( + getLoggedInCustomerQuery, + undefined, + { + headers: { + cookie: `${config.customerCookie}=${token}`, + }, + } + ) + const { customer } = data + + if (!customer) { + return res.status(400).json({ + data: null, + errors: [{ message: 'Customer not found', code: 'not_found' }], + }) + } + + return res.status(200).json({ data: { customer } }) + } + + res.status(200).json({ data: null }) +} + +export default getLoggedInCustomer diff --git a/framework/bigcommerce/api/customer/index.ts b/framework/bigcommerce/api/customer/index.ts new file mode 100644 index 000000000..47832b8a0 --- /dev/null +++ b/framework/bigcommerce/api/customer/index.ts @@ -0,0 +1,10 @@ +import type { GetAPISchema } from '@commerce/api' +import type { CustomerSchema } from '../../types/customer' +import type { BigcommerceAPI } from '..' +import getLoggedInCustomer from './get-logged-in-customer' + +export type CustomerAPI = GetAPISchema + +export type CustomerEndpoint = CustomerAPI['endpoint'] + +export const operations = { getLoggedInCustomer } diff --git a/framework/bigcommerce/api/index.ts b/framework/bigcommerce/api/index.ts index 50ea960b7..e30517171 100644 --- a/framework/bigcommerce/api/index.ts +++ b/framework/bigcommerce/api/index.ts @@ -10,6 +10,7 @@ import fetchGraphqlApi from './utils/fetch-graphql-api' import fetchStoreApi from './utils/fetch-store-api' import type { CartAPI } from './cart' +import type { CustomerAPI } from './customer' import login from './operations/login' export interface BigcommerceConfig extends CommerceAPIConfig { @@ -111,14 +112,14 @@ export const provider = { export type Provider = typeof provider -export type APIs = CartAPI +export type APIs = CartAPI | CustomerAPI export type BigcommerceAPI

= CommerceAPI

export function getCommerceApi

( customProvider: P = provider as any -): BigcommerceAPI

{ - const api = commerceApi(customProvider) +) { + const api: BigcommerceAPI

= commerceApi(customProvider) return Object.assign(api, { endpoint( diff --git a/framework/bigcommerce/types/customer.ts b/framework/bigcommerce/types/customer.ts new file mode 100644 index 000000000..427bc0b03 --- /dev/null +++ b/framework/bigcommerce/types/customer.ts @@ -0,0 +1,5 @@ +import * as Core from '@commerce/types/customer' + +export * from '@commerce/types/customer' + +export type CustomerSchema = Core.CustomerSchema diff --git a/framework/commerce/api/endpoints/cart.ts b/framework/commerce/api/endpoints/cart.ts index 6b98335ca..1f1c734ce 100644 --- a/framework/commerce/api/endpoints/cart.ts +++ b/framework/commerce/api/endpoints/cart.ts @@ -3,9 +3,10 @@ import { CommerceAPIError } from '../utils/errors' import isAllowedOperation from '../utils/is-allowed-operation' import type { GetAPISchema } from '..' -const cartApi: GetAPISchema['endpoint']['handler'] = async ( - ctx -) => { +const cartEndpoint: GetAPISchema< + any, + CartSchema +>['endpoint']['handler'] = async (ctx) => { const { req, res, operations, config } = ctx if ( @@ -19,7 +20,6 @@ const cartApi: GetAPISchema['endpoint']['handler'] = async ( return } - const body2 = req.body const { cookies } = req const cartId = cookies[config.cartCookie] @@ -59,4 +59,4 @@ const cartApi: GetAPISchema['endpoint']['handler'] = async ( } } -export default cartApi +export default cartEndpoint diff --git a/framework/commerce/api/endpoints/customer.ts b/framework/commerce/api/endpoints/customer.ts new file mode 100644 index 000000000..107650770 --- /dev/null +++ b/framework/commerce/api/endpoints/customer.ts @@ -0,0 +1,35 @@ +import type { CustomerSchema } from '../../types/customer' +import { CommerceAPIError } from '../utils/errors' +import isAllowedOperation from '../utils/is-allowed-operation' +import type { GetAPISchema } from '..' + +const customerEndpoint: GetAPISchema< + any, + CustomerSchema +>['endpoint']['handler'] = async (ctx) => { + const { req, res, operations } = ctx + + if ( + !isAllowedOperation(req, res, { + GET: operations['getLoggedInCustomer'], + }) + ) { + return + } + + try { + const body = null + return await operations['getLoggedInCustomer']({ ...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 customerEndpoint diff --git a/framework/commerce/api/index.ts b/framework/commerce/api/index.ts index e656e1872..f076657c0 100644 --- a/framework/commerce/api/index.ts +++ b/framework/commerce/api/index.ts @@ -2,6 +2,7 @@ import type { NextApiHandler } from 'next' import type { RequestInit, Response } from '@vercel/fetch' import type { APIEndpoint, APIHandler } from './utils/types' import type { CartSchema } from '../types/cart' +import type { CustomerSchema } from '../types/customer' import { defaultOperations, OPERATIONS, @@ -9,7 +10,7 @@ import { APIOperations, } from './operations' -export type APISchemas = CartSchema +export type APISchemas = CartSchema | CustomerSchema export type GetAPISchema< C extends CommerceAPI, diff --git a/framework/commerce/types/customer.ts b/framework/commerce/types/customer.ts new file mode 100644 index 000000000..4f603ca4f --- /dev/null +++ b/framework/commerce/types/customer.ts @@ -0,0 +1,23 @@ +// TODO: define this type +export type Customer = any + +export type CustomerTypes = { + customer: Customer +} + +export type CustomerSchema = { + endpoint: { + options: {} + operations: { + getLoggedInCustomer: { + data: { customer: T['customer'] } | null + } + } + } +} + +// export type CustomerOperations = { +// getLoggedInCustomer: GetCartOperation +// } + +// export type GetLoggedInCustomerOperation = {} diff --git a/pages/api/bigcommerce/cart.ts b/pages/api/cart.ts similarity index 100% rename from pages/api/bigcommerce/cart.ts rename to pages/api/cart.ts diff --git a/pages/api/customer.ts b/pages/api/customer.ts new file mode 100644 index 000000000..ba3e627b1 --- /dev/null +++ b/pages/api/customer.ts @@ -0,0 +1,8 @@ +import customer from '@commerce/api/endpoints/customer' +import { CustomerAPI, operations } from '@framework/api/customer' +import commerce from '@lib/api/commerce' + +export default commerce.endpoint({ + handler: customer as CustomerAPI['endpoint']['handler'], + operations, +})