UNPKG

hapic

Version:

A http api client based on axios.

1 lines 78.5 kB
{"version":3,"file":"index.cjs","sources":["../../../node_modules/node-fetch-native/dist/proxy-stub.mjs","../src/fetch.ts","../src/constants.ts","../src/hook/constants.ts","../src/utils/has-own-property.ts","../src/utils/type-check.ts","../src/utils/instance.ts","../src/utils/serialize.ts","../src/utils/promise.ts","../src/utils/traverse.ts","../src/header/authorization/constants.ts","../src/error/constants.ts","../src/error/entities/authorization-header.ts","../src/error/module.ts","../src/error/helpers/check.ts","../src/error/helpers/create.ts","../src/error/helpers/extend.ts","../src/header/authorization/utils.ts","../src/header/constants.ts","../src/header/utils.ts","../src/request/transformer/default.ts","../src/request/defaults.ts","../src/request/payload.ts","../src/request/utils.ts","../src/response/utils/check.ts","../src/response/utils/type-detect.ts","../src/hook/module.ts","../src/module.ts","../src/instance.ts","../src/index.ts"],"sourcesContent":["var o=Object.defineProperty;var e=(t,r)=>o(t,\"name\",{value:r,configurable:!0});var f=Object.defineProperty,c=e((t,r)=>f(t,\"name\",{value:r,configurable:!0}),\"e\");function n(){return{agent:void 0,dispatcher:void 0}}e(n,\"createProxy\"),c(n,\"createProxy\");function a(){return globalThis.fetch}e(a,\"createFetch\"),c(a,\"createFetch\");const i=globalThis.fetch;export{a as createFetch,n as createProxy,i as fetch};\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport nodeFetch, {\n AbortController as _AbortController,\n Blob as _Blob,\n File as _File,\n FormData as _FormData,\n Headers as _Headers,\n} from 'node-fetch-native';\nimport type { ProxyOptions as ProxyOptionsBase } from 'node-fetch-native/proxy';\nimport { createProxy as createProxyBase } from 'node-fetch-native/proxy';\n\nconst gT = (() => {\n if (typeof globalThis !== 'undefined') {\n return globalThis;\n }\n\n // eslint-disable-next-line no-restricted-globals\n if (typeof self !== 'undefined') {\n // eslint-disable-next-line no-restricted-globals\n return self;\n }\n\n if (typeof window !== 'undefined') {\n return window;\n }\n\n if (typeof global !== 'undefined') {\n return global;\n }\n\n throw new Error('unable to locate global object');\n})();\n\nexport const File = gT.File ||\n _File;\n\nexport const FormData = gT.FormData ||\n _FormData;\n\nexport const AbortController = gT.AbortController ||\n _AbortController;\n\nexport const fetch = gT.fetch || nodeFetch;\nexport const Headers = gT.Headers || _Headers;\nexport const Blob = gT.Blob || _Blob;\n\nexport type ProxyOptions = ProxyOptionsBase;\n\nexport function createProxy(options?: ProxyOptions) {\n return createProxyBase(options);\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum ResponseType {\n BLOB = 'blob',\n STREAM = 'stream',\n TEXT = 'text',\n ARRAY_BUFFER = 'arrayBuffer',\n JSON = 'json',\n}\n\nexport enum MethodName {\n DELETE = 'DELETE',\n GET = 'GET',\n HEAD = 'HEAD',\n PATCH = 'PATCH',\n POST = 'POST',\n PUT = 'PUT',\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum HookName {\n REQUEST = 'request',\n REQUEST_ERROR = 'requestError',\n\n RESPONSE = 'response',\n RESPONSE_ERROR = 'responseError',\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport function hasOwnProperty<X extends {}, Y extends PropertyKey>(\n obj: X,\n prop: Y,\n): obj is X & Record<Y, unknown> {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { Blob, File, FormData } from '../fetch';\n\nfunction kindOf(input: unknown) {\n return Object.prototype.toString.call(input)\n .slice(8, -1).toLowerCase();\n}\n\nfunction kindOfTest(type: string, input: unknown) {\n type = type.toLowerCase();\n\n return kindOf(input) === type;\n}\n\nexport function isObject(input: unknown): input is Record<string, any> {\n return typeof input === 'object' &&\n input !== null &&\n !!input &&\n !Array.isArray(input);\n}\n\nexport function isStream(input: unknown) : boolean {\n return isObject(input) &&\n typeof input.pipe === 'function';\n}\n\nexport function isFormData(input: unknown) : input is FormData {\n if (\n typeof FormData !== 'undefined' &&\n input instanceof FormData\n ) {\n return true;\n }\n\n const pattern = '[object FormData]';\n if (Object.prototype.toString.call(input) === pattern) {\n return true;\n }\n\n return !!input && typeof input.toString === 'function' && input.toString() === pattern;\n}\n\nexport function isArrayBuffer(input: unknown) : input is ArrayBuffer {\n if (\n typeof ArrayBuffer !== 'undefined' &&\n input instanceof ArrayBuffer\n ) {\n return true;\n }\n\n return kindOfTest('ArrayBuffer', input);\n}\n\nexport function isFile(input: unknown) : input is File {\n if (\n typeof File !== 'undefined' &&\n input instanceof File\n ) {\n return true;\n }\n\n return kindOfTest('File', input);\n}\n\nexport function isBlob(input: unknown) : input is Blob {\n if (\n typeof Blob !== 'undefined' &&\n input instanceof Blob\n ) {\n return true;\n }\n\n return kindOfTest('Blob', input);\n}\n\nexport function isURLSearchParams(input: unknown) {\n if (\n typeof URLSearchParams !== 'undefined' &&\n input instanceof URLSearchParams\n ) {\n return true;\n }\n\n return kindOfTest('URLSearchParams', input);\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from './type-check';\n\nexport function verifyInstanceBySymbol(\n input: unknown,\n name: string,\n) {\n if (!isObject(input) && typeof input !== 'function') {\n return false;\n }\n\n return (input as { '@instanceof': symbol })['@instanceof'] ===\n Symbol.for(name);\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from './type-check';\n\nexport function isSerializable(input: unknown) {\n if (input === undefined) {\n return false;\n }\n\n const t = typeof input;\n if (t === 'string' || t === 'number' || t === 'boolean' || t === null || t === 'bigint') {\n return true;\n }\n\n if (t !== 'object') {\n return false; // function, symbol, undefined\n }\n\n if (Array.isArray(input)) {\n return true;\n }\n\n return (\n isObject(input) ||\n (typeof input === 'function' && (input as Record<string, any>).toJSON === 'function')\n );\n}\n\nexport function serialize(input: unknown) {\n return JSON.stringify(\n input,\n (_key, value) => (\n typeof value === 'bigint' ?\n value.toString() :\n value),\n );\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function isPromise(p: unknown) : p is Promise<unknown> {\n return typeof p === 'object' &&\n p !== null &&\n (\n (typeof Promise !== 'undefined' && p instanceof Promise) ||\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n typeof p.then === 'function'\n );\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from './type-check';\n\n/**\n * Traverse object or array and provide the ability to replace values.\n *\n * @param input\n * @param fn\n */\nexport function traverse<T extends Record<string, any> | unknown[]>(\n input: T,\n fn: (value: unknown, key: string) => unknown,\n) {\n if (Array.isArray(input)) {\n for (let i = 0; i < input.length; i++) {\n if (isObject(input[i]) || Array.isArray(input[i])) {\n input[i] = fn(traverse(input[i], fn), `${i}`);\n continue;\n }\n\n input[i] = fn(input[i], `${i}`);\n }\n\n return input;\n }\n\n const keys = Object.keys(input);\n for (let i = 0; i < keys.length; i++) {\n const value = input[keys[i]];\n\n if (isObject(value) || Array.isArray(value)) {\n input[keys[i]] = fn(traverse(value, fn), keys[i]);\n continue;\n }\n\n input[keys[i]] = fn(value, keys[i]);\n }\n\n return input;\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum AuthorizationHeaderType {\n BEARER = 'Bearer',\n BASIC = 'Basic',\n X_API_KEY = 'X-API-Key',\n API_KEY = 'API-Key',\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum ErrorCode {\n AUTHORIZATION_HEADER_INVALID = 'auth_header_invalid',\n AUTHORIZATION_HEADER_PARSE = 'auth_header_parse',\n AUTHORIZATION_HEADER_TYPE_PARSE = 'auth_header_type_parse',\n\n CONNECTION_ABORTED = 'ECONNABORTED',\n CONNECTION_CLOSED = 'ECONNRESET',\n}\n","/*\n * Copyright (c) 2021-2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { Options } from 'ebec';\nimport { BaseError } from 'ebec';\nimport { ErrorCode } from '../constants';\n\nexport class AuthorizationHeaderError extends BaseError {\n constructor(options?: Options) {\n super({\n code: ErrorCode.AUTHORIZATION_HEADER_INVALID,\n message: 'The authorization header is not valid.',\n }, options || {});\n }\n\n /* istanbul ignore next */\n static parse() {\n throw new AuthorizationHeaderError({\n code: ErrorCode.AUTHORIZATION_HEADER_PARSE,\n message: 'The authorization header value could not be parsed.',\n });\n }\n\n /* istanbul ignore next */\n static parseType() {\n throw new AuthorizationHeaderError({\n code: ErrorCode.AUTHORIZATION_HEADER_TYPE_PARSE,\n message: 'The authorization header value type must either be \\'Bearer\\' or \\'Basic\\'',\n });\n }\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BaseError } from 'ebec';\nimport type { RequestOptions } from '../request';\nimport type { Response } from '../response';\nimport type { ClientErrorContext } from './type';\n\nexport class ClientError<T = any> extends BaseError {\n readonly '@instanceof' = Symbol.for('ClientError');\n\n readonly request: RequestOptions;\n\n readonly response?: Response<T>;\n\n readonly status?: number;\n\n readonly statusCode?: number;\n\n readonly statusMessage?: string;\n\n readonly statusText?: string;\n\n constructor(ctx: ClientErrorContext<T>) {\n super({ cause: ctx.error });\n\n this.request = ctx.request;\n this.response = ctx.response;\n\n this.code = ctx.code;\n this.status = ctx.response && ctx.response.status;\n this.statusCode = ctx.response && ctx.response.status;\n this.statusMessage = ctx.response && ctx.response.statusText;\n this.statusText = ctx.response && ctx.response.statusText;\n\n this.message = ctx.message;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ClientError);\n }\n }\n}\n","/*\n * Copyright (c) 2023-2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject, verifyInstanceBySymbol } from '../../utils';\nimport { ErrorCode } from '../constants';\nimport { ClientError } from '../module';\n\nexport function isClientError(\n error?: unknown,\n): error is ClientError {\n if (error instanceof ClientError) {\n return true;\n }\n\n return isObject(error) &&\n verifyInstanceBySymbol(error, 'ClientError');\n}\n\nexport function isClientErrorWithStatusCode(\n error: unknown,\n statusCode: number | number[],\n): boolean {\n if (!isClientError(error) || !isObject(error.response)) {\n return false;\n }\n\n const statusCodes = Array.isArray(statusCode) ?\n statusCode :\n [statusCode];\n\n for (let i = 0; i < statusCodes.length; i++) {\n if (statusCodes[i] === error.response.status) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function isClientErrorDueNetworkIssue(\n error?: unknown,\n) {\n return isClientError(error) &&\n !error.response &&\n Boolean(error.code) &&\n error.code !== ErrorCode.CONNECTION_ABORTED;\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { RequestOptions } from '../../request';\nimport { ErrorCode } from '../constants';\nimport { ClientError } from '../module';\nimport type { ClientErrorCreateContext } from '../type';\n\nfunction formatRequestOptions(input: RequestOptions): string {\n if (input.url) {\n const parts: string[] = [];\n if (input.method) {\n parts.push(input.method);\n }\n\n parts.push(input.url);\n\n return parts.join(' ');\n }\n\n return input.toString();\n}\n\nexport function createClientError<T = any>(\n context: ClientErrorCreateContext<T>,\n) {\n let message: string | undefined;\n\n if (context.request && context.response) {\n message = `${context.response.status} ${\n context.response.statusText\n } (${formatRequestOptions(context.request)})`;\n } else if (context.request) {\n message = `${formatRequestOptions(context.request)}`;\n }\n\n if (context.error) {\n if (context.error.message) {\n message = `${context.error.message} (${message})`;\n }\n }\n\n if (!message) {\n message = 'An unknown error occurred.';\n }\n\n const isAbort = (!!context.error && context.error.name === 'AbortError');\n\n let code: ErrorCode | undefined;\n if (!context.response) {\n if (isAbort) {\n code = ErrorCode.CONNECTION_ABORTED;\n } else {\n code = ErrorCode.CONNECTION_CLOSED;\n }\n }\n\n const error = new ClientError<T>({\n ...context,\n code,\n message,\n });\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(error, createClientError);\n }\n\n return error;\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from '../../utils';\n\nexport function toError(input: unknown): Error | undefined {\n if (input instanceof Error) {\n return input;\n }\n\n if (isObject(input)) {\n if (input.constructor.name === 'TypeError') {\n Object.setPrototypeOf(input, TypeError.prototype);\n return input as TypeError;\n }\n\n const error = new Error(input.message);\n extendError(error, input);\n\n return input as Error;\n }\n\n return undefined;\n}\n\nexport function extendError(error: Error, data: Record<string, any>) {\n const keys = Object.getOwnPropertyNames(data);\n for (let i = 0; i < keys.length; i++) {\n error[keys[i] as keyof Error] = data[keys[i]];\n }\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { AuthorizationHeader } from './type';\nimport { AuthorizationHeaderType } from './constants';\nimport { AuthorizationHeaderError } from '../../error';\n\nexport function parseAuthorizationHeader(value?: string): AuthorizationHeader {\n /* istanbul ignore next */\n if (typeof value !== 'string') {\n throw AuthorizationHeaderError.parse();\n }\n\n const parts: string[] = value.split(' ');\n\n if (parts.length < 2) {\n throw AuthorizationHeaderError.parseType();\n }\n\n const type: string = parts[0].toLowerCase();\n const id: string = parts[1];\n\n switch (type) {\n case 'basic': {\n const base64Decoded = Buffer.from(id, 'base64').toString('utf-8');\n const base64Parts = base64Decoded.split(':');\n\n if (base64Parts.length !== 2) {\n throw AuthorizationHeaderError.parse();\n }\n\n return {\n type: AuthorizationHeaderType.BASIC,\n username: base64Parts[0],\n password: base64Parts[1],\n };\n }\n case 'bearer':\n return {\n type: AuthorizationHeaderType.BEARER,\n token: id,\n };\n case 'api-key':\n case 'x-api-key':\n return {\n type: type === 'api-key' ?\n AuthorizationHeaderType.API_KEY :\n AuthorizationHeaderType.X_API_KEY,\n key: id,\n };\n default:\n throw AuthorizationHeaderError.parseType();\n }\n}\n\nexport function stringifyAuthorizationHeader(header: AuthorizationHeader): string {\n switch (header.type) {\n case AuthorizationHeaderType.BASIC: {\n const basicStr: string = Buffer\n .from(`${header.username}:${header.password}`)\n .toString('base64');\n\n return `Basic ${basicStr}`;\n }\n case AuthorizationHeaderType.BEARER:\n return `Bearer ${header.token}`;\n case AuthorizationHeaderType.X_API_KEY:\n case AuthorizationHeaderType.API_KEY:\n return `${header.type} ${header.key}`;\n }\n\n return '';\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum HeaderName {\n ACCEPT = 'accept',\n AUTHORIZATION = 'authorization',\n CONTENT_TYPE = 'content-type',\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { Headers } from '../fetch';\n\nexport function setHeader(\n headers: globalThis.HeadersInit | Headers,\n key: string,\n value: any,\n) {\n key = key.toLowerCase();\n\n if (\n typeof Headers !== 'undefined' &&\n headers instanceof Headers\n ) {\n headers.set(key, value);\n\n return;\n }\n\n if (Array.isArray(headers)) {\n const index = headers.findIndex((el) => el.length === 2 && el[0].toLowerCase() === key);\n if (index !== -1) {\n headers[index] = [key, value];\n } else {\n headers.push([key, value]);\n }\n return;\n }\n\n const keys = Object.keys(headers);\n const index = keys.findIndex((el) => el.toLowerCase() === key);\n if (index !== -1) {\n (headers as Record<string, any>)[keys[index]] = value;\n } else {\n (headers as Record<string, any>)[key] = value;\n }\n}\n\nexport function getHeader(\n headers: globalThis.HeadersInit | Headers,\n key: string,\n) : undefined | any {\n key = key.toLowerCase();\n\n if (\n typeof Headers !== 'undefined' &&\n headers instanceof Headers\n ) {\n const value = headers.get(key);\n return value === null ? undefined : value;\n }\n\n if (Array.isArray(headers)) {\n const index = headers.findIndex((el) => el.length === 2 && el[0].toLowerCase() === key);\n if (index !== -1) {\n return headers[index][1];\n }\n\n return undefined;\n }\n\n const keys = Object.keys(headers);\n const index = keys.findIndex((el) => el.toLowerCase() === key);\n if (index !== -1) {\n return (headers as Record<string, any>)[keys[index]];\n }\n\n return undefined;\n}\n\nexport function unsetHeader(\n headers: globalThis.HeadersInit | Headers,\n key: string,\n) {\n key = key.toLowerCase();\n\n if (\n typeof Headers !== 'undefined' &&\n headers instanceof Headers\n ) {\n headers.delete(key);\n return;\n }\n\n if (Array.isArray(headers)) {\n const index = headers.findIndex((el) => el.length === 2 && el[0].toLowerCase() === key.toLowerCase());\n if (index !== -1) {\n headers.splice(index, 1);\n }\n\n return;\n }\n\n const keys = Object.keys(headers);\n const index = keys.findIndex((el) => el.toLowerCase() === key);\n if (index !== -1) {\n delete (headers as Record<string, any>)[keys[index]];\n }\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { HeaderName } from '../../header';\nimport {\n isArrayBuffer,\n isBlob,\n isFile,\n isFormData,\n isSerializable,\n isStream,\n isURLSearchParams, serialize,\n} from '../../utils';\nimport type { RequestTransformer } from '../type';\n\nexport function createDefaultRequestTransformer() : RequestTransformer {\n return (data, headers) => {\n if (isFormData(data)) {\n headers.delete(HeaderName.CONTENT_TYPE);\n }\n\n if (\n isArrayBuffer(data) ||\n isFile(data) ||\n isBlob(data) ||\n isFormData(data) ||\n isStream(data)\n ) {\n return data;\n }\n\n if (isURLSearchParams(data)) {\n headers.set(HeaderName.CONTENT_TYPE, 'application/x-www-form-urlencoded;charset=utf-8');\n return data;\n }\n\n const contentType = headers.get(HeaderName.CONTENT_TYPE) || '';\n const contentTypeIsJson = contentType.indexOf('application/json') !== -1;\n\n if (isSerializable(data) || contentTypeIsJson) {\n data = typeof data === 'string' ?\n data :\n serialize(data);\n\n if (!headers.has(HeaderName.CONTENT_TYPE)) {\n headers.set(HeaderName.CONTENT_TYPE, 'application/json');\n }\n\n if (!headers.has(HeaderName.ACCEPT)) {\n headers.set(HeaderName.ACCEPT, 'application/json');\n }\n }\n\n return data;\n };\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createDefaultRequestTransformer } from './transformer';\nimport type { RequestBaseOptions } from './type';\n\nexport function extendRequestOptionsWithDefaults(options: RequestBaseOptions) : RequestBaseOptions {\n if (!options.transform) {\n options.transform = [\n createDefaultRequestTransformer(),\n ];\n }\n\n if (typeof options.proxy === 'undefined') {\n options.proxy = true;\n }\n\n return options;\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { MethodName } from '../constants';\n\nexport function isRequestPayloadSupported(method = 'GET') {\n method = method.toUpperCase();\n\n return method === MethodName.PATCH ||\n method === MethodName.POST ||\n method === MethodName.PUT;\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from '../utils';\nimport type { RequestOptions } from './type';\n\nexport function isRequestOptions(input: unknown) : input is RequestOptions {\n if (!isObject(input)) {\n return false;\n }\n\n return input.url === 'string';\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from '../../utils';\nimport type { Response } from '../type';\n\nexport function isResponse(input: unknown) : input is Response {\n if (!isObject(input)) {\n return false;\n }\n\n return typeof (input as Response).headers !== 'undefined' &&\n typeof (input as Response).ok === 'boolean';\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { ResponseType } from '../../constants';\n\nconst JSON_REGEX = /^application\\/(?:[\\w!#$%&*.^`~-]*\\+)?json(;.+)?$/i;\n\nexport function detectResponseType(input?: string | null) : ResponseType {\n if (typeof input !== 'string' || input.length === 0) {\n return ResponseType.STREAM;\n }\n\n const contentType = input.split(';').shift() || '';\n\n if (JSON_REGEX.test(contentType)) {\n return ResponseType.JSON;\n }\n\n const textTypes = [\n 'image/svg',\n 'application/xml',\n 'application/xhtml',\n 'application/html',\n ];\n\n if (textTypes.indexOf(contentType) !== -1 || contentType.startsWith('text/')) {\n return ResponseType.TEXT;\n }\n\n return ResponseType.JSON;\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\nimport type { ClientError } from '../error';\nimport { isPromise } from '../utils';\nimport { isRequestOptions } from '../request';\nimport type { RequestOptions } from '../request';\nimport { isResponse } from '../response';\nimport type { Response } from '../response';\nimport { HookName } from './constants';\nimport type {\n HookErrorFn,\n HookFn,\n HookReqFn,\n} from './type';\n\nexport class HookManager {\n protected items : Record<string, (undefined | HookFn)[]>;\n\n constructor() {\n this.items = {};\n }\n\n addListener(name: `${HookName}`, fn: HookFn) : number {\n this.items[name] = this.items[name] || [];\n this.items[name].push(fn);\n\n return this.items[name].length - 1;\n }\n\n removeListener(name: `${HookName}`, fn: HookFn | number) {\n if (!this.items[name]) {\n return;\n }\n\n if (typeof fn === 'number') {\n this.items[name][fn] = undefined;\n return;\n }\n\n const index = this.items[name].indexOf(fn);\n if (index !== -1) {\n this.items[name][index] = undefined;\n }\n }\n\n removeListeners(name: `${HookName}`) {\n delete this.items[name];\n }\n\n async triggerReqHook(\n input: RequestOptions,\n ) : Promise<RequestOptions> {\n const items = (this.items[HookName.REQUEST] || []) as HookReqFn[];\n\n let temp = input;\n for (let i = 0; i < items.length; i++) {\n const hook = items[i];\n if (!hook) {\n continue;\n }\n\n let output = hook(temp as any);\n if (isPromise(output)) {\n output = await output;\n }\n\n if (isRequestOptions(output)) {\n temp = output;\n }\n }\n\n return temp;\n }\n\n async triggerResHook(\n input: Response,\n ) : Promise<Response> {\n const items = (this.items[HookName.RESPONSE] || []) as HookReqFn[];\n\n let temp = input;\n for (let i = 0; i < items.length; i++) {\n const hook = items[i];\n if (!hook) {\n continue;\n }\n\n let output = hook(temp as any);\n if (isPromise(output)) {\n output = await output;\n }\n\n if (isResponse(output)) {\n temp = output;\n }\n }\n\n return temp;\n }\n\n async triggerErrorHook(\n name: `${HookName.RESPONSE_ERROR}` | `${HookName.REQUEST_ERROR}`,\n input: ClientError,\n ) : Promise<RequestOptions | Response> {\n const items = (this.items[name] || []) as HookErrorFn[];\n\n let temp = input;\n\n for (let i = 0; i < items.length; i++) {\n const hook = items[i];\n if (!hook) {\n continue;\n }\n\n try {\n let output = hook(temp);\n if (isPromise(output)) {\n output = await output;\n }\n\n if (\n isResponse(output) ||\n isRequestOptions(output)\n ) {\n return output;\n }\n } catch (e) {\n temp = e as ClientError;\n }\n }\n\n throw temp;\n }\n}\n","/*\n * Copyright (c) 2021-2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ProxyOptions } from 'node-fetch-native/proxy';\nimport { withBase, withQuery } from 'ufo';\nimport type { ClientErrorCreateContext } from './error/type';\nimport { Headers, createProxy, fetch } from './fetch';\n\nimport { MethodName, ResponseType } from './constants';\nimport type {\n HookErrorFn,\n HookFn,\n HookReqFn,\n HookResFn,\n} from './hook';\nimport type {\n RequestBaseOptions,\n RequestOptions,\n} from './request';\nimport type {\n Response,\n ResponseData,\n} from './response';\nimport {\n HookManager,\n HookName,\n} from './hook';\nimport {\n detectResponseType,\n isResponse,\n} from './response';\nimport {\n extendRequestOptionsWithDefaults,\n isRequestPayloadSupported,\n} from './request';\nimport { createClientError, toError } from './error';\nimport type { AuthorizationHeader } from './header';\nimport { HeaderName, stringifyAuthorizationHeader } from './header';\nimport { traverse } from './utils';\n\nexport class Client {\n readonly '@instanceof' = Symbol.for('BaseClient');\n\n public defaults : RequestBaseOptions;\n\n protected headers : Headers;\n\n protected hookManager : HookManager;\n\n // ---------------------------------------------------------------------------------\n\n constructor(input: RequestBaseOptions = {}) {\n this.defaults = extendRequestOptionsWithDefaults(input || {});\n this.headers = new Headers(this.defaults.headers);\n\n this.hookManager = new HookManager();\n }\n\n // ---------------------------------------------------------------------------------\n\n /**\n * Return base url\n *\n * @return string\n */\n public getBaseURL(): string | undefined {\n return this.defaults.baseURL;\n }\n\n /**\n * Overwrite existing base url.\n *\n * @param url\n */\n public setBaseURL(url: string) {\n this.defaults.baseURL = url;\n\n return this;\n }\n\n // ---------------------------------------------------------------------------------\n\n /**\n * Set a header for all upcoming requests.\n *\n * @param key\n * @param value\n */\n public setHeader(key: string, value: any) {\n this.headers.set(key, value);\n\n return this;\n }\n\n /**\n * Get a header for all upcoming requests.\n *\n * @param key\n */\n public getHeader(key: string) {\n return this.headers.get(key);\n }\n\n /**\n * Unset a specific for all upcoming requests.\n *\n * @param key\n */\n public unsetHeader(key: string) {\n if (this.headers.has(key)) {\n this.headers.delete(key);\n }\n\n return this;\n }\n\n /**\n * Unset all defined headers for the upcoming requests.\n */\n public unsetHeaders() {\n this.headers.forEach((_value, key) => {\n this.headers.delete(key);\n });\n\n return this;\n }\n\n // ---------------------------------------------------------------------------------\n\n /**\n * Set an authorization header (basic, api-key, bearer).\n *\n * @param options\n */\n public setAuthorizationHeader(options: AuthorizationHeader) {\n this.setHeader(HeaderName.AUTHORIZATION, stringifyAuthorizationHeader(options));\n\n return this;\n }\n\n /**\n * Get authorization header.\n */\n public getAuthorizationHeader() {\n const header = this.getHeader(HeaderName.AUTHORIZATION);\n if (header !== null) {\n return header;\n }\n\n return undefined;\n }\n\n /**\n * Unset an authorization header.\n */\n public unsetAuthorizationHeader() {\n this.unsetHeader(HeaderName.AUTHORIZATION);\n\n return this;\n }\n\n // ---------------------------------------------------------------------------------\n\n /**\n * Make a custom request.\n *\n * @param config\n */\n public async request<\n T = any,\n RT extends `${ResponseType}` = `${ResponseType.JSON}`,\n R = Response<ResponseData<RT, T>>,\n >(config: RequestOptions<RT>): Promise<R> {\n const headers = new Headers(config.headers);\n\n this.headers.forEach((value, key) => {\n if (!headers.has(key)) {\n headers.set(key, value);\n }\n });\n\n const baseURL = config.baseURL || this.defaults.baseURL;\n let options : RequestOptions<RT> = {\n ...this.defaults as RequestBaseOptions<RT>,\n ...config,\n headers,\n url: baseURL ? withBase(config.url, baseURL) : config.url,\n };\n\n if (options.query || options.params) {\n options.url = withQuery(\n options.url,\n traverse({\n ...options.params,\n ...options.query,\n }, (value) => {\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n return value;\n }),\n );\n }\n\n options = await this.hookManager.triggerReqHook(\n options,\n ) as RequestOptions<RT>;\n\n if (options.transform) {\n const transformers = Array.isArray(options.transform) ?\n options.transform :\n [options.transform];\n\n for (let i = 0; i < transformers.length; i++) {\n const transformer = transformers[i];\n options.body = transformer(\n options.body,\n options.headers as Headers,\n );\n }\n }\n\n const handleError = async (\n step: 'request' | 'response',\n ctx: ClientErrorCreateContext,\n ) : Promise<R> => {\n const error = createClientError(ctx);\n if (Error.captureStackTrace) {\n Error.captureStackTrace(error, this.request);\n }\n\n let output : RequestOptions | Response | undefined;\n if (step === 'request') {\n output = await this.hookManager.triggerErrorHook(HookName.REQUEST_ERROR, error);\n } else {\n output = await this.hookManager.triggerErrorHook(HookName.RESPONSE_ERROR, error);\n }\n\n if (output) {\n if (isResponse(output)) {\n return output as R;\n }\n\n return this.request(output);\n }\n\n throw error;\n };\n\n let response : Response<ResponseData<RT, T>>;\n\n try {\n if (!isRequestPayloadSupported(options.method)) {\n delete options.body;\n }\n\n const { url, proxy, ...data } = options;\n if (proxy === false) {\n response = await fetch(url, data as RequestInit);\n } else {\n let proxyOptions : ProxyOptions | undefined;\n\n if (\n typeof proxy !== 'boolean' &&\n typeof proxy !== 'undefined'\n ) {\n proxyOptions = proxy;\n }\n\n response = await fetch(url, {\n ...data,\n ...createProxy(proxyOptions),\n } as RequestInit);\n }\n } catch (e: any) {\n return handleError('request', {\n request: options,\n error: toError(e),\n });\n }\n\n const responseType = options.responseType ||\n detectResponseType(response.headers.get(HeaderName.CONTENT_TYPE));\n\n let data : ResponseData<RT, T>;\n\n switch (responseType) {\n case ResponseType.STREAM: {\n data = response.body as ResponseData<RT, T>;\n break;\n }\n case ResponseType.BLOB: {\n data = await response.blob() as ResponseData<RT, T>;\n break;\n }\n case ResponseType.ARRAY_BUFFER: {\n data = await response.arrayBuffer() as ResponseData<RT, T>;\n break;\n }\n case ResponseType.TEXT: {\n data = await response.text() as ResponseData<RT, T>;\n break;\n }\n default: {\n const temp = await response.text();\n try {\n data = JSON.parse(temp);\n } catch (e) {\n data = temp as ResponseData<RT, T>;\n }\n }\n }\n\n Object.defineProperty(response, 'data', {\n get() {\n return data;\n },\n set(value: ResponseData<RT, T>) {\n data = value;\n },\n });\n\n if (\n response.status >= 400 &&\n response.status < 600\n ) {\n return handleError('response', {\n response,\n request: options,\n });\n }\n\n return await this.hookManager.triggerResHook(response) as R;\n }\n\n // ---------------------------------------------------------------------------------\n\n /**\n * Request a resource with the GET method.\n *\n * @param url\n * @param config\n */\n public get<\n T = any,\n RT extends `${ResponseType}` = `${ResponseType.JSON}`,\n R = Response<ResponseData<RT, T>>,\n >(url: string, config?: RequestBaseOptions<RT>): Promise<R> {\n return this.request({\n ...(config || {}),\n method: MethodName.GET,\n url,\n });\n }\n\n // ---------------------------------------------------------------------------------\n\n /**\n * Delete a resource with the DELETE method.\n *\n * @param url\n * @param config\n */\n public delete<\n T = any,\n RT extends `${ResponseType}` = `${ResponseType.JSON}`,\n R = Response<ResponseData<RT, T>>,\n >(url: string, config?: RequestBaseOptions<RT>): Promise<R> {\n return this.request({\n ...(config || {}),\n method: MethodName.DELETE,\n url,\n });\n }\n\n // ---------------------------------------------------------------------------------\n\n /**\n * Make a verification resource with the HEAD method.\n *\n * @param url\n * @param config\n */\n public head<\n T = any,\n RT extends `${ResponseType}` = `${ResponseType.JSON}`,\n R = Response<ResponseData<RT, T>>,\n >(url: string, config?: RequestBaseOptions<RT>): Promise<R> {\n return this.request({\n ...(config || {}),\n method: MethodName.HEAD,\n url,\n });\n }\n\n // ---------------------------------------------------------------------------------\n\n /**\n * Create a resource with the POST method.\n *\n * @param url\n * @param body\n * @param config\n */\n public post<\n T = any,\n RT extends `${ResponseType}` = `${ResponseType.JSON}`,\n R = Response<ResponseData<RT, T>>,\n >(url: string, body?: any, config?: RequestBaseOptions<RT>): Promise<R> {\n return this.request({\n ...(config || {}),\n method: MethodName.POST,\n url,\n body,\n });\n }\n\n // ---------------------------------------------------------------------------------\n\n /**\n * Update a resource with the PUT method.\n *\n * @param url\n * @param body\n * @param config\n */\n public put<\n T = any,\n RT extends `${ResponseType}` = `${ResponseType.JSON}`,\n R = Response<ResponseData<RT, T>>,\n >(url: string, body?: any, config?: RequestBaseOptions<RT>): Promise<R> {\n return this.request({\n ...(config || {}),\n method: MethodName.PUT,\n url,\n body,\n });\n }\n\n // ---------------------------------------------------------------------------------\n\n /**\n * Update a resource with the PATCH method.\n *\n * @param url\n * @param body\n * @param config\n */\n public patch<\n T = any,\n RT extends `${ResponseType}` = `${ResponseType.JSON}`,\n R = Response<ResponseData<RT, T>>,\n >(url: string, body?: any, config?: RequestBaseOptions<RT>): Promise<R> {\n return this.request({\n ...(config || {}),\n method: MethodName.PATCH,\n url,\n body,\n });\n }\n\n //---------------------------------------------------------------------------------\n\n /**\n * Register a hook fn.\n *\n * @param name\n * @param fn\n */\n\n on(\n name: `${HookName.REQUEST}`,\n fn: HookReqFn\n ) : number;\n\n on(\n name: `${HookName.RESPONSE}`,\n fn: HookResFn\n ) : number;\n\n on(\n name: `${HookName.RESPONSE_ERROR}` | `${HookName.REQUEST_ERROR}`,\n fn: HookErrorFn\n ) : number;\n\n on(name: `${HookName}`, fn: HookFn) : number {\n return this.hookManager.addListener(name, fn);\n }\n\n /**\n * Remove single or specific hook fn(s).\n *\n * @param name\n * @param fn\n */\n off(name: `${HookName}`, fn?: HookFn | number) : this {\n if (typeof fn === 'undefined') {\n this.hookManager.removeListeners(name);\n\n return this;\n }\n\n this.hookManager.removeListener(name, fn);\n return this;\n }\n}\n","/*\n * Copyright (c) 2022-2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { RequestBaseOptions } from './request';\nimport { Client } from './module';\nimport { hasOwnProperty, verifyInstanceBySymbol } from './utils';\n\nconst instanceMap: Record<string, Client> = {};\n\nexport function hasClient(\n key?: string,\n) : boolean {\n return hasOwnProperty(instanceMap, key || 'default');\n}\n\nexport function setClient<T extends Client = Client>(\n client: T,\n key?: string,\n) : T {\n key = key || 'default';\n\n instanceMap[key] = client;\n\n return client;\n}\n\nexport function useClient<T extends Client = Client>(key?: string) : T {\n key = key || 'default';\n\n if (Object.prototype.hasOwnProperty.call(instanceMap, key)) {\n return instanceMap[key] as T;\n }\n\n const instance = createClient();\n\n instanceMap[key] = instance;\n\n return instance as T;\n}\n\nexport function unsetClient(key?: string) {\n key = key || 'default';\n if (hasOwnProperty(instanceMap, key)) {\n delete instanceMap[key];\n }\n}\n\nexport function createClient(input?: RequestBaseOptions) {\n return new Client(input);\n}\n\nexport function isClient(input: unknown): input is Client {\n if (input instanceof Client) {\n return true;\n }\n\n return verifyInstanceBySymbol(input, 'Client');\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createClient } from './instance';\n\nexport * from './hook';\nexport * from './request';\nexport * from './response';\nexport * from './constants';\nexport * from './error';\nexport * from './header';\nexport * from './module';\nexport * from './instance';\nexport * from './fetch';\nexport * from './utils';\n\nconst client = createClient();\nexport default client;\n"],"names":["o","Object","defineProperty","e","t","r","value","configurable","f","c","n","agent","dispatcher","a","globalThis","fetch","gT","self","window","global","Error","File","_File","FormData","_FormData","AbortController","_AbortController","nodeFetch","Headers","_Headers","Blob","_Blob","createProxy","options","createProxyBase","ResponseType","MethodName","HookName","hasOwnProperty","obj","prop","prototype","call","kindOf","input","toString","slice","toLowerCase","kindOfTest","type","isObject","Array","isArray","isStream","pipe","isFormData","pattern","isArrayBuffer","ArrayBuffer","isFile","isBlob","isURLSearchParams","URLSearchParams","verifyInstanceBySymbol","name","Symbol","for","isSerializable","undefined","toJSON","serialize","JSON","stringify","_key","isPromise","p","Promise","then","traverse","fn","i","length","keys","AuthorizationHeaderType","ErrorCode","AuthorizationHeaderError","BaseError","parse","code","AUTHORIZATION_HEADER_PARSE","message","parseType","AUTHORIZATION_HEADER_TYPE_PARSE","AUTHORIZATION_HEADER_INVALID","ClientError","ctx","cause","error","request","response","status","statusCode","statusMessage","statusText","captureStackTrace","isClientError","isClientErrorWithStatusCode","statusCodes","isClientErrorDueNetworkIssue","Boolean","CONNECTION_ABORTED","formatRequestOptions","url","parts","method","push","join","createClientError","context","isAbort","CONNECTION_CLOSED","toError","setPrototypeOf","TypeError","extendError","data","getOwnPropertyNames","parseAuthorizationHeader","split","id","base64Decoded","Buffer","from","base64Parts","BASIC","username","password","BEARER","token","API_KEY","X_API_KEY","key","stringifyAuthorizationHeader","header","basicStr","HeaderName","setHeader","headers","set","index","findIndex","el","getHeader","get","unsetHeader","delete","splice","createDefaultRequestTransformer","CONTENT_TYPE","contentType","contentTypeIsJson","indexOf","has","ACCEPT","extendRequestOptionsWithDefaults","transform","proxy","isRequestPayloadSupported","toUpperCase","PATCH","POST","PUT","isRequestOptions","isResponse","ok","JSON_REGEX","detectResponseType","STREAM","shift","test","textTypes","startsWith","TEXT","HookManager","addListener","items","removeListener","removeListeners","triggerReqHook","REQUEST","temp","hook","output","triggerResHook","RESPONSE","triggerErrorHook","Client","getBaseURL","defaults","baseURL","setBaseURL","unsetHeaders","forEach","_value","setAuthorizationHeader","AUTHORIZATION","getAuthorizationHeader","unsetAuthorizationHeader","config","withBase","query","params","withQuery","hookManager","transformers","transformer","body","handleError","step","REQUEST_ERROR","RESPONSE_ERROR","proxyOptions","responseType","BLOB","blob","ARRAY_BUFFER","arrayBuffer","text","GET","DELETE","head","HEAD","post","put","patch","on","off","i