UNPKG

fexios

Version:

Fetch based HTTP client with similar API to axios for browser and Node.js

1 lines 41.5 kB
{"version":3,"file":"index.umd.cjs","sources":["../src/errors.ts","../src/utils.ts","../src/response.ts","../src/query-builder.ts","../node_modules/.pnpm/callable-instance@2.0.0/node_modules/callable-instance/index.js","../src/fexios.ts","../src/index.ts"],"sourcesContent":["import type { FexiosContext, IFexiosResponse } from './types'\n\n/**\n * Error codes for Fexios\n */\nexport enum FexiosErrorCodes {\n BODY_USED = 'BODY_USED',\n NO_BODY_READER = 'NO_BODY_READER',\n TIMEOUT = 'TIMEOUT',\n NETWORK_ERROR = 'NETWORK_ERROR',\n BODY_NOT_ALLOWED = 'BODY_NOT_ALLOWED',\n HOOK_CONTEXT_CHANGED = 'HOOK_CONTEXT_CHANGED',\n ABORTED_BY_HOOK = 'ABORTED_BY_HOOK',\n INVALID_HOOK_CALLBACK = 'INVALID_HOOK_CALLBACK',\n UNEXPECTED_HOOK_RETURN = 'UNEXPECTED_HOOK_RETURN',\n}\n\n/**\n * Base Fexios error class\n */\nexport class FexiosError extends Error {\n name = 'FexiosError'\n constructor(\n readonly code: FexiosErrorCodes | string,\n message?: string,\n readonly context?: FexiosContext,\n options?: ErrorOptions\n ) {\n super(message, options)\n }\n}\n\n/**\n * Fexios response error class for HTTP errors\n */\nexport class FexiosResponseError<T> extends FexiosError {\n name = 'FexiosResponseError'\n constructor(\n message: string,\n readonly response: IFexiosResponse<T>,\n options?: ErrorOptions\n ) {\n super(response.statusText, message, undefined, options)\n }\n}\n\n/**\n * Check if the error is a FexiosError that not caused by Response error\n */\nexport const isFexiosError = (e: any): boolean => {\n return !(e instanceof FexiosResponseError) && e instanceof FexiosError\n}\n","/**\n * Utility functions for Fexios\n */\n\n/**\n * Check if the data is likely text content\n */\nexport function checkIfTextData(uint8Array: Uint8Array, maxBytesToCheck = 1024): boolean {\n // 确保输入是一个 Uint8Array\n if (!(uint8Array instanceof Uint8Array)) {\n throw new TypeError('Input must be a Uint8Array')\n }\n\n // 截取前 maxBytesToCheck 字节进行检查\n const dataToCheck = uint8Array.slice(0, maxBytesToCheck)\n\n // 使用 TextDecoder 尝试解码为 UTF-8 字符串\n const decoder = new TextDecoder('utf-8', { fatal: true })\n try {\n const decodedString = decoder.decode(dataToCheck)\n\n // 检查解码后的字符串是否包含大量不可打印字符\n const nonPrintableRegex = /[\\x00-\\x08\\x0E-\\x1F\\x7F]/g // 匹配控制字符\n const nonPrintableMatches = decodedString.match(nonPrintableRegex)\n\n // 如果不可打印字符占比过高,则认为是二进制数据\n const threshold = 0.1 // 允许最多 10% 的不可打印字符\n if (\n nonPrintableMatches &&\n nonPrintableMatches.length / decodedString.length > threshold\n ) {\n return false // 是二进制数据\n }\n\n // 否则认为是文本数据\n return true\n } catch (error) {\n // 如果解码失败(例如包含无效的 UTF-8 序列),认为是二进制数据\n return false\n }\n}\n\n/**\n * Check if given payload is a plain object\n * \"plain object\", means it is not an instance of any class or built-in type,\n * or just like Record<string, any> in TypeScript.\n */\nexport function checkIsPlainObject(payload: any): payload is Record<string, any> {\n // exclude non-object and null values\n if (typeof payload !== 'object' || payload === null) {\n return false\n }\n\n // exclude built-in types like Date, RegExp, etc.\n if (Object.prototype.toString.call(payload) !== '[object Object]') {\n return false\n }\n\n // finally check the prototype chain\n // if the prototype is Object.prototype or null, it's 99% a plain object\n // Note: why proto === null is ok? // Object.create(null)\n const proto = Object.getPrototypeOf(payload)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * Remove all undefined and null properties from an object\n * Also handles empty strings based on options\n */\nexport function dropUndefinedAndNull<T extends Record<string, any>>(\n obj: T,\n options: { dropEmptyString?: boolean } = {}\n): Partial<T> {\n const newObj: Record<string, any> = {}\n Object.entries(obj).forEach(([key, value]) => {\n // Always drop undefined and null\n if (value === undefined || value === null) {\n return\n }\n // Optionally drop empty strings\n if (options.dropEmptyString && value === '') {\n return\n }\n newObj[key] = value\n })\n return newObj as Partial<T>\n}\n","import type { FexiosConfigs, IFexiosResponse as IFexiosResponse } from './types'\nimport { FexiosError, FexiosErrorCodes, FexiosResponseError } from './errors'\nimport { checkIfTextData } from './utils'\n\n/**\n * Fexios response wrapper class\n */\nexport class FexiosResponse<T = any> implements IFexiosResponse<T> {\n public ok: boolean\n public status: number\n public statusText: string\n public headers: Headers\n\n constructor(\n public rawResponse: Response,\n public data: T,\n overrides?: Partial<Omit<FexiosResponse<T>, 'rawResponse' | 'data'>>\n ) {\n this.ok = rawResponse.ok\n this.status = rawResponse.status\n this.statusText = rawResponse.statusText\n this.headers = rawResponse.headers\n Object.entries(overrides || {}).forEach(([key, value]) => {\n ;(this as any)[key] = value\n })\n }\n}\n\n/**\n * Resolve response body based on content type and expected type\n */\nexport async function resolveResponseBody<T = any>(\n rawResponse: Response,\n expectType?: FexiosConfigs['responseType'],\n onProgress?: (progress: number, buffer?: Uint8Array) => void\n): Promise<FexiosResponse<T>> {\n if (rawResponse.bodyUsed) {\n throw new FexiosError(\n FexiosErrorCodes.BODY_USED,\n 'Response body has already been used or locked'\n )\n }\n\n const contentType = rawResponse.headers.get('content-type') || ''\n const contentLength = Number(rawResponse.headers.get('content-length')) || 0\n\n // Helper methods for content type checking\n const isJsonContent = (contentType: string, expectType?: string) =>\n expectType === 'json' || contentType.startsWith('application/json')\n\n const isBinaryContent = (\n contentType: string,\n buffer: Uint8Array,\n expectType?: string\n ) =>\n expectType === 'blob' ||\n contentType.startsWith('image/') ||\n contentType.startsWith('video/') ||\n contentType.startsWith('audio/') ||\n !checkIfTextData(buffer)\n\n // Check if the response is a WebSocket\n if (\n (rawResponse.status === 101 ||\n rawResponse.status === 426 ||\n rawResponse.headers.get('upgrade')) &&\n typeof globalThis.WebSocket !== 'undefined'\n ) {\n const ws = new WebSocket(rawResponse.url)\n await new Promise<any>((resolve, reject) => {\n ws.onopen = resolve\n ws.onerror = reject\n })\n return new FexiosResponse(rawResponse, ws as T, {\n ok: true,\n status: 101,\n statusText: 'Switching Protocols',\n })\n }\n // Check if the response is a EventSource\n // But only if the content-type is not 'text' or 'json'\n else if (\n contentType.startsWith('text/event-stream') &&\n !['text', 'json'].includes(expectType || '') &&\n typeof globalThis.EventSource !== 'undefined'\n ) {\n const es = new EventSource(rawResponse.url)\n await new Promise<any>((resolve, reject) => {\n es.onopen = resolve\n es.onerror = reject\n })\n return new FexiosResponse(rawResponse, es as T)\n }\n // Check if expectType is 'stream'\n else if (expectType === 'stream') {\n return new FexiosResponse(\n rawResponse,\n rawResponse.body as ReadableStream as T\n )\n }\n // Check if the response is a ReadableStream\n else {\n const responseCopy = rawResponse.clone()\n const reader = responseCopy.body?.getReader()\n if (!reader) {\n throw new FexiosError(\n FexiosErrorCodes.NO_BODY_READER,\n 'Failed to get ReadableStream from response body'\n )\n }\n let buffer = new Uint8Array()\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n if (value) {\n buffer = new Uint8Array([...buffer, ...value])\n if (onProgress && contentLength > 0) {\n const progress = Math.min(buffer.length / contentLength, 1)\n onProgress(progress, buffer)\n }\n }\n }\n\n const res = new FexiosResponse(rawResponse, undefined as any)\n\n // Guess the response type, maybe a Blob?\n if (isBinaryContent(contentType, buffer, expectType)) {\n res.data = new Blob([buffer], {\n type: rawResponse.headers.get('content-type') || undefined,\n }) as Blob as T\n }\n // Otherwise, try to decode the buffer as text\n else {\n res.data = new TextDecoder().decode(buffer) as T\n }\n\n // If the data resolved as a string above, try to parse it as JSON\n if (isJsonContent(contentType, expectType)) {\n try {\n res.data = JSON.parse(res.data as string) as T\n } catch (e) {\n console.warn('Failed to parse response data as JSON:', e)\n }\n }\n if (typeof res.data === 'string' && expectType !== 'text') {\n const trimmedData = (res.data as string).trim()\n const firstChar = trimmedData[0]\n const lastChar = trimmedData[trimmedData.length - 1]\n if (\n (firstChar === '{' && lastChar === '}') ||\n (firstChar === '[' && lastChar === ']')\n ) {\n try {\n res.data = JSON.parse(res.data as string) as T\n } catch (_) {\n // NOOP\n }\n }\n }\n\n // Fall back to the buffer if the data is still not resolved\n if (typeof res.data === 'undefined') {\n res.data = buffer.length > 0 ? (buffer as any) : undefined\n }\n\n if (!res.ok) {\n throw new FexiosResponseError(\n `Request failed with status code ${rawResponse.status}`,\n res as any\n )\n } else {\n return res\n }\n }\n}\n","/**\n * Static utility class for building URL search parameters\n *\n * @example\n * { foo: 'bar', baz: ['qux', 'quux'] } // ?foo=bar&baz=qux&baz=quux\n * @example\n * { 'foo[]': 'bar', 'baz[]': ['qux', 'quux'] } // ?foo[]=bar&baz[]=qux&baz[]=quux\n */\nexport class FexiosQueryBuilder {\n /**\n * Build URLSearchParams from a record object with proper array handling\n * @param query - The query object containing key-value pairs\n * @returns URLSearchParams instance\n */\n static makeSearchParams(query: Record<string, any>): URLSearchParams {\n const searchParams = new URLSearchParams()\n\n Object.entries(query).forEach(([key, value]) => {\n if (Array.isArray(value)) {\n // For array values, add multiple entries with the same key\n // This works for both regular keys and keys ending with '[]'\n value.forEach((v) => searchParams.append(key, String(v)))\n } else {\n searchParams.set(key, String(value))\n }\n })\n\n return searchParams\n }\n\n /**\n * Build query string from a record object with proper array handling\n * @param query - The query object containing key-value pairs\n * @returns URL-encoded query string\n */\n static makeQueryString(query: Record<string, any>): string {\n return this.makeSearchParams(query).toString()\n }\n}\n","function CallableInstance(property) {\n var func = this.constructor.prototype[property];\n var apply = function() { return func.apply(apply, arguments); }\n Object.setPrototypeOf(apply, this.constructor.prototype);\n Object.getOwnPropertyNames(func).forEach(function (p) {\n Object.defineProperty(apply, p, Object.getOwnPropertyDescriptor(func, p));\n });\n return apply;\n}\nCallableInstance.prototype = Object.create(Function.prototype);\n\nmodule.exports = CallableInstance;\n","import CallableInstance from 'callable-instance'\nimport type {\n FexiosConfigs,\n FexiosContext,\n FexiosRequestOptions,\n FexiosFinalContext,\n FexiosMethods,\n FexiosHookStore,\n FexiosLifecycleEvents,\n FexiosHook,\n FexiosInterceptor,\n FexiosInterceptors,\n FexiosRequestShortcut,\n} from './types'\nimport { FexiosError, FexiosErrorCodes } from './errors'\nimport { FexiosResponse, resolveResponseBody } from './response'\nimport { FexiosQueryBuilder } from './query-builder'\nimport { checkIsPlainObject, dropUndefinedAndNull } from './utils'\n\n/**\n * Fexios\n * @desc Fetch based HTTP client with similar API to axios for browser and Node.js\n */\nexport class Fexios extends CallableInstance<\n [\n string | URL | Partial<FexiosRequestOptions>,\n Partial<FexiosRequestOptions>?\n ],\n Promise<FexiosFinalContext<any>>\n> {\n protected hooks: FexiosHookStore[] = []\n readonly DEFAULT_CONFIGS: FexiosConfigs = {\n baseURL: '',\n timeout: 60 * 1000,\n credentials: 'same-origin',\n headers: {},\n query: {},\n responseType: undefined,\n }\n private readonly ALL_METHODS: FexiosMethods[] = [\n 'get',\n 'post',\n 'put',\n 'patch',\n 'delete',\n 'head',\n 'options',\n 'trace',\n ]\n private readonly METHODS_WITHOUT_BODY: FexiosMethods[] = [\n 'get',\n 'head',\n 'options',\n 'trace',\n ]\n\n constructor(public baseConfigs: Partial<FexiosConfigs> = {}) {\n super('request')\n this.ALL_METHODS.forEach(this.createMethodShortcut.bind(this))\n }\n\n async request<T = any>(\n url: string | URL,\n options?: Partial<FexiosRequestOptions>\n ): Promise<FexiosFinalContext<T>>\n async request<T = any>(\n options: Partial<FexiosRequestOptions> & { url: string | URL }\n ): Promise<FexiosFinalContext<T>>\n async request<T = any>(\n urlOrOptions:\n | string\n | URL\n | (Partial<FexiosRequestOptions> & { url: string | URL }),\n options?: Partial<FexiosRequestOptions>\n ): Promise<FexiosFinalContext<T>> {\n let ctx: FexiosContext = (options = options || {}) as any\n if (typeof urlOrOptions === 'string' || urlOrOptions instanceof URL) {\n ctx.url = urlOrOptions.toString()\n } else if (typeof urlOrOptions === 'object') {\n ctx = { ...urlOrOptions, ...ctx }\n }\n ctx = await this.emit('beforeInit', ctx)\n\n const baseUrlString =\n options.baseURL || this.baseConfigs.baseURL || globalThis.location?.href\n const baseURL = baseUrlString\n ? new URL(baseUrlString, globalThis.location?.href)\n : undefined\n const reqURL = new URL(ctx.url.toString(), baseURL)\n ctx.url = reqURL.href\n ctx.baseURL = baseURL ? baseURL.href : reqURL.origin\n\n ctx.headers = this.mergeHeaders(\n this.baseConfigs.headers,\n options.headers\n ) as any\n\n // Extract query parameters from different sources\n // Priority: requestOptions > requestURL > defaultOptions > baseURL\n const baseUrlQuery = baseURL?.searchParams\n // Create a copy of requestUrlQuery before clearing the URL search params\n const requestUrlQuery = new URLSearchParams(reqURL.searchParams)\n\n // Clear the URL search params temporarily\n reqURL.search = ''\n ctx.url = reqURL.href\n\n // prettier-ignore\n ctx.query = this.mergeQuery(\n baseUrlQuery, // baseURL query (lowest priority)\n this.baseConfigs.query, // defaultOptions (baseOptions)\n requestUrlQuery, // requestURL query (urlParams)\n options.query // requestOptions (highest priority)\n )\n\n // Build search params with proper array handling\n reqURL.search = FexiosQueryBuilder.makeQueryString(ctx.query)\n ctx.url = reqURL.toString()\n\n if (\n this.METHODS_WITHOUT_BODY.includes(\n ctx.method?.toLocaleLowerCase() as FexiosMethods\n ) &&\n ctx.body\n ) {\n throw new FexiosError(\n FexiosErrorCodes.BODY_NOT_ALLOWED,\n `Request method \"${ctx.method}\" does not allow body`\n )\n }\n\n ctx = await this.emit('beforeRequest', ctx)\n\n let body: string | FormData | URLSearchParams | Blob | undefined\n if (typeof ctx.body !== 'undefined' && ctx.body !== null) {\n // Automatically transform JSON object to JSON string\n if (\n ctx.body instanceof Blob ||\n ctx.body instanceof FormData ||\n ctx.body instanceof URLSearchParams\n ) {\n body = ctx.body\n } else if (typeof ctx.body === 'object' && ctx.body !== null) {\n body = JSON.stringify(ctx.body)\n ;(ctx.headers as any)['content-type'] = 'application/json'\n } else {\n body = ctx.body\n }\n }\n\n // Adjust content-type header\n if (!(options.headers as any)?.['content-type'] && body) {\n if (body instanceof FormData || body instanceof URLSearchParams) {\n // Let the browser automatically set content-type for FormData/URLSearchParams\n delete (ctx.headers as any)['content-type']\n } else if (typeof body === 'string' && typeof ctx.body === 'object') {\n ;(ctx.headers as any)['content-type'] = 'application/json'\n } else if (body instanceof Blob) {\n ;(ctx.headers as any)['content-type'] = body.type\n }\n }\n\n ctx.body = body\n ctx = await this.emit('afterBodyTransformed', ctx)\n\n const abortController =\n ctx.abortController || globalThis.AbortController\n ? new AbortController()\n : undefined\n const rawRequest = new Request(ctx.url, {\n method: ctx.method || 'GET',\n credentials: ctx.credentials,\n cache: ctx.cache,\n mode: ctx.mode,\n headers: ctx.headers,\n body: ctx.body as any,\n signal: abortController?.signal,\n })\n ctx.rawRequest = rawRequest\n\n ctx = await this.emit('beforeActualFetch', ctx)\n\n const timeout = ctx.timeout || this.baseConfigs.timeout || 60 * 1000\n\n if (ctx.url.startsWith('ws')) {\n console.info('WebSocket:', ctx.url)\n try {\n const ws = new WebSocket(ctx.url)\n\n // Wait for connection to establish or fail\n await new Promise<void>((resolve, reject) => {\n const connectionTimeout = setTimeout(() => {\n reject(\n new FexiosError(\n FexiosErrorCodes.TIMEOUT,\n `WebSocket connection timed out after ${timeout}ms`,\n ctx\n )\n )\n }, timeout)\n\n ws.onopen = () => {\n clearTimeout(connectionTimeout)\n resolve()\n }\n ws.onerror = (event) => {\n clearTimeout(connectionTimeout)\n reject(\n new FexiosError(\n FexiosErrorCodes.NETWORK_ERROR,\n `WebSocket connection failed`,\n ctx\n )\n )\n }\n ws.onclose = (event) => {\n // Only reject if the closure wasn't normal and we haven't resolved yet\n if (event.code !== 1000) {\n clearTimeout(connectionTimeout)\n reject(\n new FexiosError(\n FexiosErrorCodes.NETWORK_ERROR,\n `WebSocket closed with code ${event.code}`,\n ctx\n )\n )\n }\n }\n })\n\n ctx.rawResponse = new Response()\n ctx.response = new FexiosResponse(ctx.rawResponse, ws as any, {\n ok: true,\n status: 101,\n statusText: 'Switching Protocols',\n })\n ctx.data = ws\n ctx.headers = new Headers()\n return this.emit('afterResponse', ctx) as any\n } catch (error) {\n if (error instanceof FexiosError) {\n throw error\n }\n throw new FexiosError(\n FexiosErrorCodes.NETWORK_ERROR,\n `WebSocket creation failed: ${error}`,\n ctx\n )\n }\n }\n\n let timer: NodeJS.Timeout | undefined\n\n try {\n if (abortController) {\n timer = setTimeout(() => {\n abortController.abort()\n }, timeout)\n }\n\n const rawResponse = await fetch(ctx.rawRequest!).catch((err) => {\n if (timer) clearTimeout(timer)\n if (abortController?.signal.aborted) {\n throw new FexiosError(\n FexiosErrorCodes.TIMEOUT,\n `Request timed out after ${timeout}ms`,\n ctx\n )\n }\n throw new FexiosError(FexiosErrorCodes.NETWORK_ERROR, err.message, ctx)\n })\n\n if (timer) clearTimeout(timer)\n\n ctx.rawResponse = rawResponse\n ctx.response = await resolveResponseBody(\n rawResponse,\n ctx.responseType,\n (progress, buffer) => {\n console.info('Download progress:', progress)\n options?.onProgress?.(progress, buffer)\n }\n )\n ctx.data = ctx.response.data\n ctx.headers = ctx.response.headers\n\n return this.emit('afterResponse', ctx) as any\n } catch (error) {\n if (timer) clearTimeout(timer)\n throw error\n }\n }\n\n mergeQuery(\n base: Record<string, any> | string | URLSearchParams | undefined,\n ...income: (Record<string, any> | string | URLSearchParams | undefined)[]\n ): Record<string, any> {\n const result: Record<string, any> = {}\n\n const processQuerySource = (source: typeof base) => {\n if (!source) return\n\n if (checkIsPlainObject(source)) {\n Object.entries(source).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n delete result[key]\n } else if (Array.isArray(value)) {\n // Handle array values\n if (key.endsWith('[]')) {\n // For keys ending with '[]', keep multiple entries with the same key\n // Store as array to be processed later when building URLSearchParams\n result[key] = value.map(String)\n } else {\n // For regular keys, create multiple query parameters with the same name\n result[key] = value.map(String)\n }\n } else {\n result[key] = String(value)\n }\n })\n } else {\n const query = new URLSearchParams(source)\n query.forEach((value, key) => {\n result[key] = value\n })\n }\n }\n\n processQuerySource(base)\n income.forEach(processQuerySource)\n\n return result\n }\n\n mergeHeaders(\n base: Record<string, any> | Headers | undefined,\n ...income: (Record<string, any> | Headers | undefined)[]\n ): Record<string, string> {\n const obj: Record<string, string> = {}\n const baseHeaders = new Headers(base)\n for (const item of income) {\n if (item === undefined || item === null) continue\n\n const isPlainInput = checkIsPlainObject(item)\n if (isPlainInput) {\n const processedItem = dropUndefinedAndNull(item)\n // Skip if after processing, the object is empty\n if (Object.keys(processedItem).length === 0) continue\n\n const header = new Headers(processedItem as Record<string, string>)\n header.forEach((value, key) => {\n baseHeaders.set(key, value)\n })\n } else {\n const header = new Headers(item)\n header.forEach((value, key) => {\n baseHeaders.set(key, value)\n })\n }\n }\n baseHeaders.forEach((value, key) => {\n obj[key] = value\n })\n return obj\n }\n\n async emit<C = FexiosContext>(event: FexiosLifecycleEvents, ctx: C) {\n const hooks = this.hooks.filter((hook) => hook.event === event)\n try {\n let index = 0\n for (const hook of hooks) {\n const hookName = `${event}#${hook.action.name || `anonymous#${index}`}`\n\n // Set a symbol to check if the hook overrides the original context\n const symbol = Symbol('FexiosHookContext')\n ;(ctx as any)[symbol] = symbol\n\n const newCtx = (await hook.action.call(this, ctx)) as Awaited<C | false>\n\n // Excepted abort signal\n if (newCtx === false) {\n throw new FexiosError(\n FexiosErrorCodes.ABORTED_BY_HOOK,\n `Request aborted by hook \"${hookName}\"`,\n ctx as FexiosContext\n )\n }\n // Good\n else if (\n typeof newCtx === 'object' &&\n (newCtx as any)[symbol] === symbol\n ) {\n ctx = newCtx as C\n }\n // Unexpected return value\n else {\n // @ts-ignore prevent esbuild optimize\n const console = globalThis[''.concat('console')]\n try {\n throw new FexiosError(\n FexiosErrorCodes.HOOK_CONTEXT_CHANGED,\n `Hook \"${hookName}\" should return the original FexiosContext or return false to abort the request, but got \"${newCtx}\".`\n )\n } catch (e: any) {\n console.warn(e.stack || e)\n }\n }\n\n // Clean up\n delete (ctx as any)[symbol]\n\n index++\n }\n } catch (e) {\n return Promise.reject(e)\n }\n return ctx\n }\n\n on<C = FexiosContext>(\n event: FexiosLifecycleEvents,\n action: FexiosHook<C>,\n prepend = false\n ) {\n if (typeof action !== 'function') {\n throw new FexiosError(\n FexiosErrorCodes.INVALID_HOOK_CALLBACK,\n `Hook should be a function, but got \"${typeof action}\"`\n )\n }\n this.hooks[prepend ? 'unshift' : 'push']({\n event,\n action: action as FexiosHook,\n })\n return this\n }\n\n off(event: FexiosLifecycleEvents | '*' | null, action: FexiosHook<any>) {\n if (event === '*' || !event) {\n this.hooks = this.hooks.filter((hook) => hook.action !== action)\n } else {\n this.hooks = this.hooks.filter(\n (hook) => hook.event !== event || hook.action !== action\n )\n }\n return this\n }\n\n private createInterceptor<T extends FexiosLifecycleEvents>(\n event: T\n ): FexiosInterceptor {\n return {\n handlers: () =>\n this.hooks\n .filter((hook) => hook.event === event)\n .map((hook) => hook.action),\n use: <C = FexiosContext>(hook: FexiosHook<C>, prepend = false) => {\n return this.on(event, hook, prepend)\n },\n clear: () => {\n this.hooks = this.hooks.filter((hook) => hook.event !== event)\n },\n }\n }\n\n readonly interceptors: FexiosInterceptors = {\n request: this.createInterceptor('beforeRequest'),\n response: this.createInterceptor('afterResponse'),\n }\n\n private createMethodShortcut(method: FexiosMethods) {\n Object.defineProperty(this, method, {\n value: (\n url: string | URL,\n bodyOrQuery?: Record<string, any> | string | URLSearchParams,\n options?: Partial<FexiosRequestOptions>\n ) => {\n if (\n this.METHODS_WITHOUT_BODY.includes(\n method.toLocaleLowerCase() as FexiosMethods\n )\n ) {\n options = bodyOrQuery as any\n } else {\n options = options || {}\n options.body = bodyOrQuery\n }\n return this.request(url, {\n ...options,\n method: method as FexiosMethods,\n })\n },\n })\n return this\n }\n\n extends(configs: Partial<FexiosConfigs>) {\n const fexios = new Fexios({ ...this.baseConfigs, ...configs })\n fexios.hooks = [...this.hooks]\n return fexios\n }\n\n readonly create = Fexios.create\n static create(configs?: Partial<FexiosConfigs>) {\n return new Fexios(configs)\n }\n\n /**\n * Remove all undefined and null properties from an object\n * Also handles empty strings based on options\n * @deprecated Use dropUndefinedAndNull from utils instead\n */\n readonly dropUndefinedAndNull = dropUndefinedAndNull\n\n /**\n * Check if given payload is a plain object\n * @deprecated Use checkIsPlainObject from utils instead\n */\n readonly checkIsPlainObject = checkIsPlainObject\n}\n\n// declare method shortcuts\nexport interface Fexios {\n get: FexiosRequestShortcut<'get'>\n post: FexiosRequestShortcut<'post'>\n put: FexiosRequestShortcut<'put'>\n patch: FexiosRequestShortcut<'patch'>\n delete: FexiosRequestShortcut<'delete'>\n head: FexiosRequestShortcut<'head'>\n options: FexiosRequestShortcut<'options'>\n trace: FexiosRequestShortcut<'trace'>\n}\n","/**\n * Fexios\n * @desc Fetch based HTTP client with similar API to axios for browser and Node.js\n *\n * @license MIT\n * @author dragon-fish <dragon-fish@qq.com>\n */\n\n// Export all types\nexport * from './types'\n\n// Export errors\nexport * from './errors'\n\n// Export response utilities\nexport * from './response'\n\n// Export query builder\nexport * from './query-builder'\n\n// Export utilities\nexport * from './utils'\n\n// Export main Fexios class\nexport * from './fexios'\n\n// Support for direct import\nimport { Fexios } from './fexios'\nexport const createFexios = Fexios.create\nexport const fexios = createFexios()\nexport default fexios\n\n// Set global fexios instance for browser\ndeclare global {\n interface Window {\n fexios: Fexios\n }\n}\nif (typeof globalThis !== 'undefined') {\n ;(globalThis as any).fexios = fexios\n} else if (typeof window !== 'undefined') {\n window.fexios = fexios\n}\n"],"names":["FexiosErrorCodes","FexiosError","code","message","context","options","FexiosResponseError","response","isFexiosError","e","checkIfTextData","uint8Array","maxBytesToCheck","dataToCheck","decoder","decodedString","nonPrintableRegex","nonPrintableMatches","checkIsPlainObject","payload","proto","dropUndefinedAndNull","obj","newObj","key","value","FexiosResponse","rawResponse","data","overrides","resolveResponseBody","expectType","onProgress","contentType","contentLength","isJsonContent","isBinaryContent","buffer","ws","resolve","reject","es","reader","_a","done","progress","res","trimmedData","firstChar","lastChar","FexiosQueryBuilder","query","searchParams","v","CallableInstance","property","func","apply","p","callableInstance","Fexios","baseConfigs","urlOrOptions","ctx","baseUrlString","baseURL","_b","reqURL","baseUrlQuery","requestUrlQuery","_c","body","_d","abortController","rawRequest","timeout","connectionTimeout","event","error","timer","err","base","income","result","processQuerySource","source","baseHeaders","item","processedItem","hooks","hook","index","hookName","symbol","newCtx","console","action","prepend","method","url","bodyOrQuery","configs","fexios","createFexios"],"mappings":"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","x_google_ignoreList":[4]}