aspi 1.3.0 → 2.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 +464 -209
- package/dist/index.cjs +548 -149
- package/dist/index.d.cts +583 -138
- package/dist/index.d.ts +583 -138
- package/dist/index.js +548 -149
- package/package.json +13 -14
package/dist/index.d.ts
CHANGED
|
@@ -67,36 +67,176 @@ declare const getHttpErrorStatus: (status: HttpErrorCodes) => HttpErrorStatus;
|
|
|
67
67
|
*/
|
|
68
68
|
type HttpMethods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'TRACE' | 'CONNECT';
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Utility type to simplify and prettify a given type.
|
|
72
|
+
*
|
|
73
|
+
* @template Type - The type to be prettified.
|
|
74
|
+
*/
|
|
70
75
|
type Prettify<Type> = Type extends Function ? Type : Extract<{
|
|
71
76
|
[Key in keyof Type]: Type[Key];
|
|
72
77
|
}, Type>;
|
|
78
|
+
/**
|
|
79
|
+
* Merge two object types, with properties from `Object2` overriding those in `Object1`.
|
|
80
|
+
*
|
|
81
|
+
* @template Object1 - The base object type.
|
|
82
|
+
* @template Object2 - The object type whose properties will take precedence.
|
|
83
|
+
*/
|
|
73
84
|
type Merge<Object1, Object2> = Prettify<Omit<Object1, keyof Object2> & Object2>;
|
|
85
|
+
/**
|
|
86
|
+
* Represents the base URL used by Aspi.
|
|
87
|
+
*
|
|
88
|
+
* Accepts either a string representation of the URL or a native {@link URL} object.
|
|
89
|
+
*/
|
|
90
|
+
type BaseURL = string | URL;
|
|
91
|
+
/**
|
|
92
|
+
* Base configuration for Aspi.
|
|
93
|
+
*
|
|
94
|
+
* This configuration is merged with native `RequestInit` properties and
|
|
95
|
+
* is intended to be passed alongside a `RequestInit` object when initializing
|
|
96
|
+
* an Aspi instance.
|
|
97
|
+
*/
|
|
74
98
|
type AspiConfigBase = {
|
|
75
|
-
|
|
99
|
+
/**
|
|
100
|
+
* The base URL for all Aspi requests.
|
|
101
|
+
*/
|
|
102
|
+
baseUrl: BaseURL;
|
|
103
|
+
/**
|
|
104
|
+
* Optional retry configuration applied to all requests.
|
|
105
|
+
*/
|
|
76
106
|
retryConfig?: AspiRetryConfig<AspiRequestInit>;
|
|
77
107
|
};
|
|
108
|
+
/**
|
|
109
|
+
* Configuration for an Aspi instance (without request body).
|
|
110
|
+
*
|
|
111
|
+
* This type includes all standard `RequestInit` properties
|
|
112
|
+
* (`headers`, `mode`, `credentials`, `cache`, `redirect`,
|
|
113
|
+
* `referrer`, `referrerPolicy`, `integrity`, `keepalive`, `signal`)
|
|
114
|
+
* merged with the base Aspi configuration defined in {@link AspiConfigBase}.
|
|
115
|
+
*
|
|
116
|
+
* @extends Merge<Pick<RequestInit,
|
|
117
|
+
* | 'headers'
|
|
118
|
+
* | 'mode'
|
|
119
|
+
* | 'credentials'
|
|
120
|
+
* | 'cache'
|
|
121
|
+
* | 'redirect'
|
|
122
|
+
* | 'referrer'
|
|
123
|
+
* | 'referrerPolicy'
|
|
124
|
+
* | 'integrity'
|
|
125
|
+
* | 'keepalive'
|
|
126
|
+
* | 'signal'>,
|
|
127
|
+
* AspiConfigBase>
|
|
128
|
+
*/
|
|
129
|
+
interface AspiRequestInitWithoutBodyAndMethod extends Merge<Pick<RequestInit, 'headers' | 'mode' | 'credentials' | 'cache' | 'redirect' | 'referrer' | 'referrerPolicy' | 'integrity' | 'keepalive' | 'signal'>, AspiConfigBase> {
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Configuration for an Aspi request that may include a request body.
|
|
133
|
+
*
|
|
134
|
+
* Extends {@link AspiRequestInitWithoutBody} with the optional `body`
|
|
135
|
+
* property from the native {@link RequestInit} type.
|
|
136
|
+
*
|
|
137
|
+
* @template TBody - The type of the request body (defaults to `any`).
|
|
138
|
+
* @extends Merge<Pick<RequestInit, 'body'>, AspiRequestInitWithoutBody>
|
|
139
|
+
*/
|
|
140
|
+
interface AspiRequestInit<TBody = any> extends Merge<Pick<RequestInit, 'body' | 'method'>, Omit<AspiRequestInitWithoutBodyAndMethod, 'retryConfig'>> {
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Configuration options for retrying an Aspi request.
|
|
144
|
+
*
|
|
145
|
+
* @template TRequest - The request type extending {@link AspiRequestInit}.
|
|
146
|
+
*/
|
|
78
147
|
type AspiRetryConfig<TRequest extends AspiRequestInit> = {
|
|
148
|
+
/**
|
|
149
|
+
* Maximum number of retry attempts. If omitted, no retries are performed.
|
|
150
|
+
*/
|
|
79
151
|
retries?: number;
|
|
152
|
+
/**
|
|
153
|
+
* Delay before the next retry attempt.
|
|
154
|
+
*
|
|
155
|
+
* Can be a static number (milliseconds) or a function that dynamically
|
|
156
|
+
* determines the delay based on the retry state and the request/response.
|
|
157
|
+
*
|
|
158
|
+
* @param remainingRetries - Number of retries left after the current attempt.
|
|
159
|
+
* @param totalRetries - The total number of retries configured.
|
|
160
|
+
* @param request - The original {@link AspiRequest} being retried.
|
|
161
|
+
* @param response - The {@link AspiResponse} received from the failed attempt.
|
|
162
|
+
* @returns A delay in milliseconds or a promise that resolves to one.
|
|
163
|
+
*/
|
|
80
164
|
retryDelay?: number | ((remainingRetries: number, totalRetries: number, request: AspiRequest<TRequest>, response: AspiResponse) => number | Promise<number>);
|
|
165
|
+
/**
|
|
166
|
+
* Array of HTTP status codes that should trigger a retry.
|
|
167
|
+
*/
|
|
81
168
|
retryOn?: Array<HttpErrorCodes>;
|
|
169
|
+
/**
|
|
170
|
+
* Predicate function that determines whether a retry should occur based on the
|
|
171
|
+
* request and response. Returning `true` triggers a retry.
|
|
172
|
+
*
|
|
173
|
+
* @param request - The {@link AspiRequest} that was sent.
|
|
174
|
+
* @param response - The {@link AspiResponse} received.
|
|
175
|
+
* @returns A boolean or a promise that resolves to a boolean.
|
|
176
|
+
*/
|
|
82
177
|
retryWhile?: (request: AspiRequest<TRequest>, response: AspiResponse) => boolean | Promise<boolean>;
|
|
178
|
+
/**
|
|
179
|
+
* Callback invoked after each retry attempt.
|
|
180
|
+
*
|
|
181
|
+
* @param request - The {@link AspiRequest} that was retried.
|
|
182
|
+
* @param response - The {@link AspiResponse} from the failed attempt.
|
|
183
|
+
*/
|
|
83
184
|
onRetry?: (request: AspiRequest<TRequest>, response: AspiResponse) => void;
|
|
84
185
|
};
|
|
85
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Callback type for handling custom errors.
|
|
188
|
+
*
|
|
189
|
+
* @template T - The request type extending {@link AspiRequestInit}.
|
|
190
|
+
* @template A - The shape of the error object returned by the callback.
|
|
191
|
+
* @param input - Object containing the request and response that triggered the error.
|
|
192
|
+
* @param input.request - The {@link AspiRequest} associated with the failed request.
|
|
193
|
+
* @param input.response - The {@link AspiResponse} received from the server.
|
|
194
|
+
* @returns The error data of type `A`.
|
|
195
|
+
*/
|
|
86
196
|
type CustomErrorCb<T extends AspiRequestInit, A extends {}> = (input: {
|
|
87
197
|
request: AspiRequest<T>;
|
|
88
198
|
response: AspiResponse;
|
|
89
199
|
}) => A;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Transforms a request before it is sent.
|
|
202
|
+
*
|
|
203
|
+
* @template T - The original request type extending {@link AspiRequestInit}.
|
|
204
|
+
* @template U - The resulting request type extending {@link AspiRequestInit}.
|
|
205
|
+
* @param request - The request instance to be transformed.
|
|
206
|
+
* @returns The transformed request of type `U`.
|
|
207
|
+
*/
|
|
208
|
+
type RequestTransformer<T extends AspiRequestInit, U extends AspiRequestInit> = (request: T) => U;
|
|
209
|
+
/**
|
|
210
|
+
* Options for configuring an Aspi request.
|
|
211
|
+
*
|
|
212
|
+
* @template TRequest - The request initialization type extending {@link AspiRequestInit}.
|
|
213
|
+
* @property {TRequest} requestConfig - The request configuration object.
|
|
214
|
+
* @property {AspiRetryConfig<TRequest>} [retryConfig] - Optional retry configuration applied to the request.
|
|
215
|
+
* @property {RequestTransformer<TRequest, TRequest>[]} [middlewares] - Optional list of request transformers that act as middleware.
|
|
216
|
+
* @property {ErrorCallbacks} [errorCbs] - Optional collection of custom error callbacks keyed by HTTP status code.
|
|
217
|
+
* @property {boolean} [throwOnError] - When `true`, the request will throw on error instead of returning an error result.
|
|
218
|
+
* @property {boolean} [shouldBeResult] - When `true`, the request returns an {@link AspiResultOk} instead of a raw response.
|
|
219
|
+
*/
|
|
93
220
|
type RequestOptions<TRequest extends AspiRequestInit> = {
|
|
94
221
|
requestConfig: TRequest;
|
|
95
222
|
retryConfig?: AspiRetryConfig<TRequest>;
|
|
96
|
-
middlewares?:
|
|
223
|
+
middlewares?: RequestTransformer<TRequest, TRequest>[];
|
|
97
224
|
errorCbs?: ErrorCallbacks;
|
|
98
225
|
throwOnError?: boolean;
|
|
226
|
+
shouldBeResult?: boolean;
|
|
99
227
|
};
|
|
228
|
+
/**
|
|
229
|
+
* Record of custom error callbacks keyed by HTTP status code.
|
|
230
|
+
*
|
|
231
|
+
* It keeps track of the custom error callbacks (`cb`) provided for specific
|
|
232
|
+
* response codes. Each entry includes:
|
|
233
|
+
*
|
|
234
|
+
* - `cb`: a function receiving the request and response objects that generated the error.
|
|
235
|
+
* - `tag`: an optional identifier or metadata associated with the callback.
|
|
236
|
+
*
|
|
237
|
+
* This type is used in {@link RequestOptions.errorCbs} to map status codes to
|
|
238
|
+
* their corresponding handlers.
|
|
239
|
+
*/
|
|
100
240
|
type ErrorCallbacks = Record<number, {
|
|
101
241
|
cb: (input: {
|
|
102
242
|
request: any;
|
|
@@ -104,44 +244,66 @@ type ErrorCallbacks = Record<number, {
|
|
|
104
244
|
}) => any;
|
|
105
245
|
tag: unknown;
|
|
106
246
|
}>;
|
|
247
|
+
/**
|
|
248
|
+
* Represents a successful Aspi request result.
|
|
249
|
+
*
|
|
250
|
+
* @template TRequest - The request initialization options type extending {@link AspiRequestInit}.
|
|
251
|
+
* @template TData - The type of the response data.
|
|
252
|
+
* @property {TData} data - The parsed response payload.
|
|
253
|
+
* @property {AspiRequest<TRequest>} request - The request that was sent.
|
|
254
|
+
* @property {AspiResponse} response - The response wrapper containing status, status text, and the native {@link Response} object.
|
|
255
|
+
*/
|
|
107
256
|
type AspiResultOk<TRequest extends AspiRequestInit, TData> = {
|
|
108
257
|
data: TData;
|
|
109
258
|
request: AspiRequest<TRequest>;
|
|
110
259
|
response: AspiResponse;
|
|
111
260
|
};
|
|
112
|
-
type AspiPlainResponse<TRequest extends AspiRequestInit, TData> = AspiResultOk<TRequest, TData>;
|
|
113
|
-
|
|
114
261
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* @
|
|
262
|
+
* Represents a successful Aspi request result without any additional metadata.
|
|
263
|
+
*
|
|
264
|
+
* This type is an alias for {@link AspiResultOk} and is provided for semantic
|
|
265
|
+
* clarity when a plain response shape is desired.
|
|
266
|
+
*
|
|
267
|
+
* @template TRequest - The request initialization options type extending {@link AspiRequestInit}.
|
|
268
|
+
* @template TData - The type of the response payload.
|
|
121
269
|
*/
|
|
122
|
-
|
|
123
|
-
status: HttpErrorCodes;
|
|
124
|
-
statusText: HttpErrorStatus;
|
|
125
|
-
response?: Response;
|
|
126
|
-
responseData?: any;
|
|
127
|
-
}
|
|
270
|
+
type AspiPlainResponse<TRequest extends AspiRequestInit, TData> = AspiResultOk<TRequest, TData>;
|
|
128
271
|
/**
|
|
129
|
-
* Interface representing an API request configuration
|
|
272
|
+
* Interface representing an API request configuration.
|
|
273
|
+
*
|
|
130
274
|
* @interface AspiRequest
|
|
131
|
-
* @template T - Request initialization options type extending AspiRequestInit
|
|
132
|
-
* @property {string}
|
|
133
|
-
* @property {
|
|
134
|
-
* @property {
|
|
135
|
-
* @property {URLSearchParams | null} queryParams - URL query parameters, if any
|
|
136
|
-
* @property {AspiRetryConfig<T>} retryConfig - Retry configuration for failed requests
|
|
275
|
+
* @template T - Request initialization options type extending {@link AspiRequestInit}
|
|
276
|
+
* @property {string} path - Request path to append to the base URL.
|
|
277
|
+
* @property {T} requestInit - Request initialization options.
|
|
278
|
+
* @property {URLSearchParams | null} queryParams - URL query parameters, if any.
|
|
137
279
|
*/
|
|
138
280
|
interface AspiRequest<T extends AspiRequestInit> {
|
|
139
|
-
baseUrl: string;
|
|
140
281
|
path: string;
|
|
141
282
|
requestInit: T;
|
|
142
283
|
queryParams: URLSearchParams | null;
|
|
143
|
-
retryConfig: AspiRetryConfig<T>;
|
|
144
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Represents the response returned by an Aspi request.
|
|
287
|
+
*
|
|
288
|
+
* @template TData - The type of the response payload when the request succeeds.
|
|
289
|
+
* @template IsError - `true` if the response represents an error condition; `false` otherwise.
|
|
290
|
+
*
|
|
291
|
+
* @property {HttpErrorCodes} status - HTTP status code of the response.
|
|
292
|
+
* @property {HttpErrorStatus} statusText - HTTP status text associated with the status code.
|
|
293
|
+
* @property {Response} response - The native {@link Response} object.
|
|
294
|
+
* @property {TData} [responseData] - The parsed response body. When `IsError` is `true` this property is required; otherwise it is optional.
|
|
295
|
+
*/
|
|
296
|
+
type AspiResponse<TData = any, IsError extends boolean = false> = Merge<{
|
|
297
|
+
status: HttpErrorCodes;
|
|
298
|
+
statusLabel: HttpErrorStatus;
|
|
299
|
+
response: Response;
|
|
300
|
+
statusText: string;
|
|
301
|
+
}, IsError extends true ? {
|
|
302
|
+
responseData: TData;
|
|
303
|
+
} : {
|
|
304
|
+
responseData?: any;
|
|
305
|
+
}>;
|
|
306
|
+
|
|
145
307
|
/**
|
|
146
308
|
* Custom error class for API errors
|
|
147
309
|
* @class AspiError
|
|
@@ -150,17 +312,17 @@ interface AspiRequest<T extends AspiRequestInit> {
|
|
|
150
312
|
* @property {AspiRe} request - The original request configuration
|
|
151
313
|
* @property {AspiResponse} response - The error response details
|
|
152
314
|
*/
|
|
153
|
-
declare class AspiError<
|
|
315
|
+
declare class AspiError<TRequest extends AspiRequestInit> extends Error {
|
|
154
316
|
tag: "aspiError";
|
|
155
|
-
request: AspiRequest<
|
|
156
|
-
response: AspiResponse
|
|
317
|
+
request: AspiRequest<TRequest>;
|
|
318
|
+
response: AspiResponse<any, false>;
|
|
157
319
|
/**
|
|
158
320
|
* Creates an instance of AspiError
|
|
159
321
|
* @param {string} message - The error message
|
|
160
322
|
* @param {AspiRe} request - The request configuration
|
|
161
323
|
* @param {AspiResponse} response - The error response
|
|
162
324
|
*/
|
|
163
|
-
constructor(message: string, request: AspiRequest<
|
|
325
|
+
constructor(message: string, request: AspiRequest<TRequest>, response: AspiResponse);
|
|
164
326
|
/**
|
|
165
327
|
* Conditionally executes callback if status matches
|
|
166
328
|
* @template T
|
|
@@ -169,8 +331,8 @@ declare class AspiError<TReq extends AspiRequestInit> extends Error {
|
|
|
169
331
|
* @returns {T | undefined} Result of callback if status matches, undefined otherwise
|
|
170
332
|
*/
|
|
171
333
|
ifMatch<T>(status: HttpErrorStatus, cb: (args: {
|
|
172
|
-
request: AspiRequest<
|
|
173
|
-
response: AspiResponse
|
|
334
|
+
request: AspiRequest<TRequest>;
|
|
335
|
+
response: AspiResponse<any, false>;
|
|
174
336
|
}) => T): T | undefined;
|
|
175
337
|
}
|
|
176
338
|
/**
|
|
@@ -606,7 +768,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
606
768
|
error: {};
|
|
607
769
|
}> {
|
|
608
770
|
#private;
|
|
609
|
-
constructor(method: HttpMethods, path: string,
|
|
771
|
+
constructor(method: HttpMethods, path: string, requestOptions: RequestOptions<TRequest>);
|
|
610
772
|
/**
|
|
611
773
|
* Sets the base URL for the request.
|
|
612
774
|
* @param url The base URL to set
|
|
@@ -615,7 +777,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
615
777
|
* const request = new Request('/users', config);
|
|
616
778
|
* request.setBaseUrl('https://api.example.com');
|
|
617
779
|
*/
|
|
618
|
-
setBaseUrl(url:
|
|
780
|
+
setBaseUrl(url: BaseURL): this;
|
|
619
781
|
/**
|
|
620
782
|
* Sets the retry configuration for the request.
|
|
621
783
|
* @param retry The retry configuration object
|
|
@@ -631,17 +793,21 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
631
793
|
*/
|
|
632
794
|
setRetry(retry: AspiRetryConfig<TRequest>): this;
|
|
633
795
|
/**
|
|
634
|
-
*
|
|
635
|
-
*
|
|
636
|
-
* @
|
|
796
|
+
* Merges the provided headers into the request configuration.
|
|
797
|
+
*
|
|
798
|
+
* @param {HeadersInit} headers - An object or iterable containing header name/value pairs.
|
|
799
|
+
* Existing headers are retained unless a key in this object overwrites them.
|
|
800
|
+
* @returns {this} The current {@link Request} instance for method chaining.
|
|
801
|
+
*
|
|
637
802
|
* @example
|
|
803
|
+
* // Set common JSON headers
|
|
638
804
|
* const request = new Request('/users', config);
|
|
639
805
|
* request.setHeaders({
|
|
640
806
|
* 'Content-Type': 'application/json',
|
|
641
|
-
* 'Accept': 'application/json'
|
|
807
|
+
* 'Accept': 'application/json',
|
|
642
808
|
* });
|
|
643
809
|
*/
|
|
644
|
-
setHeaders(headers:
|
|
810
|
+
setHeaders(headers: HeadersInit): this;
|
|
645
811
|
/**
|
|
646
812
|
* Sets a single header for the request.
|
|
647
813
|
* @param key The header key
|
|
@@ -831,70 +997,126 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
831
997
|
error: { [K in keyof Opts["error"] | "internalServerError"]: K extends "internalServerError" ? CustomError<"internalServerError", A> : Opts["error"][K]; };
|
|
832
998
|
}>>;
|
|
833
999
|
/**
|
|
834
|
-
*
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
*
|
|
1000
|
+
* Register a custom error handler for a specific HTTP status code.
|
|
1001
|
+
*
|
|
1002
|
+
* When the response matches the provided `status`, the supplied callback `cb`
|
|
1003
|
+
* is invoked and its return value is wrapped in a {@link CustomError} with the
|
|
1004
|
+
* given `tag`. The method also augments the request's generic `Opts['error']`
|
|
1005
|
+
* type so that the custom error is reflected in the resulting `Result`
|
|
1006
|
+
* union.
|
|
1007
|
+
*
|
|
1008
|
+
* @template Tag - A string literal used as the error tag.
|
|
1009
|
+
* @template A - The shape of the data returned by the callback.
|
|
1010
|
+
*
|
|
1011
|
+
* @param {Tag} tag
|
|
1012
|
+
* A unique identifier for the custom error. This value becomes the `tag`
|
|
1013
|
+
* property of the {@link CustomError} produced by the handler.
|
|
1014
|
+
*
|
|
1015
|
+
* @param {HttpErrorStatus} status
|
|
1016
|
+
* The HTTP status code (e.g. `'BAD_REQUEST'`, `'NOT_FOUND'`) that should
|
|
1017
|
+
* trigger the custom handler.
|
|
1018
|
+
*
|
|
1019
|
+
* @param {CustomErrorCb<TRequest, A>} cb
|
|
1020
|
+
* A callback that receives the failing request and response objects and
|
|
1021
|
+
* returns an object describing the error payload.
|
|
1022
|
+
*
|
|
1023
|
+
* @returns {Request<Method, TRequest, Merge<Omit<Opts, 'error'>, { error: { [K in Tag | keyof Opts['error']]: K extends Tag ? CustomError<Tag, A> : Opts['error'][K]; } }>>}
|
|
1024
|
+
* The same {@link Request} instance, now typed with the newly added error
|
|
1025
|
+
* variant, allowing method‑chaining.
|
|
1026
|
+
*
|
|
839
1027
|
* @example
|
|
1028
|
+
* ```ts
|
|
840
1029
|
* const request = new Request('/users', config);
|
|
1030
|
+
*
|
|
1031
|
+
* // Attach a custom handler for a 400 Bad Request response
|
|
841
1032
|
* request
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
*
|
|
845
|
-
*
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
*
|
|
849
|
-
*
|
|
1033
|
+
* withResult()
|
|
1034
|
+
* .error('customError', 'BAD_REQUEST', (ctx) => {
|
|
1035
|
+
* console.log('Bad request error:', ctx);
|
|
1036
|
+
* return {
|
|
1037
|
+
* message: 'Invalid input',
|
|
1038
|
+
* details: ctx.response.responseData,
|
|
1039
|
+
* };
|
|
1040
|
+
* });
|
|
850
1041
|
*
|
|
851
|
-
* // Later when
|
|
1042
|
+
* // Later, when executing the request:
|
|
852
1043
|
* const result = await request.json();
|
|
853
|
-
* if (Result.isErr(result)) {
|
|
854
|
-
* if(result.tag === 'customError') {
|
|
1044
|
+
* if (Result.isErr(result) && result.tag === 'customError') {
|
|
855
1045
|
* console.log(result.error.data.message); // 'Invalid input'
|
|
856
1046
|
* }
|
|
1047
|
+
* ```
|
|
857
1048
|
*/
|
|
858
1049
|
error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Merge<Omit<Opts, "error">, {
|
|
859
1050
|
error: { [K in Tag | keyof Opts["error"]]: K extends Tag ? CustomError<Tag, A> : Opts["error"][K]; };
|
|
860
1051
|
}>>;
|
|
861
1052
|
/**
|
|
862
|
-
* Sets query parameters for the request URL.
|
|
863
|
-
*
|
|
864
|
-
*
|
|
1053
|
+
* Sets the query parameters for the request URL.
|
|
1054
|
+
*
|
|
1055
|
+
* Accepts any value that can be passed to the `URLSearchParams` constructor:
|
|
1056
|
+
* - an object mapping keys to string values,
|
|
1057
|
+
* - an iterable of `[key, value]` tuples,
|
|
1058
|
+
* - a raw query string, or
|
|
1059
|
+
* - an existing {@link URLSearchParams} instance.
|
|
1060
|
+
*
|
|
1061
|
+
* The supplied parameters replace any previously defined query parameters.
|
|
1062
|
+
*
|
|
1063
|
+
* @template T - The concrete type of the supplied parameters.
|
|
1064
|
+
* @param {T} params - The query parameters to apply.
|
|
1065
|
+
* @returns {this} The request instance for method‑chaining.
|
|
1066
|
+
*
|
|
865
1067
|
* @example
|
|
866
1068
|
* const request = new Request('/users', config);
|
|
867
1069
|
* request.setQueryParams({
|
|
868
1070
|
* page: '1',
|
|
869
1071
|
* limit: '10',
|
|
870
|
-
* sort: 'desc'
|
|
1072
|
+
* sort: 'desc',
|
|
871
1073
|
* });
|
|
1074
|
+
*
|
|
1075
|
+
* // Using a raw query string
|
|
1076
|
+
* request.setQueryParams('page=1&limit=10');
|
|
1077
|
+
*
|
|
1078
|
+
* // Using an array of entries
|
|
1079
|
+
* request.setQueryParams([['page', '1'], ['limit', '10']]);
|
|
1080
|
+
*
|
|
1081
|
+
* // Using an existing URLSearchParams instance
|
|
1082
|
+
* const qp = new URLSearchParams({ page: '1' });
|
|
1083
|
+
* request.setQueryParams(qp);
|
|
872
1084
|
*/
|
|
873
|
-
setQueryParams<T
|
|
1085
|
+
setQueryParams<T = any>(params: T): Request<Method, TRequest, Merge<Omit<Opts, "queryParams">, {
|
|
874
1086
|
queryParams: T;
|
|
875
1087
|
}>>;
|
|
876
1088
|
/**
|
|
877
|
-
* Sets
|
|
878
|
-
*
|
|
879
|
-
* @
|
|
1089
|
+
* Sets a validation schema for the response data.
|
|
1090
|
+
*
|
|
1091
|
+
* The provided {@link StandardSchemaV1} schema will be used to validate the
|
|
1092
|
+
* response payload when the request is executed. If validation fails, a
|
|
1093
|
+
* `parseError` is added to the request's error type.
|
|
1094
|
+
*
|
|
1095
|
+
* @template TSchema - A type extending {@link StandardSchemaV1}
|
|
1096
|
+
* @param schema - The schema used to validate the response data
|
|
1097
|
+
* @returns The request instance for chaining with an updated generic type that
|
|
1098
|
+
* includes the schema and a possible `parseError` in the error union
|
|
1099
|
+
*
|
|
880
1100
|
* @example
|
|
1101
|
+
* ```ts
|
|
881
1102
|
* import { z } from 'zod';
|
|
882
1103
|
*
|
|
883
1104
|
* const userSchema = z.object({
|
|
884
1105
|
* id: z.number(),
|
|
885
1106
|
* name: z.string(),
|
|
886
|
-
* email: z.string().email()
|
|
1107
|
+
* email: z.string().email(),
|
|
887
1108
|
* });
|
|
888
1109
|
*
|
|
889
1110
|
* const request = new Request('/users', config);
|
|
890
1111
|
* const result = await request
|
|
891
1112
|
* .withResult()
|
|
892
|
-
* .
|
|
1113
|
+
* .schema(userSchema)
|
|
893
1114
|
* .json();
|
|
894
1115
|
*
|
|
895
1116
|
* if (Result.isOk(result)) {
|
|
896
1117
|
* const user = result.value; // Typed and validated user data
|
|
897
1118
|
* }
|
|
1119
|
+
* ```
|
|
898
1120
|
*/
|
|
899
1121
|
schema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Merge<Omit<Opts, "schema">, {
|
|
900
1122
|
schema: TSchema;
|
|
@@ -903,36 +1125,77 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
903
1125
|
}>;
|
|
904
1126
|
}>>;
|
|
905
1127
|
/**
|
|
906
|
-
*
|
|
907
|
-
*
|
|
1128
|
+
* Configures the request to **throw** an exception when the response status
|
|
1129
|
+
* indicates a failure (i.e., `!response.ok`). This disables the “Result”
|
|
1130
|
+
* mode (`withResult`) and enables “throwable” mode, causing
|
|
1131
|
+
* `await request.json()` (or other response helpers) to either resolve with
|
|
1132
|
+
* the successful payload **or** reject with an `AspiError`/`CustomError`.
|
|
1133
|
+
*
|
|
1134
|
+
* Use this when you prefer traditional `try / catch` error handling over
|
|
1135
|
+
* the explicit `Result` type returned by {@link withResult}.
|
|
1136
|
+
*
|
|
1137
|
+
* @returns This {@link Request} instance, now typed with `throwable: true` and
|
|
1138
|
+
* `withResult: false` for proper chaining.
|
|
1139
|
+
*
|
|
908
1140
|
* @example
|
|
1141
|
+
* ```ts
|
|
909
1142
|
* const request = new Request('/users', config);
|
|
910
|
-
* const result = await request
|
|
911
|
-
* .withResult()
|
|
912
|
-
* .throwable()
|
|
913
|
-
* .json();
|
|
914
1143
|
*
|
|
1144
|
+
* try {
|
|
1145
|
+
* const user = await request
|
|
1146
|
+
* .throwable() // Enable throwing on HTTP errors
|
|
1147
|
+
* .json<User>(); // Will throw if the response is not ok
|
|
1148
|
+
* console.log(user);
|
|
1149
|
+
* } catch (err) {
|
|
1150
|
+
* // err is either AspiError or a CustomError returned by a custom handler
|
|
1151
|
+
* console.error('Request failed:', err);
|
|
1152
|
+
* }
|
|
1153
|
+
* ```
|
|
915
1154
|
*/
|
|
916
1155
|
throwable(): Request<Method, TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
917
1156
|
withResult: false;
|
|
918
1157
|
throwable: true;
|
|
919
1158
|
}>>;
|
|
920
1159
|
/**
|
|
921
|
-
*
|
|
922
|
-
*
|
|
1160
|
+
* Sends the request and parses the response body as JSON.
|
|
1161
|
+
*
|
|
1162
|
+
* The resolved value of the returned promise varies based on the request mode:
|
|
1163
|
+
*
|
|
1164
|
+
* - **Result mode** (`withResult()`): resolves to a {@link Result.Result} that
|
|
1165
|
+
* contains either an {@link AspiResultOk} with the parsed payload or a union
|
|
1166
|
+
* of possible error types (HTTP errors, custom errors, JSON‑parse errors,
|
|
1167
|
+
* schema‑validation errors, etc.).
|
|
1168
|
+
*
|
|
1169
|
+
* - **Throwable mode** (`throwable()`): resolves directly to the successful
|
|
1170
|
+
* payload (`AspiPlainResponse`) and throws a {@link AspiError} or
|
|
1171
|
+
* {@link CustomError} on failure.
|
|
1172
|
+
*
|
|
1173
|
+
* - **Default mode** (no explicit mode): resolves to a tuple
|
|
1174
|
+
* `[value, error]` where exactly one element is non‑null.
|
|
1175
|
+
*
|
|
1176
|
+
* @template T - The inferred output type of the response schema (if a schema
|
|
1177
|
+
* was supplied via {@link schema}). When no schema is provided `T` defaults
|
|
1178
|
+
* to `any`.
|
|
1179
|
+
*
|
|
1180
|
+
* @returns A promise whose shape depends on the selected mode (see description).
|
|
1181
|
+
* In Result mode it is `Result<ResultOk<…>, …>`, in throwable mode it is
|
|
1182
|
+
* `AspiPlainResponse<…>`, and otherwise a tuple
|
|
1183
|
+
* `[AspiResultOk<…> | null, Error | null]`.
|
|
1184
|
+
*
|
|
923
1185
|
* @example
|
|
1186
|
+
* // Using the Result API
|
|
924
1187
|
* const request = new Request('/users', config);
|
|
925
1188
|
* const result = await request
|
|
926
1189
|
* .setQueryParams({ id: '123' })
|
|
927
|
-
* .
|
|
928
|
-
|
|
929
|
-
* .notFound((error) => ({ message: 'User not found' }))
|
|
1190
|
+
* .withResult()
|
|
1191
|
+
* .notFound(() => ({ message: 'User not found' }))
|
|
930
1192
|
* .json<User>();
|
|
931
1193
|
*
|
|
932
1194
|
* if (Result.isOk(result)) {
|
|
933
|
-
*
|
|
1195
|
+
* // `result.value` has type `User`
|
|
1196
|
+
* console.log(result.value);
|
|
934
1197
|
* } else {
|
|
935
|
-
* console.error(result.error);
|
|
1198
|
+
* console.error(result.error);
|
|
936
1199
|
* }
|
|
937
1200
|
*/
|
|
938
1201
|
json<T extends StandardSchemaV1.InferOutput<Opts['schema']>>(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, T>, AspiError<TRequest> | (Opts extends {
|
|
@@ -944,14 +1207,45 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
944
1207
|
} ? Opts['error'][keyof Opts['error']] : never) | JSONParseError) | null)
|
|
945
1208
|
]>;
|
|
946
1209
|
/**
|
|
947
|
-
* Executes the request and returns the response as plain text.
|
|
948
|
-
*
|
|
1210
|
+
* Executes the request and returns the response body as plain text.
|
|
1211
|
+
*
|
|
1212
|
+
* The method respects the request mode:
|
|
1213
|
+
*
|
|
1214
|
+
* - **Result mode** (`withResult()`): resolves to a {@link Result.Result}
|
|
1215
|
+
* containing either an {@link AspiResultOk} with the text payload or an
|
|
1216
|
+
* error variant.
|
|
1217
|
+
* - **Throwable mode** (`throwable()`): resolves directly to the text string
|
|
1218
|
+
* and throws on error.
|
|
1219
|
+
* - **Default mode**: resolves to a tuple `[value, error]` where exactly one
|
|
1220
|
+
* element is `null`.
|
|
1221
|
+
*
|
|
1222
|
+
* @returns {Promise<
|
|
1223
|
+
* Opts['withResult'] extends true
|
|
1224
|
+
* ? Result.Result<
|
|
1225
|
+
* AspiResultOk<TRequest, string>,
|
|
1226
|
+
* AspiError<TRequest> |
|
|
1227
|
+
* (Opts extends { error: any } ? Opts['error'][keyof Opts['error']] : never)
|
|
1228
|
+
* >
|
|
1229
|
+
* : Opts['throwable'] extends true
|
|
1230
|
+
* ? AspiPlainResponse<TRequest, string>
|
|
1231
|
+
* : [
|
|
1232
|
+
* AspiResultOk<TRequest, string> | null,
|
|
1233
|
+
* (
|
|
1234
|
+
* | AspiError<TRequest>
|
|
1235
|
+
* | (Opts extends { error: any } ? Opts['error'][keyof Opts['error']] : never)
|
|
1236
|
+
* | null
|
|
1237
|
+
* )
|
|
1238
|
+
* ]
|
|
1239
|
+
* }>
|
|
1240
|
+
* A promise that resolves according to the selected request mode.
|
|
1241
|
+
*
|
|
949
1242
|
* @example
|
|
1243
|
+
* ```ts
|
|
950
1244
|
* const request = new Request('/data.txt', config);
|
|
951
1245
|
* const result = await request
|
|
952
1246
|
* .setQueryParams({ version: '1' })
|
|
953
1247
|
* .withResult()
|
|
954
|
-
* .notFound((
|
|
1248
|
+
* .notFound(() => ({ message: 'Text file not found' }))
|
|
955
1249
|
* .text();
|
|
956
1250
|
*
|
|
957
1251
|
* if (Result.isOk(result)) {
|
|
@@ -959,6 +1253,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
959
1253
|
* } else {
|
|
960
1254
|
* console.error(result.error); // Error handling
|
|
961
1255
|
* }
|
|
1256
|
+
* ```
|
|
962
1257
|
*/
|
|
963
1258
|
text(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, string>, AspiError<TRequest> | (Opts extends {
|
|
964
1259
|
error: any;
|
|
@@ -969,14 +1264,49 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
969
1264
|
} ? Opts['error'][keyof Opts['error']] : never)) | null)
|
|
970
1265
|
]>;
|
|
971
1266
|
/**
|
|
972
|
-
* Executes the request and returns the response as a Blob.
|
|
973
|
-
*
|
|
1267
|
+
* Executes the request and returns the response body as a {@link Blob}.
|
|
1268
|
+
*
|
|
1269
|
+
* The shape of the returned {@link Promise} depends on the request mode:
|
|
1270
|
+
*
|
|
1271
|
+
* - **Result mode** (`withResult()`): resolves to a {@link Result.Result} containing
|
|
1272
|
+
* either an {@link AspiResultOk} with `Blob` data or an error variant.
|
|
1273
|
+
* - **Throwable mode** (`throwable()`): resolves directly to a {@link Blob}
|
|
1274
|
+
* (wrapped in {@link AspiPlainResponse}) and throws on failure.
|
|
1275
|
+
* - **Default mode**: resolves to a tuple `[value, error]` where exactly one element
|
|
1276
|
+
* is `null`.
|
|
1277
|
+
*
|
|
1278
|
+
* @returns {Promise<
|
|
1279
|
+
* Opts['withResult'] extends true
|
|
1280
|
+
* ? Result.Result<
|
|
1281
|
+
* AspiResultOk<TRequest, Blob>,
|
|
1282
|
+
* | AspiError<TRequest>
|
|
1283
|
+
* | (Opts extends { error: any }
|
|
1284
|
+
* ? Opts['error'][keyof Opts['error']]
|
|
1285
|
+
* : never)
|
|
1286
|
+
* >
|
|
1287
|
+
* : Opts['throwable'] extends true
|
|
1288
|
+
* ? AspiPlainResponse<TRequest, Blob>
|
|
1289
|
+
* : [
|
|
1290
|
+
* AspiResultOk<TRequest, Blob> | null,
|
|
1291
|
+
* (
|
|
1292
|
+
* | (
|
|
1293
|
+
* | AspiError<TRequest>
|
|
1294
|
+
* | (Opts extends { error: any }
|
|
1295
|
+
* ? Opts['error'][keyof Opts['error']]
|
|
1296
|
+
* : never)
|
|
1297
|
+
* )
|
|
1298
|
+
* | null
|
|
1299
|
+
* ),
|
|
1300
|
+
* ]
|
|
1301
|
+
* }>
|
|
1302
|
+
*
|
|
974
1303
|
* @example
|
|
1304
|
+
* ```ts
|
|
975
1305
|
* const request = new Request('/image.jpg', config);
|
|
976
1306
|
* const result = await request
|
|
977
1307
|
* .setQueryParams({ size: 'large' })
|
|
978
1308
|
* .withResult()
|
|
979
|
-
* .notFound((
|
|
1309
|
+
* .notFound(() => ({ message: 'Image not found' }))
|
|
980
1310
|
* .blob();
|
|
981
1311
|
*
|
|
982
1312
|
* if (Result.isOk(result)) {
|
|
@@ -984,6 +1314,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
984
1314
|
* } else {
|
|
985
1315
|
* console.error(result.error); // Error handling
|
|
986
1316
|
* }
|
|
1317
|
+
* ```
|
|
987
1318
|
*/
|
|
988
1319
|
blob(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, Blob>, AspiError<TRequest> | (Opts extends {
|
|
989
1320
|
error: any;
|
|
@@ -994,33 +1325,122 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
994
1325
|
} ? Opts['error'][keyof Opts['error']] : never)) | null)
|
|
995
1326
|
]>;
|
|
996
1327
|
/**
|
|
997
|
-
* Returns the
|
|
998
|
-
*
|
|
1328
|
+
* Returns the fully‑qualified URL that will be used for the request.
|
|
1329
|
+
*
|
|
1330
|
+
* The URL is constructed from the configured base URL, the request path,
|
|
1331
|
+
* and any query parameters added via {@link setQueryParams}.
|
|
1332
|
+
*
|
|
1333
|
+
* @returns {string} The complete request URL.
|
|
1334
|
+
*
|
|
999
1335
|
* @example
|
|
1336
|
+
* ```ts
|
|
1000
1337
|
* const request = new Request('/users', config);
|
|
1001
1338
|
* request.setBaseUrl('https://api.example.com');
|
|
1002
1339
|
* request.setQueryParams({ id: '123' });
|
|
1003
|
-
*
|
|
1340
|
+
*
|
|
1341
|
+
* console.log(request.url());
|
|
1342
|
+
* // => 'https://api.example.com/users?id=123'
|
|
1343
|
+
* ```
|
|
1004
1344
|
*/
|
|
1005
1345
|
url(): string;
|
|
1006
1346
|
/**
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
1347
|
+
* Switches the request into **Result** mode.
|
|
1348
|
+
*
|
|
1349
|
+
* In Result mode the response helpers (`json`, `text`, `blob`, …) resolve to a
|
|
1350
|
+
* {@link Result.Result} instance instead of the default tuple
|
|
1351
|
+
* `[value, error]`. This allows callers to use pattern matching
|
|
1352
|
+
* (`Result.isOk`, `Result.isErr`) to handle success and failure.
|
|
1353
|
+
*
|
|
1354
|
+
* Calling `withResult` disables the “throwable” behaviour (see {@link throwable}).
|
|
1355
|
+
*
|
|
1356
|
+
* @returns {Request<
|
|
1357
|
+
* Method,
|
|
1358
|
+
* TRequest,
|
|
1359
|
+
* Merge<
|
|
1360
|
+
* Omit<Opts, 'withResult' | 'throwable'>,
|
|
1361
|
+
* {
|
|
1362
|
+
* withResult: true;
|
|
1363
|
+
* throwable: false;
|
|
1364
|
+
* }
|
|
1365
|
+
* >
|
|
1366
|
+
* >} The same {@link Request} instance, now typed with `withResult: true` and
|
|
1367
|
+
* `throwable: false` for fluent chaining.
|
|
1368
|
+
*
|
|
1009
1369
|
* @example
|
|
1370
|
+
* ```ts
|
|
1010
1371
|
* const request = new Request('/users', config);
|
|
1372
|
+
*
|
|
1011
1373
|
* const result = await request
|
|
1012
|
-
* .withResult()
|
|
1374
|
+
* .withResult() // enable Result mode
|
|
1013
1375
|
* .json<User>();
|
|
1014
1376
|
*
|
|
1015
|
-
* // Returns Result type instead of tuple
|
|
1016
1377
|
* if (Result.isOk(result)) {
|
|
1017
|
-
*
|
|
1378
|
+
* // `result.value` is of type `User`
|
|
1379
|
+
* console.log(result.value);
|
|
1018
1380
|
* }
|
|
1381
|
+
* ```
|
|
1019
1382
|
*/
|
|
1020
1383
|
withResult(): Request<Method, TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
1021
1384
|
withResult: true;
|
|
1022
1385
|
throwable: false;
|
|
1023
1386
|
}>>;
|
|
1387
|
+
/**
|
|
1388
|
+
* Returns the underlying {@link AspiRequest} object that will be used for the fetch call.
|
|
1389
|
+
*
|
|
1390
|
+
* This method does not perform any network activity; it simply builds and returns the
|
|
1391
|
+
* request configuration, including any applied middlewares, query parameters, etc.
|
|
1392
|
+
*
|
|
1393
|
+
* @returns {AspiRequest<TRequest>} The constructed request object.
|
|
1394
|
+
*/
|
|
1395
|
+
getRequest(): AspiRequest<TRequest>;
|
|
1396
|
+
/**
|
|
1397
|
+
* Retrieves the registry of custom error callbacks that have been
|
|
1398
|
+
* registered via {@link error}. The returned object maps HTTP status
|
|
1399
|
+
* codes to their corresponding callback functions and tags.
|
|
1400
|
+
*
|
|
1401
|
+
* @returns {ErrorCallbacks} A shallow copy of the internal error callback registry.
|
|
1402
|
+
*/
|
|
1403
|
+
getErrorCallbackRegistry(): ErrorCallbacks;
|
|
1404
|
+
/**
|
|
1405
|
+
* Returns whether the request is configured to return a {@link Result.Result}
|
|
1406
|
+
* instead of the default tuple or throwing.
|
|
1407
|
+
*
|
|
1408
|
+
* @returns {boolean} `true` when {@link withResult} has been called.
|
|
1409
|
+
*/
|
|
1410
|
+
isResult(): boolean;
|
|
1411
|
+
/**
|
|
1412
|
+
* Returns whether the request is configured to throw on HTTP errors.
|
|
1413
|
+
*
|
|
1414
|
+
* @returns {boolean} `true` when {@link throwable} has been called.
|
|
1415
|
+
*/
|
|
1416
|
+
isThrowable(): boolean;
|
|
1417
|
+
/**
|
|
1418
|
+
* Returns the effective retry configuration for this request, including defaulted values.
|
|
1419
|
+
*
|
|
1420
|
+
* The returned object contains:
|
|
1421
|
+
* - `retries` – number of retry attempts (default 1)
|
|
1422
|
+
* - `retryDelay` – delay between attempts in milliseconds or a function that returns a delay
|
|
1423
|
+
* - `retryOn` – array of HTTP status codes that should trigger a retry
|
|
1424
|
+
* - `retryWhile` – optional custom predicate executed after each response
|
|
1425
|
+
* - `onRetry` – optional callback invoked after a retry attempt
|
|
1426
|
+
*
|
|
1427
|
+
* A shallow copy is returned to avoid accidental mutation of the internal state.
|
|
1428
|
+
*
|
|
1429
|
+
* @returns {{
|
|
1430
|
+
* retries: number;
|
|
1431
|
+
* retryDelay: number | ((attempt: number, maxAttempts: number, request: AspiRequest<TRequest>, response: AspiResponse<any, true>) => number);
|
|
1432
|
+
* retryOn: number[];
|
|
1433
|
+
* retryWhile?: (request: AspiRequest<TRequest>, response: AspiResponse<any, true>) => boolean | Promise<boolean>;
|
|
1434
|
+
* onRetry?: (request: AspiRequest<TRequest>, response: AspiResponse<any, true>) => void;
|
|
1435
|
+
* }}
|
|
1436
|
+
*/
|
|
1437
|
+
getRetryConfig(): {
|
|
1438
|
+
retries: number;
|
|
1439
|
+
retryDelay: number | ((remainingRetries: number, totalRetries: number, request: AspiRequest<TRequest>, response: AspiResponse) => number | Promise<number>);
|
|
1440
|
+
retryOn: HttpErrorCodes[];
|
|
1441
|
+
retryWhile: ((request: AspiRequest<TRequest>, response: AspiResponse) => boolean | Promise<boolean>) | undefined;
|
|
1442
|
+
onRetry: ((request: AspiRequest<TRequest>, response: AspiResponse) => void) | undefined;
|
|
1443
|
+
};
|
|
1024
1444
|
}
|
|
1025
1445
|
|
|
1026
1446
|
/**
|
|
@@ -1040,16 +1460,20 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
1040
1460
|
*/
|
|
1041
1461
|
declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts extends Record<any, any> = {}> {
|
|
1042
1462
|
#private;
|
|
1043
|
-
constructor(config:
|
|
1463
|
+
constructor(config: AspiRequestInitWithoutBodyAndMethod);
|
|
1044
1464
|
/**
|
|
1045
|
-
* Sets the base URL for all API requests
|
|
1046
|
-
*
|
|
1047
|
-
*
|
|
1465
|
+
* Sets or overrides the base URL used for all subsequent API requests.
|
|
1466
|
+
*
|
|
1467
|
+
* Accepts either a string or a `URL` instance. If a `URL` object is provided,
|
|
1468
|
+
* it is converted to its string representation.
|
|
1469
|
+
*
|
|
1470
|
+
* @param url - The new base URL.
|
|
1471
|
+
* @returns The current {@link Aspi} instance for chaining.
|
|
1048
1472
|
* @example
|
|
1049
1473
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1050
1474
|
* api.setBaseUrl('https://api.newdomain.com');
|
|
1051
1475
|
*/
|
|
1052
|
-
setBaseUrl(url: string): this;
|
|
1476
|
+
setBaseUrl(url: string | URL): this;
|
|
1053
1477
|
/**
|
|
1054
1478
|
* Sets the retry configuration for failed requests
|
|
1055
1479
|
* @param {AspiRetryConfig<TRequest>} retry - The retry configuration object
|
|
@@ -1074,35 +1498,34 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1074
1498
|
*/
|
|
1075
1499
|
get(path: string): Request<"GET", TRequest, Opts>;
|
|
1076
1500
|
/**
|
|
1077
|
-
* Makes a POST request to the specified path
|
|
1078
|
-
*
|
|
1079
|
-
* @param {
|
|
1080
|
-
* @returns {Request} A Request instance for chaining
|
|
1501
|
+
* Makes a POST request to the specified path.
|
|
1502
|
+
*
|
|
1503
|
+
* @param {string} path - The path to make the request to.
|
|
1504
|
+
* @returns {Request} A Request instance for chaining.
|
|
1505
|
+
*
|
|
1081
1506
|
* @example
|
|
1082
1507
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1083
|
-
* const response = await api.post('/users'
|
|
1508
|
+
* const response = await api.post('/users').json();
|
|
1084
1509
|
*/
|
|
1085
|
-
post(path: string
|
|
1510
|
+
post(path: string): Request<"POST", TRequest, Opts>;
|
|
1086
1511
|
/**
|
|
1087
|
-
* Makes a PUT request to the specified path
|
|
1088
|
-
* @param {string} path - The path to make the request to
|
|
1089
|
-
* @
|
|
1090
|
-
* @returns {Request} A Request instance for chaining
|
|
1512
|
+
* Makes a PUT request to the specified path.
|
|
1513
|
+
* @param {string} path - The path to make the request to.
|
|
1514
|
+
* @returns {Request} A Request instance for chaining.
|
|
1091
1515
|
* @example
|
|
1092
1516
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1093
|
-
* const response = await api.put('/users/1'
|
|
1517
|
+
* const response = await api.put('/users/1').json();
|
|
1094
1518
|
*/
|
|
1095
|
-
put(path: string
|
|
1519
|
+
put(path: string): Request<"PUT", TRequest, Opts>;
|
|
1096
1520
|
/**
|
|
1097
|
-
* Makes a PATCH request to the specified path
|
|
1098
|
-
* @param {string} path - The path to make the request to
|
|
1099
|
-
* @
|
|
1100
|
-
* @returns {Request} A Request instance for chaining
|
|
1521
|
+
* Makes a PATCH request to the specified path.
|
|
1522
|
+
* @param {string} path - The path to make the request to.
|
|
1523
|
+
* @returns {Request} A Request instance for chaining.
|
|
1101
1524
|
* @example
|
|
1102
1525
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1103
|
-
* const response = await api.patch('/users/1'
|
|
1526
|
+
* const response = await api.patch('/users/1').json();
|
|
1104
1527
|
*/
|
|
1105
|
-
patch(path: string
|
|
1528
|
+
patch(path: string): Request<"PATCH", TRequest, Opts>;
|
|
1106
1529
|
/**
|
|
1107
1530
|
* Makes a DELETE request to the specified path
|
|
1108
1531
|
* @param {string} path - The path to make the request to
|
|
@@ -1131,8 +1554,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1131
1554
|
*/
|
|
1132
1555
|
options(path: string): Request<"OPTIONS", TRequest, Opts>;
|
|
1133
1556
|
/**
|
|
1134
|
-
* Sets multiple headers for all API requests
|
|
1135
|
-
*
|
|
1557
|
+
* Sets multiple headers for all API requests. Existing headers are preserved
|
|
1558
|
+
* and new ones are merged, overriding any duplicate keys.
|
|
1559
|
+
* @param {HeadersInit} headers - An object containing header key-value pairs
|
|
1136
1560
|
* @returns {Aspi} The Aspi instance for chaining
|
|
1137
1561
|
* @example
|
|
1138
1562
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
@@ -1141,12 +1565,14 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1141
1565
|
* 'Accept': 'application/json'
|
|
1142
1566
|
* });
|
|
1143
1567
|
*/
|
|
1144
|
-
setHeaders(headers:
|
|
1568
|
+
setHeaders(headers: HeadersInit): this;
|
|
1145
1569
|
/**
|
|
1146
|
-
* Sets a single header for all API requests
|
|
1147
|
-
*
|
|
1148
|
-
* @param
|
|
1149
|
-
* @
|
|
1570
|
+
* Sets a single header for all API requests.
|
|
1571
|
+
*
|
|
1572
|
+
* @param key - The header name.
|
|
1573
|
+
* @param value - The header value.
|
|
1574
|
+
* @returns This {@link Aspi} instance for chaining.
|
|
1575
|
+
*
|
|
1150
1576
|
* @example
|
|
1151
1577
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1152
1578
|
* api.setHeader('Content-Type', 'application/json');
|
|
@@ -1162,21 +1588,31 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1162
1588
|
*/
|
|
1163
1589
|
setBearer(token: string): this;
|
|
1164
1590
|
/**
|
|
1165
|
-
*
|
|
1166
|
-
*
|
|
1167
|
-
*
|
|
1591
|
+
* Register a request‑transformer middleware.
|
|
1592
|
+
*
|
|
1593
|
+
* The supplied function receives the current request initialization object
|
|
1594
|
+
* (`T`) and must return a request initialization of type `U`. The middleware
|
|
1595
|
+
* is added to the internal middleware chain and will be applied to every
|
|
1596
|
+
* request created by this {@link Aspi} instance.
|
|
1597
|
+
*
|
|
1598
|
+
* @template T - The input request type, extending the current {@link Aspi} request init type.
|
|
1599
|
+
* @template U - The output request type after transformation.
|
|
1600
|
+
* @param {RequestTransformer<T, U>} fn - The middleware function that transforms a request configuration.
|
|
1601
|
+
* @returns {Aspi<U>} A new {@link Aspi} instance typed with the transformed request configuration.
|
|
1168
1602
|
* @example
|
|
1169
1603
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1170
|
-
* api.use((req) => {
|
|
1171
|
-
* // Add custom headers
|
|
1172
|
-
*
|
|
1173
|
-
* ...req
|
|
1174
|
-
*
|
|
1604
|
+
* const apiWithHeaders = api.use((req) => {
|
|
1605
|
+
* // Add custom headers to every request
|
|
1606
|
+
* return {
|
|
1607
|
+
* ...req,
|
|
1608
|
+
* headers: {
|
|
1609
|
+
* ...req.headers,
|
|
1610
|
+
* 'x-custom-header': 'custom-value',
|
|
1611
|
+
* },
|
|
1175
1612
|
* };
|
|
1176
|
-
* return req;
|
|
1177
1613
|
* });
|
|
1178
1614
|
*/
|
|
1179
|
-
use<T extends TRequest, U extends TRequest>(fn:
|
|
1615
|
+
use<T extends TRequest, U extends TRequest>(fn: RequestTransformer<T, U>): Aspi<U>;
|
|
1180
1616
|
/**
|
|
1181
1617
|
* Registers a custom error handler for a specific HTTP status
|
|
1182
1618
|
* @param {string} tag - The error tag identifier
|
|
@@ -1283,7 +1719,7 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1283
1719
|
* api.internalServerError((req, res) => ({ message: 'Server error occurred' }));
|
|
1284
1720
|
*/
|
|
1285
1721
|
internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
|
|
1286
|
-
error: { [K in keyof Opts["error"]
|
|
1722
|
+
error: { [K in "internalServerError" | keyof Opts["error"]]: K extends "internalServerError" ? CustomError<"internalServerError", A> : Opts["error"][K]; };
|
|
1287
1723
|
}>>;
|
|
1288
1724
|
/**
|
|
1289
1725
|
* Sets the aspi to throw an error if the response status is not successful.
|
|
@@ -1296,9 +1732,18 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1296
1732
|
* .json();
|
|
1297
1733
|
*
|
|
1298
1734
|
*/
|
|
1299
|
-
throwable(): Aspi<TRequest,
|
|
1735
|
+
throwable(): Aspi<TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
1736
|
+
withResult: false;
|
|
1300
1737
|
throwable: true;
|
|
1301
1738
|
}>>;
|
|
1739
|
+
/**
|
|
1740
|
+
* Configures the request to return a Result object instead of just the response body.
|
|
1741
|
+
* @returns The Aspi instance with result handling enabled.
|
|
1742
|
+
*/
|
|
1743
|
+
withResult(): Aspi<TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
1744
|
+
withResult: true;
|
|
1745
|
+
throwable: false;
|
|
1746
|
+
}>>;
|
|
1302
1747
|
}
|
|
1303
1748
|
|
|
1304
|
-
export { Aspi, type
|
|
1749
|
+
export { Aspi, type AspiConfigBase, AspiError, type AspiPlainResponse, type AspiRequest, type AspiRequestInit, type AspiRequestInitWithoutBodyAndMethod, type AspiResponse, type AspiResultOk, type AspiRetryConfig, type BaseURL, CustomError, type CustomErrorCb, type ErrorCallbacks, type HttpErrorCodes, type HttpErrorStatus, type HttpMethods, type JSONParseError, type Merge, type Prettify, Request, type RequestOptions, type RequestTransformer, result as Result, getHttpErrorStatus, httpErrors, isAspiError, isCustomError };
|