@spree/storefront-api-v2-sdk
Version:
Node module to easily integrate your JavaScript or TypeScript application with Spree API V2. You can create an entirely custom Storefront in JS/TS with this package including one page checkout, Single Page Apps, PWAs and so on
118 lines (98 loc) • 3.27 kB
text/typescript
import {
BasicSpreeError,
ExpandedSpreeError,
MisconfigurationError,
NoResponseError,
SpreeError,
SpreeSDKError
} from './errors'
import FetchError from './errors/FetchError'
import * as result from './helpers/result'
import type { Fetcher } from './interfaces/ClientConfig'
import type { ErrorType } from './interfaces/errors/ErrorType'
import type { FetchConfig, HttpMethod, ResponseParsing } from './interfaces/FetchConfig'
import type { JsonApiResponse } from './interfaces/JsonApi'
import type { ResultResponse } from './interfaces/ResultResponse'
import type { IToken } from './interfaces/Token'
export type EndpointOptions = {
fetcher: Fetcher
}
export default class Http {
public fetcher: Fetcher
constructor({ fetcher }: EndpointOptions) {
this.fetcher = fetcher
}
protected async spreeResponse<ResponseType = JsonApiResponse>(
method: HttpMethod,
url: string,
tokens: IToken = {},
params: any = {},
responseParsing: ResponseParsing = 'automatic'
): Promise<ResultResponse<ResponseType>> {
try {
const headers = this.spreeOrderHeaders(tokens)
const fetchOptions: FetchConfig = {
url,
params,
method,
headers,
responseParsing
}
const response = await this.fetcher.fetch(fetchOptions)
return result.makeSuccess(response.data)
} catch (error) {
return result.makeFail(this.processError(error))
}
}
/**
* The HTTP error code returned by Spree is not indicative of its response shape.
* This function determines the information provided by Spree and uses everything available.
*/
protected classifySpreeError(error: FetchError): ErrorType {
const { error: errorSummary, errors } = error.data
if (typeof errorSummary === 'string') {
if (typeof errors === 'object') {
return 'full'
}
return 'basic'
}
return 'limited'
}
protected processError(error: Error): SpreeSDKError {
if ((error as FetchError).response || (error as FetchError).request) {
const fetchError = error as FetchError
if (fetchError.response) {
// Error from Spree outside HTTP 2xx codes
return this.processSpreeError(error)
}
if (fetchError.request) {
// No response received from Spree
return new NoResponseError()
}
// Incorrect request setup
return new MisconfigurationError(error.message)
}
return new SpreeSDKError(error.message)
}
protected processSpreeError(error: FetchError): SpreeError {
const { error: errorSummary, errors } = error.data
const errorType = this.classifySpreeError(error)
if (errorType === 'full') {
return new ExpandedSpreeError(error.response, errorSummary, errors)
} else if (errorType === 'basic') {
return new BasicSpreeError(error.response, errorSummary)
} else {
return new SpreeError(error.response)
}
}
protected spreeOrderHeaders(tokens: IToken): { [headerName: string]: string } {
const header = {}
if (tokens.orderToken) {
header['X-Spree-Order-Token'] = tokens.orderToken
}
if (tokens.bearerToken) {
header['Authorization'] = `Bearer ${tokens.bearerToken}`
}
return header
}
}