mirror of
https://github.com/vercel/commerce.git
synced 2025-07-03 19:51:22 +00:00
Update Spree SDK fetcher
This commit is contained in:
parent
30c29f0da8
commit
3b3a181dac
@ -11,7 +11,7 @@ import getSpreeSdkMethodFromEndpointPath from 'framework/spree/utils/getSpreeSdk
|
||||
import { SpreeSdkVariables } from 'framework/spree/types'
|
||||
import SpreeSdkMethodFromEndpointPathError from 'framework/spree/errors/SpreeSdkMethodFromEndpointPathError'
|
||||
import { GraphQLFetcher, GraphQLFetcherResult } from '@commerce/api'
|
||||
import createCreateFetchFetcher from '../../utils/createCreateFetchFetcher'
|
||||
import createCustomizedFetchFetcher from '../../utils/createCustomizedFetchFetcher'
|
||||
import fetch, { Request } from 'node-fetch'
|
||||
|
||||
const createApiFetch: (
|
||||
@ -22,10 +22,13 @@ const createApiFetch: (
|
||||
const client = makeClient({
|
||||
host: requireConfigValue('spreeApiHost') as string,
|
||||
fetcherType: 'custom',
|
||||
createFetcher: createCreateFetchFetcher({
|
||||
fetch,
|
||||
requestClass: Request,
|
||||
}),
|
||||
createFetcher: (fetcherOptions) => {
|
||||
return createCustomizedFetchFetcher({
|
||||
fetch,
|
||||
requestConstructor: Request,
|
||||
...fetcherOptions,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
return async (url, queryData = {}, fetchOptions = {}) => {
|
||||
|
@ -12,15 +12,18 @@ import getSpreeSdkMethodFromEndpointPath from './utils/getSpreeSdkMethodFromEndp
|
||||
import SpreeSdkMethodFromEndpointPathError from './errors/SpreeSdkMethodFromEndpointPathError'
|
||||
import type { SpreeSdkVariables } from './types'
|
||||
import type { GraphQLFetcherResult } from '@commerce/api'
|
||||
import createCreateFetchFetcher from './utils/createCreateFetchFetcher'
|
||||
import createCustomizedFetchFetcher from './utils/createCustomizedFetchFetcher'
|
||||
|
||||
const client = makeClient({
|
||||
host: requireConfigValue('spreeApiHost') as string,
|
||||
fetcherType: 'custom',
|
||||
createFetcher: createCreateFetchFetcher({
|
||||
fetch: globalThis.fetch,
|
||||
requestClass: globalThis.Request,
|
||||
}),
|
||||
createFetcher: (fetcherOptions) => {
|
||||
return createCustomizedFetchFetcher({
|
||||
fetch: globalThis.fetch,
|
||||
requestConstructor: globalThis.Request,
|
||||
...fetcherOptions,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const fetcher: Fetcher<
|
||||
|
@ -1,77 +0,0 @@
|
||||
import * as qs from 'qs'
|
||||
import { errors } from '@spree/storefront-api-v2-sdk'
|
||||
import type { CreateFetcher } from '@spree/storefront-api-v2-sdk/types/interfaces/ClientConfig'
|
||||
|
||||
const createCreateFetchFetcher =
|
||||
({ fetch: rawFetch, requestClass }): CreateFetcher =>
|
||||
// TODO: Fix rawFetch any type.
|
||||
(fetcherOptions) => {
|
||||
const { FetchError } = errors
|
||||
const sharedHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
return {
|
||||
fetch: async (fetchOptions) => {
|
||||
// This fetcher always returns request equal null,
|
||||
// because @vercel/fetch doesn't accept a Request object as argument
|
||||
// and it's not used by NJC anyway.
|
||||
try {
|
||||
const { url, params, method, headers } = fetchOptions
|
||||
const absoluteUrl = new URL(url, fetcherOptions.host)
|
||||
let payload
|
||||
|
||||
switch (method.toUpperCase()) {
|
||||
case 'PUT':
|
||||
case 'POST':
|
||||
case 'DELETE':
|
||||
case 'PATCH':
|
||||
payload = { body: JSON.stringify(params) }
|
||||
break
|
||||
default:
|
||||
payload = null
|
||||
absoluteUrl.search = qs.stringify(params, {
|
||||
arrayFormat: 'brackets',
|
||||
})
|
||||
}
|
||||
|
||||
const request: Request = new requestClass(absoluteUrl.toString(), {
|
||||
method: method.toUpperCase(),
|
||||
headers: { ...sharedHeaders, ...headers },
|
||||
...payload,
|
||||
})
|
||||
|
||||
try {
|
||||
const response: Response = await rawFetch(request)
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
// Use the "traditional" approach and reject non 2xx responses.
|
||||
throw new FetchError(response, request, data)
|
||||
}
|
||||
|
||||
return {
|
||||
// Add response key to the prototype so it can be passed inside the GraphQLFetcherResult type.
|
||||
// TODO: Search for a better solution than adding response to the prototype.
|
||||
data: Object.setPrototypeOf({ data }, { response }),
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
throw new FetchError(null, request, null)
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof FetchError) {
|
||||
throw error
|
||||
}
|
||||
|
||||
throw new FetchError(null, null, null, error.message)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default createCreateFetchFetcher
|
81
framework/spree/utils/createCustomizedFetchFetcher.ts
Normal file
81
framework/spree/utils/createCustomizedFetchFetcher.ts
Normal file
@ -0,0 +1,81 @@
|
||||
import * as qs from 'qs'
|
||||
import { errors } from '@spree/storefront-api-v2-sdk'
|
||||
import type { CreateCustomizedFetchFetcher } from '@spree/storefront-api-v2-sdk/types/interfaces/CreateCustomizedFetchFetcher'
|
||||
|
||||
const createCustomizedFetchFetcher: CreateCustomizedFetchFetcher = (
|
||||
fetcherOptions
|
||||
) => {
|
||||
const { FetchError } = errors
|
||||
const sharedHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
const { host, fetch, requestConstructor } = fetcherOptions
|
||||
|
||||
return {
|
||||
fetch: async (fetchOptions) => {
|
||||
// This fetcher always returns request equal null,
|
||||
// because @vercel/fetch doesn't accept a Request object as argument
|
||||
// and it's not used by NJC anyway.
|
||||
try {
|
||||
const { url, params, method, headers } = fetchOptions
|
||||
const absoluteUrl = new URL(url, host)
|
||||
let payload
|
||||
|
||||
switch (method.toUpperCase()) {
|
||||
case 'PUT':
|
||||
case 'POST':
|
||||
case 'DELETE':
|
||||
case 'PATCH':
|
||||
payload = { body: JSON.stringify(params) }
|
||||
break
|
||||
default:
|
||||
payload = null
|
||||
absoluteUrl.search = qs.stringify(params, {
|
||||
arrayFormat: 'brackets',
|
||||
})
|
||||
}
|
||||
|
||||
const request: Request = new requestConstructor(
|
||||
absoluteUrl.toString(),
|
||||
{
|
||||
method: method.toUpperCase(),
|
||||
headers: { ...sharedHeaders, ...headers },
|
||||
...payload,
|
||||
}
|
||||
)
|
||||
|
||||
try {
|
||||
const response: Response = await fetch(request)
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
// Use the "traditional" approach and reject non 2xx responses.
|
||||
throw new FetchError(response, request, data)
|
||||
}
|
||||
|
||||
return {
|
||||
// Add response key to the prototype so it can be passed inside the GraphQLFetcherResult type.
|
||||
// TODO: Search for a better solution than adding response to the prototype.
|
||||
data: Object.setPrototypeOf({ data }, { response }),
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
throw new FetchError(null, request, null)
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof FetchError) {
|
||||
throw error
|
||||
}
|
||||
|
||||
throw new FetchError(null, null, null, error.message)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default createCustomizedFetchFetcher
|
Loading…
x
Reference in New Issue
Block a user