@autofleet/rapido-http-client 0.0.17 → 0.1.0

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/README.md CHANGED
@@ -8,6 +8,7 @@
8
8
  ## Why Rapido HTTP Client?
9
9
 
10
10
  Rapido HTTP Client is the next-generation replacement for `@autofleet/network`, designed from the ground up for modern Node.js applications:
11
+
11
12
  ### Key Advantages Over @autofleet/network
12
13
 
13
14
  | Feature | Rapido HTTP Client (undici) | Network (axios) |
@@ -143,6 +144,7 @@ const response2 = await client.get('/data');
143
144
 
144
145
  ```typescript
145
146
  import { z } from 'zod';
147
+ import { errors } from '@autofleet/rapido-http-client';
146
148
 
147
149
  const UserSchema = z.object({
148
150
  id: z.number(),
@@ -151,17 +153,35 @@ const UserSchema = z.object({
151
153
  role: z.enum(['admin', 'user']),
152
154
  });
153
155
 
154
- // Type is automatically inferred from schema!
155
- const { data } = await client.get('/user/123', {
156
- responseSchema: UserSchema,
156
+ const ErrorSchema = z.object({
157
+ error: z.string(),
158
+ code: z.string(),
157
159
  });
158
160
 
159
- // TypeScript knows: data is { id: number; name: string; email: string; role: 'admin' | 'user' }
160
- console.log(data.name); // Type-safe & Runtime-validated!
161
-
162
- // Throws ZodError if response doesn't match schema
161
+ try {
162
+ const { data } = await client.get('/user/123', {
163
+ successSchema: UserSchema,
164
+ errorSchema: ErrorSchema,
165
+ });
166
+ // ✅ data is fully typed: { id: number; name: string; email: string; role: 'admin' | 'user' }
167
+ console.log(data.name);
168
+ } catch (error) {
169
+ if (errors.isRapidoHttpClientError(error)) {
170
+ // error.data is validated against ErrorSchema at runtime
171
+ // Cast to get typed access:
172
+ const apiError = error as errors.RapidoHttpClientError<z.infer<typeof ErrorSchema>>;
173
+ console.log(apiError.data.error);
174
+ }
175
+ }
163
176
  ```
164
177
 
178
+ **Benefits:**
179
+
180
+ - ✅ Runtime validation of both success and error responses
181
+ - ✅ Type-safe success responses (automatic inference)
182
+ - ✅ Validated error data (runtime check with `errorSchema`)
183
+ - ✅ Separate schemas for different response types
184
+
165
185
  </details>
166
186
 
167
187
  <details>
