| 'use strict'; | ||
| const destr = require('destr'); | ||
| const ufo = require('ufo'); | ||
| function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; } | ||
| const destr__default = /*#__PURE__*/_interopDefaultCompat(destr); | ||
| class FetchError extends Error { | ||
| constructor(message, opts) { | ||
| super(message, opts); | ||
| this.name = "FetchError"; | ||
| if (opts?.cause && !this.cause) { | ||
| this.cause = opts.cause; | ||
| } | ||
| } | ||
| } | ||
| function createFetchError(ctx) { | ||
| const errorMessage = ctx.error?.message || ctx.error?.toString() || ""; | ||
| const method = ctx.request?.method || ctx.options?.method || "GET"; | ||
| const url = ctx.request?.url || String(ctx.request) || "/"; | ||
| const requestStr = `[${method}] ${JSON.stringify(url)}`; | ||
| const statusStr = ctx.response ? `${ctx.response.status} ${ctx.response.statusText}` : "<no response>"; | ||
| const message = `${requestStr}: ${statusStr}${errorMessage ? ` ${errorMessage}` : ""}`; | ||
| const fetchError = new FetchError( | ||
| message, | ||
| ctx.error ? { cause: ctx.error } : void 0 | ||
| ); | ||
| for (const key of ["request", "options", "response"]) { | ||
| Object.defineProperty(fetchError, key, { | ||
| get() { | ||
| return ctx[key]; | ||
| } | ||
| }); | ||
| } | ||
| for (const [key, refKey] of [ | ||
| ["data", "_data"], | ||
| ["status", "status"], | ||
| ["statusCode", "status"], | ||
| ["statusText", "statusText"], | ||
| ["statusMessage", "statusText"] | ||
| ]) { | ||
| Object.defineProperty(fetchError, key, { | ||
| get() { | ||
| return ctx.response && ctx.response[refKey]; | ||
| } | ||
| }); | ||
| } | ||
| return fetchError; | ||
| } | ||
| const payloadMethods = new Set( | ||
| Object.freeze(["PATCH", "POST", "PUT", "DELETE"]) | ||
| ); | ||
| function isPayloadMethod(method = "GET") { | ||
| return payloadMethods.has(method.toUpperCase()); | ||
| } | ||
| function isJSONSerializable(value) { | ||
| if (value === void 0) { | ||
| return false; | ||
| } | ||
| const t = typeof value; | ||
| if (t === "string" || t === "number" || t === "boolean" || t === null) { | ||
| return true; | ||
| } | ||
| if (t !== "object") { | ||
| return false; | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return true; | ||
| } | ||
| if (value.buffer) { | ||
| return false; | ||
| } | ||
| if (value instanceof FormData || value instanceof URLSearchParams) { | ||
| return false; | ||
| } | ||
| return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function"; | ||
| } | ||
| const textTypes = /* @__PURE__ */ new Set([ | ||
| "image/svg", | ||
| "application/xml", | ||
| "application/xhtml", | ||
| "application/html" | ||
| ]); | ||
| const JSON_RE = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i; | ||
| function detectResponseType(_contentType = "") { | ||
| if (!_contentType) { | ||
| return "json"; | ||
| } | ||
| const contentType = _contentType.split(";").shift() || ""; | ||
| if (JSON_RE.test(contentType)) { | ||
| return "json"; | ||
| } | ||
| if (contentType === "text/event-stream") { | ||
| return "stream"; | ||
| } | ||
| if (textTypes.has(contentType) || contentType.startsWith("text/")) { | ||
| return "text"; | ||
| } | ||
| return "blob"; | ||
| } | ||
| function resolveFetchOptions(request, input, defaults, Headers) { | ||
| const headers = mergeHeaders( | ||
| input?.headers ?? request?.headers, | ||
| defaults?.headers, | ||
| Headers | ||
| ); | ||
| let query; | ||
| if (defaults?.query || defaults?.params || input?.params || input?.query) { | ||
| query = { | ||
| ...defaults?.params, | ||
| ...defaults?.query, | ||
| ...input?.params, | ||
| ...input?.query | ||
| }; | ||
| } | ||
| return { | ||
| ...defaults, | ||
| ...input, | ||
| query, | ||
| params: query, | ||
| headers | ||
| }; | ||
| } | ||
| function mergeHeaders(input, defaults, Headers) { | ||
| if (!defaults) { | ||
| return new Headers(input); | ||
| } | ||
| const headers = new Headers(defaults); | ||
| if (input) { | ||
| for (const [key, value] of Symbol.iterator in input || Array.isArray(input) ? input : new Headers(input)) { | ||
| headers.set(key, value); | ||
| } | ||
| } | ||
| return headers; | ||
| } | ||
| async function callHooks(context, hooks) { | ||
| if (hooks) { | ||
| if (Array.isArray(hooks)) { | ||
| for (const hook of hooks) { | ||
| await hook(context); | ||
| } | ||
| } else { | ||
| await hooks(context); | ||
| } | ||
| } | ||
| } | ||
| const retryStatusCodes = /* @__PURE__ */ new Set([ | ||
| 408, | ||
| // Request Timeout | ||
| 409, | ||
| // Conflict | ||
| 425, | ||
| // Too Early (Experimental) | ||
| 429, | ||
| // Too Many Requests | ||
| 500, | ||
| // Internal Server Error | ||
| 502, | ||
| // Bad Gateway | ||
| 503, | ||
| // Service Unavailable | ||
| 504 | ||
| // Gateway Timeout | ||
| ]); | ||
| const nullBodyResponses = /* @__PURE__ */ new Set([101, 204, 205, 304]); | ||
| function createFetch(globalOptions = {}) { | ||
| const { | ||
| fetch = globalThis.fetch, | ||
| Headers = globalThis.Headers, | ||
| AbortController = globalThis.AbortController | ||
| } = globalOptions; | ||
| async function onError(context) { | ||
| const isAbort = context.error && context.error.name === "AbortError" && !context.options.timeout || false; | ||
| if (context.options.retry !== false && !isAbort) { | ||
| let retries; | ||
| if (typeof context.options.retry === "number") { | ||
| retries = context.options.retry; | ||
| } else { | ||
| retries = isPayloadMethod(context.options.method) ? 0 : 1; | ||
| } | ||
| const responseCode = context.response && context.response.status || 500; | ||
| if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) { | ||
| const retryDelay = typeof context.options.retryDelay === "function" ? context.options.retryDelay(context) : context.options.retryDelay || 0; | ||
| if (retryDelay > 0) { | ||
| await new Promise((resolve) => setTimeout(resolve, retryDelay)); | ||
| } | ||
| return $fetchRaw(context.request, { | ||
| ...context.options, | ||
| retry: retries - 1 | ||
| }); | ||
| } | ||
| } | ||
| const error = createFetchError(context); | ||
| if (Error.captureStackTrace) { | ||
| Error.captureStackTrace(error, $fetchRaw); | ||
| } | ||
| throw error; | ||
| } | ||
| const $fetchRaw = async function $fetchRaw2(_request, _options = {}) { | ||
| const context = { | ||
| request: _request, | ||
| options: resolveFetchOptions( | ||
| _request, | ||
| _options, | ||
| globalOptions.defaults, | ||
| Headers | ||
| ), | ||
| response: void 0, | ||
| error: void 0 | ||
| }; | ||
| if (context.options.method) { | ||
| context.options.method = context.options.method.toUpperCase(); | ||
| } | ||
| if (context.options.onRequest) { | ||
| await callHooks(context, context.options.onRequest); | ||
| } | ||
| if (typeof context.request === "string") { | ||
| if (context.options.baseURL) { | ||
| context.request = ufo.withBase(context.request, context.options.baseURL); | ||
| } | ||
| if (context.options.query) { | ||
| context.request = ufo.withQuery(context.request, context.options.query); | ||
| delete context.options.query; | ||
| } | ||
| if ("query" in context.options) { | ||
| delete context.options.query; | ||
| } | ||
| if ("params" in context.options) { | ||
| delete context.options.params; | ||
| } | ||
| } | ||
| if (context.options.body && isPayloadMethod(context.options.method)) { | ||
| if (isJSONSerializable(context.options.body)) { | ||
| const contentType = context.options.headers.get("content-type"); | ||
| if (typeof context.options.body !== "string") { | ||
| context.options.body = contentType === "application/x-www-form-urlencoded" ? new URLSearchParams( | ||
| context.options.body | ||
| ).toString() : JSON.stringify(context.options.body); | ||
| } | ||
| context.options.headers = new Headers(context.options.headers || {}); | ||
| if (!contentType) { | ||
| context.options.headers.set("content-type", "application/json"); | ||
| } | ||
| if (!context.options.headers.has("accept")) { | ||
| context.options.headers.set("accept", "application/json"); | ||
| } | ||
| } else if ( | ||
| // ReadableStream Body | ||
| "pipeTo" in context.options.body && typeof context.options.body.pipeTo === "function" || // Node.js Stream Body | ||
| typeof context.options.body.pipe === "function" | ||
| ) { | ||
| if (!("duplex" in context.options)) { | ||
| context.options.duplex = "half"; | ||
| } | ||
| } | ||
| } | ||
| let abortTimeout; | ||
| if (!context.options.signal && context.options.timeout) { | ||
| const controller = new AbortController(); | ||
| abortTimeout = setTimeout(() => { | ||
| const error = new Error( | ||
| "[TimeoutError]: The operation was aborted due to timeout" | ||
| ); | ||
| error.name = "TimeoutError"; | ||
| error.code = 23; | ||
| controller.abort(error); | ||
| }, context.options.timeout); | ||
| context.options.signal = controller.signal; | ||
| } | ||
| try { | ||
| context.response = await fetch( | ||
| context.request, | ||
| context.options | ||
| ); | ||
| } catch (error) { | ||
| context.error = error; | ||
| if (context.options.onRequestError) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onRequestError | ||
| ); | ||
| } | ||
| return await onError(context); | ||
| } finally { | ||
| if (abortTimeout) { | ||
| clearTimeout(abortTimeout); | ||
| } | ||
| } | ||
| const hasBody = (context.response.body || // https://github.com/unjs/ofetch/issues/324 | ||
| // https://github.com/unjs/ofetch/issues/294 | ||
| // https://github.com/JakeChampion/fetch/issues/1454 | ||
| context.response._bodyInit) && !nullBodyResponses.has(context.response.status) && context.options.method !== "HEAD"; | ||
| if (hasBody) { | ||
| const responseType = (context.options.parseResponse ? "json" : context.options.responseType) || detectResponseType(context.response.headers.get("content-type") || ""); | ||
| switch (responseType) { | ||
| case "json": { | ||
| const data = await context.response.text(); | ||
| const parseFunction = context.options.parseResponse || destr__default; | ||
| context.response._data = parseFunction(data); | ||
| break; | ||
| } | ||
| case "stream": { | ||
| context.response._data = context.response.body || context.response._bodyInit; | ||
| break; | ||
| } | ||
| default: { | ||
| context.response._data = await context.response[responseType](); | ||
| } | ||
| } | ||
| } | ||
| if (context.options.onResponse) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onResponse | ||
| ); | ||
| } | ||
| if (!context.options.ignoreResponseError && context.response.status >= 400 && context.response.status < 600) { | ||
| if (context.options.onResponseError) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onResponseError | ||
| ); | ||
| } | ||
| return await onError(context); | ||
| } | ||
| return context.response; | ||
| }; | ||
| const $fetch = async function $fetch2(request, options) { | ||
| const r = await $fetchRaw(request, options); | ||
| return r._data; | ||
| }; | ||
| $fetch.raw = $fetchRaw; | ||
| $fetch.native = (...args) => fetch(...args); | ||
| $fetch.create = (defaultOptions = {}, customGlobalOptions = {}) => createFetch({ | ||
| ...globalOptions, | ||
| ...customGlobalOptions, | ||
| defaults: { | ||
| ...globalOptions.defaults, | ||
| ...customGlobalOptions.defaults, | ||
| ...defaultOptions | ||
| } | ||
| }); | ||
| return $fetch; | ||
| } | ||
| exports.FetchError = FetchError; | ||
| exports.createFetch = createFetch; | ||
| exports.createFetchError = createFetchError; |
| import * as undici from 'undici'; | ||
| interface $Fetch { | ||
| <T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<MappedResponseType<R, T>>; | ||
| raw<T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<FetchResponse<MappedResponseType<R, T>>>; | ||
| native: Fetch; | ||
| create(defaults: FetchOptions, globalOptions?: CreateFetchOptions): $Fetch; | ||
| } | ||
| interface FetchOptions<R extends ResponseType = ResponseType, T = any> extends Omit<RequestInit, "body">, FetchHooks<T, R> { | ||
| baseURL?: string; | ||
| body?: RequestInit["body"] | Record<string, any>; | ||
| ignoreResponseError?: boolean; | ||
| /** | ||
| * @deprecated use query instead. | ||
| */ | ||
| params?: Record<string, any>; | ||
| query?: Record<string, any>; | ||
| parseResponse?: (responseText: string) => any; | ||
| responseType?: R; | ||
| /** | ||
| * @experimental Set to "half" to enable duplex streaming. | ||
| * Will be automatically set to "half" when using a ReadableStream as body. | ||
| * @see https://fetch.spec.whatwg.org/#enumdef-requestduplex | ||
| */ | ||
| duplex?: "half" | undefined; | ||
| /** | ||
| * Only supported in Node.js >= 18 using undici | ||
| * | ||
| * @see https://undici.nodejs.org/#/docs/api/Dispatcher | ||
| */ | ||
| dispatcher?: InstanceType<typeof undici.Dispatcher>; | ||
| /** | ||
| * Only supported older Node.js versions using node-fetch-native polyfill. | ||
| */ | ||
| agent?: unknown; | ||
| /** timeout in milliseconds */ | ||
| timeout?: number; | ||
| retry?: number | false; | ||
| /** Delay between retries in milliseconds. */ | ||
| retryDelay?: number | ((context: FetchContext<T, R>) => number); | ||
| /** Default is [408, 409, 425, 429, 500, 502, 503, 504] */ | ||
| retryStatusCodes?: number[]; | ||
| } | ||
| interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any> extends FetchOptions<R, T> { | ||
| headers: Headers; | ||
| } | ||
| interface CreateFetchOptions { | ||
| defaults?: FetchOptions; | ||
| fetch?: Fetch; | ||
| Headers?: typeof Headers; | ||
| AbortController?: typeof AbortController; | ||
| } | ||
| type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">; | ||
| interface FetchContext<T = any, R extends ResponseType = ResponseType> { | ||
| request: FetchRequest; | ||
| options: ResolvedFetchOptions<R>; | ||
| response?: FetchResponse<T>; | ||
| error?: Error; | ||
| } | ||
| type MaybePromise<T> = T | Promise<T>; | ||
| type MaybeArray<T> = T | T[]; | ||
| type FetchHook<C extends FetchContext = FetchContext> = (context: C) => MaybePromise<void>; | ||
| interface FetchHooks<T = any, R extends ResponseType = ResponseType> { | ||
| onRequest?: MaybeArray<FetchHook<FetchContext<T, R>>>; | ||
| onRequestError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| error: Error; | ||
| }>>; | ||
| onResponse?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| onResponseError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| } | ||
| interface ResponseMap { | ||
| blob: Blob; | ||
| text: string; | ||
| arrayBuffer: ArrayBuffer; | ||
| stream: ReadableStream<Uint8Array>; | ||
| } | ||
| type ResponseType = keyof ResponseMap | "json"; | ||
| type MappedResponseType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType; | ||
| interface FetchResponse<T> extends Response { | ||
| _data?: T; | ||
| } | ||
| interface IFetchError<T = any> extends Error { | ||
| request?: FetchRequest; | ||
| options?: FetchOptions; | ||
| response?: FetchResponse<T>; | ||
| data?: T; | ||
| status?: number; | ||
| statusText?: string; | ||
| statusCode?: number; | ||
| statusMessage?: string; | ||
| } | ||
| type Fetch = typeof globalThis.fetch; | ||
| type FetchRequest = RequestInfo; | ||
| interface SearchParameters { | ||
| [key: string]: any; | ||
| } | ||
| declare function createFetch(globalOptions?: CreateFetchOptions): $Fetch; | ||
| declare class FetchError<T = any> extends Error implements IFetchError<T> { | ||
| constructor(message: string, opts?: { | ||
| cause: unknown; | ||
| }); | ||
| } | ||
| interface FetchError<T = any> extends IFetchError<T> { | ||
| } | ||
| declare function createFetchError<T = any>(ctx: FetchContext<T>): IFetchError<T>; | ||
| export { FetchError as F, createFetchError as a, createFetch as c }; | ||
| export type { $Fetch as $, CreateFetchOptions as C, GlobalOptions as G, IFetchError as I, MappedResponseType as M, ResolvedFetchOptions as R, SearchParameters as S, FetchOptions as b, FetchContext as d, FetchHook as e, FetchHooks as f, ResponseMap as g, ResponseType as h, FetchResponse as i, Fetch as j, FetchRequest as k }; |
| import * as undici from 'undici'; | ||
| interface $Fetch { | ||
| <T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<MappedResponseType<R, T>>; | ||
| raw<T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<FetchResponse<MappedResponseType<R, T>>>; | ||
| native: Fetch; | ||
| create(defaults: FetchOptions, globalOptions?: CreateFetchOptions): $Fetch; | ||
| } | ||
| interface FetchOptions<R extends ResponseType = ResponseType, T = any> extends Omit<RequestInit, "body">, FetchHooks<T, R> { | ||
| baseURL?: string; | ||
| body?: RequestInit["body"] | Record<string, any>; | ||
| ignoreResponseError?: boolean; | ||
| /** | ||
| * @deprecated use query instead. | ||
| */ | ||
| params?: Record<string, any>; | ||
| query?: Record<string, any>; | ||
| parseResponse?: (responseText: string) => any; | ||
| responseType?: R; | ||
| /** | ||
| * @experimental Set to "half" to enable duplex streaming. | ||
| * Will be automatically set to "half" when using a ReadableStream as body. | ||
| * @see https://fetch.spec.whatwg.org/#enumdef-requestduplex | ||
| */ | ||
| duplex?: "half" | undefined; | ||
| /** | ||
| * Only supported in Node.js >= 18 using undici | ||
| * | ||
| * @see https://undici.nodejs.org/#/docs/api/Dispatcher | ||
| */ | ||
| dispatcher?: InstanceType<typeof undici.Dispatcher>; | ||
| /** | ||
| * Only supported older Node.js versions using node-fetch-native polyfill. | ||
| */ | ||
| agent?: unknown; | ||
| /** timeout in milliseconds */ | ||
| timeout?: number; | ||
| retry?: number | false; | ||
| /** Delay between retries in milliseconds. */ | ||
| retryDelay?: number | ((context: FetchContext<T, R>) => number); | ||
| /** Default is [408, 409, 425, 429, 500, 502, 503, 504] */ | ||
| retryStatusCodes?: number[]; | ||
| } | ||
| interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any> extends FetchOptions<R, T> { | ||
| headers: Headers; | ||
| } | ||
| interface CreateFetchOptions { | ||
| defaults?: FetchOptions; | ||
| fetch?: Fetch; | ||
| Headers?: typeof Headers; | ||
| AbortController?: typeof AbortController; | ||
| } | ||
| type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">; | ||
| interface FetchContext<T = any, R extends ResponseType = ResponseType> { | ||
| request: FetchRequest; | ||
| options: ResolvedFetchOptions<R>; | ||
| response?: FetchResponse<T>; | ||
| error?: Error; | ||
| } | ||
| type MaybePromise<T> = T | Promise<T>; | ||
| type MaybeArray<T> = T | T[]; | ||
| type FetchHook<C extends FetchContext = FetchContext> = (context: C) => MaybePromise<void>; | ||
| interface FetchHooks<T = any, R extends ResponseType = ResponseType> { | ||
| onRequest?: MaybeArray<FetchHook<FetchContext<T, R>>>; | ||
| onRequestError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| error: Error; | ||
| }>>; | ||
| onResponse?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| onResponseError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| } | ||
| interface ResponseMap { | ||
| blob: Blob; | ||
| text: string; | ||
| arrayBuffer: ArrayBuffer; | ||
| stream: ReadableStream<Uint8Array>; | ||
| } | ||
| type ResponseType = keyof ResponseMap | "json"; | ||
| type MappedResponseType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType; | ||
| interface FetchResponse<T> extends Response { | ||
| _data?: T; | ||
| } | ||
| interface IFetchError<T = any> extends Error { | ||
| request?: FetchRequest; | ||
| options?: FetchOptions; | ||
| response?: FetchResponse<T>; | ||
| data?: T; | ||
| status?: number; | ||
| statusText?: string; | ||
| statusCode?: number; | ||
| statusMessage?: string; | ||
| } | ||
| type Fetch = typeof globalThis.fetch; | ||
| type FetchRequest = RequestInfo; | ||
| interface SearchParameters { | ||
| [key: string]: any; | ||
| } | ||
| declare function createFetch(globalOptions?: CreateFetchOptions): $Fetch; | ||
| declare class FetchError<T = any> extends Error implements IFetchError<T> { | ||
| constructor(message: string, opts?: { | ||
| cause: unknown; | ||
| }); | ||
| } | ||
| interface FetchError<T = any> extends IFetchError<T> { | ||
| } | ||
| declare function createFetchError<T = any>(ctx: FetchContext<T>): IFetchError<T>; | ||
| export { FetchError as F, createFetchError as a, createFetch as c }; | ||
| export type { $Fetch as $, CreateFetchOptions as C, GlobalOptions as G, IFetchError as I, MappedResponseType as M, ResolvedFetchOptions as R, SearchParameters as S, FetchOptions as b, FetchContext as d, FetchHook as e, FetchHooks as f, ResponseMap as g, ResponseType as h, FetchResponse as i, Fetch as j, FetchRequest as k }; |
| import * as undici from 'undici'; | ||
| interface $Fetch { | ||
| <T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<MappedResponseType<R, T>>; | ||
| raw<T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<FetchResponse<MappedResponseType<R, T>>>; | ||
| native: Fetch; | ||
| create(defaults: FetchOptions, globalOptions?: CreateFetchOptions): $Fetch; | ||
| } | ||
| interface FetchOptions<R extends ResponseType = ResponseType, T = any> extends Omit<RequestInit, "body">, FetchHooks<T, R> { | ||
| baseURL?: string; | ||
| body?: RequestInit["body"] | Record<string, any>; | ||
| ignoreResponseError?: boolean; | ||
| /** | ||
| * @deprecated use query instead. | ||
| */ | ||
| params?: Record<string, any>; | ||
| query?: Record<string, any>; | ||
| parseResponse?: (responseText: string) => any; | ||
| responseType?: R; | ||
| /** | ||
| * @experimental Set to "half" to enable duplex streaming. | ||
| * Will be automatically set to "half" when using a ReadableStream as body. | ||
| * @see https://fetch.spec.whatwg.org/#enumdef-requestduplex | ||
| */ | ||
| duplex?: "half" | undefined; | ||
| /** | ||
| * Only supported in Node.js >= 18 using undici | ||
| * | ||
| * @see https://undici.nodejs.org/#/docs/api/Dispatcher | ||
| */ | ||
| dispatcher?: InstanceType<typeof undici.Dispatcher>; | ||
| /** | ||
| * Only supported older Node.js versions using node-fetch-native polyfill. | ||
| */ | ||
| agent?: unknown; | ||
| /** timeout in milliseconds */ | ||
| timeout?: number; | ||
| retry?: number | false; | ||
| /** Delay between retries in milliseconds. */ | ||
| retryDelay?: number | ((context: FetchContext<T, R>) => number); | ||
| /** Default is [408, 409, 425, 429, 500, 502, 503, 504] */ | ||
| retryStatusCodes?: number[]; | ||
| } | ||
| interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any> extends FetchOptions<R, T> { | ||
| headers: Headers; | ||
| } | ||
| interface CreateFetchOptions { | ||
| defaults?: FetchOptions; | ||
| fetch?: Fetch; | ||
| Headers?: typeof Headers; | ||
| AbortController?: typeof AbortController; | ||
| } | ||
| type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">; | ||
| interface FetchContext<T = any, R extends ResponseType = ResponseType> { | ||
| request: FetchRequest; | ||
| options: ResolvedFetchOptions<R>; | ||
| response?: FetchResponse<T>; | ||
| error?: Error; | ||
| } | ||
| type MaybePromise<T> = T | Promise<T>; | ||
| type MaybeArray<T> = T | T[]; | ||
| type FetchHook<C extends FetchContext = FetchContext> = (context: C) => MaybePromise<void>; | ||
| interface FetchHooks<T = any, R extends ResponseType = ResponseType> { | ||
| onRequest?: MaybeArray<FetchHook<FetchContext<T, R>>>; | ||
| onRequestError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| error: Error; | ||
| }>>; | ||
| onResponse?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| onResponseError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| } | ||
| interface ResponseMap { | ||
| blob: Blob; | ||
| text: string; | ||
| arrayBuffer: ArrayBuffer; | ||
| stream: ReadableStream<Uint8Array>; | ||
| } | ||
| type ResponseType = keyof ResponseMap | "json"; | ||
| type MappedResponseType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType; | ||
| interface FetchResponse<T> extends Response { | ||
| _data?: T; | ||
| } | ||
| interface IFetchError<T = any> extends Error { | ||
| request?: FetchRequest; | ||
| options?: FetchOptions; | ||
| response?: FetchResponse<T>; | ||
| data?: T; | ||
| status?: number; | ||
| statusText?: string; | ||
| statusCode?: number; | ||
| statusMessage?: string; | ||
| } | ||
| type Fetch = typeof globalThis.fetch; | ||
| type FetchRequest = RequestInfo; | ||
| interface SearchParameters { | ||
| [key: string]: any; | ||
| } | ||
| declare function createFetch(globalOptions?: CreateFetchOptions): $Fetch; | ||
| declare class FetchError<T = any> extends Error implements IFetchError<T> { | ||
| constructor(message: string, opts?: { | ||
| cause: unknown; | ||
| }); | ||
| } | ||
| interface FetchError<T = any> extends IFetchError<T> { | ||
| } | ||
| declare function createFetchError<T = any>(ctx: FetchContext<T>): IFetchError<T>; | ||
| export { FetchError as F, createFetchError as a, createFetch as c }; | ||
| export type { $Fetch as $, CreateFetchOptions as C, GlobalOptions as G, IFetchError as I, MappedResponseType as M, ResolvedFetchOptions as R, SearchParameters as S, FetchOptions as b, FetchContext as d, FetchHook as e, FetchHooks as f, ResponseMap as g, ResponseType as h, FetchResponse as i, Fetch as j, FetchRequest as k }; |
| import destr from 'destr'; | ||
| import { withBase, withQuery } from 'ufo'; | ||
| class FetchError extends Error { | ||
| constructor(message, opts) { | ||
| super(message, opts); | ||
| this.name = "FetchError"; | ||
| if (opts?.cause && !this.cause) { | ||
| this.cause = opts.cause; | ||
| } | ||
| } | ||
| } | ||
| function createFetchError(ctx) { | ||
| const errorMessage = ctx.error?.message || ctx.error?.toString() || ""; | ||
| const method = ctx.request?.method || ctx.options?.method || "GET"; | ||
| const url = ctx.request?.url || String(ctx.request) || "/"; | ||
| const requestStr = `[${method}] ${JSON.stringify(url)}`; | ||
| const statusStr = ctx.response ? `${ctx.response.status} ${ctx.response.statusText}` : "<no response>"; | ||
| const message = `${requestStr}: ${statusStr}${errorMessage ? ` ${errorMessage}` : ""}`; | ||
| const fetchError = new FetchError( | ||
| message, | ||
| ctx.error ? { cause: ctx.error } : void 0 | ||
| ); | ||
| for (const key of ["request", "options", "response"]) { | ||
| Object.defineProperty(fetchError, key, { | ||
| get() { | ||
| return ctx[key]; | ||
| } | ||
| }); | ||
| } | ||
| for (const [key, refKey] of [ | ||
| ["data", "_data"], | ||
| ["status", "status"], | ||
| ["statusCode", "status"], | ||
| ["statusText", "statusText"], | ||
| ["statusMessage", "statusText"] | ||
| ]) { | ||
| Object.defineProperty(fetchError, key, { | ||
| get() { | ||
| return ctx.response && ctx.response[refKey]; | ||
| } | ||
| }); | ||
| } | ||
| return fetchError; | ||
| } | ||
| const payloadMethods = new Set( | ||
| Object.freeze(["PATCH", "POST", "PUT", "DELETE"]) | ||
| ); | ||
| function isPayloadMethod(method = "GET") { | ||
| return payloadMethods.has(method.toUpperCase()); | ||
| } | ||
| function isJSONSerializable(value) { | ||
| if (value === void 0) { | ||
| return false; | ||
| } | ||
| const t = typeof value; | ||
| if (t === "string" || t === "number" || t === "boolean" || t === null) { | ||
| return true; | ||
| } | ||
| if (t !== "object") { | ||
| return false; | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return true; | ||
| } | ||
| if (value.buffer) { | ||
| return false; | ||
| } | ||
| if (value instanceof FormData || value instanceof URLSearchParams) { | ||
| return false; | ||
| } | ||
| return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function"; | ||
| } | ||
| const textTypes = /* @__PURE__ */ new Set([ | ||
| "image/svg", | ||
| "application/xml", | ||
| "application/xhtml", | ||
| "application/html" | ||
| ]); | ||
| const JSON_RE = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i; | ||
| function detectResponseType(_contentType = "") { | ||
| if (!_contentType) { | ||
| return "json"; | ||
| } | ||
| const contentType = _contentType.split(";").shift() || ""; | ||
| if (JSON_RE.test(contentType)) { | ||
| return "json"; | ||
| } | ||
| if (contentType === "text/event-stream") { | ||
| return "stream"; | ||
| } | ||
| if (textTypes.has(contentType) || contentType.startsWith("text/")) { | ||
| return "text"; | ||
| } | ||
| return "blob"; | ||
| } | ||
| function resolveFetchOptions(request, input, defaults, Headers) { | ||
| const headers = mergeHeaders( | ||
| input?.headers ?? request?.headers, | ||
| defaults?.headers, | ||
| Headers | ||
| ); | ||
| let query; | ||
| if (defaults?.query || defaults?.params || input?.params || input?.query) { | ||
| query = { | ||
| ...defaults?.params, | ||
| ...defaults?.query, | ||
| ...input?.params, | ||
| ...input?.query | ||
| }; | ||
| } | ||
| return { | ||
| ...defaults, | ||
| ...input, | ||
| query, | ||
| params: query, | ||
| headers | ||
| }; | ||
| } | ||
| function mergeHeaders(input, defaults, Headers) { | ||
| if (!defaults) { | ||
| return new Headers(input); | ||
| } | ||
| const headers = new Headers(defaults); | ||
| if (input) { | ||
| for (const [key, value] of Symbol.iterator in input || Array.isArray(input) ? input : new Headers(input)) { | ||
| headers.set(key, value); | ||
| } | ||
| } | ||
| return headers; | ||
| } | ||
| async function callHooks(context, hooks) { | ||
| if (hooks) { | ||
| if (Array.isArray(hooks)) { | ||
| for (const hook of hooks) { | ||
| await hook(context); | ||
| } | ||
| } else { | ||
| await hooks(context); | ||
| } | ||
| } | ||
| } | ||
| const retryStatusCodes = /* @__PURE__ */ new Set([ | ||
| 408, | ||
| // Request Timeout | ||
| 409, | ||
| // Conflict | ||
| 425, | ||
| // Too Early (Experimental) | ||
| 429, | ||
| // Too Many Requests | ||
| 500, | ||
| // Internal Server Error | ||
| 502, | ||
| // Bad Gateway | ||
| 503, | ||
| // Service Unavailable | ||
| 504 | ||
| // Gateway Timeout | ||
| ]); | ||
| const nullBodyResponses = /* @__PURE__ */ new Set([101, 204, 205, 304]); | ||
| function createFetch(globalOptions = {}) { | ||
| const { | ||
| fetch = globalThis.fetch, | ||
| Headers = globalThis.Headers, | ||
| AbortController = globalThis.AbortController | ||
| } = globalOptions; | ||
| async function onError(context) { | ||
| const isAbort = context.error && context.error.name === "AbortError" && !context.options.timeout || false; | ||
| if (context.options.retry !== false && !isAbort) { | ||
| let retries; | ||
| if (typeof context.options.retry === "number") { | ||
| retries = context.options.retry; | ||
| } else { | ||
| retries = isPayloadMethod(context.options.method) ? 0 : 1; | ||
| } | ||
| const responseCode = context.response && context.response.status || 500; | ||
| if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) { | ||
| const retryDelay = typeof context.options.retryDelay === "function" ? context.options.retryDelay(context) : context.options.retryDelay || 0; | ||
| if (retryDelay > 0) { | ||
| await new Promise((resolve) => setTimeout(resolve, retryDelay)); | ||
| } | ||
| return $fetchRaw(context.request, { | ||
| ...context.options, | ||
| retry: retries - 1 | ||
| }); | ||
| } | ||
| } | ||
| const error = createFetchError(context); | ||
| if (Error.captureStackTrace) { | ||
| Error.captureStackTrace(error, $fetchRaw); | ||
| } | ||
| throw error; | ||
| } | ||
| const $fetchRaw = async function $fetchRaw2(_request, _options = {}) { | ||
| const context = { | ||
| request: _request, | ||
| options: resolveFetchOptions( | ||
| _request, | ||
| _options, | ||
| globalOptions.defaults, | ||
| Headers | ||
| ), | ||
| response: void 0, | ||
| error: void 0 | ||
| }; | ||
| if (context.options.method) { | ||
| context.options.method = context.options.method.toUpperCase(); | ||
| } | ||
| if (context.options.onRequest) { | ||
| await callHooks(context, context.options.onRequest); | ||
| } | ||
| if (typeof context.request === "string") { | ||
| if (context.options.baseURL) { | ||
| context.request = withBase(context.request, context.options.baseURL); | ||
| } | ||
| if (context.options.query) { | ||
| context.request = withQuery(context.request, context.options.query); | ||
| delete context.options.query; | ||
| } | ||
| if ("query" in context.options) { | ||
| delete context.options.query; | ||
| } | ||
| if ("params" in context.options) { | ||
| delete context.options.params; | ||
| } | ||
| } | ||
| if (context.options.body && isPayloadMethod(context.options.method)) { | ||
| if (isJSONSerializable(context.options.body)) { | ||
| const contentType = context.options.headers.get("content-type"); | ||
| if (typeof context.options.body !== "string") { | ||
| context.options.body = contentType === "application/x-www-form-urlencoded" ? new URLSearchParams( | ||
| context.options.body | ||
| ).toString() : JSON.stringify(context.options.body); | ||
| } | ||
| context.options.headers = new Headers(context.options.headers || {}); | ||
| if (!contentType) { | ||
| context.options.headers.set("content-type", "application/json"); | ||
| } | ||
| if (!context.options.headers.has("accept")) { | ||
| context.options.headers.set("accept", "application/json"); | ||
| } | ||
| } else if ( | ||
| // ReadableStream Body | ||
| "pipeTo" in context.options.body && typeof context.options.body.pipeTo === "function" || // Node.js Stream Body | ||
| typeof context.options.body.pipe === "function" | ||
| ) { | ||
| if (!("duplex" in context.options)) { | ||
| context.options.duplex = "half"; | ||
| } | ||
| } | ||
| } | ||
| let abortTimeout; | ||
| if (!context.options.signal && context.options.timeout) { | ||
| const controller = new AbortController(); | ||
| abortTimeout = setTimeout(() => { | ||
| const error = new Error( | ||
| "[TimeoutError]: The operation was aborted due to timeout" | ||
| ); | ||
| error.name = "TimeoutError"; | ||
| error.code = 23; | ||
| controller.abort(error); | ||
| }, context.options.timeout); | ||
| context.options.signal = controller.signal; | ||
| } | ||
| try { | ||
| context.response = await fetch( | ||
| context.request, | ||
| context.options | ||
| ); | ||
| } catch (error) { | ||
| context.error = error; | ||
| if (context.options.onRequestError) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onRequestError | ||
| ); | ||
| } | ||
| return await onError(context); | ||
| } finally { | ||
| if (abortTimeout) { | ||
| clearTimeout(abortTimeout); | ||
| } | ||
| } | ||
| const hasBody = (context.response.body || // https://github.com/unjs/ofetch/issues/324 | ||
| // https://github.com/unjs/ofetch/issues/294 | ||
| // https://github.com/JakeChampion/fetch/issues/1454 | ||
| context.response._bodyInit) && !nullBodyResponses.has(context.response.status) && context.options.method !== "HEAD"; | ||
| if (hasBody) { | ||
| const responseType = (context.options.parseResponse ? "json" : context.options.responseType) || detectResponseType(context.response.headers.get("content-type") || ""); | ||
| switch (responseType) { | ||
| case "json": { | ||
| const data = await context.response.text(); | ||
| const parseFunction = context.options.parseResponse || destr; | ||
| context.response._data = parseFunction(data); | ||
| break; | ||
| } | ||
| case "stream": { | ||
| context.response._data = context.response.body || context.response._bodyInit; | ||
| break; | ||
| } | ||
| default: { | ||
| context.response._data = await context.response[responseType](); | ||
| } | ||
| } | ||
| } | ||
| if (context.options.onResponse) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onResponse | ||
| ); | ||
| } | ||
| if (!context.options.ignoreResponseError && context.response.status >= 400 && context.response.status < 600) { | ||
| if (context.options.onResponseError) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onResponseError | ||
| ); | ||
| } | ||
| return await onError(context); | ||
| } | ||
| return context.response; | ||
| }; | ||
| const $fetch = async function $fetch2(request, options) { | ||
| const r = await $fetchRaw(request, options); | ||
| return r._data; | ||
| }; | ||
| $fetch.raw = $fetchRaw; | ||
| $fetch.native = (...args) => fetch(...args); | ||
| $fetch.create = (defaultOptions = {}, customGlobalOptions = {}) => createFetch({ | ||
| ...globalOptions, | ||
| ...customGlobalOptions, | ||
| defaults: { | ||
| ...globalOptions.defaults, | ||
| ...customGlobalOptions.defaults, | ||
| ...defaultOptions | ||
| } | ||
| }); | ||
| return $fetch; | ||
| } | ||
| export { FetchError as F, createFetchError as a, createFetch as c }; |
+3
-3
| 'use strict'; | ||
| const fetch$1 = require('./shared/ofetch.d8adb063.cjs'); | ||
| const fetch$1 = require('./shared/ofetch.-9wI71OD.cjs'); | ||
| require('destr'); | ||
| require('ufo'); | ||
| const _globalThis = function() { | ||
| const _globalThis = (function() { | ||
| if (typeof globalThis !== "undefined") { | ||
@@ -21,3 +21,3 @@ return globalThis; | ||
| throw new Error("unable to locate global object"); | ||
| }(); | ||
| })(); | ||
| const fetch = _globalThis.fetch ? (...args) => _globalThis.fetch(...args) : () => Promise.reject(new Error("[ofetch] global.fetch is not supported!")); | ||
@@ -24,0 +24,0 @@ const Headers = _globalThis.Headers; |
+2
-2
@@ -1,3 +0,3 @@ | ||
| import { $ as $Fetch } from './shared/ofetch.d0b3d489.cjs'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.d0b3d489.cjs'; | ||
| import { $ as $Fetch } from './shared/ofetch.BbrTaNPp.cjs'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.BbrTaNPp.cjs'; | ||
| import 'undici'; | ||
@@ -4,0 +4,0 @@ |
+2
-2
@@ -1,3 +0,3 @@ | ||
| import { $ as $Fetch } from './shared/ofetch.d0b3d489.mjs'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.d0b3d489.mjs'; | ||
| import { $ as $Fetch } from './shared/ofetch.BbrTaNPp.mjs'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.BbrTaNPp.mjs'; | ||
| import 'undici'; | ||
@@ -4,0 +4,0 @@ |
+2
-2
@@ -1,3 +0,3 @@ | ||
| import { $ as $Fetch } from './shared/ofetch.d0b3d489.js'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.d0b3d489.js'; | ||
| import { $ as $Fetch } from './shared/ofetch.BbrTaNPp.js'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.BbrTaNPp.js'; | ||
| import 'undici'; | ||
@@ -4,0 +4,0 @@ |
+4
-4
@@ -1,7 +0,7 @@ | ||
| import { c as createFetch } from './shared/ofetch.03887fc3.mjs'; | ||
| export { F as FetchError, a as createFetchError } from './shared/ofetch.03887fc3.mjs'; | ||
| import { c as createFetch } from './shared/ofetch.DCGFE0NK.mjs'; | ||
| export { F as FetchError, a as createFetchError } from './shared/ofetch.DCGFE0NK.mjs'; | ||
| import 'destr'; | ||
| import 'ufo'; | ||
| const _globalThis = function() { | ||
| const _globalThis = (function() { | ||
| if (typeof globalThis !== "undefined") { | ||
@@ -20,3 +20,3 @@ return globalThis; | ||
| throw new Error("unable to locate global object"); | ||
| }(); | ||
| })(); | ||
| const fetch = _globalThis.fetch ? (...args) => _globalThis.fetch(...args) : () => Promise.reject(new Error("[ofetch] global.fetch is not supported!")); | ||
@@ -23,0 +23,0 @@ const Headers = _globalThis.Headers; |
+1
-1
@@ -6,3 +6,3 @@ 'use strict'; | ||
| const nodeFetch = require('node-fetch-native'); | ||
| const fetch$1 = require('./shared/ofetch.d8adb063.cjs'); | ||
| const fetch$1 = require('./shared/ofetch.-9wI71OD.cjs'); | ||
| require('destr'); | ||
@@ -9,0 +9,0 @@ require('ufo'); |
+2
-2
@@ -1,3 +0,3 @@ | ||
| import { $ as $Fetch } from './shared/ofetch.d0b3d489.cjs'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.d0b3d489.cjs'; | ||
| import { $ as $Fetch } from './shared/ofetch.BbrTaNPp.cjs'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.BbrTaNPp.cjs'; | ||
| import 'undici'; | ||
@@ -4,0 +4,0 @@ |
+2
-2
@@ -1,3 +0,3 @@ | ||
| import { $ as $Fetch } from './shared/ofetch.d0b3d489.mjs'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.d0b3d489.mjs'; | ||
| import { $ as $Fetch } from './shared/ofetch.BbrTaNPp.mjs'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.BbrTaNPp.mjs'; | ||
| import 'undici'; | ||
@@ -4,0 +4,0 @@ |
+2
-2
@@ -1,3 +0,3 @@ | ||
| import { $ as $Fetch } from './shared/ofetch.d0b3d489.js'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.d0b3d489.js'; | ||
| import { $ as $Fetch } from './shared/ofetch.BbrTaNPp.js'; | ||
| export { C as CreateFetchOptions, j as Fetch, d as FetchContext, F as FetchError, e as FetchHook, f as FetchHooks, b as FetchOptions, k as FetchRequest, i as FetchResponse, G as GlobalOptions, I as IFetchError, M as MappedResponseType, R as ResolvedFetchOptions, g as ResponseMap, h as ResponseType, S as SearchParameters, c as createFetch, a as createFetchError } from './shared/ofetch.BbrTaNPp.js'; | ||
| import 'undici'; | ||
@@ -4,0 +4,0 @@ |
+3
-3
| import http from 'node:http'; | ||
| import https from 'node:https'; | ||
| import nodeFetch, { Headers as Headers$1, AbortController as AbortController$1 } from 'node-fetch-native'; | ||
| import { c as createFetch } from './shared/ofetch.03887fc3.mjs'; | ||
| export { F as FetchError, a as createFetchError } from './shared/ofetch.03887fc3.mjs'; | ||
| import nodeFetch, { AbortController as AbortController$1, Headers as Headers$1 } from 'node-fetch-native'; | ||
| import { c as createFetch } from './shared/ofetch.DCGFE0NK.mjs'; | ||
| export { F as FetchError, a as createFetchError } from './shared/ofetch.DCGFE0NK.mjs'; | ||
| import 'destr'; | ||
@@ -7,0 +7,0 @@ import 'ufo'; |
+18
-18
| { | ||
| "name": "ofetch", | ||
| "version": "1.4.1", | ||
| "version": "1.5.0", | ||
| "description": "A better fetch API. Works on node, browser and workers.", | ||
@@ -73,25 +73,25 @@ "repository": "unjs/ofetch", | ||
| "dependencies": { | ||
| "destr": "^2.0.3", | ||
| "node-fetch-native": "^1.6.4", | ||
| "ufo": "^1.5.4" | ||
| "destr": "^2.0.5", | ||
| "node-fetch-native": "^1.6.7", | ||
| "ufo": "^1.6.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "^22.7.5", | ||
| "@vitest/coverage-v8": "^2.1.2", | ||
| "changelogen": "^0.5.7", | ||
| "eslint": "^9.12.0", | ||
| "eslint-config-unjs": "^0.4.1", | ||
| "@types/node": "^24.9.1", | ||
| "@vitest/coverage-v8": "^4.0.4", | ||
| "changelogen": "^0.6.2", | ||
| "eslint": "^9.38.0", | ||
| "eslint-config-unjs": "^0.5.0", | ||
| "fetch-blob": "^4.0.0", | ||
| "formdata-polyfill": "^4.0.10", | ||
| "h3": "^1.13.0", | ||
| "jiti": "^2.3.3", | ||
| "h3": "^1.15.4", | ||
| "jiti": "^2.6.1", | ||
| "listhen": "^1.9.0", | ||
| "prettier": "^3.3.3", | ||
| "std-env": "^3.7.0", | ||
| "typescript": "^5.6.2", | ||
| "unbuild": "^2.0.0", | ||
| "undici": "^6.19.8", | ||
| "vitest": "^2.1.2" | ||
| "prettier": "^3.6.2", | ||
| "std-env": "^3.10.0", | ||
| "typescript": "^5.9.3", | ||
| "unbuild": "^3.6.1", | ||
| "undici": "^7.16.0", | ||
| "vitest": "^4.0.4" | ||
| }, | ||
| "packageManager": "pnpm@9.12.1" | ||
| "packageManager": "pnpm@10.19.0" | ||
| } |
+55
-5
@@ -54,3 +54,3 @@ # ofetch | ||
| You can optionally provide a different parser than `destr`, or specify `blob`, `arrayBuffer`, or `text` to force parsing the body with the respective `FetchResponse` method. | ||
| You can optionally provide a different parser than `destr`, or specify `blob`, `arrayBuffer`, `text` or `stream` to force parsing the body with the respective `FetchResponse` method. | ||
@@ -66,2 +66,5 @@ ```js | ||
| await ofetch("/api/generate-image", { responseType: "blob" }); | ||
| // Get the stream version of the response | ||
| await ofetch("/api/generate-image", { responseType: "stream" }); | ||
| ``` | ||
@@ -75,5 +78,5 @@ | ||
| For `PUT`, `PATCH`, and `POST` request methods, when a string or object body is set, `ofetch` adds the default `content-type: "application/json"` and `accept: "application/json"` headers (which you can always override). | ||
| For `PUT`, `PATCH`, and `POST` request methods, when a string or object body is set, `ofetch` adds the default `"content-type": "application/json"` and `accept: "application/json"` headers (which you can always override). | ||
| Additionally, `ofetch` supports binary responses with `Buffer`, `ReadableStream`, `Stream`, and [compatible body types](https://developer.mozilla.org/en-US/docs/Web/API/fetch#body). ofetch will automatically set the `duplex: "half"` option for streaming support! | ||
| Additionally, `ofetch` supports binary responses with `Buffer`, `ReadableStream`, `Stream`, and [compatible body types](https://developer.mozilla.org/en-US/docs/Web/API/fetch#body). `ofetch` will automatically set the `duplex: "half"` option for streaming support! | ||
@@ -138,2 +141,3 @@ **Example:** | ||
| retryDelay: 500, // ms | ||
| retryStatusCodes: [ 404, 500 ], // response status codes to retry | ||
| }); | ||
@@ -288,3 +292,3 @@ ``` | ||
| If you need to access raw response (for headers, etc), can use `ofetch.raw`: | ||
| If you need to access raw response (for headers, etc), you can use `ofetch.raw`: | ||
@@ -307,2 +311,18 @@ ```js | ||
| ## 📡 SSE | ||
| **Example:** Handle SSE response: | ||
| ```js | ||
| const stream = await ofetch("/sse") | ||
| const reader = stream.getReader(); | ||
| const decoder = new TextDecoder() | ||
| while (true) { | ||
| const { done, value } = await reader.read(); | ||
| if (done) break; | ||
| // Here is the chunked text of the SSE response. | ||
| const text = decoder.decode(value) | ||
| } | ||
| ``` | ||
| ## 🕵️ Adding HTTP(S) Agent | ||
@@ -358,3 +378,3 @@ | ||
| // Note: This makes fetch unsecure against MITM attacks. USE AT YOUW OWN RISK! | ||
| // Note: This makes fetch unsecure against MITM attacks. USE AT YOUR OWN RISK! | ||
| const unsecureAgent = new Agent({ connect: { rejectUnauthorized: false } }); | ||
@@ -382,2 +402,32 @@ const unsecureFetch = ofetch.create({ dispatcher: unsecureAgent }); | ||
| ### 💪 Augment `FetchOptions` interface | ||
| You can augment the `FetchOptions` interface to add custom properties. | ||
| ```ts | ||
| // Place this in any `.ts` or `.d.ts` file. | ||
| // Ensure it's included in the project's tsconfig.json "files". | ||
| declare module "ofetch" { | ||
| interface FetchOptions { | ||
| // Custom properties | ||
| requiresAuth?: boolean; | ||
| } | ||
| } | ||
| export {} | ||
| ``` | ||
| This lets you pass and use those properties with full type safety throughout `ofetch` calls. | ||
| ```ts | ||
| const myFetch = ofetch.create({ | ||
| onRequest(context) { | ||
| // ^? { ..., options: {..., requiresAuth?: boolean }} | ||
| console.log(context.options.requiresAuth); | ||
| }, | ||
| }); | ||
| myFetch("/foo", { requiresAuth: true }) | ||
| ``` | ||
| ## 📦 Bundler Notes | ||
@@ -384,0 +434,0 @@ |
| import destr from 'destr'; | ||
| import { withBase, withQuery } from 'ufo'; | ||
| class FetchError extends Error { | ||
| constructor(message, opts) { | ||
| super(message, opts); | ||
| this.name = "FetchError"; | ||
| if (opts?.cause && !this.cause) { | ||
| this.cause = opts.cause; | ||
| } | ||
| } | ||
| } | ||
| function createFetchError(ctx) { | ||
| const errorMessage = ctx.error?.message || ctx.error?.toString() || ""; | ||
| const method = ctx.request?.method || ctx.options?.method || "GET"; | ||
| const url = ctx.request?.url || String(ctx.request) || "/"; | ||
| const requestStr = `[${method}] ${JSON.stringify(url)}`; | ||
| const statusStr = ctx.response ? `${ctx.response.status} ${ctx.response.statusText}` : "<no response>"; | ||
| const message = `${requestStr}: ${statusStr}${errorMessage ? ` ${errorMessage}` : ""}`; | ||
| const fetchError = new FetchError( | ||
| message, | ||
| ctx.error ? { cause: ctx.error } : void 0 | ||
| ); | ||
| for (const key of ["request", "options", "response"]) { | ||
| Object.defineProperty(fetchError, key, { | ||
| get() { | ||
| return ctx[key]; | ||
| } | ||
| }); | ||
| } | ||
| for (const [key, refKey] of [ | ||
| ["data", "_data"], | ||
| ["status", "status"], | ||
| ["statusCode", "status"], | ||
| ["statusText", "statusText"], | ||
| ["statusMessage", "statusText"] | ||
| ]) { | ||
| Object.defineProperty(fetchError, key, { | ||
| get() { | ||
| return ctx.response && ctx.response[refKey]; | ||
| } | ||
| }); | ||
| } | ||
| return fetchError; | ||
| } | ||
| const payloadMethods = new Set( | ||
| Object.freeze(["PATCH", "POST", "PUT", "DELETE"]) | ||
| ); | ||
| function isPayloadMethod(method = "GET") { | ||
| return payloadMethods.has(method.toUpperCase()); | ||
| } | ||
| function isJSONSerializable(value) { | ||
| if (value === void 0) { | ||
| return false; | ||
| } | ||
| const t = typeof value; | ||
| if (t === "string" || t === "number" || t === "boolean" || t === null) { | ||
| return true; | ||
| } | ||
| if (t !== "object") { | ||
| return false; | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return true; | ||
| } | ||
| if (value.buffer) { | ||
| return false; | ||
| } | ||
| return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function"; | ||
| } | ||
| const textTypes = /* @__PURE__ */ new Set([ | ||
| "image/svg", | ||
| "application/xml", | ||
| "application/xhtml", | ||
| "application/html" | ||
| ]); | ||
| const JSON_RE = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i; | ||
| function detectResponseType(_contentType = "") { | ||
| if (!_contentType) { | ||
| return "json"; | ||
| } | ||
| const contentType = _contentType.split(";").shift() || ""; | ||
| if (JSON_RE.test(contentType)) { | ||
| return "json"; | ||
| } | ||
| if (textTypes.has(contentType) || contentType.startsWith("text/")) { | ||
| return "text"; | ||
| } | ||
| return "blob"; | ||
| } | ||
| function resolveFetchOptions(request, input, defaults, Headers) { | ||
| const headers = mergeHeaders( | ||
| input?.headers ?? request?.headers, | ||
| defaults?.headers, | ||
| Headers | ||
| ); | ||
| let query; | ||
| if (defaults?.query || defaults?.params || input?.params || input?.query) { | ||
| query = { | ||
| ...defaults?.params, | ||
| ...defaults?.query, | ||
| ...input?.params, | ||
| ...input?.query | ||
| }; | ||
| } | ||
| return { | ||
| ...defaults, | ||
| ...input, | ||
| query, | ||
| params: query, | ||
| headers | ||
| }; | ||
| } | ||
| function mergeHeaders(input, defaults, Headers) { | ||
| if (!defaults) { | ||
| return new Headers(input); | ||
| } | ||
| const headers = new Headers(defaults); | ||
| if (input) { | ||
| for (const [key, value] of Symbol.iterator in input || Array.isArray(input) ? input : new Headers(input)) { | ||
| headers.set(key, value); | ||
| } | ||
| } | ||
| return headers; | ||
| } | ||
| async function callHooks(context, hooks) { | ||
| if (hooks) { | ||
| if (Array.isArray(hooks)) { | ||
| for (const hook of hooks) { | ||
| await hook(context); | ||
| } | ||
| } else { | ||
| await hooks(context); | ||
| } | ||
| } | ||
| } | ||
| const retryStatusCodes = /* @__PURE__ */ new Set([ | ||
| 408, | ||
| // Request Timeout | ||
| 409, | ||
| // Conflict | ||
| 425, | ||
| // Too Early (Experimental) | ||
| 429, | ||
| // Too Many Requests | ||
| 500, | ||
| // Internal Server Error | ||
| 502, | ||
| // Bad Gateway | ||
| 503, | ||
| // Service Unavailable | ||
| 504 | ||
| // Gateway Timeout | ||
| ]); | ||
| const nullBodyResponses = /* @__PURE__ */ new Set([101, 204, 205, 304]); | ||
| function createFetch(globalOptions = {}) { | ||
| const { | ||
| fetch = globalThis.fetch, | ||
| Headers = globalThis.Headers, | ||
| AbortController = globalThis.AbortController | ||
| } = globalOptions; | ||
| async function onError(context) { | ||
| const isAbort = context.error && context.error.name === "AbortError" && !context.options.timeout || false; | ||
| if (context.options.retry !== false && !isAbort) { | ||
| let retries; | ||
| if (typeof context.options.retry === "number") { | ||
| retries = context.options.retry; | ||
| } else { | ||
| retries = isPayloadMethod(context.options.method) ? 0 : 1; | ||
| } | ||
| const responseCode = context.response && context.response.status || 500; | ||
| if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) { | ||
| const retryDelay = typeof context.options.retryDelay === "function" ? context.options.retryDelay(context) : context.options.retryDelay || 0; | ||
| if (retryDelay > 0) { | ||
| await new Promise((resolve) => setTimeout(resolve, retryDelay)); | ||
| } | ||
| return $fetchRaw(context.request, { | ||
| ...context.options, | ||
| retry: retries - 1 | ||
| }); | ||
| } | ||
| } | ||
| const error = createFetchError(context); | ||
| if (Error.captureStackTrace) { | ||
| Error.captureStackTrace(error, $fetchRaw); | ||
| } | ||
| throw error; | ||
| } | ||
| const $fetchRaw = async function $fetchRaw2(_request, _options = {}) { | ||
| const context = { | ||
| request: _request, | ||
| options: resolveFetchOptions( | ||
| _request, | ||
| _options, | ||
| globalOptions.defaults, | ||
| Headers | ||
| ), | ||
| response: void 0, | ||
| error: void 0 | ||
| }; | ||
| if (context.options.method) { | ||
| context.options.method = context.options.method.toUpperCase(); | ||
| } | ||
| if (context.options.onRequest) { | ||
| await callHooks(context, context.options.onRequest); | ||
| } | ||
| if (typeof context.request === "string") { | ||
| if (context.options.baseURL) { | ||
| context.request = withBase(context.request, context.options.baseURL); | ||
| } | ||
| if (context.options.query) { | ||
| context.request = withQuery(context.request, context.options.query); | ||
| delete context.options.query; | ||
| } | ||
| if ("query" in context.options) { | ||
| delete context.options.query; | ||
| } | ||
| if ("params" in context.options) { | ||
| delete context.options.params; | ||
| } | ||
| } | ||
| if (context.options.body && isPayloadMethod(context.options.method)) { | ||
| if (isJSONSerializable(context.options.body)) { | ||
| context.options.body = typeof context.options.body === "string" ? context.options.body : JSON.stringify(context.options.body); | ||
| context.options.headers = new Headers(context.options.headers || {}); | ||
| if (!context.options.headers.has("content-type")) { | ||
| context.options.headers.set("content-type", "application/json"); | ||
| } | ||
| if (!context.options.headers.has("accept")) { | ||
| context.options.headers.set("accept", "application/json"); | ||
| } | ||
| } else if ( | ||
| // ReadableStream Body | ||
| "pipeTo" in context.options.body && typeof context.options.body.pipeTo === "function" || // Node.js Stream Body | ||
| typeof context.options.body.pipe === "function" | ||
| ) { | ||
| if (!("duplex" in context.options)) { | ||
| context.options.duplex = "half"; | ||
| } | ||
| } | ||
| } | ||
| let abortTimeout; | ||
| if (!context.options.signal && context.options.timeout) { | ||
| const controller = new AbortController(); | ||
| abortTimeout = setTimeout(() => { | ||
| const error = new Error( | ||
| "[TimeoutError]: The operation was aborted due to timeout" | ||
| ); | ||
| error.name = "TimeoutError"; | ||
| error.code = 23; | ||
| controller.abort(error); | ||
| }, context.options.timeout); | ||
| context.options.signal = controller.signal; | ||
| } | ||
| try { | ||
| context.response = await fetch( | ||
| context.request, | ||
| context.options | ||
| ); | ||
| } catch (error) { | ||
| context.error = error; | ||
| if (context.options.onRequestError) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onRequestError | ||
| ); | ||
| } | ||
| return await onError(context); | ||
| } finally { | ||
| if (abortTimeout) { | ||
| clearTimeout(abortTimeout); | ||
| } | ||
| } | ||
| const hasBody = (context.response.body || // https://github.com/unjs/ofetch/issues/324 | ||
| // https://github.com/unjs/ofetch/issues/294 | ||
| // https://github.com/JakeChampion/fetch/issues/1454 | ||
| context.response._bodyInit) && !nullBodyResponses.has(context.response.status) && context.options.method !== "HEAD"; | ||
| if (hasBody) { | ||
| const responseType = (context.options.parseResponse ? "json" : context.options.responseType) || detectResponseType(context.response.headers.get("content-type") || ""); | ||
| switch (responseType) { | ||
| case "json": { | ||
| const data = await context.response.text(); | ||
| const parseFunction = context.options.parseResponse || destr; | ||
| context.response._data = parseFunction(data); | ||
| break; | ||
| } | ||
| case "stream": { | ||
| context.response._data = context.response.body || context.response._bodyInit; | ||
| break; | ||
| } | ||
| default: { | ||
| context.response._data = await context.response[responseType](); | ||
| } | ||
| } | ||
| } | ||
| if (context.options.onResponse) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onResponse | ||
| ); | ||
| } | ||
| if (!context.options.ignoreResponseError && context.response.status >= 400 && context.response.status < 600) { | ||
| if (context.options.onResponseError) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onResponseError | ||
| ); | ||
| } | ||
| return await onError(context); | ||
| } | ||
| return context.response; | ||
| }; | ||
| const $fetch = async function $fetch2(request, options) { | ||
| const r = await $fetchRaw(request, options); | ||
| return r._data; | ||
| }; | ||
| $fetch.raw = $fetchRaw; | ||
| $fetch.native = (...args) => fetch(...args); | ||
| $fetch.create = (defaultOptions = {}, customGlobalOptions = {}) => createFetch({ | ||
| ...globalOptions, | ||
| ...customGlobalOptions, | ||
| defaults: { | ||
| ...globalOptions.defaults, | ||
| ...customGlobalOptions.defaults, | ||
| ...defaultOptions | ||
| } | ||
| }); | ||
| return $fetch; | ||
| } | ||
| export { FetchError as F, createFetchError as a, createFetch as c }; |
| import * as undici from 'undici'; | ||
| interface $Fetch { | ||
| <T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<MappedResponseType<R, T>>; | ||
| raw<T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<FetchResponse<MappedResponseType<R, T>>>; | ||
| native: Fetch; | ||
| create(defaults: FetchOptions, globalOptions?: CreateFetchOptions): $Fetch; | ||
| } | ||
| interface FetchOptions<R extends ResponseType = ResponseType, T = any> extends Omit<RequestInit, "body">, FetchHooks<T, R> { | ||
| baseURL?: string; | ||
| body?: RequestInit["body"] | Record<string, any>; | ||
| ignoreResponseError?: boolean; | ||
| params?: Record<string, any>; | ||
| query?: Record<string, any>; | ||
| parseResponse?: (responseText: string) => any; | ||
| responseType?: R; | ||
| /** | ||
| * @experimental Set to "half" to enable duplex streaming. | ||
| * Will be automatically set to "half" when using a ReadableStream as body. | ||
| * @see https://fetch.spec.whatwg.org/#enumdef-requestduplex | ||
| */ | ||
| duplex?: "half" | undefined; | ||
| /** | ||
| * Only supported in Node.js >= 18 using undici | ||
| * | ||
| * @see https://undici.nodejs.org/#/docs/api/Dispatcher | ||
| */ | ||
| dispatcher?: InstanceType<typeof undici.Dispatcher>; | ||
| /** | ||
| * Only supported older Node.js versions using node-fetch-native polyfill. | ||
| */ | ||
| agent?: unknown; | ||
| /** timeout in milliseconds */ | ||
| timeout?: number; | ||
| retry?: number | false; | ||
| /** Delay between retries in milliseconds. */ | ||
| retryDelay?: number | ((context: FetchContext<T, R>) => number); | ||
| /** Default is [408, 409, 425, 429, 500, 502, 503, 504] */ | ||
| retryStatusCodes?: number[]; | ||
| } | ||
| interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any> extends FetchOptions<R, T> { | ||
| headers: Headers; | ||
| } | ||
| interface CreateFetchOptions { | ||
| defaults?: FetchOptions; | ||
| fetch?: Fetch; | ||
| Headers?: typeof Headers; | ||
| AbortController?: typeof AbortController; | ||
| } | ||
| type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">; | ||
| interface FetchContext<T = any, R extends ResponseType = ResponseType> { | ||
| request: FetchRequest; | ||
| options: ResolvedFetchOptions<R>; | ||
| response?: FetchResponse<T>; | ||
| error?: Error; | ||
| } | ||
| type MaybePromise<T> = T | Promise<T>; | ||
| type MaybeArray<T> = T | T[]; | ||
| type FetchHook<C extends FetchContext = FetchContext> = (context: C) => MaybePromise<void>; | ||
| interface FetchHooks<T = any, R extends ResponseType = ResponseType> { | ||
| onRequest?: MaybeArray<FetchHook<FetchContext<T, R>>>; | ||
| onRequestError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| error: Error; | ||
| }>>; | ||
| onResponse?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| onResponseError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| } | ||
| interface ResponseMap { | ||
| blob: Blob; | ||
| text: string; | ||
| arrayBuffer: ArrayBuffer; | ||
| stream: ReadableStream<Uint8Array>; | ||
| } | ||
| type ResponseType = keyof ResponseMap | "json"; | ||
| type MappedResponseType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType; | ||
| interface FetchResponse<T> extends Response { | ||
| _data?: T; | ||
| } | ||
| interface IFetchError<T = any> extends Error { | ||
| request?: FetchRequest; | ||
| options?: FetchOptions; | ||
| response?: FetchResponse<T>; | ||
| data?: T; | ||
| status?: number; | ||
| statusText?: string; | ||
| statusCode?: number; | ||
| statusMessage?: string; | ||
| } | ||
| type Fetch = typeof globalThis.fetch; | ||
| type FetchRequest = RequestInfo; | ||
| interface SearchParameters { | ||
| [key: string]: any; | ||
| } | ||
| declare function createFetch(globalOptions?: CreateFetchOptions): $Fetch; | ||
| declare class FetchError<T = any> extends Error implements IFetchError<T> { | ||
| constructor(message: string, opts?: { | ||
| cause: unknown; | ||
| }); | ||
| } | ||
| interface FetchError<T = any> extends IFetchError<T> { | ||
| } | ||
| declare function createFetchError<T = any>(ctx: FetchContext<T>): IFetchError<T>; | ||
| export { type $Fetch as $, type CreateFetchOptions as C, FetchError as F, type GlobalOptions as G, type IFetchError as I, type MappedResponseType as M, type ResolvedFetchOptions as R, type SearchParameters as S, createFetchError as a, type FetchOptions as b, createFetch as c, type FetchContext as d, type FetchHook as e, type FetchHooks as f, type ResponseMap as g, type ResponseType as h, type FetchResponse as i, type Fetch as j, type FetchRequest as k }; |
| import * as undici from 'undici'; | ||
| interface $Fetch { | ||
| <T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<MappedResponseType<R, T>>; | ||
| raw<T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<FetchResponse<MappedResponseType<R, T>>>; | ||
| native: Fetch; | ||
| create(defaults: FetchOptions, globalOptions?: CreateFetchOptions): $Fetch; | ||
| } | ||
| interface FetchOptions<R extends ResponseType = ResponseType, T = any> extends Omit<RequestInit, "body">, FetchHooks<T, R> { | ||
| baseURL?: string; | ||
| body?: RequestInit["body"] | Record<string, any>; | ||
| ignoreResponseError?: boolean; | ||
| params?: Record<string, any>; | ||
| query?: Record<string, any>; | ||
| parseResponse?: (responseText: string) => any; | ||
| responseType?: R; | ||
| /** | ||
| * @experimental Set to "half" to enable duplex streaming. | ||
| * Will be automatically set to "half" when using a ReadableStream as body. | ||
| * @see https://fetch.spec.whatwg.org/#enumdef-requestduplex | ||
| */ | ||
| duplex?: "half" | undefined; | ||
| /** | ||
| * Only supported in Node.js >= 18 using undici | ||
| * | ||
| * @see https://undici.nodejs.org/#/docs/api/Dispatcher | ||
| */ | ||
| dispatcher?: InstanceType<typeof undici.Dispatcher>; | ||
| /** | ||
| * Only supported older Node.js versions using node-fetch-native polyfill. | ||
| */ | ||
| agent?: unknown; | ||
| /** timeout in milliseconds */ | ||
| timeout?: number; | ||
| retry?: number | false; | ||
| /** Delay between retries in milliseconds. */ | ||
| retryDelay?: number | ((context: FetchContext<T, R>) => number); | ||
| /** Default is [408, 409, 425, 429, 500, 502, 503, 504] */ | ||
| retryStatusCodes?: number[]; | ||
| } | ||
| interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any> extends FetchOptions<R, T> { | ||
| headers: Headers; | ||
| } | ||
| interface CreateFetchOptions { | ||
| defaults?: FetchOptions; | ||
| fetch?: Fetch; | ||
| Headers?: typeof Headers; | ||
| AbortController?: typeof AbortController; | ||
| } | ||
| type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">; | ||
| interface FetchContext<T = any, R extends ResponseType = ResponseType> { | ||
| request: FetchRequest; | ||
| options: ResolvedFetchOptions<R>; | ||
| response?: FetchResponse<T>; | ||
| error?: Error; | ||
| } | ||
| type MaybePromise<T> = T | Promise<T>; | ||
| type MaybeArray<T> = T | T[]; | ||
| type FetchHook<C extends FetchContext = FetchContext> = (context: C) => MaybePromise<void>; | ||
| interface FetchHooks<T = any, R extends ResponseType = ResponseType> { | ||
| onRequest?: MaybeArray<FetchHook<FetchContext<T, R>>>; | ||
| onRequestError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| error: Error; | ||
| }>>; | ||
| onResponse?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| onResponseError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| } | ||
| interface ResponseMap { | ||
| blob: Blob; | ||
| text: string; | ||
| arrayBuffer: ArrayBuffer; | ||
| stream: ReadableStream<Uint8Array>; | ||
| } | ||
| type ResponseType = keyof ResponseMap | "json"; | ||
| type MappedResponseType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType; | ||
| interface FetchResponse<T> extends Response { | ||
| _data?: T; | ||
| } | ||
| interface IFetchError<T = any> extends Error { | ||
| request?: FetchRequest; | ||
| options?: FetchOptions; | ||
| response?: FetchResponse<T>; | ||
| data?: T; | ||
| status?: number; | ||
| statusText?: string; | ||
| statusCode?: number; | ||
| statusMessage?: string; | ||
| } | ||
| type Fetch = typeof globalThis.fetch; | ||
| type FetchRequest = RequestInfo; | ||
| interface SearchParameters { | ||
| [key: string]: any; | ||
| } | ||
| declare function createFetch(globalOptions?: CreateFetchOptions): $Fetch; | ||
| declare class FetchError<T = any> extends Error implements IFetchError<T> { | ||
| constructor(message: string, opts?: { | ||
| cause: unknown; | ||
| }); | ||
| } | ||
| interface FetchError<T = any> extends IFetchError<T> { | ||
| } | ||
| declare function createFetchError<T = any>(ctx: FetchContext<T>): IFetchError<T>; | ||
| export { type $Fetch as $, type CreateFetchOptions as C, FetchError as F, type GlobalOptions as G, type IFetchError as I, type MappedResponseType as M, type ResolvedFetchOptions as R, type SearchParameters as S, createFetchError as a, type FetchOptions as b, createFetch as c, type FetchContext as d, type FetchHook as e, type FetchHooks as f, type ResponseMap as g, type ResponseType as h, type FetchResponse as i, type Fetch as j, type FetchRequest as k }; |
| import * as undici from 'undici'; | ||
| interface $Fetch { | ||
| <T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<MappedResponseType<R, T>>; | ||
| raw<T = any, R extends ResponseType = "json">(request: FetchRequest, options?: FetchOptions<R>): Promise<FetchResponse<MappedResponseType<R, T>>>; | ||
| native: Fetch; | ||
| create(defaults: FetchOptions, globalOptions?: CreateFetchOptions): $Fetch; | ||
| } | ||
| interface FetchOptions<R extends ResponseType = ResponseType, T = any> extends Omit<RequestInit, "body">, FetchHooks<T, R> { | ||
| baseURL?: string; | ||
| body?: RequestInit["body"] | Record<string, any>; | ||
| ignoreResponseError?: boolean; | ||
| params?: Record<string, any>; | ||
| query?: Record<string, any>; | ||
| parseResponse?: (responseText: string) => any; | ||
| responseType?: R; | ||
| /** | ||
| * @experimental Set to "half" to enable duplex streaming. | ||
| * Will be automatically set to "half" when using a ReadableStream as body. | ||
| * @see https://fetch.spec.whatwg.org/#enumdef-requestduplex | ||
| */ | ||
| duplex?: "half" | undefined; | ||
| /** | ||
| * Only supported in Node.js >= 18 using undici | ||
| * | ||
| * @see https://undici.nodejs.org/#/docs/api/Dispatcher | ||
| */ | ||
| dispatcher?: InstanceType<typeof undici.Dispatcher>; | ||
| /** | ||
| * Only supported older Node.js versions using node-fetch-native polyfill. | ||
| */ | ||
| agent?: unknown; | ||
| /** timeout in milliseconds */ | ||
| timeout?: number; | ||
| retry?: number | false; | ||
| /** Delay between retries in milliseconds. */ | ||
| retryDelay?: number | ((context: FetchContext<T, R>) => number); | ||
| /** Default is [408, 409, 425, 429, 500, 502, 503, 504] */ | ||
| retryStatusCodes?: number[]; | ||
| } | ||
| interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any> extends FetchOptions<R, T> { | ||
| headers: Headers; | ||
| } | ||
| interface CreateFetchOptions { | ||
| defaults?: FetchOptions; | ||
| fetch?: Fetch; | ||
| Headers?: typeof Headers; | ||
| AbortController?: typeof AbortController; | ||
| } | ||
| type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">; | ||
| interface FetchContext<T = any, R extends ResponseType = ResponseType> { | ||
| request: FetchRequest; | ||
| options: ResolvedFetchOptions<R>; | ||
| response?: FetchResponse<T>; | ||
| error?: Error; | ||
| } | ||
| type MaybePromise<T> = T | Promise<T>; | ||
| type MaybeArray<T> = T | T[]; | ||
| type FetchHook<C extends FetchContext = FetchContext> = (context: C) => MaybePromise<void>; | ||
| interface FetchHooks<T = any, R extends ResponseType = ResponseType> { | ||
| onRequest?: MaybeArray<FetchHook<FetchContext<T, R>>>; | ||
| onRequestError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| error: Error; | ||
| }>>; | ||
| onResponse?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| onResponseError?: MaybeArray<FetchHook<FetchContext<T, R> & { | ||
| response: FetchResponse<T>; | ||
| }>>; | ||
| } | ||
| interface ResponseMap { | ||
| blob: Blob; | ||
| text: string; | ||
| arrayBuffer: ArrayBuffer; | ||
| stream: ReadableStream<Uint8Array>; | ||
| } | ||
| type ResponseType = keyof ResponseMap | "json"; | ||
| type MappedResponseType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType; | ||
| interface FetchResponse<T> extends Response { | ||
| _data?: T; | ||
| } | ||
| interface IFetchError<T = any> extends Error { | ||
| request?: FetchRequest; | ||
| options?: FetchOptions; | ||
| response?: FetchResponse<T>; | ||
| data?: T; | ||
| status?: number; | ||
| statusText?: string; | ||
| statusCode?: number; | ||
| statusMessage?: string; | ||
| } | ||
| type Fetch = typeof globalThis.fetch; | ||
| type FetchRequest = RequestInfo; | ||
| interface SearchParameters { | ||
| [key: string]: any; | ||
| } | ||
| declare function createFetch(globalOptions?: CreateFetchOptions): $Fetch; | ||
| declare class FetchError<T = any> extends Error implements IFetchError<T> { | ||
| constructor(message: string, opts?: { | ||
| cause: unknown; | ||
| }); | ||
| } | ||
| interface FetchError<T = any> extends IFetchError<T> { | ||
| } | ||
| declare function createFetchError<T = any>(ctx: FetchContext<T>): IFetchError<T>; | ||
| export { type $Fetch as $, type CreateFetchOptions as C, FetchError as F, type GlobalOptions as G, type IFetchError as I, type MappedResponseType as M, type ResolvedFetchOptions as R, type SearchParameters as S, createFetchError as a, type FetchOptions as b, createFetch as c, type FetchContext as d, type FetchHook as e, type FetchHooks as f, type ResponseMap as g, type ResponseType as h, type FetchResponse as i, type Fetch as j, type FetchRequest as k }; |
| 'use strict'; | ||
| const destr = require('destr'); | ||
| const ufo = require('ufo'); | ||
| function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; } | ||
| const destr__default = /*#__PURE__*/_interopDefaultCompat(destr); | ||
| class FetchError extends Error { | ||
| constructor(message, opts) { | ||
| super(message, opts); | ||
| this.name = "FetchError"; | ||
| if (opts?.cause && !this.cause) { | ||
| this.cause = opts.cause; | ||
| } | ||
| } | ||
| } | ||
| function createFetchError(ctx) { | ||
| const errorMessage = ctx.error?.message || ctx.error?.toString() || ""; | ||
| const method = ctx.request?.method || ctx.options?.method || "GET"; | ||
| const url = ctx.request?.url || String(ctx.request) || "/"; | ||
| const requestStr = `[${method}] ${JSON.stringify(url)}`; | ||
| const statusStr = ctx.response ? `${ctx.response.status} ${ctx.response.statusText}` : "<no response>"; | ||
| const message = `${requestStr}: ${statusStr}${errorMessage ? ` ${errorMessage}` : ""}`; | ||
| const fetchError = new FetchError( | ||
| message, | ||
| ctx.error ? { cause: ctx.error } : void 0 | ||
| ); | ||
| for (const key of ["request", "options", "response"]) { | ||
| Object.defineProperty(fetchError, key, { | ||
| get() { | ||
| return ctx[key]; | ||
| } | ||
| }); | ||
| } | ||
| for (const [key, refKey] of [ | ||
| ["data", "_data"], | ||
| ["status", "status"], | ||
| ["statusCode", "status"], | ||
| ["statusText", "statusText"], | ||
| ["statusMessage", "statusText"] | ||
| ]) { | ||
| Object.defineProperty(fetchError, key, { | ||
| get() { | ||
| return ctx.response && ctx.response[refKey]; | ||
| } | ||
| }); | ||
| } | ||
| return fetchError; | ||
| } | ||
| const payloadMethods = new Set( | ||
| Object.freeze(["PATCH", "POST", "PUT", "DELETE"]) | ||
| ); | ||
| function isPayloadMethod(method = "GET") { | ||
| return payloadMethods.has(method.toUpperCase()); | ||
| } | ||
| function isJSONSerializable(value) { | ||
| if (value === void 0) { | ||
| return false; | ||
| } | ||
| const t = typeof value; | ||
| if (t === "string" || t === "number" || t === "boolean" || t === null) { | ||
| return true; | ||
| } | ||
| if (t !== "object") { | ||
| return false; | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return true; | ||
| } | ||
| if (value.buffer) { | ||
| return false; | ||
| } | ||
| return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function"; | ||
| } | ||
| const textTypes = /* @__PURE__ */ new Set([ | ||
| "image/svg", | ||
| "application/xml", | ||
| "application/xhtml", | ||
| "application/html" | ||
| ]); | ||
| const JSON_RE = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i; | ||
| function detectResponseType(_contentType = "") { | ||
| if (!_contentType) { | ||
| return "json"; | ||
| } | ||
| const contentType = _contentType.split(";").shift() || ""; | ||
| if (JSON_RE.test(contentType)) { | ||
| return "json"; | ||
| } | ||
| if (textTypes.has(contentType) || contentType.startsWith("text/")) { | ||
| return "text"; | ||
| } | ||
| return "blob"; | ||
| } | ||
| function resolveFetchOptions(request, input, defaults, Headers) { | ||
| const headers = mergeHeaders( | ||
| input?.headers ?? request?.headers, | ||
| defaults?.headers, | ||
| Headers | ||
| ); | ||
| let query; | ||
| if (defaults?.query || defaults?.params || input?.params || input?.query) { | ||
| query = { | ||
| ...defaults?.params, | ||
| ...defaults?.query, | ||
| ...input?.params, | ||
| ...input?.query | ||
| }; | ||
| } | ||
| return { | ||
| ...defaults, | ||
| ...input, | ||
| query, | ||
| params: query, | ||
| headers | ||
| }; | ||
| } | ||
| function mergeHeaders(input, defaults, Headers) { | ||
| if (!defaults) { | ||
| return new Headers(input); | ||
| } | ||
| const headers = new Headers(defaults); | ||
| if (input) { | ||
| for (const [key, value] of Symbol.iterator in input || Array.isArray(input) ? input : new Headers(input)) { | ||
| headers.set(key, value); | ||
| } | ||
| } | ||
| return headers; | ||
| } | ||
| async function callHooks(context, hooks) { | ||
| if (hooks) { | ||
| if (Array.isArray(hooks)) { | ||
| for (const hook of hooks) { | ||
| await hook(context); | ||
| } | ||
| } else { | ||
| await hooks(context); | ||
| } | ||
| } | ||
| } | ||
| const retryStatusCodes = /* @__PURE__ */ new Set([ | ||
| 408, | ||
| // Request Timeout | ||
| 409, | ||
| // Conflict | ||
| 425, | ||
| // Too Early (Experimental) | ||
| 429, | ||
| // Too Many Requests | ||
| 500, | ||
| // Internal Server Error | ||
| 502, | ||
| // Bad Gateway | ||
| 503, | ||
| // Service Unavailable | ||
| 504 | ||
| // Gateway Timeout | ||
| ]); | ||
| const nullBodyResponses = /* @__PURE__ */ new Set([101, 204, 205, 304]); | ||
| function createFetch(globalOptions = {}) { | ||
| const { | ||
| fetch = globalThis.fetch, | ||
| Headers = globalThis.Headers, | ||
| AbortController = globalThis.AbortController | ||
| } = globalOptions; | ||
| async function onError(context) { | ||
| const isAbort = context.error && context.error.name === "AbortError" && !context.options.timeout || false; | ||
| if (context.options.retry !== false && !isAbort) { | ||
| let retries; | ||
| if (typeof context.options.retry === "number") { | ||
| retries = context.options.retry; | ||
| } else { | ||
| retries = isPayloadMethod(context.options.method) ? 0 : 1; | ||
| } | ||
| const responseCode = context.response && context.response.status || 500; | ||
| if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) { | ||
| const retryDelay = typeof context.options.retryDelay === "function" ? context.options.retryDelay(context) : context.options.retryDelay || 0; | ||
| if (retryDelay > 0) { | ||
| await new Promise((resolve) => setTimeout(resolve, retryDelay)); | ||
| } | ||
| return $fetchRaw(context.request, { | ||
| ...context.options, | ||
| retry: retries - 1 | ||
| }); | ||
| } | ||
| } | ||
| const error = createFetchError(context); | ||
| if (Error.captureStackTrace) { | ||
| Error.captureStackTrace(error, $fetchRaw); | ||
| } | ||
| throw error; | ||
| } | ||
| const $fetchRaw = async function $fetchRaw2(_request, _options = {}) { | ||
| const context = { | ||
| request: _request, | ||
| options: resolveFetchOptions( | ||
| _request, | ||
| _options, | ||
| globalOptions.defaults, | ||
| Headers | ||
| ), | ||
| response: void 0, | ||
| error: void 0 | ||
| }; | ||
| if (context.options.method) { | ||
| context.options.method = context.options.method.toUpperCase(); | ||
| } | ||
| if (context.options.onRequest) { | ||
| await callHooks(context, context.options.onRequest); | ||
| } | ||
| if (typeof context.request === "string") { | ||
| if (context.options.baseURL) { | ||
| context.request = ufo.withBase(context.request, context.options.baseURL); | ||
| } | ||
| if (context.options.query) { | ||
| context.request = ufo.withQuery(context.request, context.options.query); | ||
| delete context.options.query; | ||
| } | ||
| if ("query" in context.options) { | ||
| delete context.options.query; | ||
| } | ||
| if ("params" in context.options) { | ||
| delete context.options.params; | ||
| } | ||
| } | ||
| if (context.options.body && isPayloadMethod(context.options.method)) { | ||
| if (isJSONSerializable(context.options.body)) { | ||
| context.options.body = typeof context.options.body === "string" ? context.options.body : JSON.stringify(context.options.body); | ||
| context.options.headers = new Headers(context.options.headers || {}); | ||
| if (!context.options.headers.has("content-type")) { | ||
| context.options.headers.set("content-type", "application/json"); | ||
| } | ||
| if (!context.options.headers.has("accept")) { | ||
| context.options.headers.set("accept", "application/json"); | ||
| } | ||
| } else if ( | ||
| // ReadableStream Body | ||
| "pipeTo" in context.options.body && typeof context.options.body.pipeTo === "function" || // Node.js Stream Body | ||
| typeof context.options.body.pipe === "function" | ||
| ) { | ||
| if (!("duplex" in context.options)) { | ||
| context.options.duplex = "half"; | ||
| } | ||
| } | ||
| } | ||
| let abortTimeout; | ||
| if (!context.options.signal && context.options.timeout) { | ||
| const controller = new AbortController(); | ||
| abortTimeout = setTimeout(() => { | ||
| const error = new Error( | ||
| "[TimeoutError]: The operation was aborted due to timeout" | ||
| ); | ||
| error.name = "TimeoutError"; | ||
| error.code = 23; | ||
| controller.abort(error); | ||
| }, context.options.timeout); | ||
| context.options.signal = controller.signal; | ||
| } | ||
| try { | ||
| context.response = await fetch( | ||
| context.request, | ||
| context.options | ||
| ); | ||
| } catch (error) { | ||
| context.error = error; | ||
| if (context.options.onRequestError) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onRequestError | ||
| ); | ||
| } | ||
| return await onError(context); | ||
| } finally { | ||
| if (abortTimeout) { | ||
| clearTimeout(abortTimeout); | ||
| } | ||
| } | ||
| const hasBody = (context.response.body || // https://github.com/unjs/ofetch/issues/324 | ||
| // https://github.com/unjs/ofetch/issues/294 | ||
| // https://github.com/JakeChampion/fetch/issues/1454 | ||
| context.response._bodyInit) && !nullBodyResponses.has(context.response.status) && context.options.method !== "HEAD"; | ||
| if (hasBody) { | ||
| const responseType = (context.options.parseResponse ? "json" : context.options.responseType) || detectResponseType(context.response.headers.get("content-type") || ""); | ||
| switch (responseType) { | ||
| case "json": { | ||
| const data = await context.response.text(); | ||
| const parseFunction = context.options.parseResponse || destr__default; | ||
| context.response._data = parseFunction(data); | ||
| break; | ||
| } | ||
| case "stream": { | ||
| context.response._data = context.response.body || context.response._bodyInit; | ||
| break; | ||
| } | ||
| default: { | ||
| context.response._data = await context.response[responseType](); | ||
| } | ||
| } | ||
| } | ||
| if (context.options.onResponse) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onResponse | ||
| ); | ||
| } | ||
| if (!context.options.ignoreResponseError && context.response.status >= 400 && context.response.status < 600) { | ||
| if (context.options.onResponseError) { | ||
| await callHooks( | ||
| context, | ||
| context.options.onResponseError | ||
| ); | ||
| } | ||
| return await onError(context); | ||
| } | ||
| return context.response; | ||
| }; | ||
| const $fetch = async function $fetch2(request, options) { | ||
| const r = await $fetchRaw(request, options); | ||
| return r._data; | ||
| }; | ||
| $fetch.raw = $fetchRaw; | ||
| $fetch.native = (...args) => fetch(...args); | ||
| $fetch.create = (defaultOptions = {}, customGlobalOptions = {}) => createFetch({ | ||
| ...globalOptions, | ||
| ...customGlobalOptions, | ||
| defaults: { | ||
| ...globalOptions.defaults, | ||
| ...customGlobalOptions.defaults, | ||
| ...defaultOptions | ||
| } | ||
| }); | ||
| return $fetch; | ||
| } | ||
| exports.FetchError = FetchError; | ||
| exports.createFetch = createFetch; | ||
| exports.createFetchError = createFetchError; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
63736
3.01%959
2.79%468
11.96%Updated
Updated
Updated