@autofleet/rapido-http-client 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/testing.cjs +1 -1
- package/dist/testing.js +1 -1
- package/dist/{utils-BQCBgtvv.cjs → utils--WaygnX8.cjs} +2 -2
- package/dist/{utils-BQCBgtvv.cjs.map → utils--WaygnX8.cjs.map} +1 -1
- package/dist/{utils-mRM3B8RW.js → utils-CjxOAe9E.js} +2 -2
- package/dist/{utils-mRM3B8RW.js.map → utils-CjxOAe9E.js.map} +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,`__esModule`,{value:!0});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));const c=require(`./utils
|
|
1
|
+
Object.defineProperty(exports,`__esModule`,{value:!0});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));const c=require(`./utils--WaygnX8.cjs`);let l=require(`node:http`),u=require(`undici`);u=s(u);let d=require(`@autofleet/outbreak`);const f=Symbol.for(`RapidoHttpClientErrorBrand`);let p;(function(e){e.UndiciError=u.errors.UndiciError,e.ConnectTimeoutError=u.errors.ConnectTimeoutError,e.HeadersTimeoutError=u.errors.HeadersTimeoutError,e.HeadersOverflowError=u.errors.HeadersOverflowError,e.BodyTimeoutError=u.errors.BodyTimeoutError,e.ResponseError=u.errors.ResponseError,e.InvalidArgumentError=u.errors.InvalidArgumentError,e.InvalidReturnValueError=u.errors.InvalidReturnValueError,e.RequestAbortedError=u.errors.RequestAbortedError,e.InformationalError=u.errors.InformationalError,e.RequestContentLengthMismatchError=u.errors.RequestContentLengthMismatchError,e.ResponseContentLengthMismatchError=u.errors.ResponseContentLengthMismatchError,e.ClientDestroyedError=u.errors.ClientDestroyedError,e.ClientClosedError=u.errors.ClientClosedError,e.SocketError=u.errors.SocketError,e.NotSupportedError=u.errors.NotSupportedError,e.BalancedPoolMissingUpstreamError=u.errors.BalancedPoolMissingUpstreamError,e.HTTPParserError=u.errors.HTTPParserError,e.ResponseExceededMaxSizeError=u.errors.ResponseExceededMaxSizeError,e.RequestRetryError=u.errors.RequestRetryError,e.SecureProxyConnectionError=u.errors.SecureProxyConnectionError,e.MaxOriginsReachedError=u.errors.MaxOriginsReachedError;function t(e){return typeof e==`object`&&!!e&&f in e}e.isRapidoHttpClientError=t;class n extends u.errors.ResponseError{constructor(e,t,n,r){super(`HTTP Error ${t.statusCode}`,t.statusCode,{headers:t.headers,body:e}),this.response=t,this.data=n,this.status=t.statusCode,this.statusText=l.STATUS_CODES[t.statusCode]||`Unknown Status`,this.requestOptions=r?.requestOptions,r?.cause&&(this.cause=r.cause),Object.defineProperty(this,f,{value:!0,enumerable:!1,writable:!1})}static isRapidoHttpClientError(e){return t(e)}}e.RapidoHttpClientError=n})(p||={});const m=Symbol(`testAgentParam`),h=e=>function(t,n){let r=(0,d.getCurrentContext)().context;if(r){let e;e=Array.isArray(t.headers)?Object.fromEntries(t.headers):{...t.headers};for(let[t,n]of r)typeof n==`symbol`||n===void 0||(e[t]=n);t.headers=e}return e(t,n)},{cacheStores:g}=u.default,{cache:_,retry:v,decompress:y}=u.interceptors,b=[`GET`,`HEAD`,`OPTIONS`,`PUT`,`DELETE`,`TRACE`,`QUERY`];var x=class{#e;get(e,t){return this.#i(`GET`,e,void 0,t)}post(e,t,n){return this.#i(`POST`,e,t,n)}delete(e,t){return this.#i(`DELETE`,e,void 0,t)}head(e,t){return this.#i(`HEAD`,e,void 0,t)}put(e,t,n){return this.#i(`PUT`,e,t,n)}patch(e,t,n){return this.#i(`PATCH`,e,t,n)}options(e,t){return this.#i(`OPTIONS`,e,void 0,t)}query(e,t,n){return this.#i(`QUERY`,e,t,n)}constructor(e){this.#e=e.logger.child(`RapidoHttpClient`,{}),this.settings=c.o(e.autoDecompress?c.i:c.r,e),this.#t();let t=globalThis.__RAPIDO_HTTP_CLIENT_MOCK_AGENT__;this.client=this.settings[m]??t??new u.Agent({connect:{timeout:this.settings.timeout},keepAliveTimeout:this.settings.keepAliveTimeout,keepAliveMaxTimeout:this.settings.keepAliveMaxTimeout,connections:this.settings.connections}),this.settings.cache&&(this.client=this.client.compose(_({store:new g.MemoryCacheStore({...this.settings.cache})}))),this.settings.retries&&(this.client=this.client.compose(v({methods:b,...this.settings.retries,retry:(e,t,n)=>{let{counter:r}=t.state,i=t.opts.retryOptions?.maxRetries??5;(this.settings.retries?.retry??c.n)(e,t,a=>{if(!a){let{method:n,origin:a,path:o}=t.opts,s=!a||typeof a==`string`?a:a.origin;this.#e.warn(`Request retry attempt ${r}/${i}: ${c.t(n,s,o)}`,{err:e})}n(a)})}}))),this.settings.autoDecompress&&(this.client=this.client.compose(y({skipErrorResponses:!1}))),this.client=this.client.compose(h)}#t(){let e=c.c(this.settings),t=new URL(e);this.settings.baseURL=t.origin,this.settings.basePath=t.pathname===`/`?``:t.pathname}#n(e,t){if(!e&&!t)return{signal:void 0,timeoutSignal:void 0};if(e&&!t)return{signal:e,timeoutSignal:void 0};let n=AbortSignal.timeout(t);return!e&&t?{signal:n,timeoutSignal:n}:{signal:AbortSignal.any([e,n]),timeoutSignal:n}}#r(e,t){if(e!=null){if(c.a(e))return!t[`Content-Type`]&&!t[`content-type`]&&(t[`Content-Type`]=`application/x-www-form-urlencoded`),e;if(typeof e==`object`&&!Buffer.isBuffer(e)){let n=t[`Content-Type`]||t[`content-type`];if(n&&/application\/x-www-form-urlencoded/i.test(n)){let t=new URLSearchParams;for(let[n,r]of Object.entries(e))Array.isArray(r)?r.forEach(e=>t.append(n,String(e))):r!=null&&t.append(n,String(r));return t.toString()}return!t[`Content-Type`]&&!t[`content-type`]&&(t[`Content-Type`]=`application/json`),JSON.stringify(e)}return typeof e==`string`||Buffer.isBuffer(e)?e:String(e)}}async#i(e,t,n,r={}){let i=c.o(this.settings,r);if(i.signal?.aborted)throw this.#e.error(`Request aborted before start: ${c.t(e,i.baseURL,t)}`),new p.RequestAbortedError(i.signal.reason?.message||`Request aborted`,{cause:i.signal.reason});let{successSchema:a,errorSchema:o}=r,s={...i.headers},u=this.#r(n,s),{origin:d,path:f}=c.s(t,i.baseURL,i.basePath),m={method:e,baseURL:d,url:t};if(i.params)for(let[e,t]of Object.entries(i.params))Array.isArray(t)&&!e.endsWith(`[]`)&&(i.params[`${e}[]`]=t,delete i.params[e]);let{signal:h,timeoutSignal:g}=this.#n(i.signal,i.timeout);try{this.#e.info(`Start Request: ${c.t(e,d,f)}`);let t={path:f,origin:d,method:e,signal:h,headers:s,body:u,query:i.params},n=await this.client.request(t);if(d.startsWith(`http://`)&&n.statusCode>=300&&n.statusCode<400){let e=[n.headers.location].flat()[0]??`unknown location`;throw new p.RapidoHttpClientError(u,n,void 0,{requestOptions:t,cause:Error(`Redirect to ${e} on HTTP origin, which is not supported for security reasons`)})}if(!(i.validateStatus??(()=>n.statusCode<400))(n.statusCode)){let r=await this.#s(u,n,o);throw this.#e.error(`Finish Request with error ${c.t(e,d,f)}`,{status:n.statusCode,data:r}),new p.RapidoHttpClientError(u,n,r,{requestOptions:t})}return this.#e.info(`Finish Request: ${c.t(e,d,f)}`),{data:n.statusCode===204?void 0:await this.#o(u,n,a),status:n.statusCode,statusText:l.STATUS_CODES[n.statusCode]||``,headers:n.headers,config:m}}catch(t){if(g&&g.reason===t){this.#e.error(`Request timeout: ${c.t(e,d,f)}`);let t=new p.UndiciError(`Request timeout after ${i.timeout}ms`,{cause:g.reason});throw t.code=`UND_ERR_TIMEOUT`,t}throw h&&h.reason===t?(this.#e.error(`Request aborted: ${c.t(e,d,f)}`),new p.RequestAbortedError(h.reason.message,{cause:h.reason})):(this.#e.error(`Finish Request with error ${c.t(e,d,f)}`,{error:t}),t)}}async#a(e,t,n){let r=t.headers[`content-type`]||``,i=await t.body.text();if(!i)return;if(/text/i.test(r)){if(!n)return i;let e=n.safeParse(i);if(e.success)return e.data;throw Object.assign(e.error,{json:i})}let a;try{a=JSON.parse(i)}catch(r){if(!n)return i;let a=n.safeParse(i);if(a.success)return a.data;throw new p.RapidoHttpClientError(e,t,void 0,{cause:r})}if(!n)return a;let o=n.safeParse(a);if(o.success)return o.data;throw Object.assign(o.error,{json:a})}async#o(e,t,n){return this.#a(e,t,n)}async#s(e,t,n){return this.#a(e,t,n)}async getAllPages(e,t={}){let n=[],r=null,i=null,a={...t,params:{...t.params,page:1}};for(a.params.page||=1;(a.params.page===1||i===r)&&i!==0;){let{data:t}=await this.get(e,a);i=t.length,a.params.page===1&&(r=t.length),a.params.page+=1,Array.prototype.push.apply(n,t)}return n}async getAllPagesFromQueryEndpoint(e,t={},n=100){let r=[],i=!0,a=1;for(;i&&(n===-1||a<n);){let{data:n}=await this.post(e,{...t,page:a}),{rows:o,count:s}=n;a+=1,Array.prototype.push.apply(r,o),i=r.length<s}return r}async close(){await this.client.close()}async[Symbol.asyncDispose](){await this.close()}},S=x;exports.RapidoHttpClient=x,exports.default=S,Object.defineProperty(exports,`errors`,{enumerable:!0,get:function(){return p}}),exports.t=s;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["undiciErrors","response: Dispatcher.ResponseData","data: TError","STATUS_CODES","testAgentParam: unique symbol","outbreakInterceptor: Dispatcher.DispatcherComposeInterceptor","headers: Record<string, string | string[]>","Undici","interceptors","retriableMethods: Dispatcher.HttpMethod[]","#logger","#request","mergeConfig","defaultSettingsWithDecompress","defaultSettings","#createBaseUrl","Agent","defaultRetryMethod","createRequestString","resolveServiceUrl","isFormData","headers: Record<string, string>","#prepareRequestBody","parseUrlAndOrigin","#getSignal","requestOptions: Dispatcher.RequestOptions","#parseErrorResponse","#parseSuccessResponse","STATUS_CODES","error","#parseResponse","json: unknown","parseResult","currentResult: T[]","resultsInFirstPage: number | null","lastResultsSize: number | null"],"sources":["../src/errors.ts","../src/testingHelper.ts","../src/outbreakInterceptor.ts","../src/index.ts"],"sourcesContent":["import { STATUS_CODES } from 'node:http';\nimport { type Dispatcher, errors as undiciErrors } from 'undici';\n\nconst RapidoHttpClientErrorBrand = Symbol.for('RapidoHttpClientErrorBrand');\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace errors {\n export import UndiciError = undiciErrors.UndiciError;\n export import ConnectTimeoutError = undiciErrors.ConnectTimeoutError;\n export import HeadersTimeoutError = undiciErrors.HeadersTimeoutError;\n export import HeadersOverflowError = undiciErrors.HeadersOverflowError;\n export import BodyTimeoutError = undiciErrors.BodyTimeoutError;\n export import ResponseError = undiciErrors.ResponseError;\n export import InvalidArgumentError = undiciErrors.InvalidArgumentError;\n export import InvalidReturnValueError = undiciErrors.InvalidReturnValueError;\n export import RequestAbortedError = undiciErrors.RequestAbortedError;\n export import InformationalError = undiciErrors.InformationalError;\n export import RequestContentLengthMismatchError = undiciErrors.RequestContentLengthMismatchError;\n export import ResponseContentLengthMismatchError = undiciErrors.ResponseContentLengthMismatchError;\n export import ClientDestroyedError = undiciErrors.ClientDestroyedError;\n export import ClientClosedError = undiciErrors.ClientClosedError;\n export import SocketError = undiciErrors.SocketError;\n export import NotSupportedError = undiciErrors.NotSupportedError;\n export import BalancedPoolMissingUpstreamError = undiciErrors.BalancedPoolMissingUpstreamError;\n export import HTTPParserError = undiciErrors.HTTPParserError;\n export import ResponseExceededMaxSizeError = undiciErrors.ResponseExceededMaxSizeError;\n export import RequestRetryError = undiciErrors.RequestRetryError;\n export import SecureProxyConnectionError = undiciErrors.SecureProxyConnectionError;\n export import MaxOriginsReachedError = undiciErrors.MaxOriginsReachedError;\n\n export function isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError {\n return typeof value === 'object' && value !== null && RapidoHttpClientErrorBrand in value;\n }\n\n export class RapidoHttpClientError<TError = unknown> extends undiciErrors.ResponseError {\n public readonly status: number;\n public readonly statusText: string;\n\n constructor(\n body: ConstructorParameters<typeof undiciErrors.ResponseError>[2]['body'],\n public readonly response: Dispatcher.ResponseData,\n public readonly data: TError,\n errorOptions?: ErrorOptions,\n ) {\n super(`HTTP Error ${response.statusCode}`, response.statusCode, { headers: response.headers, body });\n this.status = response.statusCode;\n this.statusText = STATUS_CODES[response.statusCode] || 'Unknown Status';\n if (errorOptions?.cause) {\n this.cause = errorOptions.cause;\n }\n\n Object.defineProperty(this, RapidoHttpClientErrorBrand, {\n value: true,\n enumerable: false,\n writable: false,\n });\n }\n\n public static isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError {\n return isRapidoHttpClientError(value);\n }\n }\n}\n","export const testAgentParam: unique symbol = Symbol('testAgentParam');\n","import type { Dispatcher } from 'undici';\nimport { getCurrentContext } from '@autofleet/outbreak';\n\nexport const outbreakInterceptor: Dispatcher.DispatcherComposeInterceptor = dispatch => function outbreakInterceptorInner(opts, handler) {\n const currentTraceContext = getCurrentContext().context;\n if (currentTraceContext) {\n // Convert headers to object format if they're in array format\n let headers: Record<string, string | string[]>;\n if (Array.isArray(opts.headers)) {\n /* c8 ignore next */\n headers = Object.fromEntries(opts.headers as unknown as [string, string | string[]][]);\n } else {\n headers = { ...opts.headers as Record<string, string | string[]> };\n }\n\n // Inject outbreak trace headers\n for (const [header, value] of currentTraceContext) {\n if (typeof value === 'symbol' || typeof value === 'undefined') {\n continue;\n }\n headers[header] = value as string;\n }\n opts.headers = headers;\n }\n return dispatch(opts, handler);\n};\n","import { STATUS_CODES } from 'node:http';\nimport type { ZodType, output } from 'zod';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport type CacheHandler from 'undici/types/cache-interceptor';\nimport Undici, { Agent, type Dispatcher, interceptors } from 'undici';\nimport { errors } from './errors';\nimport { testAgentParam } from './testingHelper';\nimport { outbreakInterceptor } from './outbreakInterceptor';\nimport {\n createRequestString,\n defaultRetryMethod,\n defaultSettings,\n defaultSettingsWithDecompress,\n isFormData,\n mergeConfig,\n parseUrlAndOrigin,\n resolveServiceUrl,\n} from './utils';\n\nconst { cacheStores } = Undici;\nconst { cache, retry, decompress } = interceptors;\n\nexport interface RapidoHttpClientSettings {\n [testAgentParam]?: Dispatcher;\n /** The MS name to be used to resolve the base URL using K8S service discovery. Ignored if `serviceUrl` is provided as well. */\n serviceName?: string;\n /** The base URL to be used. Overrides `serviceName` when provided. */\n serviceUrl?: string;\n logger: LoggerInstanceManager;\n /** The request timeout in milliseconds. @default 10_000 */\n timeout?: number;\n /** Settings for retrying requests on failure */\n retries?: interceptors.RetryInterceptorOpts;\n /** Common headers applied to all requests of this `RapidoHttpClient` instance. */\n headers?: Record<string, string> | string[][];\n keepAliveTimeout?: number;\n keepAliveMaxTimeout?: number;\n /** The amount of concurrent connections to be maintained using a connection pool. @default 10 */\n connections?: number;\n /** The settings for caching requests */\n cache?: CacheHandler.MemoryCacheStoreOpts;\n /** Whether to automatically decompress response bodies. When `true` will automatically add an `Accept-Encoding` header. @default false */\n autoDecompress?: boolean;\n /**\n * A function to validate the HTTP response status code.\n * Return `true` to consider the status valid, `false` otherwise.\n *\n * When status is invalid, a {@link errors.RapidoHttpClientError `RapidoHttpClientError`} will be thrown.\n *\n * @example (status) => status >= 200 && status < 300\n * @example (status) => status !== 401\n *\n * @default (status) => status < 400\n */\n validateStatus?(status: number): boolean;\n}\n\nexport interface RequestConfig {\n params?: Record<string, any>;\n body?: any;\n /** The request timeout in milliseconds. This overrides the client's instance setting @default 10_000 */\n timeout?: number;\n /** Headers applied to this request, appending on the client's common headers. */\n headers?: Record<string, string>;\n /** An `AbortSignal` which should abort the request and it's parsing when aborted. */\n signal?: AbortSignal;\n /**\n * Zod schema for successful responses. Used when `validateStatus` returns `true` (default: status < 400).\n */\n successSchema?: ZodType;\n /**\n * Zod schema for error responses. Used when `validateStatus` returns `false` (default: status >= 400).\n * The validated error data is available in the thrown `RapidoHttpClientError`.\n */\n errorSchema?: ZodType;\n /**\n * A function to validate the HTTP response status code.\n * Return `true` to consider the status valid, `false` otherwise.\n *\n * When status is invalid, a {@link errors.RapidoHttpClientError `RapidoHttpClientError`} will be thrown.\n *\n * @example (status) => status >= 200 && status < 300\n * @example (status) => status !== 401\n *\n * @default (status) => status < 400\n */\n validateStatus?(status: number): boolean;\n}\n\nexport interface RapidoHttpClientResponse<T = any> {\n data: T;\n status: number;\n statusText: string;\n headers: Record<string, string | string[]>;\n config: RequestConfig & { url: string; method: string; baseURL?: string; };\n}\n\nconst retriableMethods: Dispatcher.HttpMethod[] = ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE', 'QUERY'];\n\nexport class RapidoHttpClient {\n readonly #logger: LoggerInstanceManager;\n private readonly settings: RapidoHttpClientSettings & { baseURL?: string; basePath?: string; };\n public readonly client: Dispatcher.ComposedDispatcher;\n\n public get<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public get<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public get<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public get<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('GET', url, undefined, config);\n }\n\n public post<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public post<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public post<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public post<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('POST', url, body, config);\n }\n\n public delete<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public delete<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public delete<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public delete<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('DELETE', url, undefined, config);\n }\n\n public head<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public head<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public head<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public head<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('HEAD', url, undefined, config);\n }\n\n public put<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public put<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public put<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public put<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('PUT', url, body, config);\n }\n\n public patch<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public patch<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public patch<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public patch<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('PATCH', url, body, config);\n }\n\n public options<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public options<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public options<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public options<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('OPTIONS', url, undefined, config);\n }\n\n public query<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public query<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public query<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public query<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('QUERY', url, body, config);\n }\n\n constructor(settings: RapidoHttpClientSettings) {\n this.#logger = settings.logger.child('RapidoHttpClient', {});\n this.settings = mergeConfig<typeof defaultSettings, Partial<typeof settings>>(\n settings.autoDecompress ? defaultSettingsWithDecompress : defaultSettings,\n settings,\n ) as RapidoHttpClientSettings & { baseURL?: string; };\n this.#createBaseUrl();\n\n // In test mode, use the test dispatcher directly (MockAgent or MockPool) Otherwise, create an Agent which creates Client Pools\n // Check for global mock agent first (for testing), then test param, then create real Agent\n /* c8 ignore next */\n const globalMockAgent = (globalThis as any).__RAPIDO_HTTP_CLIENT_MOCK_AGENT__;\n /* c8 ignore next */\n this.client = this.settings[testAgentParam] ?? globalMockAgent ?? new Agent({\n connect: {\n timeout: this.settings.timeout,\n },\n keepAliveTimeout: this.settings.keepAliveTimeout,\n keepAliveMaxTimeout: this.settings.keepAliveMaxTimeout,\n connections: this.settings.connections,\n });\n\n if (this.settings.cache) {\n this.client = this.client.compose(cache({\n store: new cacheStores.MemoryCacheStore({\n ...this.settings.cache,\n }),\n }));\n }\n\n if (this.settings.retries) {\n this.client = this.client.compose(retry({\n methods: retriableMethods,\n ...this.settings.retries,\n retry: (err, context, callback) => {\n const { counter } = context.state;\n /* c8 ignore next */\n const maxRetries = context.opts.retryOptions?.maxRetries ?? 5;\n\n const retryToUse = this.settings.retries?.retry ?? defaultRetryMethod;\n const callbackWithLogging = (result?: Error | null) => {\n if (!result) {\n const { method, origin, path } = context.opts;\n const baseUrl = (!origin || typeof origin === 'string') ? origin : origin.origin;\n this.#logger.warn(`Request retry attempt ${counter}/${maxRetries}: ${createRequestString(method, baseUrl, path)}`, { err });\n }\n callback(result);\n };\n retryToUse(err, context, callbackWithLogging);\n },\n }));\n }\n\n if (this.settings.autoDecompress) {\n this.client = this.client.compose(decompress({ skipErrorResponses: false }));\n }\n\n this.client = this.client.compose(outbreakInterceptor);\n }\n\n #createBaseUrl(): void {\n const fullUrl = resolveServiceUrl(this.settings);\n const urlObj = new URL(fullUrl);\n this.settings.baseURL = urlObj.origin;\n this.settings.basePath = urlObj.pathname !== '/' ? urlObj.pathname : '';\n }\n\n #getSignal(currentSignal?: AbortSignal, timeout?: number): { signal?: AbortSignal; timeoutSignal?: AbortSignal; } {\n if (!currentSignal && !timeout) {\n return { signal: undefined, timeoutSignal: undefined };\n }\n\n if (currentSignal && !timeout) {\n return { signal: currentSignal, timeoutSignal: undefined };\n }\n\n const timeoutSignal = AbortSignal.timeout(timeout!);\n if (!currentSignal && timeout) {\n return { signal: timeoutSignal, timeoutSignal };\n }\n\n return { signal: AbortSignal.any([currentSignal!, timeoutSignal]), timeoutSignal };\n }\n\n #prepareRequestBody(body: any, headers: Record<string, string>): string | Buffer | FormData | undefined {\n if (body === undefined || body === null) {\n return undefined;\n }\n\n // Handle FormData instances automatically\n if (isFormData(body)) {\n if (!headers['Content-Type'] && !headers['content-type']) {\n headers['Content-Type'] = 'application/x-www-form-urlencoded';\n }\n return body;\n }\n\n if (typeof body === 'object' && !Buffer.isBuffer(body)) {\n // Check if Content-Type is set to application/x-www-form-urlencoded\n const contentType = headers['Content-Type'] || headers['content-type'];\n if (contentType && /application\\/x-www-form-urlencoded/i.test(contentType)) {\n // Encode as URL parameters\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(body)) {\n if (Array.isArray(value)) {\n value.forEach(v => params.append(key, String(v)));\n } else if (value !== undefined && value !== null) {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n params.append(key, String(value));\n }\n }\n return params.toString();\n }\n // Default to JSON\n if (!headers['Content-Type'] && !headers['content-type']) {\n headers['Content-Type'] = 'application/json';\n }\n return JSON.stringify(body);\n }\n if (typeof body === 'string') {\n return body;\n }\n if (Buffer.isBuffer(body)) {\n return body;\n }\n return String(body);\n }\n\n async #request<T = any>(\n method: Dispatcher.HttpMethod,\n url: string,\n body?: any,\n config: RequestConfig = {},\n ): Promise<RapidoHttpClientResponse<T>> {\n const mergedConfig = mergeConfig(this.settings, config);\n\n if (mergedConfig.signal?.aborted) {\n this.#logger.error(`Request aborted before start: ${createRequestString(method, mergedConfig.baseURL, url)}`);\n throw new errors.RequestAbortedError(mergedConfig.signal.reason?.message || 'Request aborted', { cause: mergedConfig.signal.reason });\n }\n\n // Get schemas from config\n const { successSchema, errorSchema } = config;\n\n const headers: Record<string, string> = { ...mergedConfig.headers };\n const requestBody = this.#prepareRequestBody(body, headers);\n\n const { origin, path } = parseUrlAndOrigin(url, mergedConfig.baseURL!, mergedConfig.basePath);\n const requestInfo = { method, baseURL: origin, url };\n\n if (mergedConfig.params) {\n for (const [key, value] of Object.entries(mergedConfig.params)) {\n if (Array.isArray(value) && !key.endsWith('[]')) {\n mergedConfig.params[`${key}[]`] = value;\n delete mergedConfig.params[key];\n }\n }\n }\n\n const { signal, timeoutSignal } = this.#getSignal(mergedConfig.signal, mergedConfig.timeout);\n\n try {\n this.#logger.info(`Start Request: ${createRequestString(method, origin, path)}`);\n\n const requestOptions: Dispatcher.RequestOptions = {\n path,\n origin,\n method,\n signal,\n headers,\n body: requestBody,\n query: mergedConfig.params,\n };\n\n const response = await this.client.request(requestOptions);\n\n const isStatusValid = mergedConfig.validateStatus ?? (() => response.statusCode < 400);\n if (!isStatusValid(response.statusCode)) {\n const data = await this.#parseErrorResponse(requestBody, response, errorSchema);\n this.#logger.error(`Finish Request with error ${createRequestString(method, origin, path)}`, {\n status: response.statusCode,\n data,\n });\n\n throw new errors.RapidoHttpClientError(requestBody, response, data);\n }\n\n this.#logger.info(`Finish Request: ${createRequestString(method, origin, path)}`);\n\n const data = response.statusCode !== 204 ? await this.#parseSuccessResponse<T>(requestBody, response, successSchema) : undefined as T;\n\n return {\n data,\n status: response.statusCode,\n statusText: STATUS_CODES[response.statusCode] || '',\n headers: response.headers as Record<string, string | string[]>,\n config: requestInfo,\n };\n } catch (error) {\n if (timeoutSignal && timeoutSignal.reason === error) {\n // If the timeoutSignal aborted (config timeout), throw a timeout-specific error\n this.#logger.error(`Request timeout: ${createRequestString(method, origin, path)}`);\n const error = new errors.UndiciError(`Request timeout after ${mergedConfig.timeout}ms`, { cause: timeoutSignal.reason });\n error.code = 'UND_ERR_TIMEOUT';\n throw error;\n }\n if (signal && signal.reason === error) {\n // If the user's signal aborted, throw RequestAbortedError\n this.#logger.error(`Request aborted: ${createRequestString(method, origin, path)}`);\n throw new errors.RequestAbortedError(signal.reason.message, { cause: signal.reason });\n }\n\n this.#logger.error(`Finish Request with error ${createRequestString(method, origin, path)}`, { error });\n throw error;\n }\n }\n\n async #parseResponse<T>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<T> {\n const contentType = (response.headers['content-type'] as string) || '';\n const bodyText = await response.body.text();\n\n if (!bodyText) {\n return undefined as T;\n }\n\n if (/text/i.test(contentType)) {\n return bodyText as T;\n }\n\n let json: unknown;\n try {\n json = JSON.parse(bodyText);\n } catch (error) {\n if (!schema) {\n return bodyText as T;\n }\n const parseResult = schema.safeParse(bodyText);\n if (parseResult.success) {\n return parseResult.data as T;\n }\n throw new errors.RapidoHttpClientError(requestBody, response, undefined, { cause: error as Error });\n }\n if (!schema) {\n return json as T;\n }\n const parseResult = schema.safeParse(json);\n if (parseResult.success) {\n return parseResult.data as T;\n }\n throw Object.assign(parseResult.error, { json });\n }\n\n async #parseSuccessResponse<T>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<T> {\n return this.#parseResponse<T>(requestBody, response, schema);\n }\n\n async #parseErrorResponse<TError>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<TError> {\n return this.#parseResponse<TError>(requestBody, response, schema);\n }\n\n /**\n * @param url The endpoint URL to send the request to.\n * @param options Additional options to include in the request payload.\n * @returns A promise that resolves to an array of all results.\n */\n async getAllPages<T>(url: string, options: RequestConfig = {}): Promise<T[]> {\n const currentResult: T[] = [];\n let resultsInFirstPage: number | null = null;\n let lastResultsSize: number | null = null;\n\n const localOptions = { ...options, params: { ...options.params, page: 1 } };\n // Make sure even if `options` had `params` we initialize `page` to 1.\n localOptions.params.page ||= 1;\n\n while ((localOptions.params.page === 1 || lastResultsSize === resultsInFirstPage) && lastResultsSize !== 0) {\n const { data } = await this.get<T[]>(url, localOptions as Omit<RequestConfig, 'successSchema' | 'errorSchema'>);\n lastResultsSize = data.length;\n if (localOptions.params.page === 1) {\n resultsInFirstPage = data.length;\n }\n\n localOptions.params.page += 1;\n Array.prototype.push.apply(currentResult, data);\n }\n\n return currentResult;\n }\n\n /**\n * Fetches all pages from a paginated API endpoint until all results are retrieved\n * or an optional page limit is reached.\n *\n * @param url The endpoint URL to send the request to.\n * @param options Additional options to include in the request payload.\n * @param pageLimit The maximum number of pages to fetch. Set to -1 for no limit.\n * @returns A promise that resolves to an array of all results.\n */\n async getAllPagesFromQueryEndpoint<T>(url: string, options: object = {}, pageLimit = 100): Promise<T[]> {\n const currentResult: T[] = [];\n\n let moreResultsToLoad = true;\n let page = 1;\n while (moreResultsToLoad && (pageLimit === -1 || page < pageLimit)) {\n const { data } = await this.post<{ rows: T[]; count: number; }>(url, {\n ...options,\n page,\n });\n const { rows, count } = data;\n page += 1;\n Array.prototype.push.apply(currentResult, rows);\n moreResultsToLoad = currentResult.length < count;\n }\n\n return currentResult;\n }\n\n async close(): Promise<void> {\n await this.client.close();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n}\n\nexport default RapidoHttpClient;\nexport { errors };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["undiciErrors","response: Dispatcher.ResponseData","data: TError","STATUS_CODES","testAgentParam: unique symbol","outbreakInterceptor: Dispatcher.DispatcherComposeInterceptor","headers: Record<string, string | string[]>","Undici","interceptors","retriableMethods: Dispatcher.HttpMethod[]","#logger","#request","mergeConfig","defaultSettingsWithDecompress","defaultSettings","#createBaseUrl","Agent","defaultRetryMethod","createRequestString","resolveServiceUrl","isFormData","headers: Record<string, string>","#prepareRequestBody","parseUrlAndOrigin","#getSignal","requestOptions: Dispatcher.RequestOptions","#parseErrorResponse","#parseSuccessResponse","STATUS_CODES","error","#parseResponse","parseResult","json: unknown","currentResult: T[]","resultsInFirstPage: number | null","lastResultsSize: number | null"],"sources":["../src/errors.ts","../src/testingHelper.ts","../src/outbreakInterceptor.ts","../src/index.ts"],"sourcesContent":["import { STATUS_CODES } from 'node:http';\nimport { type Dispatcher, errors as undiciErrors } from 'undici';\n\nconst RapidoHttpClientErrorBrand = Symbol.for('RapidoHttpClientErrorBrand');\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace errors {\n export import UndiciError = undiciErrors.UndiciError;\n export import ConnectTimeoutError = undiciErrors.ConnectTimeoutError;\n export import HeadersTimeoutError = undiciErrors.HeadersTimeoutError;\n export import HeadersOverflowError = undiciErrors.HeadersOverflowError;\n export import BodyTimeoutError = undiciErrors.BodyTimeoutError;\n export import ResponseError = undiciErrors.ResponseError;\n export import InvalidArgumentError = undiciErrors.InvalidArgumentError;\n export import InvalidReturnValueError = undiciErrors.InvalidReturnValueError;\n export import RequestAbortedError = undiciErrors.RequestAbortedError;\n export import InformationalError = undiciErrors.InformationalError;\n export import RequestContentLengthMismatchError = undiciErrors.RequestContentLengthMismatchError;\n export import ResponseContentLengthMismatchError = undiciErrors.ResponseContentLengthMismatchError;\n export import ClientDestroyedError = undiciErrors.ClientDestroyedError;\n export import ClientClosedError = undiciErrors.ClientClosedError;\n export import SocketError = undiciErrors.SocketError;\n export import NotSupportedError = undiciErrors.NotSupportedError;\n export import BalancedPoolMissingUpstreamError = undiciErrors.BalancedPoolMissingUpstreamError;\n export import HTTPParserError = undiciErrors.HTTPParserError;\n export import ResponseExceededMaxSizeError = undiciErrors.ResponseExceededMaxSizeError;\n export import RequestRetryError = undiciErrors.RequestRetryError;\n export import SecureProxyConnectionError = undiciErrors.SecureProxyConnectionError;\n export import MaxOriginsReachedError = undiciErrors.MaxOriginsReachedError;\n\n export function isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError {\n return typeof value === 'object' && value !== null && RapidoHttpClientErrorBrand in value;\n }\n\n export class RapidoHttpClientError<TError = unknown> extends undiciErrors.ResponseError {\n public readonly status: number;\n public readonly statusText: string;\n public readonly requestOptions?: Dispatcher.RequestOptions;\n\n constructor(\n body: ConstructorParameters<typeof undiciErrors.ResponseError>[2]['body'],\n public readonly response: Dispatcher.ResponseData,\n public readonly data: TError,\n errorOptions?: ErrorOptions & { requestOptions?: Dispatcher.RequestOptions; },\n ) {\n super(`HTTP Error ${response.statusCode}`, response.statusCode, { headers: response.headers, body });\n this.status = response.statusCode;\n this.statusText = STATUS_CODES[response.statusCode] || 'Unknown Status';\n this.requestOptions = errorOptions?.requestOptions;\n if (errorOptions?.cause) {\n this.cause = errorOptions.cause;\n }\n\n Object.defineProperty(this, RapidoHttpClientErrorBrand, {\n value: true,\n enumerable: false,\n writable: false,\n });\n }\n\n public static isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError {\n return isRapidoHttpClientError(value);\n }\n }\n}\n","export const testAgentParam: unique symbol = Symbol('testAgentParam');\n","import type { Dispatcher } from 'undici';\nimport { getCurrentContext } from '@autofleet/outbreak';\n\nexport const outbreakInterceptor: Dispatcher.DispatcherComposeInterceptor = dispatch => function outbreakInterceptorInner(opts, handler) {\n const currentTraceContext = getCurrentContext().context;\n if (currentTraceContext) {\n // Convert headers to object format if they're in array format\n let headers: Record<string, string | string[]>;\n if (Array.isArray(opts.headers)) {\n /* c8 ignore next */\n headers = Object.fromEntries(opts.headers as unknown as [string, string | string[]][]);\n } else {\n headers = { ...opts.headers as Record<string, string | string[]> };\n }\n\n // Inject outbreak trace headers\n for (const [header, value] of currentTraceContext) {\n if (typeof value === 'symbol' || typeof value === 'undefined') {\n continue;\n }\n headers[header] = value as string;\n }\n opts.headers = headers;\n }\n return dispatch(opts, handler);\n};\n","import { STATUS_CODES } from 'node:http';\nimport type { ZodType, output } from 'zod';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport type CacheHandler from 'undici/types/cache-interceptor';\nimport Undici, { Agent, type Dispatcher, interceptors } from 'undici';\nimport { errors } from './errors';\nimport { testAgentParam } from './testingHelper';\nimport { outbreakInterceptor } from './outbreakInterceptor';\nimport {\n createRequestString,\n defaultRetryMethod,\n defaultSettings,\n defaultSettingsWithDecompress,\n isFormData,\n mergeConfig,\n parseUrlAndOrigin,\n resolveServiceUrl,\n} from './utils';\n\nconst { cacheStores } = Undici;\nconst { cache, retry, decompress } = interceptors;\n\nexport interface RapidoHttpClientSettings {\n [testAgentParam]?: Dispatcher;\n /** The MS name to be used to resolve the base URL using K8S service discovery. Ignored if `serviceUrl` is provided as well. */\n serviceName?: string;\n /** The base URL to be used. Overrides `serviceName` when provided. */\n serviceUrl?: string;\n logger: LoggerInstanceManager;\n /** The request timeout in milliseconds. @default 10_000 */\n timeout?: number;\n /** Settings for retrying requests on failure */\n retries?: interceptors.RetryInterceptorOpts;\n /** Common headers applied to all requests of this `RapidoHttpClient` instance. */\n headers?: Record<string, string> | string[][];\n keepAliveTimeout?: number;\n keepAliveMaxTimeout?: number;\n /** The amount of concurrent connections to be maintained using a connection pool. @default 10 */\n connections?: number;\n /** The settings for caching requests */\n cache?: CacheHandler.MemoryCacheStoreOpts;\n /** Whether to automatically decompress response bodies. When `true` will automatically add an `Accept-Encoding` header. @default false */\n autoDecompress?: boolean;\n /**\n * A function to validate the HTTP response status code.\n * Return `true` to consider the status valid, `false` otherwise.\n *\n * When status is invalid, a {@link errors.RapidoHttpClientError `RapidoHttpClientError`} will be thrown.\n *\n * @example (status) => status >= 200 && status < 300\n * @example (status) => status !== 401\n *\n * @default (status) => status < 400\n */\n validateStatus?(status: number): boolean;\n}\n\nexport interface RequestConfig {\n params?: Record<string, any>;\n body?: any;\n /** The request timeout in milliseconds. This overrides the client's instance setting @default 10_000 */\n timeout?: number;\n /** Headers applied to this request, appending on the client's common headers. */\n headers?: Record<string, string>;\n /** An `AbortSignal` which should abort the request and it's parsing when aborted. */\n signal?: AbortSignal;\n /**\n * Zod schema for successful responses. Used when `validateStatus` returns `true` (default: status < 400).\n */\n successSchema?: ZodType;\n /**\n * Zod schema for error responses. Used when `validateStatus` returns `false` (default: status >= 400).\n * The validated error data is available in the thrown `RapidoHttpClientError`.\n */\n errorSchema?: ZodType;\n /**\n * A function to validate the HTTP response status code.\n * Return `true` to consider the status valid, `false` otherwise.\n *\n * When status is invalid, a {@link errors.RapidoHttpClientError `RapidoHttpClientError`} will be thrown.\n *\n * @example (status) => status >= 200 && status < 300\n * @example (status) => status !== 401\n *\n * @default (status) => status < 400\n */\n validateStatus?(status: number): boolean;\n}\n\nexport interface RapidoHttpClientResponse<T = any> {\n data: T;\n status: number;\n statusText: string;\n headers: Record<string, string | string[]>;\n config: RequestConfig & { url: string; method: string; baseURL?: string; };\n}\n\nconst retriableMethods: Dispatcher.HttpMethod[] = ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE', 'QUERY'];\n\nexport class RapidoHttpClient {\n readonly #logger: LoggerInstanceManager;\n private readonly settings: RapidoHttpClientSettings & { baseURL?: string; basePath?: string; };\n public readonly client: Dispatcher.ComposedDispatcher;\n\n public get<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public get<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public get<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public get<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('GET', url, undefined, config);\n }\n\n public post<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public post<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public post<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public post<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('POST', url, body, config);\n }\n\n public delete<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public delete<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public delete<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public delete<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('DELETE', url, undefined, config);\n }\n\n public head<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public head<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public head<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public head<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('HEAD', url, undefined, config);\n }\n\n public put<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public put<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public put<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public put<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('PUT', url, body, config);\n }\n\n public patch<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public patch<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public patch<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public patch<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('PATCH', url, body, config);\n }\n\n public options<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public options<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public options<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public options<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('OPTIONS', url, undefined, config);\n }\n\n public query<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public query<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public query<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public query<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('QUERY', url, body, config);\n }\n\n constructor(settings: RapidoHttpClientSettings) {\n this.#logger = settings.logger.child('RapidoHttpClient', {});\n this.settings = mergeConfig<typeof defaultSettings, Partial<typeof settings>>(\n settings.autoDecompress ? defaultSettingsWithDecompress : defaultSettings,\n settings,\n ) as RapidoHttpClientSettings & { baseURL?: string; };\n this.#createBaseUrl();\n\n // In test mode, use the test dispatcher directly (MockAgent or MockPool) Otherwise, create an Agent which creates Client Pools\n // Check for global mock agent first (for testing), then test param, then create real Agent\n /* c8 ignore next */\n const globalMockAgent = (globalThis as any).__RAPIDO_HTTP_CLIENT_MOCK_AGENT__;\n /* c8 ignore next */\n this.client = this.settings[testAgentParam] ?? globalMockAgent ?? new Agent({\n connect: {\n timeout: this.settings.timeout,\n },\n keepAliveTimeout: this.settings.keepAliveTimeout,\n keepAliveMaxTimeout: this.settings.keepAliveMaxTimeout,\n connections: this.settings.connections,\n });\n\n if (this.settings.cache) {\n this.client = this.client.compose(cache({\n store: new cacheStores.MemoryCacheStore({\n ...this.settings.cache,\n }),\n }));\n }\n\n if (this.settings.retries) {\n this.client = this.client.compose(retry({\n methods: retriableMethods,\n ...this.settings.retries,\n retry: (err, context, callback) => {\n const { counter } = context.state;\n /* c8 ignore next */\n const maxRetries = context.opts.retryOptions?.maxRetries ?? 5;\n\n const retryToUse = this.settings.retries?.retry ?? defaultRetryMethod;\n const callbackWithLogging = (result?: Error | null) => {\n if (!result) {\n const { method, origin, path } = context.opts;\n const baseUrl = (!origin || typeof origin === 'string') ? origin : origin.origin;\n this.#logger.warn(`Request retry attempt ${counter}/${maxRetries}: ${createRequestString(method, baseUrl, path)}`, { err });\n }\n callback(result);\n };\n retryToUse(err, context, callbackWithLogging);\n },\n }));\n }\n\n if (this.settings.autoDecompress) {\n this.client = this.client.compose(decompress({ skipErrorResponses: false }));\n }\n\n this.client = this.client.compose(outbreakInterceptor);\n }\n\n #createBaseUrl(): void {\n const fullUrl = resolveServiceUrl(this.settings);\n const urlObj = new URL(fullUrl);\n this.settings.baseURL = urlObj.origin;\n this.settings.basePath = urlObj.pathname !== '/' ? urlObj.pathname : '';\n }\n\n #getSignal(currentSignal?: AbortSignal, timeout?: number): { signal?: AbortSignal; timeoutSignal?: AbortSignal; } {\n if (!currentSignal && !timeout) {\n return { signal: undefined, timeoutSignal: undefined };\n }\n\n if (currentSignal && !timeout) {\n return { signal: currentSignal, timeoutSignal: undefined };\n }\n\n const timeoutSignal = AbortSignal.timeout(timeout!);\n if (!currentSignal && timeout) {\n return { signal: timeoutSignal, timeoutSignal };\n }\n\n return { signal: AbortSignal.any([currentSignal!, timeoutSignal]), timeoutSignal };\n }\n\n #prepareRequestBody(body: any, headers: Record<string, string>): string | Buffer | FormData | undefined {\n if (body === undefined || body === null) {\n return undefined;\n }\n\n // Handle FormData instances automatically\n if (isFormData(body)) {\n if (!headers['Content-Type'] && !headers['content-type']) {\n headers['Content-Type'] = 'application/x-www-form-urlencoded';\n }\n return body;\n }\n\n if (typeof body === 'object' && !Buffer.isBuffer(body)) {\n // Check if Content-Type is set to application/x-www-form-urlencoded\n const contentType = headers['Content-Type'] || headers['content-type'];\n if (contentType && /application\\/x-www-form-urlencoded/i.test(contentType)) {\n // Encode as URL parameters\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(body)) {\n if (Array.isArray(value)) {\n value.forEach(v => params.append(key, String(v)));\n } else if (value !== undefined && value !== null) {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n params.append(key, String(value));\n }\n }\n return params.toString();\n }\n // Default to JSON\n if (!headers['Content-Type'] && !headers['content-type']) {\n headers['Content-Type'] = 'application/json';\n }\n return JSON.stringify(body);\n }\n if (typeof body === 'string') {\n return body;\n }\n if (Buffer.isBuffer(body)) {\n return body;\n }\n return String(body);\n }\n\n async #request<T = any>(\n method: Dispatcher.HttpMethod,\n url: string,\n body?: any,\n config: RequestConfig = {},\n ): Promise<RapidoHttpClientResponse<T>> {\n const mergedConfig = mergeConfig(this.settings, config);\n\n if (mergedConfig.signal?.aborted) {\n this.#logger.error(`Request aborted before start: ${createRequestString(method, mergedConfig.baseURL, url)}`);\n throw new errors.RequestAbortedError(mergedConfig.signal.reason?.message || 'Request aborted', { cause: mergedConfig.signal.reason });\n }\n\n // Get schemas from config\n const { successSchema, errorSchema } = config;\n\n const headers: Record<string, string> = { ...mergedConfig.headers };\n const requestBody = this.#prepareRequestBody(body, headers);\n\n const { origin, path } = parseUrlAndOrigin(url, mergedConfig.baseURL!, mergedConfig.basePath);\n const requestInfo = { method, baseURL: origin, url };\n\n if (mergedConfig.params) {\n for (const [key, value] of Object.entries(mergedConfig.params)) {\n if (Array.isArray(value) && !key.endsWith('[]')) {\n mergedConfig.params[`${key}[]`] = value;\n delete mergedConfig.params[key];\n }\n }\n }\n\n const { signal, timeoutSignal } = this.#getSignal(mergedConfig.signal, mergedConfig.timeout);\n\n try {\n this.#logger.info(`Start Request: ${createRequestString(method, origin, path)}`);\n\n const requestOptions: Dispatcher.RequestOptions = {\n path,\n origin,\n method,\n signal,\n headers,\n body: requestBody,\n query: mergedConfig.params,\n };\n\n const response = await this.client.request(requestOptions);\n\n if (origin.startsWith('http://') && response.statusCode >= 300 && response.statusCode < 400) {\n const location = [response.headers.location].flat()[0] ?? 'unknown location';\n throw new errors.RapidoHttpClientError(requestBody, response, undefined, {\n requestOptions,\n cause: new Error(`Redirect to ${location} on HTTP origin, which is not supported for security reasons`),\n });\n }\n\n const isStatusValid = mergedConfig.validateStatus ?? (() => response.statusCode < 400);\n if (!isStatusValid(response.statusCode)) {\n const data = await this.#parseErrorResponse(requestBody, response, errorSchema);\n this.#logger.error(`Finish Request with error ${createRequestString(method, origin, path)}`, {\n status: response.statusCode,\n data,\n });\n\n throw new errors.RapidoHttpClientError(requestBody, response, data, { requestOptions });\n }\n\n this.#logger.info(`Finish Request: ${createRequestString(method, origin, path)}`);\n\n const data = response.statusCode !== 204 ? await this.#parseSuccessResponse<T>(requestBody, response, successSchema) : undefined as T;\n\n return {\n data,\n status: response.statusCode,\n statusText: STATUS_CODES[response.statusCode] || '',\n headers: response.headers as Record<string, string | string[]>,\n config: requestInfo,\n };\n } catch (error) {\n if (timeoutSignal && timeoutSignal.reason === error) {\n // If the timeoutSignal aborted (config timeout), throw a timeout-specific error\n this.#logger.error(`Request timeout: ${createRequestString(method, origin, path)}`);\n const error = new errors.UndiciError(`Request timeout after ${mergedConfig.timeout}ms`, { cause: timeoutSignal.reason });\n error.code = 'UND_ERR_TIMEOUT';\n throw error;\n }\n if (signal && signal.reason === error) {\n // If the user's signal aborted, throw RequestAbortedError\n this.#logger.error(`Request aborted: ${createRequestString(method, origin, path)}`);\n throw new errors.RequestAbortedError(signal.reason.message, { cause: signal.reason });\n }\n\n this.#logger.error(`Finish Request with error ${createRequestString(method, origin, path)}`, { error });\n throw error;\n }\n }\n\n async #parseResponse<T>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<T> {\n const contentType = (response.headers['content-type'] as string) || '';\n const bodyText = await response.body.text();\n\n if (!bodyText) {\n return undefined as T;\n }\n\n if (/text/i.test(contentType)) {\n if (!schema) {\n return bodyText as T;\n }\n const parseResult = schema.safeParse(bodyText);\n if (parseResult.success) {\n return parseResult.data as T;\n }\n throw Object.assign(parseResult.error, { json: bodyText });\n }\n\n let json: unknown;\n try {\n json = JSON.parse(bodyText);\n } catch (error) {\n if (!schema) {\n return bodyText as T;\n }\n const parseResult = schema.safeParse(bodyText);\n if (parseResult.success) {\n return parseResult.data as T;\n }\n throw new errors.RapidoHttpClientError(requestBody, response, undefined, { cause: error as Error });\n }\n if (!schema) {\n return json as T;\n }\n const parseResult = schema.safeParse(json);\n if (parseResult.success) {\n return parseResult.data as T;\n }\n throw Object.assign(parseResult.error, { json });\n }\n\n async #parseSuccessResponse<T>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<T> {\n return this.#parseResponse<T>(requestBody, response, schema);\n }\n\n async #parseErrorResponse<TError>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<TError> {\n return this.#parseResponse<TError>(requestBody, response, schema);\n }\n\n /**\n * @param url The endpoint URL to send the request to.\n * @param options Additional options to include in the request payload.\n * @returns A promise that resolves to an array of all results.\n */\n async getAllPages<T>(url: string, options: RequestConfig = {}): Promise<T[]> {\n const currentResult: T[] = [];\n let resultsInFirstPage: number | null = null;\n let lastResultsSize: number | null = null;\n\n const localOptions = { ...options, params: { ...options.params, page: 1 } };\n // Make sure even if `options` had `params` we initialize `page` to 1.\n localOptions.params.page ||= 1;\n\n while ((localOptions.params.page === 1 || lastResultsSize === resultsInFirstPage) && lastResultsSize !== 0) {\n const { data } = await this.get<T[]>(url, localOptions as Omit<RequestConfig, 'successSchema' | 'errorSchema'>);\n lastResultsSize = data.length;\n if (localOptions.params.page === 1) {\n resultsInFirstPage = data.length;\n }\n\n localOptions.params.page += 1;\n Array.prototype.push.apply(currentResult, data);\n }\n\n return currentResult;\n }\n\n /**\n * Fetches all pages from a paginated API endpoint until all results are retrieved\n * or an optional page limit is reached.\n *\n * @param url The endpoint URL to send the request to.\n * @param options Additional options to include in the request payload.\n * @param pageLimit The maximum number of pages to fetch. Set to -1 for no limit.\n * @returns A promise that resolves to an array of all results.\n */\n async getAllPagesFromQueryEndpoint<T>(url: string, options: object = {}, pageLimit = 100): Promise<T[]> {\n const currentResult: T[] = [];\n\n let moreResultsToLoad = true;\n let page = 1;\n while (moreResultsToLoad && (pageLimit === -1 || page < pageLimit)) {\n const { data } = await this.post<{ rows: T[]; count: number; }>(url, {\n ...options,\n page,\n });\n const { rows, count } = data;\n page += 1;\n Array.prototype.push.apply(currentResult, rows);\n moreResultsToLoad = currentResult.length < count;\n }\n\n return currentResult;\n }\n\n async close(): Promise<void> {\n await this.client.close();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n}\n\nexport default RapidoHttpClient;\nexport { errors };\n"],"mappings":"wpBAGA,MAAM,EAA6B,OAAO,IAAI,6BAA6B,kCAI7CA,EAAAA,OAAa,kCACLA,EAAAA,OAAa,0CACbA,EAAAA,OAAa,2CACZA,EAAAA,OAAa,wCACjBA,EAAAA,OAAa,iCAChBA,EAAAA,OAAa,qCACNA,EAAAA,OAAa,+CACVA,EAAAA,OAAa,8CACjBA,EAAAA,OAAa,yCACdA,EAAAA,OAAa,uDACEA,EAAAA,OAAa,uEACZA,EAAAA,OAAa,0DAC3BA,EAAAA,OAAa,yCAChBA,EAAAA,OAAa,gCACnBA,EAAAA,OAAa,gCACPA,EAAAA,OAAa,qDACEA,EAAAA,OAAa,mDAC9BA,EAAAA,OAAa,+CACAA,EAAAA,OAAa,iDACxBA,EAAAA,OAAa,+CACJA,EAAAA,OAAa,oDACjBA,EAAAA,OAAa,uBAE7C,SAAS,EAAwB,EAAgD,CACtF,OAAO,OAAO,GAAU,YAAY,GAAkB,KAA8B,8BAG/E,MAAM,UAAgDA,EAAAA,OAAa,aAAc,CAKtF,YACE,EACA,EACA,EACA,EACA,CACA,MAAM,cAAc,EAAS,aAAc,EAAS,WAAY,CAAE,QAAS,EAAS,QAAS,OAAM,CAAC,CAJpF,KAAA,SAAA,EACA,KAAA,KAAA,EAIhB,KAAK,OAAS,EAAS,WACvB,KAAK,WAAaG,EAAAA,aAAa,EAAS,aAAe,iBACvD,KAAK,eAAiB,GAAc,eAChC,GAAc,QAChB,KAAK,MAAQ,EAAa,OAG5B,OAAO,eAAe,KAAM,EAA4B,CACtD,MAAO,GACP,WAAY,GACZ,SAAU,GACX,CAAC,CAGJ,OAAc,wBAAwB,EAAgD,CACpF,OAAO,EAAwB,EAAM,sCC7D3C,MAAaC,EAAgC,OAAO,iBAAiB,CCGxDC,EAA+D,GAAY,SAAkC,EAAM,EAAS,CACvI,IAAM,GAAA,EAAA,EAAA,oBAAyC,CAAC,QAChD,GAAI,EAAqB,CAEvB,IAAIC,EACJ,AAIE,EAJE,MAAM,QAAQ,EAAK,QAAQ,CAEnB,OAAO,YAAY,EAAK,QAAoD,CAE5E,CAAE,GAAG,EAAK,QAA8C,CAIpE,IAAK,GAAM,CAAC,EAAQ,KAAU,EACxB,OAAO,GAAU,UAAmB,IAAU,SAGlD,EAAQ,GAAU,GAEpB,EAAK,QAAU,EAEjB,OAAO,EAAS,EAAM,EAAQ,ECL1B,CAAE,eAAgBC,EAAAA,QAClB,CAAE,QAAO,QAAO,cAAeC,EAAAA,aA6E/BC,EAA4C,CAAC,MAAO,OAAQ,UAAW,MAAO,SAAU,QAAS,QAAQ,CAE/G,IAAa,EAAb,KAA8B,CAC5B,GAgBA,IAAwB,EAAa,EAA8D,CACjG,OAAO,MAAA,EAAiB,MAAO,EAAK,IAAA,GAAW,EAAO,CAkBxD,KAAyB,EAAa,EAAY,EAA8D,CAC9G,OAAO,MAAA,EAAiB,OAAQ,EAAK,EAAM,EAAO,CAepD,OAA2B,EAAa,EAA8D,CACpG,OAAO,MAAA,EAAiB,SAAU,EAAK,IAAA,GAAW,EAAO,CAe3D,KAAyB,EAAa,EAA8D,CAClG,OAAO,MAAA,EAAiB,OAAQ,EAAK,IAAA,GAAW,EAAO,CAkBzD,IAAwB,EAAa,EAAY,EAA8D,CAC7G,OAAO,MAAA,EAAiB,MAAO,EAAK,EAAM,EAAO,CAkBnD,MAA0B,EAAa,EAAY,EAA8D,CAC/G,OAAO,MAAA,EAAiB,QAAS,EAAK,EAAM,EAAO,CAerD,QAA4B,EAAa,EAA8D,CACrG,OAAO,MAAA,EAAiB,UAAW,EAAK,IAAA,GAAW,EAAO,CAkB5D,MAA0B,EAAa,EAAY,EAA8D,CAC/G,OAAO,MAAA,EAAiB,QAAS,EAAK,EAAM,EAAO,CAGrD,YAAY,EAAoC,CAC9C,MAAA,EAAe,EAAS,OAAO,MAAM,mBAAoB,EAAE,CAAC,CAC5D,KAAK,SAAWG,EAAAA,EACd,EAAS,eAAiBC,EAAAA,EAAgCC,EAAAA,EAC1D,EACD,CACD,MAAA,GAAqB,CAKrB,IAAM,EAAmB,WAAmB,kCAE5C,KAAK,OAAS,KAAK,SAAS,IAAmB,GAAmB,IAAIE,EAAAA,MAAM,CAC1E,QAAS,CACP,QAAS,KAAK,SAAS,QACxB,CACD,iBAAkB,KAAK,SAAS,iBAChC,oBAAqB,KAAK,SAAS,oBACnC,YAAa,KAAK,SAAS,YAC5B,CAAC,CAEE,KAAK,SAAS,QAChB,KAAK,OAAS,KAAK,OAAO,QAAQ,EAAM,CACtC,MAAO,IAAI,EAAY,iBAAiB,CACtC,GAAG,KAAK,SAAS,MAClB,CAAC,CACH,CAAC,CAAC,EAGD,KAAK,SAAS,UAChB,KAAK,OAAS,KAAK,OAAO,QAAQ,EAAM,CACtC,QAAS,EACT,GAAG,KAAK,SAAS,QACjB,OAAQ,EAAK,EAAS,IAAa,CACjC,GAAM,CAAE,WAAY,EAAQ,MAEtB,EAAa,EAAQ,KAAK,cAAc,YAAc,GAEzC,KAAK,SAAS,SAAS,OAASC,EAAAA,GASxC,EAAK,EARa,GAA0B,CACrD,GAAI,CAAC,EAAQ,CACX,GAAM,CAAE,SAAQ,SAAQ,QAAS,EAAQ,KACnC,EAAW,CAAC,GAAU,OAAO,GAAW,SAAY,EAAS,EAAO,OAC1E,MAAA,EAAa,KAAK,yBAAyB,EAAQ,GAAG,EAAW,IAAIC,EAAAA,EAAoB,EAAQ,EAAS,EAAK,GAAI,CAAE,MAAK,CAAC,CAE7H,EAAS,EAAO,EAE2B,EAEhD,CAAC,CAAC,EAGD,KAAK,SAAS,iBAChB,KAAK,OAAS,KAAK,OAAO,QAAQ,EAAW,CAAE,mBAAoB,GAAO,CAAC,CAAC,EAG9E,KAAK,OAAS,KAAK,OAAO,QAAQ,EAAoB,CAGxD,IAAuB,CACrB,IAAM,EAAUC,EAAAA,EAAkB,KAAK,SAAS,CAC1C,EAAS,IAAI,IAAI,EAAQ,CAC/B,KAAK,SAAS,QAAU,EAAO,OAC/B,KAAK,SAAS,SAAW,EAAO,WAAa,IAAwB,GAAlB,EAAO,SAG5D,GAAW,EAA6B,EAA0E,CAChH,GAAI,CAAC,GAAiB,CAAC,EACrB,MAAO,CAAE,OAAQ,IAAA,GAAW,cAAe,IAAA,GAAW,CAGxD,GAAI,GAAiB,CAAC,EACpB,MAAO,CAAE,OAAQ,EAAe,cAAe,IAAA,GAAW,CAG5D,IAAM,EAAgB,YAAY,QAAQ,EAAS,CAKnD,MAJI,CAAC,GAAiB,EACb,CAAE,OAAQ,EAAe,gBAAe,CAG1C,CAAE,OAAQ,YAAY,IAAI,CAAC,EAAgB,EAAc,CAAC,CAAE,gBAAe,CAGpF,GAAoB,EAAW,EAAyE,CAClG,MAA+B,KAKnC,IAAIC,EAAAA,EAAW,EAAK,CAIlB,MAHI,CAAC,EAAQ,iBAAmB,CAAC,EAAQ,kBACvC,EAAQ,gBAAkB,qCAErB,EAGT,GAAI,OAAO,GAAS,UAAY,CAAC,OAAO,SAAS,EAAK,CAAE,CAEtD,IAAM,EAAc,EAAQ,iBAAmB,EAAQ,gBACvD,GAAI,GAAe,sCAAsC,KAAK,EAAY,CAAE,CAE1E,IAAM,EAAS,IAAI,gBACnB,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAK,CACzC,MAAM,QAAQ,EAAM,CACtB,EAAM,QAAQ,GAAK,EAAO,OAAO,EAAK,OAAO,EAAE,CAAC,CAAC,CACxC,GAAiC,MAE1C,EAAO,OAAO,EAAK,OAAO,EAAM,CAAC,CAGrC,OAAO,EAAO,UAAU,CAM1B,MAHI,CAAC,EAAQ,iBAAmB,CAAC,EAAQ,kBACvC,EAAQ,gBAAkB,oBAErB,KAAK,UAAU,EAAK,CAQ7B,OANI,OAAO,GAAS,UAGhB,OAAO,SAAS,EAAK,CAChB,EAEF,OAAO,EAAK,EAGrB,MAAA,EACE,EACA,EACA,EACA,EAAwB,EAAE,CACY,CACtC,IAAM,EAAeR,EAAAA,EAAY,KAAK,SAAU,EAAO,CAEvD,GAAI,EAAa,QAAQ,QAEvB,MADA,MAAA,EAAa,MAAM,iCAAiCM,EAAAA,EAAoB,EAAQ,EAAa,QAAS,EAAI,GAAG,CACvG,IAAI,EAAO,oBAAoB,EAAa,OAAO,QAAQ,SAAW,kBAAmB,CAAE,MAAO,EAAa,OAAO,OAAQ,CAAC,CAIvI,GAAM,CAAE,gBAAe,eAAgB,EAEjCG,EAAkC,CAAE,GAAG,EAAa,QAAS,CAC7D,EAAc,MAAA,EAAyB,EAAM,EAAQ,CAErD,CAAE,SAAQ,QAASE,EAAAA,EAAkB,EAAK,EAAa,QAAU,EAAa,SAAS,CACvF,EAAc,CAAE,SAAQ,QAAS,EAAQ,MAAK,CAEpD,GAAI,EAAa,WACV,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAa,OAAO,CACxD,MAAM,QAAQ,EAAM,EAAI,CAAC,EAAI,SAAS,KAAK,GAC7C,EAAa,OAAO,GAAG,EAAI,KAAO,EAClC,OAAO,EAAa,OAAO,IAKjC,GAAM,CAAE,SAAQ,iBAAkB,MAAA,EAAgB,EAAa,OAAQ,EAAa,QAAQ,CAE5F,GAAI,CACF,MAAA,EAAa,KAAK,kBAAkBL,EAAAA,EAAoB,EAAQ,EAAQ,EAAK,GAAG,CAEhF,IAAMO,EAA4C,CAChD,OACA,SACA,SACA,SACA,UACA,KAAM,EACN,MAAO,EAAa,OACrB,CAEK,EAAW,MAAM,KAAK,OAAO,QAAQ,EAAe,CAE1D,GAAI,EAAO,WAAW,UAAU,EAAI,EAAS,YAAc,KAAO,EAAS,WAAa,IAAK,CAC3F,IAAM,EAAW,CAAC,EAAS,QAAQ,SAAS,CAAC,MAAM,CAAC,IAAM,mBAC1D,MAAM,IAAI,EAAO,sBAAsB,EAAa,EAAU,IAAA,GAAW,CACvE,iBACA,MAAW,MAAM,eAAe,EAAS,8DAA8D,CACxG,CAAC,CAIJ,GAAI,EADkB,EAAa,qBAAyB,EAAS,WAAa,MAC/D,EAAS,WAAW,CAAE,CACvC,IAAM,EAAO,MAAM,MAAA,EAAyB,EAAa,EAAU,EAAY,CAM/E,MALA,MAAA,EAAa,MAAM,6BAA6BP,EAAAA,EAAoB,EAAQ,EAAQ,EAAK,GAAI,CAC3F,OAAQ,EAAS,WACjB,OACD,CAAC,CAEI,IAAI,EAAO,sBAAsB,EAAa,EAAU,EAAM,CAAE,iBAAgB,CAAC,CAOzF,OAJA,MAAA,EAAa,KAAK,mBAAmBA,EAAAA,EAAoB,EAAQ,EAAQ,EAAK,GAAG,CAI1E,CACL,KAHW,EAAS,aAAe,IAAkF,IAAA,GAA5E,MAAM,MAAA,EAA8B,EAAa,EAAU,EAAc,CAIlH,OAAQ,EAAS,WACjB,WAAYU,EAAAA,aAAa,EAAS,aAAe,GACjD,QAAS,EAAS,QAClB,OAAQ,EACT,OACM,EAAO,CACd,GAAI,GAAiB,EAAc,SAAW,EAAO,CAEnD,MAAA,EAAa,MAAM,oBAAoBV,EAAAA,EAAoB,EAAQ,EAAQ,EAAK,GAAG,CACnF,IAAMW,EAAQ,IAAI,EAAO,YAAY,yBAAyB,EAAa,QAAQ,IAAK,CAAE,MAAO,EAAc,OAAQ,CAAC,CAExH,KADA,GAAM,KAAO,kBACPA,EASR,MAPI,GAAU,EAAO,SAAW,GAE9B,MAAA,EAAa,MAAM,oBAAoBX,EAAAA,EAAoB,EAAQ,EAAQ,EAAK,GAAG,CAC7E,IAAI,EAAO,oBAAoB,EAAO,OAAO,QAAS,CAAE,MAAO,EAAO,OAAQ,CAAC,GAGvF,MAAA,EAAa,MAAM,6BAA6BA,EAAAA,EAAoB,EAAQ,EAAQ,EAAK,GAAI,CAAE,QAAO,CAAC,CACjG,IAIV,MAAA,EAAwB,EAA4E,EAAmC,EAA8B,CACnK,IAAM,EAAe,EAAS,QAAQ,iBAA8B,GAC9D,EAAW,MAAM,EAAS,KAAK,MAAM,CAE3C,GAAI,CAAC,EACH,OAGF,GAAI,QAAQ,KAAK,EAAY,CAAE,CAC7B,GAAI,CAAC,EACH,OAAO,EAET,IAAMa,EAAc,EAAO,UAAU,EAAS,CAC9C,GAAIA,EAAY,QACd,OAAOA,EAAY,KAErB,MAAM,OAAO,OAAOA,EAAY,MAAO,CAAE,KAAM,EAAU,CAAC,CAG5D,IAAIC,EACJ,GAAI,CACF,EAAO,KAAK,MAAM,EAAS,OACpB,EAAO,CACd,GAAI,CAAC,EACH,OAAO,EAET,IAAMD,EAAc,EAAO,UAAU,EAAS,CAC9C,GAAIA,EAAY,QACd,OAAOA,EAAY,KAErB,MAAM,IAAI,EAAO,sBAAsB,EAAa,EAAU,IAAA,GAAW,CAAE,MAAO,EAAgB,CAAC,CAErG,GAAI,CAAC,EACH,OAAO,EAET,IAAM,EAAc,EAAO,UAAU,EAAK,CAC1C,GAAI,EAAY,QACd,OAAO,EAAY,KAErB,MAAM,OAAO,OAAO,EAAY,MAAO,CAAE,OAAM,CAAC,CAGlD,MAAA,EAA+B,EAA4E,EAAmC,EAA8B,CAC1K,OAAO,MAAA,EAAuB,EAAa,EAAU,EAAO,CAG9D,MAAA,EAAkC,EAA4E,EAAmC,EAAmC,CAClL,OAAO,MAAA,EAA4B,EAAa,EAAU,EAAO,CAQnE,MAAM,YAAe,EAAa,EAAyB,EAAE,CAAgB,CAC3E,IAAME,EAAqB,EAAE,CACzBC,EAAoC,KACpCC,EAAiC,KAE/B,EAAe,CAAE,GAAG,EAAS,OAAQ,CAAE,GAAG,EAAQ,OAAQ,KAAM,EAAG,CAAE,CAI3E,IAFA,EAAa,OAAO,OAAS,GAErB,EAAa,OAAO,OAAS,GAAK,IAAoB,IAAuB,IAAoB,GAAG,CAC1G,GAAM,CAAE,QAAS,MAAM,KAAK,IAAS,EAAK,EAAqE,CAC/G,EAAkB,EAAK,OACnB,EAAa,OAAO,OAAS,IAC/B,EAAqB,EAAK,QAG5B,EAAa,OAAO,MAAQ,EAC5B,MAAM,UAAU,KAAK,MAAM,EAAe,EAAK,CAGjD,OAAO,EAYT,MAAM,6BAAgC,EAAa,EAAkB,EAAE,CAAE,EAAY,IAAmB,CACtG,IAAMF,EAAqB,EAAE,CAEzB,EAAoB,GACpB,EAAO,EACX,KAAO,IAAsB,IAAc,IAAM,EAAO,IAAY,CAClE,GAAM,CAAE,QAAS,MAAM,KAAK,KAAoC,EAAK,CACnE,GAAG,EACH,OACD,CAAC,CACI,CAAE,OAAM,SAAU,EACxB,GAAQ,EACR,MAAM,UAAU,KAAK,MAAM,EAAe,EAAK,CAC/C,EAAoB,EAAc,OAAS,EAG7C,OAAO,EAGT,MAAM,OAAuB,CAC3B,MAAM,KAAK,OAAO,OAAO,CAG3B,MAAO,OAAO,eAA+B,CAC3C,MAAM,KAAK,OAAO,GAItB,EAAe"}
|
package/dist/index.d.cts
CHANGED
|
@@ -33,7 +33,10 @@ declare namespace errors {
|
|
|
33
33
|
readonly data: TError;
|
|
34
34
|
readonly status: number;
|
|
35
35
|
readonly statusText: string;
|
|
36
|
-
|
|
36
|
+
readonly requestOptions?: Dispatcher.RequestOptions;
|
|
37
|
+
constructor(body: ConstructorParameters<typeof errors$1.ResponseError>[2]["body"], response: Dispatcher.ResponseData, data: TError, errorOptions?: ErrorOptions & {
|
|
38
|
+
requestOptions?: Dispatcher.RequestOptions;
|
|
39
|
+
});
|
|
37
40
|
static isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError;
|
|
38
41
|
}
|
|
39
42
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -33,7 +33,10 @@ declare namespace errors {
|
|
|
33
33
|
readonly data: TError;
|
|
34
34
|
readonly status: number;
|
|
35
35
|
readonly statusText: string;
|
|
36
|
-
|
|
36
|
+
readonly requestOptions?: Dispatcher.RequestOptions;
|
|
37
|
+
constructor(body: ConstructorParameters<typeof errors$1.ResponseError>[2]["body"], response: Dispatcher.ResponseData, data: TError, errorOptions?: ErrorOptions & {
|
|
38
|
+
requestOptions?: Dispatcher.RequestOptions;
|
|
39
|
+
});
|
|
37
40
|
static isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError;
|
|
38
41
|
}
|
|
39
42
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./utils-
|
|
1
|
+
import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./utils-CjxOAe9E.js";import{STATUS_CODES as c}from"node:http";import l,{Agent as u,errors as d,interceptors as f}from"undici";import{getCurrentContext as p}from"@autofleet/outbreak";const m=Symbol.for(`RapidoHttpClientErrorBrand`);let h;(function(e){e.UndiciError=d.UndiciError,e.ConnectTimeoutError=d.ConnectTimeoutError,e.HeadersTimeoutError=d.HeadersTimeoutError,e.HeadersOverflowError=d.HeadersOverflowError,e.BodyTimeoutError=d.BodyTimeoutError,e.ResponseError=d.ResponseError,e.InvalidArgumentError=d.InvalidArgumentError,e.InvalidReturnValueError=d.InvalidReturnValueError,e.RequestAbortedError=d.RequestAbortedError,e.InformationalError=d.InformationalError,e.RequestContentLengthMismatchError=d.RequestContentLengthMismatchError,e.ResponseContentLengthMismatchError=d.ResponseContentLengthMismatchError,e.ClientDestroyedError=d.ClientDestroyedError,e.ClientClosedError=d.ClientClosedError,e.SocketError=d.SocketError,e.NotSupportedError=d.NotSupportedError,e.BalancedPoolMissingUpstreamError=d.BalancedPoolMissingUpstreamError,e.HTTPParserError=d.HTTPParserError,e.ResponseExceededMaxSizeError=d.ResponseExceededMaxSizeError,e.RequestRetryError=d.RequestRetryError,e.SecureProxyConnectionError=d.SecureProxyConnectionError,e.MaxOriginsReachedError=d.MaxOriginsReachedError;function t(e){return typeof e==`object`&&!!e&&m in e}e.isRapidoHttpClientError=t;class n extends d.ResponseError{constructor(e,t,n,r){super(`HTTP Error ${t.statusCode}`,t.statusCode,{headers:t.headers,body:e}),this.response=t,this.data=n,this.status=t.statusCode,this.statusText=c[t.statusCode]||`Unknown Status`,this.requestOptions=r?.requestOptions,r?.cause&&(this.cause=r.cause),Object.defineProperty(this,m,{value:!0,enumerable:!1,writable:!1})}static isRapidoHttpClientError(e){return t(e)}}e.RapidoHttpClientError=n})(h||={});const g=Symbol(`testAgentParam`),_=e=>function(t,n){let r=p().context;if(r){let e;e=Array.isArray(t.headers)?Object.fromEntries(t.headers):{...t.headers};for(let[t,n]of r)typeof n==`symbol`||n===void 0||(e[t]=n);t.headers=e}return e(t,n)},{cacheStores:v}=l,{cache:y,retry:b,decompress:x}=f,S=[`GET`,`HEAD`,`OPTIONS`,`PUT`,`DELETE`,`TRACE`,`QUERY`];var C=class{#e;get(e,t){return this.#i(`GET`,e,void 0,t)}post(e,t,n){return this.#i(`POST`,e,t,n)}delete(e,t){return this.#i(`DELETE`,e,void 0,t)}head(e,t){return this.#i(`HEAD`,e,void 0,t)}put(e,t,n){return this.#i(`PUT`,e,t,n)}patch(e,t,n){return this.#i(`PATCH`,e,t,n)}options(e,t){return this.#i(`OPTIONS`,e,void 0,t)}query(e,t,n){return this.#i(`QUERY`,e,t,n)}constructor(e){this.#e=e.logger.child(`RapidoHttpClient`,{}),this.settings=i(e.autoDecompress?n:a,e),this.#t();let t=globalThis.__RAPIDO_HTTP_CLIENT_MOCK_AGENT__;this.client=this.settings[g]??t??new u({connect:{timeout:this.settings.timeout},keepAliveTimeout:this.settings.keepAliveTimeout,keepAliveMaxTimeout:this.settings.keepAliveMaxTimeout,connections:this.settings.connections}),this.settings.cache&&(this.client=this.client.compose(y({store:new v.MemoryCacheStore({...this.settings.cache})}))),this.settings.retries&&(this.client=this.client.compose(b({methods:S,...this.settings.retries,retry:(e,t,n)=>{let{counter:i}=t.state,a=t.opts.retryOptions?.maxRetries??5;(this.settings.retries?.retry??r)(e,t,r=>{if(!r){let{method:n,origin:r,path:o}=t.opts,c=!r||typeof r==`string`?r:r.origin;this.#e.warn(`Request retry attempt ${i}/${a}: ${s(n,c,o)}`,{err:e})}n(r)})}}))),this.settings.autoDecompress&&(this.client=this.client.compose(x({skipErrorResponses:!1}))),this.client=this.client.compose(_)}#t(){let e=t(this.settings),n=new URL(e);this.settings.baseURL=n.origin,this.settings.basePath=n.pathname===`/`?``:n.pathname}#n(e,t){if(!e&&!t)return{signal:void 0,timeoutSignal:void 0};if(e&&!t)return{signal:e,timeoutSignal:void 0};let n=AbortSignal.timeout(t);return!e&&t?{signal:n,timeoutSignal:n}:{signal:AbortSignal.any([e,n]),timeoutSignal:n}}#r(t,n){if(t!=null){if(e(t))return!n[`Content-Type`]&&!n[`content-type`]&&(n[`Content-Type`]=`application/x-www-form-urlencoded`),t;if(typeof t==`object`&&!Buffer.isBuffer(t)){let e=n[`Content-Type`]||n[`content-type`];if(e&&/application\/x-www-form-urlencoded/i.test(e)){let e=new URLSearchParams;for(let[n,r]of Object.entries(t))Array.isArray(r)?r.forEach(t=>e.append(n,String(t))):r!=null&&e.append(n,String(r));return e.toString()}return!n[`Content-Type`]&&!n[`content-type`]&&(n[`Content-Type`]=`application/json`),JSON.stringify(t)}return typeof t==`string`||Buffer.isBuffer(t)?t:String(t)}}async#i(e,t,n,r={}){let a=i(this.settings,r);if(a.signal?.aborted)throw this.#e.error(`Request aborted before start: ${s(e,a.baseURL,t)}`),new h.RequestAbortedError(a.signal.reason?.message||`Request aborted`,{cause:a.signal.reason});let{successSchema:l,errorSchema:u}=r,d={...a.headers},f=this.#r(n,d),{origin:p,path:m}=o(t,a.baseURL,a.basePath),g={method:e,baseURL:p,url:t};if(a.params)for(let[e,t]of Object.entries(a.params))Array.isArray(t)&&!e.endsWith(`[]`)&&(a.params[`${e}[]`]=t,delete a.params[e]);let{signal:_,timeoutSignal:v}=this.#n(a.signal,a.timeout);try{this.#e.info(`Start Request: ${s(e,p,m)}`);let t={path:m,origin:p,method:e,signal:_,headers:d,body:f,query:a.params},n=await this.client.request(t);if(p.startsWith(`http://`)&&n.statusCode>=300&&n.statusCode<400){let e=[n.headers.location].flat()[0]??`unknown location`;throw new h.RapidoHttpClientError(f,n,void 0,{requestOptions:t,cause:Error(`Redirect to ${e} on HTTP origin, which is not supported for security reasons`)})}if(!(a.validateStatus??(()=>n.statusCode<400))(n.statusCode)){let r=await this.#s(f,n,u);throw this.#e.error(`Finish Request with error ${s(e,p,m)}`,{status:n.statusCode,data:r}),new h.RapidoHttpClientError(f,n,r,{requestOptions:t})}return this.#e.info(`Finish Request: ${s(e,p,m)}`),{data:n.statusCode===204?void 0:await this.#o(f,n,l),status:n.statusCode,statusText:c[n.statusCode]||``,headers:n.headers,config:g}}catch(t){if(v&&v.reason===t){this.#e.error(`Request timeout: ${s(e,p,m)}`);let t=new h.UndiciError(`Request timeout after ${a.timeout}ms`,{cause:v.reason});throw t.code=`UND_ERR_TIMEOUT`,t}throw _&&_.reason===t?(this.#e.error(`Request aborted: ${s(e,p,m)}`),new h.RequestAbortedError(_.reason.message,{cause:_.reason})):(this.#e.error(`Finish Request with error ${s(e,p,m)}`,{error:t}),t)}}async#a(e,t,n){let r=t.headers[`content-type`]||``,i=await t.body.text();if(!i)return;if(/text/i.test(r)){if(!n)return i;let e=n.safeParse(i);if(e.success)return e.data;throw Object.assign(e.error,{json:i})}let a;try{a=JSON.parse(i)}catch(r){if(!n)return i;let a=n.safeParse(i);if(a.success)return a.data;throw new h.RapidoHttpClientError(e,t,void 0,{cause:r})}if(!n)return a;let o=n.safeParse(a);if(o.success)return o.data;throw Object.assign(o.error,{json:a})}async#o(e,t,n){return this.#a(e,t,n)}async#s(e,t,n){return this.#a(e,t,n)}async getAllPages(e,t={}){let n=[],r=null,i=null,a={...t,params:{...t.params,page:1}};for(a.params.page||=1;(a.params.page===1||i===r)&&i!==0;){let{data:t}=await this.get(e,a);i=t.length,a.params.page===1&&(r=t.length),a.params.page+=1,Array.prototype.push.apply(n,t)}return n}async getAllPagesFromQueryEndpoint(e,t={},n=100){let r=[],i=!0,a=1;for(;i&&(n===-1||a<n);){let{data:n}=await this.post(e,{...t,page:a}),{rows:o,count:s}=n;a+=1,Array.prototype.push.apply(r,o),i=r.length<s}return r}async close(){await this.client.close()}async[Symbol.asyncDispose](){await this.close()}},w=C;export{C as RapidoHttpClient,w as default,h as errors};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["undiciErrors","response: Dispatcher.ResponseData","data: TError","testAgentParam: unique symbol","outbreakInterceptor: Dispatcher.DispatcherComposeInterceptor","headers: Record<string, string | string[]>","retriableMethods: Dispatcher.HttpMethod[]","#logger","#request","#createBaseUrl","headers: Record<string, string>","#prepareRequestBody","#getSignal","requestOptions: Dispatcher.RequestOptions","#parseErrorResponse","#parseSuccessResponse","error","#parseResponse","json: unknown","parseResult","currentResult: T[]","resultsInFirstPage: number | null","lastResultsSize: number | null"],"sources":["../src/errors.ts","../src/testingHelper.ts","../src/outbreakInterceptor.ts","../src/index.ts"],"sourcesContent":["import { STATUS_CODES } from 'node:http';\nimport { type Dispatcher, errors as undiciErrors } from 'undici';\n\nconst RapidoHttpClientErrorBrand = Symbol.for('RapidoHttpClientErrorBrand');\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace errors {\n export import UndiciError = undiciErrors.UndiciError;\n export import ConnectTimeoutError = undiciErrors.ConnectTimeoutError;\n export import HeadersTimeoutError = undiciErrors.HeadersTimeoutError;\n export import HeadersOverflowError = undiciErrors.HeadersOverflowError;\n export import BodyTimeoutError = undiciErrors.BodyTimeoutError;\n export import ResponseError = undiciErrors.ResponseError;\n export import InvalidArgumentError = undiciErrors.InvalidArgumentError;\n export import InvalidReturnValueError = undiciErrors.InvalidReturnValueError;\n export import RequestAbortedError = undiciErrors.RequestAbortedError;\n export import InformationalError = undiciErrors.InformationalError;\n export import RequestContentLengthMismatchError = undiciErrors.RequestContentLengthMismatchError;\n export import ResponseContentLengthMismatchError = undiciErrors.ResponseContentLengthMismatchError;\n export import ClientDestroyedError = undiciErrors.ClientDestroyedError;\n export import ClientClosedError = undiciErrors.ClientClosedError;\n export import SocketError = undiciErrors.SocketError;\n export import NotSupportedError = undiciErrors.NotSupportedError;\n export import BalancedPoolMissingUpstreamError = undiciErrors.BalancedPoolMissingUpstreamError;\n export import HTTPParserError = undiciErrors.HTTPParserError;\n export import ResponseExceededMaxSizeError = undiciErrors.ResponseExceededMaxSizeError;\n export import RequestRetryError = undiciErrors.RequestRetryError;\n export import SecureProxyConnectionError = undiciErrors.SecureProxyConnectionError;\n export import MaxOriginsReachedError = undiciErrors.MaxOriginsReachedError;\n\n export function isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError {\n return typeof value === 'object' && value !== null && RapidoHttpClientErrorBrand in value;\n }\n\n export class RapidoHttpClientError<TError = unknown> extends undiciErrors.ResponseError {\n public readonly status: number;\n public readonly statusText: string;\n\n constructor(\n body: ConstructorParameters<typeof undiciErrors.ResponseError>[2]['body'],\n public readonly response: Dispatcher.ResponseData,\n public readonly data: TError,\n errorOptions?: ErrorOptions,\n ) {\n super(`HTTP Error ${response.statusCode}`, response.statusCode, { headers: response.headers, body });\n this.status = response.statusCode;\n this.statusText = STATUS_CODES[response.statusCode] || 'Unknown Status';\n if (errorOptions?.cause) {\n this.cause = errorOptions.cause;\n }\n\n Object.defineProperty(this, RapidoHttpClientErrorBrand, {\n value: true,\n enumerable: false,\n writable: false,\n });\n }\n\n public static isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError {\n return isRapidoHttpClientError(value);\n }\n }\n}\n","export const testAgentParam: unique symbol = Symbol('testAgentParam');\n","import type { Dispatcher } from 'undici';\nimport { getCurrentContext } from '@autofleet/outbreak';\n\nexport const outbreakInterceptor: Dispatcher.DispatcherComposeInterceptor = dispatch => function outbreakInterceptorInner(opts, handler) {\n const currentTraceContext = getCurrentContext().context;\n if (currentTraceContext) {\n // Convert headers to object format if they're in array format\n let headers: Record<string, string | string[]>;\n if (Array.isArray(opts.headers)) {\n /* c8 ignore next */\n headers = Object.fromEntries(opts.headers as unknown as [string, string | string[]][]);\n } else {\n headers = { ...opts.headers as Record<string, string | string[]> };\n }\n\n // Inject outbreak trace headers\n for (const [header, value] of currentTraceContext) {\n if (typeof value === 'symbol' || typeof value === 'undefined') {\n continue;\n }\n headers[header] = value as string;\n }\n opts.headers = headers;\n }\n return dispatch(opts, handler);\n};\n","import { STATUS_CODES } from 'node:http';\nimport type { ZodType, output } from 'zod';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport type CacheHandler from 'undici/types/cache-interceptor';\nimport Undici, { Agent, type Dispatcher, interceptors } from 'undici';\nimport { errors } from './errors';\nimport { testAgentParam } from './testingHelper';\nimport { outbreakInterceptor } from './outbreakInterceptor';\nimport {\n createRequestString,\n defaultRetryMethod,\n defaultSettings,\n defaultSettingsWithDecompress,\n isFormData,\n mergeConfig,\n parseUrlAndOrigin,\n resolveServiceUrl,\n} from './utils';\n\nconst { cacheStores } = Undici;\nconst { cache, retry, decompress } = interceptors;\n\nexport interface RapidoHttpClientSettings {\n [testAgentParam]?: Dispatcher;\n /** The MS name to be used to resolve the base URL using K8S service discovery. Ignored if `serviceUrl` is provided as well. */\n serviceName?: string;\n /** The base URL to be used. Overrides `serviceName` when provided. */\n serviceUrl?: string;\n logger: LoggerInstanceManager;\n /** The request timeout in milliseconds. @default 10_000 */\n timeout?: number;\n /** Settings for retrying requests on failure */\n retries?: interceptors.RetryInterceptorOpts;\n /** Common headers applied to all requests of this `RapidoHttpClient` instance. */\n headers?: Record<string, string> | string[][];\n keepAliveTimeout?: number;\n keepAliveMaxTimeout?: number;\n /** The amount of concurrent connections to be maintained using a connection pool. @default 10 */\n connections?: number;\n /** The settings for caching requests */\n cache?: CacheHandler.MemoryCacheStoreOpts;\n /** Whether to automatically decompress response bodies. When `true` will automatically add an `Accept-Encoding` header. @default false */\n autoDecompress?: boolean;\n /**\n * A function to validate the HTTP response status code.\n * Return `true` to consider the status valid, `false` otherwise.\n *\n * When status is invalid, a {@link errors.RapidoHttpClientError `RapidoHttpClientError`} will be thrown.\n *\n * @example (status) => status >= 200 && status < 300\n * @example (status) => status !== 401\n *\n * @default (status) => status < 400\n */\n validateStatus?(status: number): boolean;\n}\n\nexport interface RequestConfig {\n params?: Record<string, any>;\n body?: any;\n /** The request timeout in milliseconds. This overrides the client's instance setting @default 10_000 */\n timeout?: number;\n /** Headers applied to this request, appending on the client's common headers. */\n headers?: Record<string, string>;\n /** An `AbortSignal` which should abort the request and it's parsing when aborted. */\n signal?: AbortSignal;\n /**\n * Zod schema for successful responses. Used when `validateStatus` returns `true` (default: status < 400).\n */\n successSchema?: ZodType;\n /**\n * Zod schema for error responses. Used when `validateStatus` returns `false` (default: status >= 400).\n * The validated error data is available in the thrown `RapidoHttpClientError`.\n */\n errorSchema?: ZodType;\n /**\n * A function to validate the HTTP response status code.\n * Return `true` to consider the status valid, `false` otherwise.\n *\n * When status is invalid, a {@link errors.RapidoHttpClientError `RapidoHttpClientError`} will be thrown.\n *\n * @example (status) => status >= 200 && status < 300\n * @example (status) => status !== 401\n *\n * @default (status) => status < 400\n */\n validateStatus?(status: number): boolean;\n}\n\nexport interface RapidoHttpClientResponse<T = any> {\n data: T;\n status: number;\n statusText: string;\n headers: Record<string, string | string[]>;\n config: RequestConfig & { url: string; method: string; baseURL?: string; };\n}\n\nconst retriableMethods: Dispatcher.HttpMethod[] = ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE', 'QUERY'];\n\nexport class RapidoHttpClient {\n readonly #logger: LoggerInstanceManager;\n private readonly settings: RapidoHttpClientSettings & { baseURL?: string; basePath?: string; };\n public readonly client: Dispatcher.ComposedDispatcher;\n\n public get<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public get<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public get<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public get<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('GET', url, undefined, config);\n }\n\n public post<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public post<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public post<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public post<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('POST', url, body, config);\n }\n\n public delete<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public delete<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public delete<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public delete<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('DELETE', url, undefined, config);\n }\n\n public head<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public head<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public head<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public head<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('HEAD', url, undefined, config);\n }\n\n public put<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public put<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public put<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public put<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('PUT', url, body, config);\n }\n\n public patch<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public patch<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public patch<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public patch<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('PATCH', url, body, config);\n }\n\n public options<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public options<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public options<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public options<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('OPTIONS', url, undefined, config);\n }\n\n public query<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public query<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public query<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public query<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('QUERY', url, body, config);\n }\n\n constructor(settings: RapidoHttpClientSettings) {\n this.#logger = settings.logger.child('RapidoHttpClient', {});\n this.settings = mergeConfig<typeof defaultSettings, Partial<typeof settings>>(\n settings.autoDecompress ? defaultSettingsWithDecompress : defaultSettings,\n settings,\n ) as RapidoHttpClientSettings & { baseURL?: string; };\n this.#createBaseUrl();\n\n // In test mode, use the test dispatcher directly (MockAgent or MockPool) Otherwise, create an Agent which creates Client Pools\n // Check for global mock agent first (for testing), then test param, then create real Agent\n /* c8 ignore next */\n const globalMockAgent = (globalThis as any).__RAPIDO_HTTP_CLIENT_MOCK_AGENT__;\n /* c8 ignore next */\n this.client = this.settings[testAgentParam] ?? globalMockAgent ?? new Agent({\n connect: {\n timeout: this.settings.timeout,\n },\n keepAliveTimeout: this.settings.keepAliveTimeout,\n keepAliveMaxTimeout: this.settings.keepAliveMaxTimeout,\n connections: this.settings.connections,\n });\n\n if (this.settings.cache) {\n this.client = this.client.compose(cache({\n store: new cacheStores.MemoryCacheStore({\n ...this.settings.cache,\n }),\n }));\n }\n\n if (this.settings.retries) {\n this.client = this.client.compose(retry({\n methods: retriableMethods,\n ...this.settings.retries,\n retry: (err, context, callback) => {\n const { counter } = context.state;\n /* c8 ignore next */\n const maxRetries = context.opts.retryOptions?.maxRetries ?? 5;\n\n const retryToUse = this.settings.retries?.retry ?? defaultRetryMethod;\n const callbackWithLogging = (result?: Error | null) => {\n if (!result) {\n const { method, origin, path } = context.opts;\n const baseUrl = (!origin || typeof origin === 'string') ? origin : origin.origin;\n this.#logger.warn(`Request retry attempt ${counter}/${maxRetries}: ${createRequestString(method, baseUrl, path)}`, { err });\n }\n callback(result);\n };\n retryToUse(err, context, callbackWithLogging);\n },\n }));\n }\n\n if (this.settings.autoDecompress) {\n this.client = this.client.compose(decompress({ skipErrorResponses: false }));\n }\n\n this.client = this.client.compose(outbreakInterceptor);\n }\n\n #createBaseUrl(): void {\n const fullUrl = resolveServiceUrl(this.settings);\n const urlObj = new URL(fullUrl);\n this.settings.baseURL = urlObj.origin;\n this.settings.basePath = urlObj.pathname !== '/' ? urlObj.pathname : '';\n }\n\n #getSignal(currentSignal?: AbortSignal, timeout?: number): { signal?: AbortSignal; timeoutSignal?: AbortSignal; } {\n if (!currentSignal && !timeout) {\n return { signal: undefined, timeoutSignal: undefined };\n }\n\n if (currentSignal && !timeout) {\n return { signal: currentSignal, timeoutSignal: undefined };\n }\n\n const timeoutSignal = AbortSignal.timeout(timeout!);\n if (!currentSignal && timeout) {\n return { signal: timeoutSignal, timeoutSignal };\n }\n\n return { signal: AbortSignal.any([currentSignal!, timeoutSignal]), timeoutSignal };\n }\n\n #prepareRequestBody(body: any, headers: Record<string, string>): string | Buffer | FormData | undefined {\n if (body === undefined || body === null) {\n return undefined;\n }\n\n // Handle FormData instances automatically\n if (isFormData(body)) {\n if (!headers['Content-Type'] && !headers['content-type']) {\n headers['Content-Type'] = 'application/x-www-form-urlencoded';\n }\n return body;\n }\n\n if (typeof body === 'object' && !Buffer.isBuffer(body)) {\n // Check if Content-Type is set to application/x-www-form-urlencoded\n const contentType = headers['Content-Type'] || headers['content-type'];\n if (contentType && /application\\/x-www-form-urlencoded/i.test(contentType)) {\n // Encode as URL parameters\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(body)) {\n if (Array.isArray(value)) {\n value.forEach(v => params.append(key, String(v)));\n } else if (value !== undefined && value !== null) {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n params.append(key, String(value));\n }\n }\n return params.toString();\n }\n // Default to JSON\n if (!headers['Content-Type'] && !headers['content-type']) {\n headers['Content-Type'] = 'application/json';\n }\n return JSON.stringify(body);\n }\n if (typeof body === 'string') {\n return body;\n }\n if (Buffer.isBuffer(body)) {\n return body;\n }\n return String(body);\n }\n\n async #request<T = any>(\n method: Dispatcher.HttpMethod,\n url: string,\n body?: any,\n config: RequestConfig = {},\n ): Promise<RapidoHttpClientResponse<T>> {\n const mergedConfig = mergeConfig(this.settings, config);\n\n if (mergedConfig.signal?.aborted) {\n this.#logger.error(`Request aborted before start: ${createRequestString(method, mergedConfig.baseURL, url)}`);\n throw new errors.RequestAbortedError(mergedConfig.signal.reason?.message || 'Request aborted', { cause: mergedConfig.signal.reason });\n }\n\n // Get schemas from config\n const { successSchema, errorSchema } = config;\n\n const headers: Record<string, string> = { ...mergedConfig.headers };\n const requestBody = this.#prepareRequestBody(body, headers);\n\n const { origin, path } = parseUrlAndOrigin(url, mergedConfig.baseURL!, mergedConfig.basePath);\n const requestInfo = { method, baseURL: origin, url };\n\n if (mergedConfig.params) {\n for (const [key, value] of Object.entries(mergedConfig.params)) {\n if (Array.isArray(value) && !key.endsWith('[]')) {\n mergedConfig.params[`${key}[]`] = value;\n delete mergedConfig.params[key];\n }\n }\n }\n\n const { signal, timeoutSignal } = this.#getSignal(mergedConfig.signal, mergedConfig.timeout);\n\n try {\n this.#logger.info(`Start Request: ${createRequestString(method, origin, path)}`);\n\n const requestOptions: Dispatcher.RequestOptions = {\n path,\n origin,\n method,\n signal,\n headers,\n body: requestBody,\n query: mergedConfig.params,\n };\n\n const response = await this.client.request(requestOptions);\n\n const isStatusValid = mergedConfig.validateStatus ?? (() => response.statusCode < 400);\n if (!isStatusValid(response.statusCode)) {\n const data = await this.#parseErrorResponse(requestBody, response, errorSchema);\n this.#logger.error(`Finish Request with error ${createRequestString(method, origin, path)}`, {\n status: response.statusCode,\n data,\n });\n\n throw new errors.RapidoHttpClientError(requestBody, response, data);\n }\n\n this.#logger.info(`Finish Request: ${createRequestString(method, origin, path)}`);\n\n const data = response.statusCode !== 204 ? await this.#parseSuccessResponse<T>(requestBody, response, successSchema) : undefined as T;\n\n return {\n data,\n status: response.statusCode,\n statusText: STATUS_CODES[response.statusCode] || '',\n headers: response.headers as Record<string, string | string[]>,\n config: requestInfo,\n };\n } catch (error) {\n if (timeoutSignal && timeoutSignal.reason === error) {\n // If the timeoutSignal aborted (config timeout), throw a timeout-specific error\n this.#logger.error(`Request timeout: ${createRequestString(method, origin, path)}`);\n const error = new errors.UndiciError(`Request timeout after ${mergedConfig.timeout}ms`, { cause: timeoutSignal.reason });\n error.code = 'UND_ERR_TIMEOUT';\n throw error;\n }\n if (signal && signal.reason === error) {\n // If the user's signal aborted, throw RequestAbortedError\n this.#logger.error(`Request aborted: ${createRequestString(method, origin, path)}`);\n throw new errors.RequestAbortedError(signal.reason.message, { cause: signal.reason });\n }\n\n this.#logger.error(`Finish Request with error ${createRequestString(method, origin, path)}`, { error });\n throw error;\n }\n }\n\n async #parseResponse<T>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<T> {\n const contentType = (response.headers['content-type'] as string) || '';\n const bodyText = await response.body.text();\n\n if (!bodyText) {\n return undefined as T;\n }\n\n if (/text/i.test(contentType)) {\n return bodyText as T;\n }\n\n let json: unknown;\n try {\n json = JSON.parse(bodyText);\n } catch (error) {\n if (!schema) {\n return bodyText as T;\n }\n const parseResult = schema.safeParse(bodyText);\n if (parseResult.success) {\n return parseResult.data as T;\n }\n throw new errors.RapidoHttpClientError(requestBody, response, undefined, { cause: error as Error });\n }\n if (!schema) {\n return json as T;\n }\n const parseResult = schema.safeParse(json);\n if (parseResult.success) {\n return parseResult.data as T;\n }\n throw Object.assign(parseResult.error, { json });\n }\n\n async #parseSuccessResponse<T>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<T> {\n return this.#parseResponse<T>(requestBody, response, schema);\n }\n\n async #parseErrorResponse<TError>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<TError> {\n return this.#parseResponse<TError>(requestBody, response, schema);\n }\n\n /**\n * @param url The endpoint URL to send the request to.\n * @param options Additional options to include in the request payload.\n * @returns A promise that resolves to an array of all results.\n */\n async getAllPages<T>(url: string, options: RequestConfig = {}): Promise<T[]> {\n const currentResult: T[] = [];\n let resultsInFirstPage: number | null = null;\n let lastResultsSize: number | null = null;\n\n const localOptions = { ...options, params: { ...options.params, page: 1 } };\n // Make sure even if `options` had `params` we initialize `page` to 1.\n localOptions.params.page ||= 1;\n\n while ((localOptions.params.page === 1 || lastResultsSize === resultsInFirstPage) && lastResultsSize !== 0) {\n const { data } = await this.get<T[]>(url, localOptions as Omit<RequestConfig, 'successSchema' | 'errorSchema'>);\n lastResultsSize = data.length;\n if (localOptions.params.page === 1) {\n resultsInFirstPage = data.length;\n }\n\n localOptions.params.page += 1;\n Array.prototype.push.apply(currentResult, data);\n }\n\n return currentResult;\n }\n\n /**\n * Fetches all pages from a paginated API endpoint until all results are retrieved\n * or an optional page limit is reached.\n *\n * @param url The endpoint URL to send the request to.\n * @param options Additional options to include in the request payload.\n * @param pageLimit The maximum number of pages to fetch. Set to -1 for no limit.\n * @returns A promise that resolves to an array of all results.\n */\n async getAllPagesFromQueryEndpoint<T>(url: string, options: object = {}, pageLimit = 100): Promise<T[]> {\n const currentResult: T[] = [];\n\n let moreResultsToLoad = true;\n let page = 1;\n while (moreResultsToLoad && (pageLimit === -1 || page < pageLimit)) {\n const { data } = await this.post<{ rows: T[]; count: number; }>(url, {\n ...options,\n page,\n });\n const { rows, count } = data;\n page += 1;\n Array.prototype.push.apply(currentResult, rows);\n moreResultsToLoad = currentResult.length < count;\n }\n\n return currentResult;\n }\n\n async close(): Promise<void> {\n await this.client.close();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n}\n\nexport default RapidoHttpClient;\nexport { errors };\n"],"mappings":"0PAGA,MAAM,EAA6B,OAAO,IAAI,6BAA6B,kCAI7CA,EAAa,kCACLA,EAAa,0CACbA,EAAa,2CACZA,EAAa,wCACjBA,EAAa,iCAChBA,EAAa,qCACNA,EAAa,+CACVA,EAAa,8CACjBA,EAAa,yCACdA,EAAa,uDACEA,EAAa,uEACZA,EAAa,0DAC3BA,EAAa,yCAChBA,EAAa,gCACnBA,EAAa,gCACPA,EAAa,qDACEA,EAAa,mDAC9BA,EAAa,+CACAA,EAAa,iDACxBA,EAAa,+CACJA,EAAa,oDACjBA,EAAa,uBAE7C,SAAS,EAAwB,EAAgD,CACtF,OAAO,OAAO,GAAU,YAAY,GAAkB,KAA8B,8BAG/E,MAAM,UAAgDA,EAAa,aAAc,CAItF,YACE,EACA,EACA,EACA,EACA,CACA,MAAM,cAAc,EAAS,aAAc,EAAS,WAAY,CAAE,QAAS,EAAS,QAAS,OAAM,CAAC,CAJpF,KAAA,SAAA,EACA,KAAA,KAAA,EAIhB,KAAK,OAAS,EAAS,WACvB,KAAK,WAAa,EAAa,EAAS,aAAe,iBACnD,GAAc,QAChB,KAAK,MAAQ,EAAa,OAG5B,OAAO,eAAe,KAAM,EAA4B,CACtD,MAAO,GACP,WAAY,GACZ,SAAU,GACX,CAAC,CAGJ,OAAc,wBAAwB,EAAgD,CACpF,OAAO,EAAwB,EAAM,sCC3D3C,MAAaG,EAAgC,OAAO,iBAAiB,CCGxDC,EAA+D,GAAY,SAAkC,EAAM,EAAS,CACvI,IAAM,EAAsB,GAAmB,CAAC,QAChD,GAAI,EAAqB,CAEvB,IAAIC,EACJ,AAIE,EAJE,MAAM,QAAQ,EAAK,QAAQ,CAEnB,OAAO,YAAY,EAAK,QAAoD,CAE5E,CAAE,GAAG,EAAK,QAA8C,CAIpE,IAAK,GAAM,CAAC,EAAQ,KAAU,EACxB,OAAO,GAAU,UAAmB,IAAU,SAGlD,EAAQ,GAAU,GAEpB,EAAK,QAAU,EAEjB,OAAO,EAAS,EAAM,EAAQ,ECL1B,CAAE,eAAgB,EAClB,CAAE,QAAO,QAAO,cAAe,EA6E/BC,EAA4C,CAAC,MAAO,OAAQ,UAAW,MAAO,SAAU,QAAS,QAAQ,CAE/G,IAAa,EAAb,KAA8B,CAC5B,GAgBA,IAAwB,EAAa,EAA8D,CACjG,OAAO,MAAA,EAAiB,MAAO,EAAK,IAAA,GAAW,EAAO,CAkBxD,KAAyB,EAAa,EAAY,EAA8D,CAC9G,OAAO,MAAA,EAAiB,OAAQ,EAAK,EAAM,EAAO,CAepD,OAA2B,EAAa,EAA8D,CACpG,OAAO,MAAA,EAAiB,SAAU,EAAK,IAAA,GAAW,EAAO,CAe3D,KAAyB,EAAa,EAA8D,CAClG,OAAO,MAAA,EAAiB,OAAQ,EAAK,IAAA,GAAW,EAAO,CAkBzD,IAAwB,EAAa,EAAY,EAA8D,CAC7G,OAAO,MAAA,EAAiB,MAAO,EAAK,EAAM,EAAO,CAkBnD,MAA0B,EAAa,EAAY,EAA8D,CAC/G,OAAO,MAAA,EAAiB,QAAS,EAAK,EAAM,EAAO,CAerD,QAA4B,EAAa,EAA8D,CACrG,OAAO,MAAA,EAAiB,UAAW,EAAK,IAAA,GAAW,EAAO,CAkB5D,MAA0B,EAAa,EAAY,EAA8D,CAC/G,OAAO,MAAA,EAAiB,QAAS,EAAK,EAAM,EAAO,CAGrD,YAAY,EAAoC,CAC9C,MAAA,EAAe,EAAS,OAAO,MAAM,mBAAoB,EAAE,CAAC,CAC5D,KAAK,SAAW,EACd,EAAS,eAAiB,EAAgC,EAC1D,EACD,CACD,MAAA,GAAqB,CAKrB,IAAM,EAAmB,WAAmB,kCAE5C,KAAK,OAAS,KAAK,SAAS,IAAmB,GAAmB,IAAI,EAAM,CAC1E,QAAS,CACP,QAAS,KAAK,SAAS,QACxB,CACD,iBAAkB,KAAK,SAAS,iBAChC,oBAAqB,KAAK,SAAS,oBACnC,YAAa,KAAK,SAAS,YAC5B,CAAC,CAEE,KAAK,SAAS,QAChB,KAAK,OAAS,KAAK,OAAO,QAAQ,EAAM,CACtC,MAAO,IAAI,EAAY,iBAAiB,CACtC,GAAG,KAAK,SAAS,MAClB,CAAC,CACH,CAAC,CAAC,EAGD,KAAK,SAAS,UAChB,KAAK,OAAS,KAAK,OAAO,QAAQ,EAAM,CACtC,QAAS,EACT,GAAG,KAAK,SAAS,QACjB,OAAQ,EAAK,EAAS,IAAa,CACjC,GAAM,CAAE,WAAY,EAAQ,MAEtB,EAAa,EAAQ,KAAK,cAAc,YAAc,GAEzC,KAAK,SAAS,SAAS,OAAS,GASxC,EAAK,EARa,GAA0B,CACrD,GAAI,CAAC,EAAQ,CACX,GAAM,CAAE,SAAQ,SAAQ,QAAS,EAAQ,KACnC,EAAW,CAAC,GAAU,OAAO,GAAW,SAAY,EAAS,EAAO,OAC1E,MAAA,EAAa,KAAK,yBAAyB,EAAQ,GAAG,EAAW,IAAI,EAAoB,EAAQ,EAAS,EAAK,GAAI,CAAE,MAAK,CAAC,CAE7H,EAAS,EAAO,EAE2B,EAEhD,CAAC,CAAC,EAGD,KAAK,SAAS,iBAChB,KAAK,OAAS,KAAK,OAAO,QAAQ,EAAW,CAAE,mBAAoB,GAAO,CAAC,CAAC,EAG9E,KAAK,OAAS,KAAK,OAAO,QAAQ,EAAoB,CAGxD,IAAuB,CACrB,IAAM,EAAU,EAAkB,KAAK,SAAS,CAC1C,EAAS,IAAI,IAAI,EAAQ,CAC/B,KAAK,SAAS,QAAU,EAAO,OAC/B,KAAK,SAAS,SAAW,EAAO,WAAa,IAAwB,GAAlB,EAAO,SAG5D,GAAW,EAA6B,EAA0E,CAChH,GAAI,CAAC,GAAiB,CAAC,EACrB,MAAO,CAAE,OAAQ,IAAA,GAAW,cAAe,IAAA,GAAW,CAGxD,GAAI,GAAiB,CAAC,EACpB,MAAO,CAAE,OAAQ,EAAe,cAAe,IAAA,GAAW,CAG5D,IAAM,EAAgB,YAAY,QAAQ,EAAS,CAKnD,MAJI,CAAC,GAAiB,EACb,CAAE,OAAQ,EAAe,gBAAe,CAG1C,CAAE,OAAQ,YAAY,IAAI,CAAC,EAAgB,EAAc,CAAC,CAAE,gBAAe,CAGpF,GAAoB,EAAW,EAAyE,CAClG,MAA+B,KAKnC,IAAI,EAAW,EAAK,CAIlB,MAHI,CAAC,EAAQ,iBAAmB,CAAC,EAAQ,kBACvC,EAAQ,gBAAkB,qCAErB,EAGT,GAAI,OAAO,GAAS,UAAY,CAAC,OAAO,SAAS,EAAK,CAAE,CAEtD,IAAM,EAAc,EAAQ,iBAAmB,EAAQ,gBACvD,GAAI,GAAe,sCAAsC,KAAK,EAAY,CAAE,CAE1E,IAAM,EAAS,IAAI,gBACnB,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAK,CACzC,MAAM,QAAQ,EAAM,CACtB,EAAM,QAAQ,GAAK,EAAO,OAAO,EAAK,OAAO,EAAE,CAAC,CAAC,CACxC,GAAiC,MAE1C,EAAO,OAAO,EAAK,OAAO,EAAM,CAAC,CAGrC,OAAO,EAAO,UAAU,CAM1B,MAHI,CAAC,EAAQ,iBAAmB,CAAC,EAAQ,kBACvC,EAAQ,gBAAkB,oBAErB,KAAK,UAAU,EAAK,CAQ7B,OANI,OAAO,GAAS,UAGhB,OAAO,SAAS,EAAK,CAChB,EAEF,OAAO,EAAK,EAGrB,MAAA,EACE,EACA,EACA,EACA,EAAwB,EAAE,CACY,CACtC,IAAM,EAAe,EAAY,KAAK,SAAU,EAAO,CAEvD,GAAI,EAAa,QAAQ,QAEvB,MADA,MAAA,EAAa,MAAM,iCAAiC,EAAoB,EAAQ,EAAa,QAAS,EAAI,GAAG,CACvG,IAAI,EAAO,oBAAoB,EAAa,OAAO,QAAQ,SAAW,kBAAmB,CAAE,MAAO,EAAa,OAAO,OAAQ,CAAC,CAIvI,GAAM,CAAE,gBAAe,eAAgB,EAEjCI,EAAkC,CAAE,GAAG,EAAa,QAAS,CAC7D,EAAc,MAAA,EAAyB,EAAM,EAAQ,CAErD,CAAE,SAAQ,QAAS,EAAkB,EAAK,EAAa,QAAU,EAAa,SAAS,CACvF,EAAc,CAAE,SAAQ,QAAS,EAAQ,MAAK,CAEpD,GAAI,EAAa,WACV,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAa,OAAO,CACxD,MAAM,QAAQ,EAAM,EAAI,CAAC,EAAI,SAAS,KAAK,GAC7C,EAAa,OAAO,GAAG,EAAI,KAAO,EAClC,OAAO,EAAa,OAAO,IAKjC,GAAM,CAAE,SAAQ,iBAAkB,MAAA,EAAgB,EAAa,OAAQ,EAAa,QAAQ,CAE5F,GAAI,CACF,MAAA,EAAa,KAAK,kBAAkB,EAAoB,EAAQ,EAAQ,EAAK,GAAG,CAEhF,IAAMG,EAA4C,CAChD,OACA,SACA,SACA,SACA,UACA,KAAM,EACN,MAAO,EAAa,OACrB,CAEK,EAAW,MAAM,KAAK,OAAO,QAAQ,EAAe,CAG1D,GAAI,EADkB,EAAa,qBAAyB,EAAS,WAAa,MAC/D,EAAS,WAAW,CAAE,CACvC,IAAM,EAAO,MAAM,MAAA,EAAyB,EAAa,EAAU,EAAY,CAM/E,MALA,MAAA,EAAa,MAAM,6BAA6B,EAAoB,EAAQ,EAAQ,EAAK,GAAI,CAC3F,OAAQ,EAAS,WACjB,OACD,CAAC,CAEI,IAAI,EAAO,sBAAsB,EAAa,EAAU,EAAK,CAOrE,OAJA,MAAA,EAAa,KAAK,mBAAmB,EAAoB,EAAQ,EAAQ,EAAK,GAAG,CAI1E,CACL,KAHW,EAAS,aAAe,IAAkF,IAAA,GAA5E,MAAM,MAAA,EAA8B,EAAa,EAAU,EAAc,CAIlH,OAAQ,EAAS,WACjB,WAAY,EAAa,EAAS,aAAe,GACjD,QAAS,EAAS,QAClB,OAAQ,EACT,OACM,EAAO,CACd,GAAI,GAAiB,EAAc,SAAW,EAAO,CAEnD,MAAA,EAAa,MAAM,oBAAoB,EAAoB,EAAQ,EAAQ,EAAK,GAAG,CACnF,IAAMG,EAAQ,IAAI,EAAO,YAAY,yBAAyB,EAAa,QAAQ,IAAK,CAAE,MAAO,EAAc,OAAQ,CAAC,CAExH,KADA,GAAM,KAAO,kBACPA,EASR,MAPI,GAAU,EAAO,SAAW,GAE9B,MAAA,EAAa,MAAM,oBAAoB,EAAoB,EAAQ,EAAQ,EAAK,GAAG,CAC7E,IAAI,EAAO,oBAAoB,EAAO,OAAO,QAAS,CAAE,MAAO,EAAO,OAAQ,CAAC,GAGvF,MAAA,EAAa,MAAM,6BAA6B,EAAoB,EAAQ,EAAQ,EAAK,GAAI,CAAE,QAAO,CAAC,CACjG,IAIV,MAAA,EAAwB,EAA4E,EAAmC,EAA8B,CACnK,IAAM,EAAe,EAAS,QAAQ,iBAA8B,GAC9D,EAAW,MAAM,EAAS,KAAK,MAAM,CAE3C,GAAI,CAAC,EACH,OAGF,GAAI,QAAQ,KAAK,EAAY,CAC3B,OAAO,EAGT,IAAIE,EACJ,GAAI,CACF,EAAO,KAAK,MAAM,EAAS,OACpB,EAAO,CACd,GAAI,CAAC,EACH,OAAO,EAET,IAAMC,EAAc,EAAO,UAAU,EAAS,CAC9C,GAAIA,EAAY,QACd,OAAOA,EAAY,KAErB,MAAM,IAAI,EAAO,sBAAsB,EAAa,EAAU,IAAA,GAAW,CAAE,MAAO,EAAgB,CAAC,CAErG,GAAI,CAAC,EACH,OAAO,EAET,IAAM,EAAc,EAAO,UAAU,EAAK,CAC1C,GAAI,EAAY,QACd,OAAO,EAAY,KAErB,MAAM,OAAO,OAAO,EAAY,MAAO,CAAE,OAAM,CAAC,CAGlD,MAAA,EAA+B,EAA4E,EAAmC,EAA8B,CAC1K,OAAO,MAAA,EAAuB,EAAa,EAAU,EAAO,CAG9D,MAAA,EAAkC,EAA4E,EAAmC,EAAmC,CAClL,OAAO,MAAA,EAA4B,EAAa,EAAU,EAAO,CAQnE,MAAM,YAAe,EAAa,EAAyB,EAAE,CAAgB,CAC3E,IAAMC,EAAqB,EAAE,CACzBC,EAAoC,KACpCC,EAAiC,KAE/B,EAAe,CAAE,GAAG,EAAS,OAAQ,CAAE,GAAG,EAAQ,OAAQ,KAAM,EAAG,CAAE,CAI3E,IAFA,EAAa,OAAO,OAAS,GAErB,EAAa,OAAO,OAAS,GAAK,IAAoB,IAAuB,IAAoB,GAAG,CAC1G,GAAM,CAAE,QAAS,MAAM,KAAK,IAAS,EAAK,EAAqE,CAC/G,EAAkB,EAAK,OACnB,EAAa,OAAO,OAAS,IAC/B,EAAqB,EAAK,QAG5B,EAAa,OAAO,MAAQ,EAC5B,MAAM,UAAU,KAAK,MAAM,EAAe,EAAK,CAGjD,OAAO,EAYT,MAAM,6BAAgC,EAAa,EAAkB,EAAE,CAAE,EAAY,IAAmB,CACtG,IAAMF,EAAqB,EAAE,CAEzB,EAAoB,GACpB,EAAO,EACX,KAAO,IAAsB,IAAc,IAAM,EAAO,IAAY,CAClE,GAAM,CAAE,QAAS,MAAM,KAAK,KAAoC,EAAK,CACnE,GAAG,EACH,OACD,CAAC,CACI,CAAE,OAAM,SAAU,EACxB,GAAQ,EACR,MAAM,UAAU,KAAK,MAAM,EAAe,EAAK,CAC/C,EAAoB,EAAc,OAAS,EAG7C,OAAO,EAGT,MAAM,OAAuB,CAC3B,MAAM,KAAK,OAAO,OAAO,CAG3B,MAAO,OAAO,eAA+B,CAC3C,MAAM,KAAK,OAAO,GAItB,EAAe"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["undiciErrors","response: Dispatcher.ResponseData","data: TError","testAgentParam: unique symbol","outbreakInterceptor: Dispatcher.DispatcherComposeInterceptor","headers: Record<string, string | string[]>","retriableMethods: Dispatcher.HttpMethod[]","#logger","#request","#createBaseUrl","headers: Record<string, string>","#prepareRequestBody","#getSignal","requestOptions: Dispatcher.RequestOptions","#parseErrorResponse","#parseSuccessResponse","error","#parseResponse","parseResult","json: unknown","currentResult: T[]","resultsInFirstPage: number | null","lastResultsSize: number | null"],"sources":["../src/errors.ts","../src/testingHelper.ts","../src/outbreakInterceptor.ts","../src/index.ts"],"sourcesContent":["import { STATUS_CODES } from 'node:http';\nimport { type Dispatcher, errors as undiciErrors } from 'undici';\n\nconst RapidoHttpClientErrorBrand = Symbol.for('RapidoHttpClientErrorBrand');\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace errors {\n export import UndiciError = undiciErrors.UndiciError;\n export import ConnectTimeoutError = undiciErrors.ConnectTimeoutError;\n export import HeadersTimeoutError = undiciErrors.HeadersTimeoutError;\n export import HeadersOverflowError = undiciErrors.HeadersOverflowError;\n export import BodyTimeoutError = undiciErrors.BodyTimeoutError;\n export import ResponseError = undiciErrors.ResponseError;\n export import InvalidArgumentError = undiciErrors.InvalidArgumentError;\n export import InvalidReturnValueError = undiciErrors.InvalidReturnValueError;\n export import RequestAbortedError = undiciErrors.RequestAbortedError;\n export import InformationalError = undiciErrors.InformationalError;\n export import RequestContentLengthMismatchError = undiciErrors.RequestContentLengthMismatchError;\n export import ResponseContentLengthMismatchError = undiciErrors.ResponseContentLengthMismatchError;\n export import ClientDestroyedError = undiciErrors.ClientDestroyedError;\n export import ClientClosedError = undiciErrors.ClientClosedError;\n export import SocketError = undiciErrors.SocketError;\n export import NotSupportedError = undiciErrors.NotSupportedError;\n export import BalancedPoolMissingUpstreamError = undiciErrors.BalancedPoolMissingUpstreamError;\n export import HTTPParserError = undiciErrors.HTTPParserError;\n export import ResponseExceededMaxSizeError = undiciErrors.ResponseExceededMaxSizeError;\n export import RequestRetryError = undiciErrors.RequestRetryError;\n export import SecureProxyConnectionError = undiciErrors.SecureProxyConnectionError;\n export import MaxOriginsReachedError = undiciErrors.MaxOriginsReachedError;\n\n export function isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError {\n return typeof value === 'object' && value !== null && RapidoHttpClientErrorBrand in value;\n }\n\n export class RapidoHttpClientError<TError = unknown> extends undiciErrors.ResponseError {\n public readonly status: number;\n public readonly statusText: string;\n public readonly requestOptions?: Dispatcher.RequestOptions;\n\n constructor(\n body: ConstructorParameters<typeof undiciErrors.ResponseError>[2]['body'],\n public readonly response: Dispatcher.ResponseData,\n public readonly data: TError,\n errorOptions?: ErrorOptions & { requestOptions?: Dispatcher.RequestOptions; },\n ) {\n super(`HTTP Error ${response.statusCode}`, response.statusCode, { headers: response.headers, body });\n this.status = response.statusCode;\n this.statusText = STATUS_CODES[response.statusCode] || 'Unknown Status';\n this.requestOptions = errorOptions?.requestOptions;\n if (errorOptions?.cause) {\n this.cause = errorOptions.cause;\n }\n\n Object.defineProperty(this, RapidoHttpClientErrorBrand, {\n value: true,\n enumerable: false,\n writable: false,\n });\n }\n\n public static isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError {\n return isRapidoHttpClientError(value);\n }\n }\n}\n","export const testAgentParam: unique symbol = Symbol('testAgentParam');\n","import type { Dispatcher } from 'undici';\nimport { getCurrentContext } from '@autofleet/outbreak';\n\nexport const outbreakInterceptor: Dispatcher.DispatcherComposeInterceptor = dispatch => function outbreakInterceptorInner(opts, handler) {\n const currentTraceContext = getCurrentContext().context;\n if (currentTraceContext) {\n // Convert headers to object format if they're in array format\n let headers: Record<string, string | string[]>;\n if (Array.isArray(opts.headers)) {\n /* c8 ignore next */\n headers = Object.fromEntries(opts.headers as unknown as [string, string | string[]][]);\n } else {\n headers = { ...opts.headers as Record<string, string | string[]> };\n }\n\n // Inject outbreak trace headers\n for (const [header, value] of currentTraceContext) {\n if (typeof value === 'symbol' || typeof value === 'undefined') {\n continue;\n }\n headers[header] = value as string;\n }\n opts.headers = headers;\n }\n return dispatch(opts, handler);\n};\n","import { STATUS_CODES } from 'node:http';\nimport type { ZodType, output } from 'zod';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport type CacheHandler from 'undici/types/cache-interceptor';\nimport Undici, { Agent, type Dispatcher, interceptors } from 'undici';\nimport { errors } from './errors';\nimport { testAgentParam } from './testingHelper';\nimport { outbreakInterceptor } from './outbreakInterceptor';\nimport {\n createRequestString,\n defaultRetryMethod,\n defaultSettings,\n defaultSettingsWithDecompress,\n isFormData,\n mergeConfig,\n parseUrlAndOrigin,\n resolveServiceUrl,\n} from './utils';\n\nconst { cacheStores } = Undici;\nconst { cache, retry, decompress } = interceptors;\n\nexport interface RapidoHttpClientSettings {\n [testAgentParam]?: Dispatcher;\n /** The MS name to be used to resolve the base URL using K8S service discovery. Ignored if `serviceUrl` is provided as well. */\n serviceName?: string;\n /** The base URL to be used. Overrides `serviceName` when provided. */\n serviceUrl?: string;\n logger: LoggerInstanceManager;\n /** The request timeout in milliseconds. @default 10_000 */\n timeout?: number;\n /** Settings for retrying requests on failure */\n retries?: interceptors.RetryInterceptorOpts;\n /** Common headers applied to all requests of this `RapidoHttpClient` instance. */\n headers?: Record<string, string> | string[][];\n keepAliveTimeout?: number;\n keepAliveMaxTimeout?: number;\n /** The amount of concurrent connections to be maintained using a connection pool. @default 10 */\n connections?: number;\n /** The settings for caching requests */\n cache?: CacheHandler.MemoryCacheStoreOpts;\n /** Whether to automatically decompress response bodies. When `true` will automatically add an `Accept-Encoding` header. @default false */\n autoDecompress?: boolean;\n /**\n * A function to validate the HTTP response status code.\n * Return `true` to consider the status valid, `false` otherwise.\n *\n * When status is invalid, a {@link errors.RapidoHttpClientError `RapidoHttpClientError`} will be thrown.\n *\n * @example (status) => status >= 200 && status < 300\n * @example (status) => status !== 401\n *\n * @default (status) => status < 400\n */\n validateStatus?(status: number): boolean;\n}\n\nexport interface RequestConfig {\n params?: Record<string, any>;\n body?: any;\n /** The request timeout in milliseconds. This overrides the client's instance setting @default 10_000 */\n timeout?: number;\n /** Headers applied to this request, appending on the client's common headers. */\n headers?: Record<string, string>;\n /** An `AbortSignal` which should abort the request and it's parsing when aborted. */\n signal?: AbortSignal;\n /**\n * Zod schema for successful responses. Used when `validateStatus` returns `true` (default: status < 400).\n */\n successSchema?: ZodType;\n /**\n * Zod schema for error responses. Used when `validateStatus` returns `false` (default: status >= 400).\n * The validated error data is available in the thrown `RapidoHttpClientError`.\n */\n errorSchema?: ZodType;\n /**\n * A function to validate the HTTP response status code.\n * Return `true` to consider the status valid, `false` otherwise.\n *\n * When status is invalid, a {@link errors.RapidoHttpClientError `RapidoHttpClientError`} will be thrown.\n *\n * @example (status) => status >= 200 && status < 300\n * @example (status) => status !== 401\n *\n * @default (status) => status < 400\n */\n validateStatus?(status: number): boolean;\n}\n\nexport interface RapidoHttpClientResponse<T = any> {\n data: T;\n status: number;\n statusText: string;\n headers: Record<string, string | string[]>;\n config: RequestConfig & { url: string; method: string; baseURL?: string; };\n}\n\nconst retriableMethods: Dispatcher.HttpMethod[] = ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE', 'QUERY'];\n\nexport class RapidoHttpClient {\n readonly #logger: LoggerInstanceManager;\n private readonly settings: RapidoHttpClientSettings & { baseURL?: string; basePath?: string; };\n public readonly client: Dispatcher.ComposedDispatcher;\n\n public get<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public get<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public get<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public get<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('GET', url, undefined, config);\n }\n\n public post<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public post<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public post<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public post<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('POST', url, body, config);\n }\n\n public delete<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public delete<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public delete<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public delete<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('DELETE', url, undefined, config);\n }\n\n public head<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public head<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public head<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public head<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('HEAD', url, undefined, config);\n }\n\n public put<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public put<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public put<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public put<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('PUT', url, body, config);\n }\n\n public patch<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public patch<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public patch<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public patch<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('PATCH', url, body, config);\n }\n\n public options<T = unknown>(\n url: string,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public options<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public options<TSuccess extends ZodType>(\n url: string,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public options<T = unknown>(url: string, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('OPTIONS', url, undefined, config);\n }\n\n public query<T = unknown>(\n url: string,\n body?: any,\n config?: Omit<RequestConfig, 'successSchema' | 'errorSchema'> & { successSchema?: never; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<T>>;\n public query<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: never; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public query<TSuccess extends ZodType>(\n url: string,\n body: any,\n config: RequestConfig & { successSchema: TSuccess; errorSchema?: ZodType; }\n ): Promise<RapidoHttpClientResponse<output<TSuccess>>>;\n public query<T = unknown>(url: string, body?: any, config?: RequestConfig): Promise<RapidoHttpClientResponse<T>> {\n return this.#request<T>('QUERY', url, body, config);\n }\n\n constructor(settings: RapidoHttpClientSettings) {\n this.#logger = settings.logger.child('RapidoHttpClient', {});\n this.settings = mergeConfig<typeof defaultSettings, Partial<typeof settings>>(\n settings.autoDecompress ? defaultSettingsWithDecompress : defaultSettings,\n settings,\n ) as RapidoHttpClientSettings & { baseURL?: string; };\n this.#createBaseUrl();\n\n // In test mode, use the test dispatcher directly (MockAgent or MockPool) Otherwise, create an Agent which creates Client Pools\n // Check for global mock agent first (for testing), then test param, then create real Agent\n /* c8 ignore next */\n const globalMockAgent = (globalThis as any).__RAPIDO_HTTP_CLIENT_MOCK_AGENT__;\n /* c8 ignore next */\n this.client = this.settings[testAgentParam] ?? globalMockAgent ?? new Agent({\n connect: {\n timeout: this.settings.timeout,\n },\n keepAliveTimeout: this.settings.keepAliveTimeout,\n keepAliveMaxTimeout: this.settings.keepAliveMaxTimeout,\n connections: this.settings.connections,\n });\n\n if (this.settings.cache) {\n this.client = this.client.compose(cache({\n store: new cacheStores.MemoryCacheStore({\n ...this.settings.cache,\n }),\n }));\n }\n\n if (this.settings.retries) {\n this.client = this.client.compose(retry({\n methods: retriableMethods,\n ...this.settings.retries,\n retry: (err, context, callback) => {\n const { counter } = context.state;\n /* c8 ignore next */\n const maxRetries = context.opts.retryOptions?.maxRetries ?? 5;\n\n const retryToUse = this.settings.retries?.retry ?? defaultRetryMethod;\n const callbackWithLogging = (result?: Error | null) => {\n if (!result) {\n const { method, origin, path } = context.opts;\n const baseUrl = (!origin || typeof origin === 'string') ? origin : origin.origin;\n this.#logger.warn(`Request retry attempt ${counter}/${maxRetries}: ${createRequestString(method, baseUrl, path)}`, { err });\n }\n callback(result);\n };\n retryToUse(err, context, callbackWithLogging);\n },\n }));\n }\n\n if (this.settings.autoDecompress) {\n this.client = this.client.compose(decompress({ skipErrorResponses: false }));\n }\n\n this.client = this.client.compose(outbreakInterceptor);\n }\n\n #createBaseUrl(): void {\n const fullUrl = resolveServiceUrl(this.settings);\n const urlObj = new URL(fullUrl);\n this.settings.baseURL = urlObj.origin;\n this.settings.basePath = urlObj.pathname !== '/' ? urlObj.pathname : '';\n }\n\n #getSignal(currentSignal?: AbortSignal, timeout?: number): { signal?: AbortSignal; timeoutSignal?: AbortSignal; } {\n if (!currentSignal && !timeout) {\n return { signal: undefined, timeoutSignal: undefined };\n }\n\n if (currentSignal && !timeout) {\n return { signal: currentSignal, timeoutSignal: undefined };\n }\n\n const timeoutSignal = AbortSignal.timeout(timeout!);\n if (!currentSignal && timeout) {\n return { signal: timeoutSignal, timeoutSignal };\n }\n\n return { signal: AbortSignal.any([currentSignal!, timeoutSignal]), timeoutSignal };\n }\n\n #prepareRequestBody(body: any, headers: Record<string, string>): string | Buffer | FormData | undefined {\n if (body === undefined || body === null) {\n return undefined;\n }\n\n // Handle FormData instances automatically\n if (isFormData(body)) {\n if (!headers['Content-Type'] && !headers['content-type']) {\n headers['Content-Type'] = 'application/x-www-form-urlencoded';\n }\n return body;\n }\n\n if (typeof body === 'object' && !Buffer.isBuffer(body)) {\n // Check if Content-Type is set to application/x-www-form-urlencoded\n const contentType = headers['Content-Type'] || headers['content-type'];\n if (contentType && /application\\/x-www-form-urlencoded/i.test(contentType)) {\n // Encode as URL parameters\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(body)) {\n if (Array.isArray(value)) {\n value.forEach(v => params.append(key, String(v)));\n } else if (value !== undefined && value !== null) {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n params.append(key, String(value));\n }\n }\n return params.toString();\n }\n // Default to JSON\n if (!headers['Content-Type'] && !headers['content-type']) {\n headers['Content-Type'] = 'application/json';\n }\n return JSON.stringify(body);\n }\n if (typeof body === 'string') {\n return body;\n }\n if (Buffer.isBuffer(body)) {\n return body;\n }\n return String(body);\n }\n\n async #request<T = any>(\n method: Dispatcher.HttpMethod,\n url: string,\n body?: any,\n config: RequestConfig = {},\n ): Promise<RapidoHttpClientResponse<T>> {\n const mergedConfig = mergeConfig(this.settings, config);\n\n if (mergedConfig.signal?.aborted) {\n this.#logger.error(`Request aborted before start: ${createRequestString(method, mergedConfig.baseURL, url)}`);\n throw new errors.RequestAbortedError(mergedConfig.signal.reason?.message || 'Request aborted', { cause: mergedConfig.signal.reason });\n }\n\n // Get schemas from config\n const { successSchema, errorSchema } = config;\n\n const headers: Record<string, string> = { ...mergedConfig.headers };\n const requestBody = this.#prepareRequestBody(body, headers);\n\n const { origin, path } = parseUrlAndOrigin(url, mergedConfig.baseURL!, mergedConfig.basePath);\n const requestInfo = { method, baseURL: origin, url };\n\n if (mergedConfig.params) {\n for (const [key, value] of Object.entries(mergedConfig.params)) {\n if (Array.isArray(value) && !key.endsWith('[]')) {\n mergedConfig.params[`${key}[]`] = value;\n delete mergedConfig.params[key];\n }\n }\n }\n\n const { signal, timeoutSignal } = this.#getSignal(mergedConfig.signal, mergedConfig.timeout);\n\n try {\n this.#logger.info(`Start Request: ${createRequestString(method, origin, path)}`);\n\n const requestOptions: Dispatcher.RequestOptions = {\n path,\n origin,\n method,\n signal,\n headers,\n body: requestBody,\n query: mergedConfig.params,\n };\n\n const response = await this.client.request(requestOptions);\n\n if (origin.startsWith('http://') && response.statusCode >= 300 && response.statusCode < 400) {\n const location = [response.headers.location].flat()[0] ?? 'unknown location';\n throw new errors.RapidoHttpClientError(requestBody, response, undefined, {\n requestOptions,\n cause: new Error(`Redirect to ${location} on HTTP origin, which is not supported for security reasons`),\n });\n }\n\n const isStatusValid = mergedConfig.validateStatus ?? (() => response.statusCode < 400);\n if (!isStatusValid(response.statusCode)) {\n const data = await this.#parseErrorResponse(requestBody, response, errorSchema);\n this.#logger.error(`Finish Request with error ${createRequestString(method, origin, path)}`, {\n status: response.statusCode,\n data,\n });\n\n throw new errors.RapidoHttpClientError(requestBody, response, data, { requestOptions });\n }\n\n this.#logger.info(`Finish Request: ${createRequestString(method, origin, path)}`);\n\n const data = response.statusCode !== 204 ? await this.#parseSuccessResponse<T>(requestBody, response, successSchema) : undefined as T;\n\n return {\n data,\n status: response.statusCode,\n statusText: STATUS_CODES[response.statusCode] || '',\n headers: response.headers as Record<string, string | string[]>,\n config: requestInfo,\n };\n } catch (error) {\n if (timeoutSignal && timeoutSignal.reason === error) {\n // If the timeoutSignal aborted (config timeout), throw a timeout-specific error\n this.#logger.error(`Request timeout: ${createRequestString(method, origin, path)}`);\n const error = new errors.UndiciError(`Request timeout after ${mergedConfig.timeout}ms`, { cause: timeoutSignal.reason });\n error.code = 'UND_ERR_TIMEOUT';\n throw error;\n }\n if (signal && signal.reason === error) {\n // If the user's signal aborted, throw RequestAbortedError\n this.#logger.error(`Request aborted: ${createRequestString(method, origin, path)}`);\n throw new errors.RequestAbortedError(signal.reason.message, { cause: signal.reason });\n }\n\n this.#logger.error(`Finish Request with error ${createRequestString(method, origin, path)}`, { error });\n throw error;\n }\n }\n\n async #parseResponse<T>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<T> {\n const contentType = (response.headers['content-type'] as string) || '';\n const bodyText = await response.body.text();\n\n if (!bodyText) {\n return undefined as T;\n }\n\n if (/text/i.test(contentType)) {\n if (!schema) {\n return bodyText as T;\n }\n const parseResult = schema.safeParse(bodyText);\n if (parseResult.success) {\n return parseResult.data as T;\n }\n throw Object.assign(parseResult.error, { json: bodyText });\n }\n\n let json: unknown;\n try {\n json = JSON.parse(bodyText);\n } catch (error) {\n if (!schema) {\n return bodyText as T;\n }\n const parseResult = schema.safeParse(bodyText);\n if (parseResult.success) {\n return parseResult.data as T;\n }\n throw new errors.RapidoHttpClientError(requestBody, response, undefined, { cause: error as Error });\n }\n if (!schema) {\n return json as T;\n }\n const parseResult = schema.safeParse(json);\n if (parseResult.success) {\n return parseResult.data as T;\n }\n throw Object.assign(parseResult.error, { json });\n }\n\n async #parseSuccessResponse<T>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<T> {\n return this.#parseResponse<T>(requestBody, response, schema);\n }\n\n async #parseErrorResponse<TError>(requestBody: ConstructorParameters<typeof errors.RapidoHttpClientError>[0], response: Dispatcher.ResponseData, schema?: ZodType): Promise<TError> {\n return this.#parseResponse<TError>(requestBody, response, schema);\n }\n\n /**\n * @param url The endpoint URL to send the request to.\n * @param options Additional options to include in the request payload.\n * @returns A promise that resolves to an array of all results.\n */\n async getAllPages<T>(url: string, options: RequestConfig = {}): Promise<T[]> {\n const currentResult: T[] = [];\n let resultsInFirstPage: number | null = null;\n let lastResultsSize: number | null = null;\n\n const localOptions = { ...options, params: { ...options.params, page: 1 } };\n // Make sure even if `options` had `params` we initialize `page` to 1.\n localOptions.params.page ||= 1;\n\n while ((localOptions.params.page === 1 || lastResultsSize === resultsInFirstPage) && lastResultsSize !== 0) {\n const { data } = await this.get<T[]>(url, localOptions as Omit<RequestConfig, 'successSchema' | 'errorSchema'>);\n lastResultsSize = data.length;\n if (localOptions.params.page === 1) {\n resultsInFirstPage = data.length;\n }\n\n localOptions.params.page += 1;\n Array.prototype.push.apply(currentResult, data);\n }\n\n return currentResult;\n }\n\n /**\n * Fetches all pages from a paginated API endpoint until all results are retrieved\n * or an optional page limit is reached.\n *\n * @param url The endpoint URL to send the request to.\n * @param options Additional options to include in the request payload.\n * @param pageLimit The maximum number of pages to fetch. Set to -1 for no limit.\n * @returns A promise that resolves to an array of all results.\n */\n async getAllPagesFromQueryEndpoint<T>(url: string, options: object = {}, pageLimit = 100): Promise<T[]> {\n const currentResult: T[] = [];\n\n let moreResultsToLoad = true;\n let page = 1;\n while (moreResultsToLoad && (pageLimit === -1 || page < pageLimit)) {\n const { data } = await this.post<{ rows: T[]; count: number; }>(url, {\n ...options,\n page,\n });\n const { rows, count } = data;\n page += 1;\n Array.prototype.push.apply(currentResult, rows);\n moreResultsToLoad = currentResult.length < count;\n }\n\n return currentResult;\n }\n\n async close(): Promise<void> {\n await this.client.close();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n}\n\nexport default RapidoHttpClient;\nexport { errors };\n"],"mappings":"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"}
|
package/dist/testing.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`./utils
|
|
1
|
+
const e=require(`./utils--WaygnX8.cjs`),t=require(`./index.cjs`);let n=require(`undici`);function r({blockNonMockedNetwork:t,collectCallHistory:r}={}){let i=new n.MockAgent({enableCallHistory:r??!1});(t??!0)&&i.disableNetConnect(),globalThis.__RAPIDO_HTTP_CLIENT_MOCK_AGENT__=i;let a=new Map,o=new Map,s=e=>{let t=new URL(e),n=t.origin,r=t.pathname===`/`?``:t.pathname.replace(/\/$/,``),s=n+r;if(!a.has(s)){let e=i.get(n);a.set(s,e),o.set(s,r)}return{pool:a.get(s),basePath:o.get(s)||``}},c=(e,t)=>{if(typeof e==`string`)return{path:t+e};let n={...e};if(typeof n.path==`string`&&(n.path=t+n.path),n.body&&typeof n.body==`object`&&!(n.body instanceof RegExp)&&typeof n.body!=`function`){let e=n.headers,t=e?.[`Content-Type`]||e?.[`content-type`];if(t&&/application\/x-www-form-urlencoded/i.test(t)){let e=new URLSearchParams;for(let[t,r]of Object.entries(n.body))Array.isArray(r)?r.forEach(n=>e.append(t,String(n))):r!=null&&e.append(t,String(r));n.body=e.toString()}else n.body=JSON.stringify(n.body)}if(n.query)for(let[e,t]of Object.entries(n.query))Array.isArray(t)&&!e.endsWith(`[]`)&&(n.query[`${e}[]`]=t,delete n.query[e]);return n};return{intercept:t=>{let{pool:n,basePath:r}=s(typeof t==`string`?t:e.c(t));return{get:e=>n.intercept({...c(e,r),method:`GET`}),head:e=>n.intercept({...c(e,r),method:`HEAD`}),delete:e=>n.intercept({...c(e,r),method:`DELETE`}),options:e=>n.intercept({...c(e,r),method:`OPTIONS`}),put:e=>n.intercept({...c(e,r),method:`PUT`}),post:e=>n.intercept({...c(e,r),method:`POST`}),patch:e=>n.intercept({...c(e,r),method:`PATCH`}),query:e=>n.intercept({...c(e,r),method:`QUERY`})}},getPool:t=>s(typeof t==`string`?t:e.c(t)).pool,cleanup:async()=>{delete globalThis.__RAPIDO_HTTP_CLIENT_MOCK_AGENT__,a.clear(),o.clear(),await i.close(),i.clearCallHistory()},get calls(){return i.getCallHistory()?.calls()??[]},clearCallHistory:()=>i.clearCallHistory(),enableCallHistory:()=>{i.enableCallHistory()},disableCallHistory:()=>{i.disableCallHistory()},mockAgent:i}}exports.setupRapidoHttpClientMock=r;
|
|
2
2
|
//# sourceMappingURL=testing.cjs.map
|
package/dist/testing.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{c as e}from"./utils-
|
|
1
|
+
import{c as e}from"./utils-CjxOAe9E.js";import{MockAgent as t}from"undici";function n({blockNonMockedNetwork:n,collectCallHistory:r}={}){let i=new t({enableCallHistory:r??!1});(n??!0)&&i.disableNetConnect(),globalThis.__RAPIDO_HTTP_CLIENT_MOCK_AGENT__=i;let a=new Map,o=new Map,s=e=>{let t=new URL(e),n=t.origin,r=t.pathname===`/`?``:t.pathname.replace(/\/$/,``),s=n+r;if(!a.has(s)){let e=i.get(n);a.set(s,e),o.set(s,r)}return{pool:a.get(s),basePath:o.get(s)||``}},c=(e,t)=>{if(typeof e==`string`)return{path:t+e};let n={...e};if(typeof n.path==`string`&&(n.path=t+n.path),n.body&&typeof n.body==`object`&&!(n.body instanceof RegExp)&&typeof n.body!=`function`){let e=n.headers,t=e?.[`Content-Type`]||e?.[`content-type`];if(t&&/application\/x-www-form-urlencoded/i.test(t)){let e=new URLSearchParams;for(let[t,r]of Object.entries(n.body))Array.isArray(r)?r.forEach(n=>e.append(t,String(n))):r!=null&&e.append(t,String(r));n.body=e.toString()}else n.body=JSON.stringify(n.body)}if(n.query)for(let[e,t]of Object.entries(n.query))Array.isArray(t)&&!e.endsWith(`[]`)&&(n.query[`${e}[]`]=t,delete n.query[e]);return n};return{intercept:t=>{let{pool:n,basePath:r}=s(typeof t==`string`?t:e(t));return{get:e=>n.intercept({...c(e,r),method:`GET`}),head:e=>n.intercept({...c(e,r),method:`HEAD`}),delete:e=>n.intercept({...c(e,r),method:`DELETE`}),options:e=>n.intercept({...c(e,r),method:`OPTIONS`}),put:e=>n.intercept({...c(e,r),method:`PUT`}),post:e=>n.intercept({...c(e,r),method:`POST`}),patch:e=>n.intercept({...c(e,r),method:`PATCH`}),query:e=>n.intercept({...c(e,r),method:`QUERY`})}},getPool:t=>s(typeof t==`string`?t:e(t)).pool,cleanup:async()=>{delete globalThis.__RAPIDO_HTTP_CLIENT_MOCK_AGENT__,a.clear(),o.clear(),await i.close(),i.clearCallHistory()},get calls(){return i.getCallHistory()?.calls()??[]},clearCallHistory:()=>i.clearCallHistory(),enableCallHistory:()=>{i.enableCallHistory()},disableCallHistory:()=>{i.disableCallHistory()},mockAgent:i}}export{n as setupRapidoHttpClientMock};
|
|
2
2
|
//# sourceMappingURL=testing.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`./index.cjs`);let t=require(`undici`),n=require(`node:process`),r=require(`node:zlib`);var i=`0.
|
|
2
|
-
//# sourceMappingURL=utils
|
|
1
|
+
const e=require(`./index.cjs`);let t=require(`undici`),n=require(`node:process`),r=require(`node:zlib`);var i=`0.3.1`;const a=()=>typeof r.createZstdDecompress==`function`,o={timeout:1e4,headers:{"User-Agent":`rapido-http-client/${i}`,"X-AF-AUTH":`ANYONE`,"X-IAF-ORIGIN-SERVICE":n.env.AF_SERVICE_NAME||``},keepAliveTimeout:5e3,keepAliveMaxTimeout:1e4,connections:10},s={...o,headers:{...o.headers,"Accept-Encoding":`${a()?`zstd, `:``}br, gzip`}},c=Object.getOwnPropertySymbols(t.RetryHandler).find(e=>typeof Object.getOwnPropertyDescriptor(t.RetryHandler,e)?.value==`function`&&e.toString().includes(`default retry`)),l=t.RetryHandler[c],u=e=>e instanceof FormData||Object.prototype.toString.call(e)===`[object FormData]`;function d(e){if(!e.serviceUrl&&!e.serviceName)throw Error(`At least one of the settings Missing serviceUrl or serviceName`);if(e.serviceUrl)return e.serviceUrl;let t=`${e.serviceName}_SERVICE_HOST`,r=n.env[t];if(!r&&n.env.NODE_ENV!==`test`)throw Error(`Environment variable ${t} is not set`);return`http://${r}`}const f=(e,t,n)=>`[${e.toUpperCase()}] ${t??`unknown-base-url`}${n}`,p=(e,t,n)=>{if(/^https?:\/\//i.test(e)){let t=new URL(e);return{origin:t.origin,path:t.pathname+t.search+t.hash}}let r=e;if(n){let t=n.endsWith(`/`),i=e.startsWith(`/`);r=t&&i?n+e.slice(1):!t&&!i?n+`/`+e:n+e}return{origin:t,path:r}},m=(e,t)=>{let n={...e,...t};return t.headers&&(n.headers={...e.headers,...t.headers}),n};Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return f}});
|
|
2
|
+
//# sourceMappingURL=utils--WaygnX8.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils
|
|
1
|
+
{"version":3,"file":"utils--WaygnX8.cjs","names":["createZstdDecompress","defaultSettings: Omit<RapidoHttpClientSettings, 'logger'>","env","defaultSettingsWithDecompress: Omit<RapidoHttpClientSettings, 'logger'>","RetryHandler"],"sources":["../package.json","../src/utils.ts"],"sourcesContent":["","import { env } from 'node:process';\nimport { RetryHandler } from 'undici';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore createZstdDecompress is rather new, so our @types/node is unaware of it\nimport { createZstdDecompress } from 'node:zlib';\nimport type { RapidoHttpClientSettings } from '.';\nimport { version } from '../package.json' with { type: 'json' };\n\n/** The support for zstd in Node was added during 22 & 23, so this function checks if it's exists in runtime */\nexport const isZstdSupported = (): boolean => typeof createZstdDecompress === 'function';\n\nexport const defaultSettings: Omit<RapidoHttpClientSettings, 'logger'> = {\n timeout: 10_000,\n headers: {\n 'User-Agent': `rapido-http-client/${version}`,\n 'X-AF-AUTH': 'ANYONE',\n 'X-IAF-ORIGIN-SERVICE': env.AF_SERVICE_NAME || '',\n },\n keepAliveTimeout: 5_000,\n keepAliveMaxTimeout: 10_000,\n connections: 10,\n};\n\nexport const defaultSettingsWithDecompress: Omit<RapidoHttpClientSettings, 'logger'> = {\n ...defaultSettings,\n headers: {\n ...defaultSettings.headers,\n /* c8 ignore next */\n 'Accept-Encoding': `${isZstdSupported() ? 'zstd, ' : ''}br, gzip`,\n },\n};\n\nconst retryHandlerDefaultRetryKey = Object.getOwnPropertySymbols(RetryHandler)\n .find(k => typeof Object.getOwnPropertyDescriptor(RetryHandler, k)?.value === 'function' && k.toString().includes('default retry'))!;\nexport const defaultRetryMethod = (RetryHandler as any)[retryHandlerDefaultRetryKey] as RetryHandler.RetryCallback;\n\nexport const isFormData = (obj: unknown): obj is FormData => obj instanceof FormData || Object.prototype.toString.call(obj) === '[object FormData]';\n\n/**\n * Resolves a service configuration to a base URL\n *\n * @param config - Object with either serviceName or serviceUrl\n * @returns The resolved base URL\n * @throws Error if neither serviceName nor serviceUrl is provided, or if the environment variable for serviceName is not set\n */\nexport function resolveServiceUrl(config: { serviceName?: string; serviceUrl?: string; }): string {\n if (!config.serviceUrl && !config.serviceName) {\n throw new Error('At least one of the settings Missing serviceUrl or serviceName');\n }\n\n if (config.serviceUrl) {\n return config.serviceUrl;\n }\n\n const envServiceHostName = `${config.serviceName}_SERVICE_HOST`;\n const host = env[envServiceHostName];\n if (!host && env.NODE_ENV !== 'test') {\n throw new Error(`Environment variable ${envServiceHostName} is not set`);\n }\n return `http://${host}`;\n}\n\nexport const createRequestString = (method: string, baseURL: string | undefined, url: string): string => `[${method.toUpperCase()}] ${baseURL ?? 'unknown-base-url'}${url}`;\n\nexport const parseUrlAndOrigin = (url: string, baseURL: string, basePath?: string): { origin: string; path: string; } => {\n // Check if url is a full URL (starts with http:// or https://)\n const isFullUrl = /^https?:\\/\\//i.test(url);\n\n if (isFullUrl) {\n // Parse the full URL to extract origin and path\n const urlObj = new URL(url);\n return {\n origin: urlObj.origin,\n path: urlObj.pathname + urlObj.search + urlObj.hash,\n };\n }\n\n // Use base URL and the provided path, prepending basePath if provided\n let finalPath = url;\n if (basePath) {\n // Normalize: ensure exactly one slash between basePath and url\n const baseEndsWithSlash = basePath.endsWith('/');\n const urlStartsWithSlash = url.startsWith('/');\n\n if (baseEndsWithSlash && urlStartsWithSlash) {\n // Both have slash, remove one\n finalPath = basePath + url.slice(1);\n } else if (!baseEndsWithSlash && !urlStartsWithSlash) {\n // Neither has slash, add one\n finalPath = basePath + '/' + url;\n } else {\n // One has slash, just concatenate\n finalPath = basePath + url;\n }\n }\n return {\n origin: baseURL,\n path: finalPath,\n };\n};\n\nexport const mergeConfig = <T extends Record<string, any>, U extends Record<string, any>>(\n defaults: T,\n overrides: U,\n): T & U => {\n const result = { ...defaults, ...overrides };\n\n // Special handling for headers - merge them instead of replacing\n if (overrides.headers) {\n (result as unknown as { headers: Record<string, string>; }).headers = {\n ...defaults.headers,\n ...overrides.headers,\n };\n }\n\n return result;\n};\n"],"mappings":"sHCSA,MAAa,MAAiC,OAAOA,EAAAA,sBAAyB,WAEjEC,EAA4D,CACvE,QAAS,IACT,QAAS,CACP,aAAc,sBAAsB,IACpC,YAAa,SACb,uBAAwBC,EAAAA,IAAI,iBAAmB,GAChD,CACD,iBAAkB,IAClB,oBAAqB,IACrB,YAAa,GACd,CAEYC,EAA0E,CACrF,GAAG,EACH,QAAS,CACP,GAAG,EAAgB,QAEnB,kBAAmB,GAAG,GAAiB,CAAG,SAAW,GAAG,UACzD,CACF,CAEK,EAA8B,OAAO,sBAAsBC,EAAAA,aAAa,CAC3E,KAAK,GAAK,OAAO,OAAO,yBAAyBA,EAAAA,aAAc,EAAE,EAAE,OAAU,YAAc,EAAE,UAAU,CAAC,SAAS,gBAAgB,CAAC,CACxH,EAAsBA,EAAAA,aAAqB,GAE3C,EAAc,GAAkC,aAAe,UAAY,OAAO,UAAU,SAAS,KAAK,EAAI,GAAK,oBAShI,SAAgB,EAAkB,EAAgE,CAChG,GAAI,CAAC,EAAO,YAAc,CAAC,EAAO,YAChC,MAAU,MAAM,iEAAiE,CAGnF,GAAI,EAAO,WACT,OAAO,EAAO,WAGhB,IAAM,EAAqB,GAAG,EAAO,YAAY,eAC3C,EAAOF,EAAAA,IAAI,GACjB,GAAI,CAAC,GAAQA,EAAAA,IAAI,WAAa,OAC5B,MAAU,MAAM,wBAAwB,EAAmB,aAAa,CAE1E,MAAO,UAAU,IAGnB,MAAa,GAAuB,EAAgB,EAA6B,IAAwB,IAAI,EAAO,aAAa,CAAC,IAAI,GAAW,qBAAqB,IAEzJ,GAAqB,EAAa,EAAiB,IAAyD,CAIvH,GAFkB,gBAAgB,KAAK,EAAI,CAE5B,CAEb,IAAM,EAAS,IAAI,IAAI,EAAI,CAC3B,MAAO,CACL,OAAQ,EAAO,OACf,KAAM,EAAO,SAAW,EAAO,OAAS,EAAO,KAChD,CAIH,IAAI,EAAY,EAChB,GAAI,EAAU,CAEZ,IAAM,EAAoB,EAAS,SAAS,IAAI,CAC1C,EAAqB,EAAI,WAAW,IAAI,CAE9C,AAQE,EARE,GAAqB,EAEX,EAAW,EAAI,MAAM,EAAE,CAC1B,CAAC,GAAqB,CAAC,EAEpB,EAAW,IAAM,EAGjB,EAAW,EAG3B,MAAO,CACL,OAAQ,EACR,KAAM,EACP,EAGU,GACX,EACA,IACU,CACV,IAAM,EAAS,CAAE,GAAG,EAAU,GAAG,EAAW,CAU5C,OAPI,EAAU,UACX,EAA2D,QAAU,CACpE,GAAG,EAAS,QACZ,GAAG,EAAU,QACd,EAGI"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{RetryHandler as e}from"undici";import{env as t}from"node:process";import{createZstdDecompress as n}from"node:zlib";var r=`0.
|
|
2
|
-
//# sourceMappingURL=utils-
|
|
1
|
+
import{RetryHandler as e}from"undici";import{env as t}from"node:process";import{createZstdDecompress as n}from"node:zlib";var r=`0.3.1`;const i=()=>typeof n==`function`,a={timeout:1e4,headers:{"User-Agent":`rapido-http-client/${r}`,"X-AF-AUTH":`ANYONE`,"X-IAF-ORIGIN-SERVICE":t.AF_SERVICE_NAME||``},keepAliveTimeout:5e3,keepAliveMaxTimeout:1e4,connections:10},o={...a,headers:{...a.headers,"Accept-Encoding":`${i()?`zstd, `:``}br, gzip`}},s=e[Object.getOwnPropertySymbols(e).find(t=>typeof Object.getOwnPropertyDescriptor(e,t)?.value==`function`&&t.toString().includes(`default retry`))],c=e=>e instanceof FormData||Object.prototype.toString.call(e)===`[object FormData]`;function l(e){if(!e.serviceUrl&&!e.serviceName)throw Error(`At least one of the settings Missing serviceUrl or serviceName`);if(e.serviceUrl)return e.serviceUrl;let n=`${e.serviceName}_SERVICE_HOST`,r=t[n];if(!r&&t.NODE_ENV!==`test`)throw Error(`Environment variable ${n} is not set`);return`http://${r}`}const u=(e,t,n)=>`[${e.toUpperCase()}] ${t??`unknown-base-url`}${n}`,d=(e,t,n)=>{if(/^https?:\/\//i.test(e)){let t=new URL(e);return{origin:t.origin,path:t.pathname+t.search+t.hash}}let r=e;if(n){let t=n.endsWith(`/`),i=e.startsWith(`/`);r=t&&i?n+e.slice(1):!t&&!i?n+`/`+e:n+e}return{origin:t,path:r}},f=(e,t)=>{let n={...e,...t};return t.headers&&(n.headers={...e.headers,...t.headers}),n};export{c as a,l as c,o as i,s as n,f as o,a as r,d as s,u as t};
|
|
2
|
+
//# sourceMappingURL=utils-CjxOAe9E.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils-
|
|
1
|
+
{"version":3,"file":"utils-CjxOAe9E.js","names":["defaultSettings: Omit<RapidoHttpClientSettings, 'logger'>","defaultSettingsWithDecompress: Omit<RapidoHttpClientSettings, 'logger'>"],"sources":["../package.json","../src/utils.ts"],"sourcesContent":["","import { env } from 'node:process';\nimport { RetryHandler } from 'undici';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore createZstdDecompress is rather new, so our @types/node is unaware of it\nimport { createZstdDecompress } from 'node:zlib';\nimport type { RapidoHttpClientSettings } from '.';\nimport { version } from '../package.json' with { type: 'json' };\n\n/** The support for zstd in Node was added during 22 & 23, so this function checks if it's exists in runtime */\nexport const isZstdSupported = (): boolean => typeof createZstdDecompress === 'function';\n\nexport const defaultSettings: Omit<RapidoHttpClientSettings, 'logger'> = {\n timeout: 10_000,\n headers: {\n 'User-Agent': `rapido-http-client/${version}`,\n 'X-AF-AUTH': 'ANYONE',\n 'X-IAF-ORIGIN-SERVICE': env.AF_SERVICE_NAME || '',\n },\n keepAliveTimeout: 5_000,\n keepAliveMaxTimeout: 10_000,\n connections: 10,\n};\n\nexport const defaultSettingsWithDecompress: Omit<RapidoHttpClientSettings, 'logger'> = {\n ...defaultSettings,\n headers: {\n ...defaultSettings.headers,\n /* c8 ignore next */\n 'Accept-Encoding': `${isZstdSupported() ? 'zstd, ' : ''}br, gzip`,\n },\n};\n\nconst retryHandlerDefaultRetryKey = Object.getOwnPropertySymbols(RetryHandler)\n .find(k => typeof Object.getOwnPropertyDescriptor(RetryHandler, k)?.value === 'function' && k.toString().includes('default retry'))!;\nexport const defaultRetryMethod = (RetryHandler as any)[retryHandlerDefaultRetryKey] as RetryHandler.RetryCallback;\n\nexport const isFormData = (obj: unknown): obj is FormData => obj instanceof FormData || Object.prototype.toString.call(obj) === '[object FormData]';\n\n/**\n * Resolves a service configuration to a base URL\n *\n * @param config - Object with either serviceName or serviceUrl\n * @returns The resolved base URL\n * @throws Error if neither serviceName nor serviceUrl is provided, or if the environment variable for serviceName is not set\n */\nexport function resolveServiceUrl(config: { serviceName?: string; serviceUrl?: string; }): string {\n if (!config.serviceUrl && !config.serviceName) {\n throw new Error('At least one of the settings Missing serviceUrl or serviceName');\n }\n\n if (config.serviceUrl) {\n return config.serviceUrl;\n }\n\n const envServiceHostName = `${config.serviceName}_SERVICE_HOST`;\n const host = env[envServiceHostName];\n if (!host && env.NODE_ENV !== 'test') {\n throw new Error(`Environment variable ${envServiceHostName} is not set`);\n }\n return `http://${host}`;\n}\n\nexport const createRequestString = (method: string, baseURL: string | undefined, url: string): string => `[${method.toUpperCase()}] ${baseURL ?? 'unknown-base-url'}${url}`;\n\nexport const parseUrlAndOrigin = (url: string, baseURL: string, basePath?: string): { origin: string; path: string; } => {\n // Check if url is a full URL (starts with http:// or https://)\n const isFullUrl = /^https?:\\/\\//i.test(url);\n\n if (isFullUrl) {\n // Parse the full URL to extract origin and path\n const urlObj = new URL(url);\n return {\n origin: urlObj.origin,\n path: urlObj.pathname + urlObj.search + urlObj.hash,\n };\n }\n\n // Use base URL and the provided path, prepending basePath if provided\n let finalPath = url;\n if (basePath) {\n // Normalize: ensure exactly one slash between basePath and url\n const baseEndsWithSlash = basePath.endsWith('/');\n const urlStartsWithSlash = url.startsWith('/');\n\n if (baseEndsWithSlash && urlStartsWithSlash) {\n // Both have slash, remove one\n finalPath = basePath + url.slice(1);\n } else if (!baseEndsWithSlash && !urlStartsWithSlash) {\n // Neither has slash, add one\n finalPath = basePath + '/' + url;\n } else {\n // One has slash, just concatenate\n finalPath = basePath + url;\n }\n }\n return {\n origin: baseURL,\n path: finalPath,\n };\n};\n\nexport const mergeConfig = <T extends Record<string, any>, U extends Record<string, any>>(\n defaults: T,\n overrides: U,\n): T & U => {\n const result = { ...defaults, ...overrides };\n\n // Special handling for headers - merge them instead of replacing\n if (overrides.headers) {\n (result as unknown as { headers: Record<string, string>; }).headers = {\n ...defaults.headers,\n ...overrides.headers,\n };\n }\n\n return result;\n};\n"],"mappings":"wICSA,MAAa,MAAiC,OAAO,GAAyB,WAEjEA,EAA4D,CACvE,QAAS,IACT,QAAS,CACP,aAAc,sBAAsB,IACpC,YAAa,SACb,uBAAwB,EAAI,iBAAmB,GAChD,CACD,iBAAkB,IAClB,oBAAqB,IACrB,YAAa,GACd,CAEYC,EAA0E,CACrF,GAAG,EACH,QAAS,CACP,GAAG,EAAgB,QAEnB,kBAAmB,GAAG,GAAiB,CAAG,SAAW,GAAG,UACzD,CACF,CAIY,EAAsB,EAFC,OAAO,sBAAsB,EAAa,CAC3E,KAAK,GAAK,OAAO,OAAO,yBAAyB,EAAc,EAAE,EAAE,OAAU,YAAc,EAAE,UAAU,CAAC,SAAS,gBAAgB,CAAC,EAGxH,EAAc,GAAkC,aAAe,UAAY,OAAO,UAAU,SAAS,KAAK,EAAI,GAAK,oBAShI,SAAgB,EAAkB,EAAgE,CAChG,GAAI,CAAC,EAAO,YAAc,CAAC,EAAO,YAChC,MAAU,MAAM,iEAAiE,CAGnF,GAAI,EAAO,WACT,OAAO,EAAO,WAGhB,IAAM,EAAqB,GAAG,EAAO,YAAY,eAC3C,EAAO,EAAI,GACjB,GAAI,CAAC,GAAQ,EAAI,WAAa,OAC5B,MAAU,MAAM,wBAAwB,EAAmB,aAAa,CAE1E,MAAO,UAAU,IAGnB,MAAa,GAAuB,EAAgB,EAA6B,IAAwB,IAAI,EAAO,aAAa,CAAC,IAAI,GAAW,qBAAqB,IAEzJ,GAAqB,EAAa,EAAiB,IAAyD,CAIvH,GAFkB,gBAAgB,KAAK,EAAI,CAE5B,CAEb,IAAM,EAAS,IAAI,IAAI,EAAI,CAC3B,MAAO,CACL,OAAQ,EAAO,OACf,KAAM,EAAO,SAAW,EAAO,OAAS,EAAO,KAChD,CAIH,IAAI,EAAY,EAChB,GAAI,EAAU,CAEZ,IAAM,EAAoB,EAAS,SAAS,IAAI,CAC1C,EAAqB,EAAI,WAAW,IAAI,CAE9C,AAQE,EARE,GAAqB,EAEX,EAAW,EAAI,MAAM,EAAE,CAC1B,CAAC,GAAqB,CAAC,EAEpB,EAAW,IAAM,EAGjB,EAAW,EAG3B,MAAO,CACL,OAAQ,EACR,KAAM,EACP,EAGU,GACX,EACA,IACU,CACV,IAAM,EAAS,CAAE,GAAG,EAAU,GAAG,EAAW,CAU5C,OAPI,EAAU,UACX,EAA2D,QAAU,CACpE,GAAG,EAAS,QACZ,GAAG,EAAU,QACd,EAGI"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/rapido-http-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Modern undici-based HTTP client with logging, retries, and global configuration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
"@types/node": "^20.0.0",
|
|
62
62
|
"nock": "^14.0.1",
|
|
63
63
|
"zod": "^4.2.1",
|
|
64
|
-
"@autofleet/logger": "^4.2.
|
|
65
|
-
"@autofleet/
|
|
66
|
-
"@autofleet/
|
|
64
|
+
"@autofleet/logger": "^4.2.47",
|
|
65
|
+
"@autofleet/outbreak": "^2.6.2",
|
|
66
|
+
"@autofleet/network": "^1.9.16"
|
|
67
67
|
},
|
|
68
68
|
"scripts": {
|
|
69
69
|
"test": "vitest",
|