mirror of
https://github.com/vercel/commerce.git
synced 2025-04-25 12:27:50 +00:00
181 lines
4.4 KiB
TypeScript
181 lines
4.4 KiB
TypeScript
import vercelFetch from '@vercel/fetch'
|
|
import { FetcherError } from '@commerce/utils/errors'
|
|
import { CustomNodeJsGlobal } from '../../types/node';
|
|
|
|
import { OrdercloudConfig } from '../index'
|
|
|
|
// Get an instance to vercel fetch
|
|
const fetch = vercelFetch()
|
|
|
|
// Get token util
|
|
async function getToken({
|
|
baseUrl,
|
|
clientId,
|
|
clientSecret,
|
|
}: {
|
|
baseUrl: string
|
|
clientId: string
|
|
clientSecret?: string
|
|
}): Promise<string> {
|
|
// If not, get a new one and store it
|
|
const authResponse = await fetch(`${baseUrl}/oauth/token`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
Accept: 'application/json',
|
|
},
|
|
body: `client_id=${clientId}&client_secret=${clientSecret}&grant_type=client_credentials`,
|
|
})
|
|
|
|
// If something failed getting the auth response
|
|
if (!authResponse.ok) {
|
|
// Get the body of it
|
|
const error = await authResponse.json()
|
|
|
|
// And return an error
|
|
throw new FetcherError({
|
|
errors: [{ message: error.error_description.Code }],
|
|
status: error.error_description.HttpStatus,
|
|
})
|
|
}
|
|
|
|
// Return the token
|
|
return authResponse
|
|
.json()
|
|
.then((response: { access_token: string }) => response.access_token)
|
|
}
|
|
|
|
export async function fetchData<T>(opts: {
|
|
token: string
|
|
path: string
|
|
method: string
|
|
config: OrdercloudConfig
|
|
fetchOptions?: Record<string, any>
|
|
body?: Record<string, unknown>
|
|
}): Promise<T> {
|
|
// Destructure opts
|
|
const { path, body, fetchOptions, config, token, method = 'GET' } = opts
|
|
|
|
// Do the request with the correct headers
|
|
const dataResponse = await fetch(
|
|
`${config.commerceUrl}/${config.apiVersion}${path}`,
|
|
{
|
|
...fetchOptions,
|
|
method,
|
|
headers: {
|
|
...fetchOptions?.headers,
|
|
'Content-Type': 'application/json',
|
|
accept: 'application/json, text/plain, */*',
|
|
authorization: `Bearer ${token}`,
|
|
},
|
|
body: body ? JSON.stringify(body) : undefined,
|
|
}
|
|
)
|
|
|
|
// If something failed getting the data response
|
|
if (!dataResponse.ok) {
|
|
// Get the body of it
|
|
const error = await dataResponse.textConverted()
|
|
|
|
// And return an error
|
|
throw new FetcherError({
|
|
errors: [{ message: error || dataResponse.statusText }],
|
|
status: dataResponse.status,
|
|
})
|
|
}
|
|
|
|
try {
|
|
// Return data response as json
|
|
return (await dataResponse.json()) as Promise<T>
|
|
} catch (error) {
|
|
// If response is empty return it as text
|
|
return null as unknown as Promise<T>
|
|
}
|
|
}
|
|
|
|
export const createMiddlewareFetcher: (
|
|
getConfig: () => OrdercloudConfig
|
|
) => <T>(
|
|
method: string,
|
|
path: string,
|
|
body?: Record<string, unknown>,
|
|
fetchOptions?: Record<string, any>
|
|
) => Promise<T> =
|
|
(getConfig) =>
|
|
async <T>(
|
|
method: string,
|
|
path: string,
|
|
body?: Record<string, unknown>,
|
|
fetchOptions?: Record<string, any>
|
|
) => {
|
|
// Get provider config
|
|
const config = getConfig()
|
|
|
|
// Get a token
|
|
const token = await getToken({
|
|
baseUrl: config.commerceUrl,
|
|
clientId: process.env.ORDERCLOUD_MIDDLEWARE_CLIENT_ID as string,
|
|
clientSecret: process.env.ORDERCLOUD_MIDDLEWARE_CLIENT_SECRET,
|
|
})
|
|
|
|
// Return the data and specify the expected type
|
|
return fetchData<T>({
|
|
token,
|
|
fetchOptions,
|
|
method,
|
|
config,
|
|
path,
|
|
body,
|
|
})
|
|
}
|
|
|
|
export const createBuyerFetcher: (
|
|
getConfig: () => OrdercloudConfig
|
|
) => <T>(
|
|
method: string,
|
|
path: string,
|
|
body?: Record<string, unknown>,
|
|
fetchOptions?: Record<string, any>
|
|
) => Promise<T> =
|
|
(getConfig) =>
|
|
async <T>(
|
|
method: string,
|
|
path: string,
|
|
body?: Record<string, unknown>,
|
|
fetchOptions?: Record<string, any>
|
|
) => {
|
|
const customGlobal = global as unknown as CustomNodeJsGlobal;
|
|
|
|
// Get provider config
|
|
const config = getConfig()
|
|
|
|
|
|
// If a token was passed, set it on global
|
|
if (fetchOptions?.token) {
|
|
customGlobal.token = fetchOptions.token
|
|
}
|
|
|
|
// Get a token
|
|
if (!customGlobal.token) {
|
|
customGlobal.token = await getToken({
|
|
baseUrl: config.commerceUrl,
|
|
clientId: process.env.ORDERCLOUD_BUYER_CLIENT_ID as string,
|
|
})
|
|
}
|
|
|
|
// Return the data and specify the expected type
|
|
const data = await fetchData<T>({
|
|
token: customGlobal.token as string,
|
|
fetchOptions,
|
|
config,
|
|
method,
|
|
path,
|
|
body,
|
|
})
|
|
|
|
return {
|
|
...data,
|
|
meta: { token: customGlobal.token as string },
|
|
}
|
|
}
|