forked from crowetic/commerce
Updated types, API, and make the signup work
This commit is contained in:
parent
7e73f00860
commit
e4a99601f5
@ -26,7 +26,7 @@ const getLoggedInCustomer: CustomersHandlers['getLoggedInCustomer'] = async ({
|
|||||||
res,
|
res,
|
||||||
config,
|
config,
|
||||||
}) => {
|
}) => {
|
||||||
const data = await config.fetch<GetLoggedInCustomerQuery>(
|
const { data } = await config.fetch<GetLoggedInCustomerQuery>(
|
||||||
getLoggedInCustomerQuery
|
getLoggedInCustomerQuery
|
||||||
)
|
)
|
||||||
const { customer } = data
|
const { customer } = data
|
||||||
|
@ -18,51 +18,45 @@ const signup: SignupHandlers['signup'] = async ({
|
|||||||
// Passwords must be at least 7 characters and contain both alphabetic
|
// Passwords must be at least 7 characters and contain both alphabetic
|
||||||
// and numeric characters.
|
// and numeric characters.
|
||||||
|
|
||||||
let result: { data?: any } = {}
|
try {
|
||||||
|
await config.storeApiFetch('/v3/customers', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify([
|
||||||
|
{
|
||||||
|
first_name: firstName,
|
||||||
|
last_name: lastName,
|
||||||
|
email,
|
||||||
|
authentication: {
|
||||||
|
new_password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof BigcommerceApiError && error.status === 422) {
|
||||||
|
const hasEmailError = '0.email' in error.data?.errors
|
||||||
|
|
||||||
// try {
|
// If there's an error with the email, it most likely means it's duplicated
|
||||||
// result = await config.storeApiFetch('/v3/customers', {
|
if (hasEmailError) {
|
||||||
// method: 'POST',
|
return res.status(400).json({
|
||||||
// body: JSON.stringify([
|
data: null,
|
||||||
// {
|
errors: [
|
||||||
// first_name: firstName,
|
{
|
||||||
// last_name: lastName,
|
message: 'The email is already in use',
|
||||||
// email,
|
code: 'duplicated_email',
|
||||||
// authentication: {
|
},
|
||||||
// new_password: password,
|
],
|
||||||
// },
|
})
|
||||||
// },
|
}
|
||||||
// ]),
|
}
|
||||||
// })
|
|
||||||
// } catch (error) {
|
|
||||||
// if (error instanceof BigcommerceApiError && error.status === 422) {
|
|
||||||
// const hasEmailError = '0.email' in error.data?.errors
|
|
||||||
|
|
||||||
// // If there's an error with the email, it most likely means it's duplicated
|
throw error
|
||||||
// if (hasEmailError) {
|
}
|
||||||
// return res.status(400).json({
|
|
||||||
// data: null,
|
|
||||||
// errors: [
|
|
||||||
// {
|
|
||||||
// message: 'The email is already in use',
|
|
||||||
// code: 'duplicated_email',
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// throw error
|
// Login the customer right after creating it
|
||||||
// }
|
await login({ variables: { email, password }, res, config })
|
||||||
|
|
||||||
console.log('DATA', result.data)
|
res.status(200).json({ data: null })
|
||||||
|
|
||||||
// TODO: Currently not working, fix this asap.
|
|
||||||
const loginData = await login({ variables: { email, password }, config })
|
|
||||||
|
|
||||||
console.log('LOGIN DATA', loginData)
|
|
||||||
|
|
||||||
res.status(200).json({ data: result.data ?? null })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default signup
|
export default signup
|
||||||
|
@ -49,9 +49,9 @@ async function getAllProductPaths({
|
|||||||
config = getConfig(config)
|
config = getConfig(config)
|
||||||
// RecursivePartial forces the method to check for every prop in the data, which is
|
// RecursivePartial forces the method to check for every prop in the data, which is
|
||||||
// required in case there's a custom `query`
|
// required in case there's a custom `query`
|
||||||
const data = await config.fetch<RecursivePartial<GetAllProductPathsQuery>>(
|
const { data } = await config.fetch<
|
||||||
query
|
RecursivePartial<GetAllProductPathsQuery>
|
||||||
)
|
>(query)
|
||||||
const products = data.site?.products?.edges
|
const products = data.site?.products?.edges
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -111,7 +111,7 @@ async function getAllProducts({
|
|||||||
|
|
||||||
// RecursivePartial forces the method to check for every prop in the data, which is
|
// RecursivePartial forces the method to check for every prop in the data, which is
|
||||||
// required in case there's a custom `query`
|
// required in case there's a custom `query`
|
||||||
const data = await config.fetch<RecursivePartial<GetAllProductsQuery>>(
|
const { data } = await config.fetch<RecursivePartial<GetAllProductsQuery>>(
|
||||||
query,
|
query,
|
||||||
{ variables }
|
{ variables }
|
||||||
)
|
)
|
||||||
|
@ -71,9 +71,10 @@ async function getProduct({
|
|||||||
...vars,
|
...vars,
|
||||||
path: slug ? `/${slug}/` : vars.path!,
|
path: slug ? `/${slug}/` : vars.path!,
|
||||||
}
|
}
|
||||||
const data = await config.fetch<RecursivePartial<GetProductQuery>>(query, {
|
const { data } = await config.fetch<RecursivePartial<GetProductQuery>>(
|
||||||
variables,
|
query,
|
||||||
})
|
{ variables }
|
||||||
|
)
|
||||||
const product = data.site?.route?.node
|
const product = data.site?.route?.node
|
||||||
|
|
||||||
if (product?.__typename === 'Product') {
|
if (product?.__typename === 'Product') {
|
||||||
|
@ -90,9 +90,10 @@ async function getSiteInfo({
|
|||||||
config = getConfig(config)
|
config = getConfig(config)
|
||||||
// RecursivePartial forces the method to check for every prop in the data, which is
|
// RecursivePartial forces the method to check for every prop in the data, which is
|
||||||
// required in case there's a custom `query`
|
// required in case there's a custom `query`
|
||||||
const data = await config.fetch<RecursivePartial<GetSiteInfoQuery>>(query, {
|
const { data } = await config.fetch<RecursivePartial<GetSiteInfoQuery>>(
|
||||||
variables,
|
query,
|
||||||
})
|
{ variables }
|
||||||
|
)
|
||||||
const categories = data.site?.categoryTree
|
const categories = data.site?.categoryTree
|
||||||
const brands = data.site?.brands?.edges
|
const brands = data.site?.brands?.edges
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
import type { ServerResponse } from 'http'
|
||||||
import type {
|
import type {
|
||||||
LoginMutation,
|
LoginMutation,
|
||||||
LoginMutationVariables,
|
LoginMutationVariables,
|
||||||
} from 'lib/bigcommerce/schema'
|
} from 'lib/bigcommerce/schema'
|
||||||
import type { RecursivePartial } from '../utils/types'
|
import type { RecursivePartial } from '../utils/types'
|
||||||
|
import concatHeader from '../utils/concat-cookie'
|
||||||
import { BigcommerceConfig, getConfig } from '..'
|
import { BigcommerceConfig, getConfig } from '..'
|
||||||
|
|
||||||
export const loginMutation = /* GraphQL */ `
|
export const loginMutation = /* GraphQL */ `
|
||||||
@ -20,28 +22,41 @@ export type LoginVariables = LoginMutationVariables
|
|||||||
async function login(opts: {
|
async function login(opts: {
|
||||||
variables: LoginVariables
|
variables: LoginVariables
|
||||||
config?: BigcommerceConfig
|
config?: BigcommerceConfig
|
||||||
|
res: ServerResponse
|
||||||
}): Promise<LoginResult>
|
}): Promise<LoginResult>
|
||||||
|
|
||||||
async function login<T extends { result?: any }, V = any>(opts: {
|
async function login<T extends { result?: any }, V = any>(opts: {
|
||||||
query: string
|
query: string
|
||||||
variables: V
|
variables: V
|
||||||
|
res: ServerResponse
|
||||||
config?: BigcommerceConfig
|
config?: BigcommerceConfig
|
||||||
}): Promise<LoginResult<T>>
|
}): Promise<LoginResult<T>>
|
||||||
|
|
||||||
async function login({
|
async function login({
|
||||||
query = loginMutation,
|
query = loginMutation,
|
||||||
variables,
|
variables,
|
||||||
|
res: response,
|
||||||
config,
|
config,
|
||||||
}: {
|
}: {
|
||||||
query?: string
|
query?: string
|
||||||
variables: LoginVariables
|
variables: LoginVariables
|
||||||
|
res: ServerResponse
|
||||||
config?: BigcommerceConfig
|
config?: BigcommerceConfig
|
||||||
}): Promise<LoginResult> {
|
}): Promise<LoginResult> {
|
||||||
config = getConfig(config)
|
config = getConfig(config)
|
||||||
|
|
||||||
const data = await config.fetch<RecursivePartial<LoginMutation>>(query, {
|
const { data, res } = await config.fetch<RecursivePartial<LoginMutation>>(
|
||||||
variables,
|
query,
|
||||||
})
|
{ variables }
|
||||||
|
)
|
||||||
|
const cookie = res.headers.get('Set-Cookie')
|
||||||
|
|
||||||
|
if (cookie && typeof cookie === 'string') {
|
||||||
|
response.setHeader(
|
||||||
|
'Set-Cookie',
|
||||||
|
concatHeader(response.getHeader('Set-Cookie'), cookie)!
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
result: data.login?.result,
|
result: data.login?.result,
|
||||||
|
14
lib/bigcommerce/api/utils/concat-cookie.ts
Normal file
14
lib/bigcommerce/api/utils/concat-cookie.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
type Header = string | number | string[] | undefined
|
||||||
|
|
||||||
|
export default function concatHeader(prev: Header, val: Header) {
|
||||||
|
if (!val) return prev
|
||||||
|
if (!prev) return val
|
||||||
|
|
||||||
|
if (Array.isArray(prev)) return prev.concat(String(val))
|
||||||
|
|
||||||
|
prev = String(prev)
|
||||||
|
|
||||||
|
if (Array.isArray(val)) return [prev].concat(val)
|
||||||
|
|
||||||
|
return [prev, String(val)]
|
||||||
|
}
|
@ -1,18 +1,21 @@
|
|||||||
import { CommerceAPIFetchOptions } from 'lib/commerce/api'
|
import type { GraphQLFetcher } from 'lib/commerce/api'
|
||||||
import { getConfig } from '..'
|
import { getConfig } from '..'
|
||||||
import log from '@lib/logger'
|
import log from '@lib/logger'
|
||||||
|
|
||||||
export default async function fetchGraphqlApi<Q, V = any>(
|
const fetchGraphqlApi: GraphQLFetcher = async (
|
||||||
query: string,
|
query: string,
|
||||||
{ variables, preview }: CommerceAPIFetchOptions<V> = {}
|
{ variables, preview } = {},
|
||||||
): Promise<Q> {
|
fetchOptions
|
||||||
|
) => {
|
||||||
// log.warn(query)
|
// log.warn(query)
|
||||||
const config = getConfig()
|
const config = getConfig()
|
||||||
const res = await fetch(config.commerceUrl + (preview ? '/preview' : ''), {
|
const res = await fetch(config.commerceUrl + (preview ? '/preview' : ''), {
|
||||||
|
...fetchOptions,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
|
||||||
Authorization: `Bearer ${config.apiToken}`,
|
Authorization: `Bearer ${config.apiToken}`,
|
||||||
|
...fetchOptions?.headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
query,
|
query,
|
||||||
@ -20,22 +23,13 @@ export default async function fetchGraphqlApi<Q, V = any>(
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
// console.log('HEADERS', getRawHeaders(res))
|
|
||||||
|
|
||||||
const json = await res.json()
|
const json = await res.json()
|
||||||
if (json.errors) {
|
if (json.errors) {
|
||||||
console.error(json.errors)
|
console.error(json.errors)
|
||||||
throw new Error('Failed to fetch BigCommerce API')
|
throw new Error('Failed to fetch BigCommerce API')
|
||||||
}
|
}
|
||||||
return json.data
|
|
||||||
|
return { data: json.data, res }
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRawHeaders(res: Response) {
|
export default fetchGraphqlApi
|
||||||
const headers: { [key: string]: string } = {}
|
|
||||||
|
|
||||||
res.headers.forEach((value, key) => {
|
|
||||||
headers[key] = value
|
|
||||||
})
|
|
||||||
|
|
||||||
return headers
|
|
||||||
}
|
|
||||||
|
@ -3,14 +3,29 @@ export interface CommerceAPIConfig {
|
|||||||
apiToken: string
|
apiToken: string
|
||||||
cartCookie: string
|
cartCookie: string
|
||||||
cartCookieMaxAge: number
|
cartCookieMaxAge: number
|
||||||
fetch<Q, V = any>(
|
fetch<Data = any, Variables = any>(
|
||||||
query: string,
|
query: string,
|
||||||
queryData?: CommerceAPIFetchOptions<V>
|
queryData?: CommerceAPIFetchOptions<Variables>,
|
||||||
): Promise<Q>
|
fetchOptions?: RequestInit
|
||||||
|
): Promise<GraphQLFetcherResult<Data>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CommerceAPIFetchOptions<V> {
|
export type GraphQLFetcher<
|
||||||
variables?: V
|
Data extends GraphQLFetcherResult = GraphQLFetcherResult,
|
||||||
|
Variables = any
|
||||||
|
> = (
|
||||||
|
query: string,
|
||||||
|
queryData?: CommerceAPIFetchOptions<Variables>,
|
||||||
|
fetchOptions?: RequestInit
|
||||||
|
) => Promise<Data>
|
||||||
|
|
||||||
|
export interface GraphQLFetcherResult<Data = any> {
|
||||||
|
data: Data
|
||||||
|
res: Response
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CommerceAPIFetchOptions<Variables> {
|
||||||
|
variables?: Variables
|
||||||
preview?: boolean
|
preview?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user