UNPKG

up-fetch

Version:

Advanced fetch client builder for typescript.

1 lines 19.5 kB
{"version":3,"sources":["../src/index.ts","../src/response-error.ts","../src/validation-error.ts","../src/utils.ts","../src/fallback-options.ts","../src/stream.ts","../src/up.ts"],"sourcesContent":["export { up } from './up'\nexport type {\n FetcherOptions,\n DefaultOptions,\n RetryOptions,\n UpFetch,\n GetDefaultParsedData,\n GetDefaultRawBody,\n} from './types'\nexport { ResponseError, isResponseError } from './response-error'\nexport { type ValidationError, isValidationError } from './validation-error'\nexport { isJsonifiable } from './utils'\nexport type { StandardSchemaV1 } from '@standard-schema/spec'\n","export class ResponseError<TData = any> extends Error {\n response: Response\n request: Request\n data: TData\n status: number\n\n constructor(props: {\n message: string\n response: Response\n data: TData\n request: Request\n }) {\n // super(`[${response.status}] ${response.statusText}`)\n super(props.message)\n this.name = 'ResponseError'\n this.response = props.response\n this.request = props.request\n this.data = props.data\n this.status = props.response.status\n }\n}\n\nexport const isResponseError = <TData = any>(\n error: unknown,\n): error is ResponseError<TData> => error instanceof ResponseError\n","import type { StandardSchemaV1 } from '@standard-schema/spec'\n\nexport class ValidationError<TData = any> extends Error {\n override name: 'ValidationError'\n issues: readonly StandardSchemaV1.Issue[]\n data: TData\n\n constructor(result: StandardSchemaV1.FailureResult, data: TData) {\n super(JSON.stringify(result.issues))\n this.name = 'ValidationError'\n this.issues = result.issues\n this.data = data\n }\n}\n\nexport const isValidationError = (error: unknown): error is ValidationError =>\n error instanceof ValidationError\n","import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type {\n DistributiveOmit,\n HeadersObject,\n JsonifiableArray,\n JsonifiableObject,\n KeyOf,\n Params,\n SerializeParams,\n} from './types'\nimport { ValidationError } from './validation-error'\n\nexport const mergeHeaders = (\n headerInits: (HeadersInit | HeadersObject | undefined)[],\n) => {\n const res: Record<string, string> = {}\n headerInits.forEach((init) => {\n // casting `init` to `HeadersInit` because `Record<string, any>` is\n // properly transformed to `Record<string,string>` by `new Headers(init)`\n new Headers(init as HeadersInit | undefined).forEach((value, key) => {\n value === 'null' || value === 'undefined'\n ? delete res[key]\n : (res[key] = value)\n })\n })\n return res\n}\n\nexport const withTimeout = (\n signal: AbortSignal | undefined,\n timeout: number | undefined,\n): AbortSignal | undefined =>\n // if AbortSignal.any is not supported\n // AbortSignal.timeout is not supported either.\n // Feature detection is fine on AbortSignal.any only\n 'any' in AbortSignal\n ? AbortSignal.any(\n [signal, timeout && AbortSignal.timeout(timeout)].filter(\n Boolean,\n ) as AbortSignal[],\n )\n : signal\n\nexport const omit = <O extends object, K extends KeyOf<O> | (string & {})>(\n obj?: O,\n keys: K[] | readonly K[] = [],\n): DistributiveOmit<O, K> => {\n const copy = { ...obj } as DistributiveOmit<O, K>\n for (const key in copy) {\n keys.includes(key as any) && delete copy[key]\n }\n return copy\n}\n\nexport const isJsonifiable = (\n value: any,\n): value is JsonifiableObject | JsonifiableArray =>\n isPlainObject(value) ||\n Array.isArray(value) ||\n typeof value?.toJSON === 'function'\n\nconst isPlainObject = (value: any): value is Record<string, any> =>\n value && typeof value === 'object' && value.constructor?.name === 'Object'\n\nexport const resolveUrl = (\n base: string | undefined = '',\n input: URL | string,\n defaultOptsParams: Params | undefined,\n fetcherOptsParams: Params | undefined,\n serializeParams: SerializeParams,\n): string => {\n input = (input as URL).href ?? input\n const qs = serializeParams({\n // Removing the 'url.searchParams.keys()' from the defaultParams\n // but not from the 'fetcherParams'. The user is responsible for not\n // specifying the params in both the \"input\" and the fetcher \"params\" option.\n ...omit(defaultOptsParams, [\n ...new URL(input, 'http://a').searchParams.keys(),\n ]),\n ...fetcherOptsParams,\n })\n\n let url: string = /^https?:\\/\\//.test(input)\n ? input\n : !base || !input\n ? base + input\n : base.replace(/\\/$/, '') + '/' + input.replace(/^\\//, '')\n\n if (qs) {\n url += (url.includes('?') ? '&' : '?') + qs.replace(/^\\?/, '')\n }\n return url\n}\n\nexport const abortableDelay = (delay: number, signal?: AbortSignal) =>\n new Promise<void>((resolve, reject) => {\n signal?.addEventListener('abort', handleAbort, { once: true })\n\n const token = setTimeout(() => {\n signal?.removeEventListener('abort', handleAbort)\n resolve()\n }, delay)\n\n function handleAbort() {\n clearTimeout(token)\n reject(signal!.reason)\n }\n })\n\nexport async function validate<TSchema extends StandardSchemaV1>(\n schema: TSchema,\n data: StandardSchemaV1.InferInput<TSchema>,\n): Promise<StandardSchemaV1.InferOutput<TSchema>> {\n const result = await schema['~standard'].validate(data)\n if (result.issues) throw new ValidationError(result, data)\n return result.value\n}\n","import { ResponseError } from './response-error'\nimport type { FallbackOptions } from './types'\nimport { isJsonifiable } from './utils'\n\nexport const fallbackOptions: FallbackOptions = {\n parseResponse: (res) =>\n res\n .clone()\n .json()\n .catch(() => res.text())\n .then((data) => data || null),\n\n parseRejected: async (response, request) =>\n new ResponseError({\n message: `[${response.status}] ${response.statusText}`,\n data: await fallbackOptions.parseResponse(response, request),\n response,\n request,\n }),\n\n // TODO: find a lighter way to do this with about the same amount of code\n serializeParams: (params) =>\n // JSON.parse(JSON.stringify(params)) recursively transforms Dates to ISO strings and strips undefined\n new URLSearchParams(\n JSON.parse(JSON.stringify(params)) as Record<string, string>,\n ).toString(),\n\n serializeBody: (body: any) =>\n isJsonifiable(body) ? JSON.stringify(body) : body,\n\n reject: (response) => !response.ok,\n\n retry: {\n when: (ctx) => ctx.response?.ok === false,\n attempts: 0,\n delay: 0,\n },\n}\n","import type { StreamingEvent } from './types'\n\n/**\n * Safari does not support for await...of iteration on response/request bodies,\n * so we use the ReadableStream reader API directly\n */\n\nconst isWebkit =\n typeof window !== 'undefined' &&\n /AppleWebKit/i.test(navigator.userAgent) &&\n !/Chrome/i.test(navigator.userAgent)\n\nexport async function toStreamable<R extends Request | Response>(\n reqOrRes: R,\n onChunk?: (event: StreamingEvent, reqOrRes: R) => void,\n): Promise<R> {\n const isResponse = 'ok' in reqOrRes\n const isNotSupported = isWebkit && !isResponse\n // clone reqOrRes here to support IOS & Safari 14, otherwise support 15+\n if (isNotSupported || !onChunk || !reqOrRes.clone().body) return reqOrRes\n const contentLength = reqOrRes.headers.get('content-length')\n let totalBytes: number = +(contentLength || 0)\n // For the Request, when no \"Content-Length\" header is present, we read the total bytes from the body\n if (!isResponse && !contentLength) {\n const reader = reqOrRes.clone().body!.getReader()\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n totalBytes += value.byteLength\n }\n }\n\n let transferredBytes = 0\n await onChunk(\n { totalBytes, transferredBytes, chunk: new Uint8Array() },\n reqOrRes,\n )\n\n const stream = new ReadableStream({\n async start(controller) {\n const reader = reqOrRes.body!.getReader()\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n transferredBytes += value.byteLength\n totalBytes = Math.max(totalBytes, transferredBytes)\n await onChunk(\n { totalBytes, transferredBytes, chunk: value },\n reqOrRes,\n )\n controller.enqueue(value)\n }\n controller.close()\n },\n })\n\n return isResponse\n ? (new Response(stream, reqOrRes) as R)\n : // @ts-expect-error outdated ts types\n (new Request(reqOrRes, { body: stream, duplex: 'half' }) as R)\n}\n","import { fallbackOptions } from './fallback-options'\nimport { toStreamable } from './stream'\nimport type {\n DefaultOptions,\n DefaultRawBody,\n FetcherOptions,\n MaybePromise,\n MinFetchFn,\n UpFetch,\n} from './types'\nimport {\n abortableDelay,\n isJsonifiable,\n mergeHeaders,\n omit,\n resolveUrl,\n validate,\n withTimeout,\n} from './utils'\n\nconst emptyOptions = {} as any\n\nexport const up =\n <\n const TFetchFn extends MinFetchFn,\n const TDefaultOptions extends DefaultOptions<\n TFetchFn,\n any,\n any\n > = DefaultOptions<TFetchFn, any, DefaultRawBody>,\n >(\n fetchFn: TFetchFn,\n getDefaultOptions: (\n input: Parameters<TFetchFn>[0],\n fetcherOpts: FetcherOptions<TFetchFn, any, any, any>,\n ctx?: Parameters<TFetchFn>[2],\n ) => MaybePromise<TDefaultOptions> = () => emptyOptions,\n ): UpFetch<TFetchFn, TDefaultOptions> =>\n async (input, fetcherOpts = emptyOptions, ctx) => {\n const defaultOpts = await getDefaultOptions(input, fetcherOpts, ctx)\n\n const options = {\n ...fallbackOptions,\n ...defaultOpts,\n ...fetcherOpts,\n ...(emptyOptions as { body: BodyInit | null | undefined }),\n retry: {\n ...fallbackOptions.retry,\n ...defaultOpts.retry,\n ...fetcherOpts.retry,\n },\n }\n\n options.body =\n fetcherOpts.body === null || fetcherOpts.body === undefined\n ? (fetcherOpts.body as null | undefined)\n : options.serializeBody(fetcherOpts.body)\n\n options.headers = mergeHeaders([\n isJsonifiable(fetcherOpts.body) && typeof options.body === 'string'\n ? { 'content-type': 'application/json' }\n : {},\n defaultOpts.headers,\n fetcherOpts.headers,\n ])\n\n let attempt = 0\n let request: Request\n let response: Response | undefined\n let error: unknown\n\n do {\n // per-try timeout\n options.signal = withTimeout(fetcherOpts.signal, options.timeout)\n\n request = await toStreamable(\n new Request(\n input.url\n ? input // Request\n : resolveUrl(\n options.baseUrl,\n input as unknown as string | URL,\n defaultOpts.params,\n fetcherOpts.params,\n options.serializeParams,\n ),\n options as any,\n ),\n fetcherOpts.onRequestStreaming,\n )\n\n try {\n //https://github.com/L-Blondy/up-fetch/issues/67\n await defaultOpts.onRequest?.(request)\n await fetcherOpts.onRequest?.(request)\n\n response = await toStreamable(\n await fetchFn(\n request,\n // do not override the request body & patch headers again\n { ...omit(options, ['body']), headers: request.headers },\n ctx,\n ),\n fetcherOpts.onResponseStreaming,\n )\n error = undefined\n } catch (e: any) {\n error = e\n // continue to retry\n }\n\n try {\n if (\n !(await options.retry.when({ request, response, error })) ||\n ++attempt >\n (typeof options.retry.attempts === 'function'\n ? await options.retry.attempts({ request })\n : options.retry.attempts)\n )\n break\n\n const retryCtx = { attempt, request, response, error }\n await abortableDelay(\n typeof options.retry.delay === 'function'\n ? await options.retry.delay(retryCtx)\n : options.retry.delay,\n options.signal,\n )\n defaultOpts.onRetry?.(retryCtx)\n fetcherOpts.onRetry?.(retryCtx)\n } catch (e: any) {\n error = e\n break // no retry\n }\n // biome-ignore lint/correctness/noConstantCondition: <explanation>\n } while (true)\n\n try {\n if (error) throw error\n if (await options.reject(response!)) {\n throw await options.parseRejected(response!, request)\n }\n const parsed = await options.parseResponse(response!, request)\n const data = options.schema\n ? await validate(options.schema, parsed)\n : parsed\n defaultOpts.onSuccess?.(data, request)\n fetcherOpts.onSuccess?.(data, request)\n return data\n } catch (error: any) {\n defaultOpts.onError?.(error, request)\n fetcherOpts.onError?.(error, request)\n throw error\n }\n }\n"],"mappings":"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","names":["error"]}