UNPKG

@sanity/client

Version:

Client for retrieving, creating and patching data from Sanity.io

85 lines (79 loc) 3.25 kB
import {defineRequester, type EnvironmentOptions} from './http/request' import type {ClientConfig, HttpRequest} from './types' export {isTimeoutError, type TimeoutErrorLike} from 'get-it' export {validateApiPerspective} from './config' export { ChannelError, connectEventSource, ConnectionFailedError, DisconnectError, type EventSourceEvent, type EventSourceInstance, MessageError, MessageParseError, type ServerSentEvent, } from './data/eventsource' export * from './data/patch' export * from './data/transaction' export { ClientError, CorsOriginError, formatQueryParseError, type HttpError, isHttpError, isQueryParseError, ServerError, } from './http/errors' export * as Context from './context/types' export * from './SanityClient' export * from './types' /** * Create the `requester` and `createClient` exports, that have environment specific middleware for node and browsers * @internal */ export default function defineCreateClientExports< SanityClientType, ClientConfigType extends ClientConfig, >( envOptions: EnvironmentOptions, ClassConstructor: new (httpRequest: HttpRequest, config: ClientConfigType) => SanityClientType, ) { // Set the http client to use for requests, and its environment specific options const defaultRequester = defineRequester(envOptions).observable const createClient = (config: ClientConfigType) => { const {observable: clientRequester, promise: clientRequesterPromise} = defineRequester( envOptions, { ignoreWarnings: config.ignoreWarnings, maxRetries: config.maxRetries, retryDelay: config.retryDelay, }, ) // The single transport for the whole client. Resolves a request to its // parsed response body as a Promise; the observable client surface wraps // this in `new Observable(...)` (see `_observe` in dataMethods). // Redirects are surfaced rather than followed unless a request opts in // (via the public `maxRedirects` option, translated in `requestOptions`). const performRequest = async (options: Parameters<HttpRequest>[0]): Promise<unknown> => { const event = await clientRequesterPromise({redirect: 'manual', ...options}) return event.body } const httpRequest: HttpRequest = (options, requestHandler) => requestHandler ? requestHandler(options, performRequest) : performRequest(options) // Populate `requester` on the initialized config so internal paths // (e.g. the asset upload event stream) can reach the underlying transport. // `resolveFetch` is threaded onto the config so request building and // EventSource fetches can reach the environment's fetch without importing // `get-it/node` from a browser-shared module (would leak `undici` into // the browser bundle). A caller-supplied `resolveFetch` wins over the // environment's — that is the supported way to swap the transport (the // test suite injects its mock fetch through it). const resolvedConfig = { ...config, requester: clientRequester, resolveFetch: config.resolveFetch ?? envOptions.resolveFetch, } return new ClassConstructor(httpRequest, resolvedConfig) } return {requester: defaultRequester, createClient} }