@@ -777,4 +797,4 @@ const client = new RapidoHttpClient({
777
797
  2. **Error Handling**: Uses undici's error classes (`ResponseError`, `RequestAbortedError`, `UndiciError`)
778
798
  3. **Cache**: Built-in HTTP caching support (no external plugin needed)
779
799
  4. **Schema Validation**: Native Zod support with type inference
780
- 5. **Disposal**: Supports async disposal pattern (`await using`)
800
+ 5. **Disposal**: Supports async disposal pattern (`await using`)
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-Dh5SqGdK.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`,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 a={...i.headers},o=this.#r(n,a),{origin:s,path:u}=c.s(t,i.baseURL,i.basePath),d={method:e,baseURL:s,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:f,timeoutSignal:m}=this.#n(i.signal,i.timeout);try{this.#e.info(`Start Request: ${c.t(e,s,u)}`);let t={path:u,origin:s,method:e,signal:f,headers:a,body:o,query:i.params},n=await this.client.request(t);if(!(i.validateStatus??(()=>n.statusCode<400))(n.statusCode)){let t=await this.#a(o,n,r.responseSchema);throw this.#e.error(`Finish Request with error ${c.t(e,s,u)}`,{status:n.statusCode,data:t}),new p.RapidoHttpClientError(o,n,t)}return this.#e.info(`Finish Request: ${c.t(e,s,u)}`),{data:n.statusCode===204?void 0:await this.#a(o,n,r.responseSchema),status:n.statusCode,statusText:l.STATUS_CODES[n.statusCode]||``,headers:n.headers,config:d}}catch(t){if(m&&m.reason===t){this.#e.error(`Request timeout: ${c.t(e,s,u)}`);let t=new p.UndiciError(`Request timeout after ${i.timeout}ms`,{cause:m.reason});throw t.code=`UND_ERR_TIMEOUT`,t}throw f&&f.reason===t?(this.#e.error(`Request aborted: ${c.t(e,s,u)}`),new p.RequestAbortedError(f.reason.message,{cause:f.reason})):(this.#e.error(`Finish Request with error ${c.t(e,s,u)}`,{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))return 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 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;
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-Dh5SqGdK.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`,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(!(i.validateStatus??(()=>n.statusCode<400))(n.statusCode)){let t=await this.#s(u,n,o);throw this.#e.error(`Finish Request with error ${c.t(e,d,f)}`,{status:n.statusCode,data:t}),new p.RapidoHttpClientError(u,n,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))return 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
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["undiciErrors","response: Dispatcher.ResponseData","data: T","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","#parseResponse","STATUS_CODES","error","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<unknown> {\n return typeof value === 'object' && value !== null && RapidoHttpClientErrorBrand in value;\n }\n\n export class RapidoHttpClientError<T> 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: T,\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<unknown> {\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 /** A Zod schema defining what the response should look like. This also parses error responses. */\n responseSchema?: 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>(url: string, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public get<T extends ZodType>(url: string, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, body?: any, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public post<T extends ZodType>(url: string, body: any, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public delete<T extends ZodType>(url: string, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public head<T extends ZodType>(url: string, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, body?: any, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public put<T extends ZodType>(url: string, body: any, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, body?: any, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public patch<T extends ZodType>(url: string, body: any, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public options<T extends ZodType>(url: string, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, body?: any, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public query<T extends ZodType>(url: string, body: any, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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 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.#parseResponse<T>(requestBody, response, config.responseSchema);\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<T>(requestBody, response, data);\n }\n\n this.#logger.info(`Finish Request: ${createRequestString(method, origin, path)}`);\n\n const data = response.statusCode !== 204 ? await this.#parseResponse<T>(requestBody, response, config.responseSchema) : 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 /**\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, 'responseSchema'>);\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","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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"}
package/dist/index.d.cts CHANGED
@@ -27,14 +27,14 @@ declare namespace errors {
27
27
  import RequestRetryError = undiciErrors.RequestRetryError;
28
28
  import SecureProxyConnectionError = undiciErrors.SecureProxyConnectionError;
29
29
  import MaxOriginsReachedError = undiciErrors.MaxOriginsReachedError;
30
- function isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError<unknown>;
31
- class RapidoHttpClientError<T> extends errors$1.ResponseError {
30
+ function isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError;
31
+ class RapidoHttpClientError<TError = unknown> extends errors$1.ResponseError {
32
32
  readonly response: Dispatcher.ResponseData;
33
- readonly data: T;
33
+ readonly data: TError;
34
34
  readonly status: number;
35
35
  readonly statusText: string;
36
- constructor(body: ConstructorParameters<typeof errors$1.ResponseError>[2]["body"], response: Dispatcher.ResponseData, data: T, errorOptions?: ErrorOptions);
37
- static isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError<unknown>;
36
+ constructor(body: ConstructorParameters<typeof errors$1.ResponseError>[2]["body"], response: Dispatcher.ResponseData, data: TError, errorOptions?: ErrorOptions);
37
+ static isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError;
38
38
  }
39
39
  }
40
40
  //#endregion
@@ -85,8 +85,15 @@ interface RequestConfig {
85
85
  headers?: Record<string, string>;
86
86
  /** An `AbortSignal` which should abort the request and it's parsing when aborted. */
87
87
  signal?: AbortSignal;
88
- /** A Zod schema defining what the response should look like. This also parses error responses. */
89
- responseSchema?: ZodType;
88
+ /**
89
+ * Zod schema for successful responses. Used when `validateStatus` returns `true` (default: status < 400).
90
+ */
91
+ successSchema?: ZodType;
92
+ /**
93
+ * Zod schema for error responses. Used when `validateStatus` returns `false` (default: status >= 400).
94
+ * The validated error data is available in the thrown `RapidoHttpClientError`.
95
+ */
96
+ errorSchema?: ZodType;
90
97
  /**
91
98
  * A function to validate the HTTP response status code.
92
99
  * Return `true` to consider the status valid, `false` otherwise.
@@ -115,54 +122,102 @@ declare class RapidoHttpClient {
115
122
  #private;
116
123
  private readonly settings;
117
124
  readonly client: Dispatcher.ComposedDispatcher;
118
- get<T = unknown>(url: string, config?: Omit<RequestConfig, "responseSchema"> & {
119
- responseSchema?: never;
125
+ get<T = unknown>(url: string, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
126
+ successSchema?: never;
127
+ errorSchema?: never;
120
128
  }): Promise<RapidoHttpClientResponse<T>>;
121
- get<T extends ZodType>(url: string, config: RequestConfig & {
122
- responseSchema: T;
123
- }): Promise<RapidoHttpClientResponse<output<T>>>;
124
- post<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "responseSchema"> & {
125
- responseSchema?: never;
129
+ get<TSuccess extends ZodType>(url: string, config: RequestConfig & {
130
+ successSchema: TSuccess;
131
+ errorSchema?: never;
132
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
133
+ get<TSuccess extends ZodType>(url: string, config: RequestConfig & {
134
+ successSchema: TSuccess;
135
+ errorSchema?: ZodType;
136
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
137
+ post<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
138
+ successSchema?: never;
139
+ errorSchema?: never;
126
140
  }): Promise<RapidoHttpClientResponse<T>>;
127
- post<T extends ZodType>(url: string, body: any, config: RequestConfig & {
128
- responseSchema: T;
129
- }): Promise<RapidoHttpClientResponse<output<T>>>;
130
- delete<T = unknown>(url: string, config?: Omit<RequestConfig, "responseSchema"> & {
131
- responseSchema?: never;
141
+ post<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
142
+ successSchema: TSuccess;
143
+ errorSchema?: never;
144
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
145
+ post<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
146
+ successSchema: TSuccess;
147
+ errorSchema?: ZodType;
148
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
149
+ delete<T = unknown>(url: string, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
150
+ successSchema?: never;
151
+ errorSchema?: never;
132
152
  }): Promise<RapidoHttpClientResponse<T>>;
133
- delete<T extends ZodType>(url: string, config: RequestConfig & {
134
- responseSchema: T;
135
- }): Promise<RapidoHttpClientResponse<output<T>>>;
136
- head<T = unknown>(url: string, config?: Omit<RequestConfig, "responseSchema"> & {
137
- responseSchema?: never;
153
+ delete<TSuccess extends ZodType>(url: string, config: RequestConfig & {
154
+ successSchema: TSuccess;
155
+ errorSchema?: never;
156
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
157
+ delete<TSuccess extends ZodType>(url: string, config: RequestConfig & {
158
+ successSchema: TSuccess;
159
+ errorSchema?: ZodType;
160
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
161
+ head<T = unknown>(url: string, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
162
+ successSchema?: never;
163
+ errorSchema?: never;
138
164
  }): Promise<RapidoHttpClientResponse<T>>;
139
- head<T extends ZodType>(url: string, config: RequestConfig & {
140
- responseSchema: T;
141
- }): Promise<RapidoHttpClientResponse<output<T>>>;
142
- put<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "responseSchema"> & {
143
- responseSchema?: never;
165
+ head<TSuccess extends ZodType>(url: string, config: RequestConfig & {
166
+ successSchema: TSuccess;
167
+ errorSchema?: never;
168
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
169
+ head<TSuccess extends ZodType>(url: string, config: RequestConfig & {
170
+ successSchema: TSuccess;
171
+ errorSchema?: ZodType;
172
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
173
+ put<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
174
+ successSchema?: never;
175
+ errorSchema?: never;
144
176
  }): Promise<RapidoHttpClientResponse<T>>;
145
- put<T extends ZodType>(url: string, body: any, config: RequestConfig & {
146
- responseSchema: T;
147
- }): Promise<RapidoHttpClientResponse<output<T>>>;
148
- patch<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "responseSchema"> & {
149
- responseSchema?: never;
177
+ put<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
178
+ successSchema: TSuccess;
179
+ errorSchema?: never;
180
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
181
+ put<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
182
+ successSchema: TSuccess;
183
+ errorSchema?: ZodType;
184
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
185
+ patch<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
186
+ successSchema?: never;
187
+ errorSchema?: never;
150
188
  }): Promise<RapidoHttpClientResponse<T>>;
151
- patch<T extends ZodType>(url: string, body: any, config: RequestConfig & {
152
- responseSchema: T;
153
- }): Promise<RapidoHttpClientResponse<output<T>>>;
154
- options<T = unknown>(url: string, config?: Omit<RequestConfig, "responseSchema"> & {
155
- responseSchema?: never;
189
+ patch<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
190
+ successSchema: TSuccess;
191
+ errorSchema?: never;
192
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
193
+ patch<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
194
+ successSchema: TSuccess;
195
+ errorSchema?: ZodType;
196
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
197
+ options<T = unknown>(url: string, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
198
+ successSchema?: never;
199
+ errorSchema?: never;
156
200
  }): Promise<RapidoHttpClientResponse<T>>;
157
- options<T extends ZodType>(url: string, config: RequestConfig & {
158
- responseSchema: T;
159
- }): Promise<RapidoHttpClientResponse<output<T>>>;
160
- query<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "responseSchema"> & {
161
- responseSchema?: never;
201
+ options<TSuccess extends ZodType>(url: string, config: RequestConfig & {
202
+ successSchema: TSuccess;
203
+ errorSchema?: never;
204
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
205
+ options<TSuccess extends ZodType>(url: string, config: RequestConfig & {
206
+ successSchema: TSuccess;
207
+ errorSchema?: ZodType;
208
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
209
+ query<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
210
+ successSchema?: never;
211
+ errorSchema?: never;
162
212
  }): Promise<RapidoHttpClientResponse<T>>;
163
- query<T extends ZodType>(url: string, body: any, config: RequestConfig & {
164
- responseSchema: T;
165
- }): Promise<RapidoHttpClientResponse<output<T>>>;
213
+ query<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
214
+ successSchema: TSuccess;
215
+ errorSchema?: never;
216
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
217
+ query<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
218
+ successSchema: TSuccess;
219
+ errorSchema?: ZodType;
220
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
166
221
  constructor(settings: RapidoHttpClientSettings);
167
222
  /**
168
223
  * @param url The endpoint URL to send the request to.
package/dist/index.d.ts CHANGED
@@ -27,14 +27,14 @@ declare namespace errors {
27
27
  import RequestRetryError = undiciErrors.RequestRetryError;
28
28
  import SecureProxyConnectionError = undiciErrors.SecureProxyConnectionError;
29
29
  import MaxOriginsReachedError = undiciErrors.MaxOriginsReachedError;
30
- function isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError<unknown>;
31
- class RapidoHttpClientError<T> extends errors$1.ResponseError {
30
+ function isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError;
31
+ class RapidoHttpClientError<TError = unknown> extends errors$1.ResponseError {
32
32
  readonly response: Dispatcher.ResponseData;
33
- readonly data: T;
33
+ readonly data: TError;
34
34
  readonly status: number;
35
35
  readonly statusText: string;
36
- constructor(body: ConstructorParameters<typeof errors$1.ResponseError>[2]["body"], response: Dispatcher.ResponseData, data: T, errorOptions?: ErrorOptions);
37
- static isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError<unknown>;
36
+ constructor(body: ConstructorParameters<typeof errors$1.ResponseError>[2]["body"], response: Dispatcher.ResponseData, data: TError, errorOptions?: ErrorOptions);
37
+ static isRapidoHttpClientError(value: unknown): value is RapidoHttpClientError;
38
38
  }
39
39
  }
40
40
  //#endregion
@@ -85,8 +85,15 @@ interface RequestConfig {
85
85
  headers?: Record<string, string>;
86
86
  /** An `AbortSignal` which should abort the request and it's parsing when aborted. */
87
87
  signal?: AbortSignal;
88
- /** A Zod schema defining what the response should look like. This also parses error responses. */
89
- responseSchema?: ZodType;
88
+ /**
89
+ * Zod schema for successful responses. Used when `validateStatus` returns `true` (default: status < 400).
90
+ */
91
+ successSchema?: ZodType;
92
+ /**
93
+ * Zod schema for error responses. Used when `validateStatus` returns `false` (default: status >= 400).
94
+ * The validated error data is available in the thrown `RapidoHttpClientError`.
95
+ */
96
+ errorSchema?: ZodType;
90
97
  /**
91
98
  * A function to validate the HTTP response status code.
92
99
  * Return `true` to consider the status valid, `false` otherwise.
@@ -115,54 +122,102 @@ declare class RapidoHttpClient {
115
122
  #private;
116
123
  private readonly settings;
117
124
  readonly client: Dispatcher.ComposedDispatcher;
118
- get<T = unknown>(url: string, config?: Omit<RequestConfig, "responseSchema"> & {
119
- responseSchema?: never;
125
+ get<T = unknown>(url: string, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
126
+ successSchema?: never;
127
+ errorSchema?: never;
120
128
  }): Promise<RapidoHttpClientResponse<T>>;
121
- get<T extends ZodType>(url: string, config: RequestConfig & {
122
- responseSchema: T;
123
- }): Promise<RapidoHttpClientResponse<output<T>>>;
124
- post<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "responseSchema"> & {
125
- responseSchema?: never;
129
+ get<TSuccess extends ZodType>(url: string, config: RequestConfig & {
130
+ successSchema: TSuccess;
131
+ errorSchema?: never;
132
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
133
+ get<TSuccess extends ZodType>(url: string, config: RequestConfig & {
134
+ successSchema: TSuccess;
135
+ errorSchema?: ZodType;
136
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
137
+ post<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
138
+ successSchema?: never;
139
+ errorSchema?: never;
126
140
  }): Promise<RapidoHttpClientResponse<T>>;
127
- post<T extends ZodType>(url: string, body: any, config: RequestConfig & {
128
- responseSchema: T;
129
- }): Promise<RapidoHttpClientResponse<output<T>>>;
130
- delete<T = unknown>(url: string, config?: Omit<RequestConfig, "responseSchema"> & {
131
- responseSchema?: never;
141
+ post<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
142
+ successSchema: TSuccess;
143
+ errorSchema?: never;
144
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
145
+ post<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
146
+ successSchema: TSuccess;
147
+ errorSchema?: ZodType;
148
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
149
+ delete<T = unknown>(url: string, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
150
+ successSchema?: never;
151
+ errorSchema?: never;
132
152
  }): Promise<RapidoHttpClientResponse<T>>;
133
- delete<T extends ZodType>(url: string, config: RequestConfig & {
134
- responseSchema: T;
135
- }): Promise<RapidoHttpClientResponse<output<T>>>;
136
- head<T = unknown>(url: string, config?: Omit<RequestConfig, "responseSchema"> & {
137
- responseSchema?: never;
153
+ delete<TSuccess extends ZodType>(url: string, config: RequestConfig & {
154
+ successSchema: TSuccess;
155
+ errorSchema?: never;
156
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
157
+ delete<TSuccess extends ZodType>(url: string, config: RequestConfig & {
158
+ successSchema: TSuccess;
159
+ errorSchema?: ZodType;
160
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
161
+ head<T = unknown>(url: string, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
162
+ successSchema?: never;
163
+ errorSchema?: never;
138
164
  }): Promise<RapidoHttpClientResponse<T>>;
139
- head<T extends ZodType>(url: string, config: RequestConfig & {
140
- responseSchema: T;
141
- }): Promise<RapidoHttpClientResponse<output<T>>>;
142
- put<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "responseSchema"> & {
143
- responseSchema?: never;
165
+ head<TSuccess extends ZodType>(url: string, config: RequestConfig & {
166
+ successSchema: TSuccess;
167
+ errorSchema?: never;
168
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
169
+ head<TSuccess extends ZodType>(url: string, config: RequestConfig & {
170
+ successSchema: TSuccess;
171
+ errorSchema?: ZodType;
172
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
173
+ put<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
174
+ successSchema?: never;
175
+ errorSchema?: never;
144
176
  }): Promise<RapidoHttpClientResponse<T>>;
145
- put<T extends ZodType>(url: string, body: any, config: RequestConfig & {
146
- responseSchema: T;
147
- }): Promise<RapidoHttpClientResponse<output<T>>>;
148
- patch<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "responseSchema"> & {
149
- responseSchema?: never;
177
+ put<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
178
+ successSchema: TSuccess;
179
+ errorSchema?: never;
180
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
181
+ put<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
182
+ successSchema: TSuccess;
183
+ errorSchema?: ZodType;
184
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
185
+ patch<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
186
+ successSchema?: never;
187
+ errorSchema?: never;
150
188
  }): Promise<RapidoHttpClientResponse<T>>;
151
- patch<T extends ZodType>(url: string, body: any, config: RequestConfig & {
152
- responseSchema: T;
153
- }): Promise<RapidoHttpClientResponse<output<T>>>;
154
- options<T = unknown>(url: string, config?: Omit<RequestConfig, "responseSchema"> & {
155
- responseSchema?: never;
189
+ patch<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
190
+ successSchema: TSuccess;
191
+ errorSchema?: never;
192
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
193
+ patch<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
194
+ successSchema: TSuccess;
195
+ errorSchema?: ZodType;
196
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
197
+ options<T = unknown>(url: string, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
198
+ successSchema?: never;
199
+ errorSchema?: never;
156
200
  }): Promise<RapidoHttpClientResponse<T>>;
157
- options<T extends ZodType>(url: string, config: RequestConfig & {
158
- responseSchema: T;
159
- }): Promise<RapidoHttpClientResponse<output<T>>>;
160
- query<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "responseSchema"> & {
161
- responseSchema?: never;
201
+ options<TSuccess extends ZodType>(url: string, config: RequestConfig & {
202
+ successSchema: TSuccess;
203
+ errorSchema?: never;
204
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
205
+ options<TSuccess extends ZodType>(url: string, config: RequestConfig & {
206
+ successSchema: TSuccess;
207
+ errorSchema?: ZodType;
208
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
209
+ query<T = unknown>(url: string, body?: any, config?: Omit<RequestConfig, "successSchema" | "errorSchema"> & {
210
+ successSchema?: never;
211
+ errorSchema?: never;
162
212
  }): Promise<RapidoHttpClientResponse<T>>;
163
- query<T extends ZodType>(url: string, body: any, config: RequestConfig & {
164
- responseSchema: T;
165
- }): Promise<RapidoHttpClientResponse<output<T>>>;
213
+ query<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
214
+ successSchema: TSuccess;
215
+ errorSchema?: never;
216
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
217
+ query<TSuccess extends ZodType>(url: string, body: any, config: RequestConfig & {
218
+ successSchema: TSuccess;
219
+ errorSchema?: ZodType;
220
+ }): Promise<RapidoHttpClientResponse<output<TSuccess>>>;
166
221
  constructor(settings: RapidoHttpClientSettings);
167
222
  /**
168
223
  * @param url The endpoint URL to send the request to.
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-CN26OYva.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`,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 l={...a.headers},u=this.#r(n,l),{origin:d,path:f}=o(t,a.baseURL,a.basePath),p={method:e,baseURL:d,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:m,timeoutSignal:g}=this.#n(a.signal,a.timeout);try{this.#e.info(`Start Request: ${s(e,d,f)}`);let t={path:f,origin:d,method:e,signal:m,headers:l,body:u,query:a.params},n=await this.client.request(t);if(!(a.validateStatus??(()=>n.statusCode<400))(n.statusCode)){let t=await this.#a(u,n,r.responseSchema);throw this.#e.error(`Finish Request with error ${s(e,d,f)}`,{status:n.statusCode,data:t}),new h.RapidoHttpClientError(u,n,t)}return this.#e.info(`Finish Request: ${s(e,d,f)}`),{data:n.statusCode===204?void 0:await this.#a(u,n,r.responseSchema),status:n.statusCode,statusText:c[n.statusCode]||``,headers:n.headers,config:p}}catch(t){if(g&&g.reason===t){this.#e.error(`Request timeout: ${s(e,d,f)}`);let t=new h.UndiciError(`Request timeout after ${a.timeout}ms`,{cause:g.reason});throw t.code=`UND_ERR_TIMEOUT`,t}throw m&&m.reason===t?(this.#e.error(`Request aborted: ${s(e,d,f)}`),new h.RequestAbortedError(m.reason.message,{cause:m.reason})):(this.#e.error(`Finish Request with error ${s(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))return 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 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};
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-CN26OYva.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`,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(!(a.validateStatus??(()=>n.statusCode<400))(n.statusCode)){let t=await this.#s(f,n,u);throw this.#e.error(`Finish Request with error ${s(e,p,m)}`,{status:n.statusCode,data:t}),new h.RapidoHttpClientError(f,n,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))return 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: T","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","#parseResponse","error","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<unknown> {\n return typeof value === 'object' && value !== null && RapidoHttpClientErrorBrand in value;\n }\n\n export class RapidoHttpClientError<T> 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: T,\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<unknown> {\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 /** A Zod schema defining what the response should look like. This also parses error responses. */\n responseSchema?: 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>(url: string, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public get<T extends ZodType>(url: string, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, body?: any, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public post<T extends ZodType>(url: string, body: any, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public delete<T extends ZodType>(url: string, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public head<T extends ZodType>(url: string, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, body?: any, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public put<T extends ZodType>(url: string, body: any, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, body?: any, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public patch<T extends ZodType>(url: string, body: any, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public options<T extends ZodType>(url: string, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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>(url: string, body?: any, config?: Omit<RequestConfig, 'responseSchema'> & { responseSchema?: never; }): Promise<RapidoHttpClientResponse<T>>;\n public query<T extends ZodType>(url: string, body: any, config: RequestConfig & { responseSchema: T; }): Promise<RapidoHttpClientResponse<output<T>>>;\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 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.#parseResponse<T>(requestBody, response, config.responseSchema);\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<T>(requestBody, response, data);\n }\n\n this.#logger.info(`Finish Request: ${createRequestString(method, origin, path)}`);\n\n const data = response.statusCode !== 204 ? await this.#parseResponse<T>(requestBody, response, config.responseSchema) : 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 /**\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, 'responseSchema'>);\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.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":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rapido-http-client",
3
- "version": "0.0.17",
3
+ "version": "0.1.0",
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.45",
65
64
  "@autofleet/network": "^1.9.13",
66
- "@autofleet/outbreak": "^2.5.14"
65
+ "@autofleet/outbreak": "^2.5.14",
66
+ "@autofleet/logger": "^4.2.45"
67
67
  },
68
68
  "scripts": {
69
69
  "test": "vitest",