aspi 1.3.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +402 -209
- package/dist/index.cjs +486 -140
- package/dist/index.d.cts +580 -136
- package/dist/index.d.ts +580 -136
- package/dist/index.js +486 -140
- package/package.json +1 -1
package/dist/index.d.cts
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,65 @@ 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
|
+
statusText: HttpErrorStatus;
|
|
299
|
+
response: Response;
|
|
300
|
+
}, IsError extends true ? {
|
|
301
|
+
responseData: TData;
|
|
302
|
+
} : {
|
|
303
|
+
responseData?: any;
|
|
304
|
+
}>;
|
|
305
|
+
|
|
145
306
|
/**
|
|
146
307
|
* Custom error class for API errors
|
|
147
308
|
* @class AspiError
|
|
@@ -150,17 +311,17 @@ interface AspiRequest<T extends AspiRequestInit> {
|
|
|
150
311
|
* @property {AspiRe} request - The original request configuration
|
|
151
312
|
* @property {AspiResponse} response - The error response details
|
|
152
313
|
*/
|
|
153
|
-
declare class AspiError<
|
|
314
|
+
declare class AspiError<TRequest extends AspiRequestInit> extends Error {
|
|
154
315
|
tag: "aspiError";
|
|
155
|
-
request: AspiRequest<
|
|
156
|
-
response: AspiResponse
|
|
316
|
+
request: AspiRequest<TRequest>;
|
|
317
|
+
response: AspiResponse<any, false>;
|
|
157
318
|
/**
|
|
158
319
|
* Creates an instance of AspiError
|
|
159
320
|
* @param {string} message - The error message
|
|
160
321
|
* @param {AspiRe} request - The request configuration
|
|
161
322
|
* @param {AspiResponse} response - The error response
|
|
162
323
|
*/
|
|
163
|
-
constructor(message: string, request: AspiRequest<
|
|
324
|
+
constructor(message: string, request: AspiRequest<TRequest>, response: AspiResponse);
|
|
164
325
|
/**
|
|
165
326
|
* Conditionally executes callback if status matches
|
|
166
327
|
* @template T
|
|
@@ -169,8 +330,8 @@ declare class AspiError<TReq extends AspiRequestInit> extends Error {
|
|
|
169
330
|
* @returns {T | undefined} Result of callback if status matches, undefined otherwise
|
|
170
331
|
*/
|
|
171
332
|
ifMatch<T>(status: HttpErrorStatus, cb: (args: {
|
|
172
|
-
request: AspiRequest<
|
|
173
|
-
response: AspiResponse
|
|
333
|
+
request: AspiRequest<TRequest>;
|
|
334
|
+
response: AspiResponse<any, false>;
|
|
174
335
|
}) => T): T | undefined;
|
|
175
336
|
}
|
|
176
337
|
/**
|
|
@@ -606,7 +767,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
606
767
|
error: {};
|
|
607
768
|
}> {
|
|
608
769
|
#private;
|
|
609
|
-
constructor(method: HttpMethods, path: string,
|
|
770
|
+
constructor(method: HttpMethods, path: string, requestOptions: RequestOptions<TRequest>);
|
|
610
771
|
/**
|
|
611
772
|
* Sets the base URL for the request.
|
|
612
773
|
* @param url The base URL to set
|
|
@@ -615,7 +776,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
615
776
|
* const request = new Request('/users', config);
|
|
616
777
|
* request.setBaseUrl('https://api.example.com');
|
|
617
778
|
*/
|
|
618
|
-
setBaseUrl(url:
|
|
779
|
+
setBaseUrl(url: BaseURL): this;
|
|
619
780
|
/**
|
|
620
781
|
* Sets the retry configuration for the request.
|
|
621
782
|
* @param retry The retry configuration object
|
|
@@ -631,17 +792,21 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
631
792
|
*/
|
|
632
793
|
setRetry(retry: AspiRetryConfig<TRequest>): this;
|
|
633
794
|
/**
|
|
634
|
-
*
|
|
635
|
-
*
|
|
636
|
-
* @
|
|
795
|
+
* Merges the provided headers into the request configuration.
|
|
796
|
+
*
|
|
797
|
+
* @param {HeadersInit} headers - An object or iterable containing header name/value pairs.
|
|
798
|
+
* Existing headers are retained unless a key in this object overwrites them.
|
|
799
|
+
* @returns {this} The current {@link Request} instance for method chaining.
|
|
800
|
+
*
|
|
637
801
|
* @example
|
|
802
|
+
* // Set common JSON headers
|
|
638
803
|
* const request = new Request('/users', config);
|
|
639
804
|
* request.setHeaders({
|
|
640
805
|
* 'Content-Type': 'application/json',
|
|
641
|
-
* 'Accept': 'application/json'
|
|
806
|
+
* 'Accept': 'application/json',
|
|
642
807
|
* });
|
|
643
808
|
*/
|
|
644
|
-
setHeaders(headers:
|
|
809
|
+
setHeaders(headers: HeadersInit): this;
|
|
645
810
|
/**
|
|
646
811
|
* Sets a single header for the request.
|
|
647
812
|
* @param key The header key
|
|
@@ -831,70 +996,126 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
831
996
|
error: { [K in keyof Opts["error"] | "internalServerError"]: K extends "internalServerError" ? CustomError<"internalServerError", A> : Opts["error"][K]; };
|
|
832
997
|
}>>;
|
|
833
998
|
/**
|
|
834
|
-
*
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
*
|
|
999
|
+
* Register a custom error handler for a specific HTTP status code.
|
|
1000
|
+
*
|
|
1001
|
+
* When the response matches the provided `status`, the supplied callback `cb`
|
|
1002
|
+
* is invoked and its return value is wrapped in a {@link CustomError} with the
|
|
1003
|
+
* given `tag`. The method also augments the request's generic `Opts['error']`
|
|
1004
|
+
* type so that the custom error is reflected in the resulting `Result`
|
|
1005
|
+
* union.
|
|
1006
|
+
*
|
|
1007
|
+
* @template Tag - A string literal used as the error tag.
|
|
1008
|
+
* @template A - The shape of the data returned by the callback.
|
|
1009
|
+
*
|
|
1010
|
+
* @param {Tag} tag
|
|
1011
|
+
* A unique identifier for the custom error. This value becomes the `tag`
|
|
1012
|
+
* property of the {@link CustomError} produced by the handler.
|
|
1013
|
+
*
|
|
1014
|
+
* @param {HttpErrorStatus} status
|
|
1015
|
+
* The HTTP status code (e.g. `'BAD_REQUEST'`, `'NOT_FOUND'`) that should
|
|
1016
|
+
* trigger the custom handler.
|
|
1017
|
+
*
|
|
1018
|
+
* @param {CustomErrorCb<TRequest, A>} cb
|
|
1019
|
+
* A callback that receives the failing request and response objects and
|
|
1020
|
+
* returns an object describing the error payload.
|
|
1021
|
+
*
|
|
1022
|
+
* @returns {Request<Method, TRequest, Merge<Omit<Opts, 'error'>, { error: { [K in Tag | keyof Opts['error']]: K extends Tag ? CustomError<Tag, A> : Opts['error'][K]; } }>>}
|
|
1023
|
+
* The same {@link Request} instance, now typed with the newly added error
|
|
1024
|
+
* variant, allowing method‑chaining.
|
|
1025
|
+
*
|
|
839
1026
|
* @example
|
|
1027
|
+
* ```ts
|
|
840
1028
|
* const request = new Request('/users', config);
|
|
1029
|
+
*
|
|
1030
|
+
* // Attach a custom handler for a 400 Bad Request response
|
|
841
1031
|
* request
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
*
|
|
845
|
-
*
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
*
|
|
849
|
-
*
|
|
1032
|
+
* withResult()
|
|
1033
|
+
* .error('customError', 'BAD_REQUEST', (ctx) => {
|
|
1034
|
+
* console.log('Bad request error:', ctx);
|
|
1035
|
+
* return {
|
|
1036
|
+
* message: 'Invalid input',
|
|
1037
|
+
* details: ctx.response.responseData,
|
|
1038
|
+
* };
|
|
1039
|
+
* });
|
|
850
1040
|
*
|
|
851
|
-
* // Later when
|
|
1041
|
+
* // Later, when executing the request:
|
|
852
1042
|
* const result = await request.json();
|
|
853
|
-
* if (Result.isErr(result)) {
|
|
854
|
-
* if(result.tag === 'customError') {
|
|
1043
|
+
* if (Result.isErr(result) && result.tag === 'customError') {
|
|
855
1044
|
* console.log(result.error.data.message); // 'Invalid input'
|
|
856
1045
|
* }
|
|
1046
|
+
* ```
|
|
857
1047
|
*/
|
|
858
1048
|
error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Merge<Omit<Opts, "error">, {
|
|
859
1049
|
error: { [K in Tag | keyof Opts["error"]]: K extends Tag ? CustomError<Tag, A> : Opts["error"][K]; };
|
|
860
1050
|
}>>;
|
|
861
1051
|
/**
|
|
862
|
-
* Sets query parameters for the request URL.
|
|
863
|
-
*
|
|
864
|
-
*
|
|
1052
|
+
* Sets the query parameters for the request URL.
|
|
1053
|
+
*
|
|
1054
|
+
* Accepts any value that can be passed to the `URLSearchParams` constructor:
|
|
1055
|
+
* - an object mapping keys to string values,
|
|
1056
|
+
* - an iterable of `[key, value]` tuples,
|
|
1057
|
+
* - a raw query string, or
|
|
1058
|
+
* - an existing {@link URLSearchParams} instance.
|
|
1059
|
+
*
|
|
1060
|
+
* The supplied parameters replace any previously defined query parameters.
|
|
1061
|
+
*
|
|
1062
|
+
* @template T - The concrete type of the supplied parameters.
|
|
1063
|
+
* @param {T} params - The query parameters to apply.
|
|
1064
|
+
* @returns {this} The request instance for method‑chaining.
|
|
1065
|
+
*
|
|
865
1066
|
* @example
|
|
866
1067
|
* const request = new Request('/users', config);
|
|
867
1068
|
* request.setQueryParams({
|
|
868
1069
|
* page: '1',
|
|
869
1070
|
* limit: '10',
|
|
870
|
-
* sort: 'desc'
|
|
1071
|
+
* sort: 'desc',
|
|
871
1072
|
* });
|
|
1073
|
+
*
|
|
1074
|
+
* // Using a raw query string
|
|
1075
|
+
* request.setQueryParams('page=1&limit=10');
|
|
1076
|
+
*
|
|
1077
|
+
* // Using an array of entries
|
|
1078
|
+
* request.setQueryParams([['page', '1'], ['limit', '10']]);
|
|
1079
|
+
*
|
|
1080
|
+
* // Using an existing URLSearchParams instance
|
|
1081
|
+
* const qp = new URLSearchParams({ page: '1' });
|
|
1082
|
+
* request.setQueryParams(qp);
|
|
872
1083
|
*/
|
|
873
1084
|
setQueryParams<T extends Record<string, string> | string[][] | string | URLSearchParams>(params: T): Request<Method, TRequest, Merge<Omit<Opts, "queryParams">, {
|
|
874
1085
|
queryParams: T;
|
|
875
1086
|
}>>;
|
|
876
1087
|
/**
|
|
877
|
-
* Sets
|
|
878
|
-
*
|
|
879
|
-
* @
|
|
1088
|
+
* Sets a validation schema for the response data.
|
|
1089
|
+
*
|
|
1090
|
+
* The provided {@link StandardSchemaV1} schema will be used to validate the
|
|
1091
|
+
* response payload when the request is executed. If validation fails, a
|
|
1092
|
+
* `parseError` is added to the request's error type.
|
|
1093
|
+
*
|
|
1094
|
+
* @template TSchema - A type extending {@link StandardSchemaV1}
|
|
1095
|
+
* @param schema - The schema used to validate the response data
|
|
1096
|
+
* @returns The request instance for chaining with an updated generic type that
|
|
1097
|
+
* includes the schema and a possible `parseError` in the error union
|
|
1098
|
+
*
|
|
880
1099
|
* @example
|
|
1100
|
+
* ```ts
|
|
881
1101
|
* import { z } from 'zod';
|
|
882
1102
|
*
|
|
883
1103
|
* const userSchema = z.object({
|
|
884
1104
|
* id: z.number(),
|
|
885
1105
|
* name: z.string(),
|
|
886
|
-
* email: z.string().email()
|
|
1106
|
+
* email: z.string().email(),
|
|
887
1107
|
* });
|
|
888
1108
|
*
|
|
889
1109
|
* const request = new Request('/users', config);
|
|
890
1110
|
* const result = await request
|
|
891
1111
|
* .withResult()
|
|
892
|
-
* .
|
|
1112
|
+
* .schema(userSchema)
|
|
893
1113
|
* .json();
|
|
894
1114
|
*
|
|
895
1115
|
* if (Result.isOk(result)) {
|
|
896
1116
|
* const user = result.value; // Typed and validated user data
|
|
897
1117
|
* }
|
|
1118
|
+
* ```
|
|
898
1119
|
*/
|
|
899
1120
|
schema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Merge<Omit<Opts, "schema">, {
|
|
900
1121
|
schema: TSchema;
|
|
@@ -903,36 +1124,77 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
903
1124
|
}>;
|
|
904
1125
|
}>>;
|
|
905
1126
|
/**
|
|
906
|
-
*
|
|
907
|
-
*
|
|
1127
|
+
* Configures the request to **throw** an exception when the response status
|
|
1128
|
+
* indicates a failure (i.e., `!response.ok`). This disables the “Result”
|
|
1129
|
+
* mode (`withResult`) and enables “throwable” mode, causing
|
|
1130
|
+
* `await request.json()` (or other response helpers) to either resolve with
|
|
1131
|
+
* the successful payload **or** reject with an `AspiError`/`CustomError`.
|
|
1132
|
+
*
|
|
1133
|
+
* Use this when you prefer traditional `try / catch` error handling over
|
|
1134
|
+
* the explicit `Result` type returned by {@link withResult}.
|
|
1135
|
+
*
|
|
1136
|
+
* @returns This {@link Request} instance, now typed with `throwable: true` and
|
|
1137
|
+
* `withResult: false` for proper chaining.
|
|
1138
|
+
*
|
|
908
1139
|
* @example
|
|
1140
|
+
* ```ts
|
|
909
1141
|
* const request = new Request('/users', config);
|
|
910
|
-
* const result = await request
|
|
911
|
-
* .withResult()
|
|
912
|
-
* .throwable()
|
|
913
|
-
* .json();
|
|
914
1142
|
*
|
|
1143
|
+
* try {
|
|
1144
|
+
* const user = await request
|
|
1145
|
+
* .throwable() // Enable throwing on HTTP errors
|
|
1146
|
+
* .json<User>(); // Will throw if the response is not ok
|
|
1147
|
+
* console.log(user);
|
|
1148
|
+
* } catch (err) {
|
|
1149
|
+
* // err is either AspiError or a CustomError returned by a custom handler
|
|
1150
|
+
* console.error('Request failed:', err);
|
|
1151
|
+
* }
|
|
1152
|
+
* ```
|
|
915
1153
|
*/
|
|
916
1154
|
throwable(): Request<Method, TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
917
1155
|
withResult: false;
|
|
918
1156
|
throwable: true;
|
|
919
1157
|
}>>;
|
|
920
1158
|
/**
|
|
921
|
-
*
|
|
922
|
-
*
|
|
1159
|
+
* Sends the request and parses the response body as JSON.
|
|
1160
|
+
*
|
|
1161
|
+
* The resolved value of the returned promise varies based on the request mode:
|
|
1162
|
+
*
|
|
1163
|
+
* - **Result mode** (`withResult()`): resolves to a {@link Result.Result} that
|
|
1164
|
+
* contains either an {@link AspiResultOk} with the parsed payload or a union
|
|
1165
|
+
* of possible error types (HTTP errors, custom errors, JSON‑parse errors,
|
|
1166
|
+
* schema‑validation errors, etc.).
|
|
1167
|
+
*
|
|
1168
|
+
* - **Throwable mode** (`throwable()`): resolves directly to the successful
|
|
1169
|
+
* payload (`AspiPlainResponse`) and throws a {@link AspiError} or
|
|
1170
|
+
* {@link CustomError} on failure.
|
|
1171
|
+
*
|
|
1172
|
+
* - **Default mode** (no explicit mode): resolves to a tuple
|
|
1173
|
+
* `[value, error]` where exactly one element is non‑null.
|
|
1174
|
+
*
|
|
1175
|
+
* @template T - The inferred output type of the response schema (if a schema
|
|
1176
|
+
* was supplied via {@link schema}). When no schema is provided `T` defaults
|
|
1177
|
+
* to `any`.
|
|
1178
|
+
*
|
|
1179
|
+
* @returns A promise whose shape depends on the selected mode (see description).
|
|
1180
|
+
* In Result mode it is `Result<ResultOk<…>, …>`, in throwable mode it is
|
|
1181
|
+
* `AspiPlainResponse<…>`, and otherwise a tuple
|
|
1182
|
+
* `[AspiResultOk<…> | null, Error | null]`.
|
|
1183
|
+
*
|
|
923
1184
|
* @example
|
|
1185
|
+
* // Using the Result API
|
|
924
1186
|
* const request = new Request('/users', config);
|
|
925
1187
|
* const result = await request
|
|
926
1188
|
* .setQueryParams({ id: '123' })
|
|
927
|
-
* .
|
|
928
|
-
|
|
929
|
-
* .notFound((error) => ({ message: 'User not found' }))
|
|
1189
|
+
* .withResult()
|
|
1190
|
+
* .notFound(() => ({ message: 'User not found' }))
|
|
930
1191
|
* .json<User>();
|
|
931
1192
|
*
|
|
932
1193
|
* if (Result.isOk(result)) {
|
|
933
|
-
*
|
|
1194
|
+
* // `result.value` has type `User`
|
|
1195
|
+
* console.log(result.value);
|
|
934
1196
|
* } else {
|
|
935
|
-
* console.error(result.error);
|
|
1197
|
+
* console.error(result.error);
|
|
936
1198
|
* }
|
|
937
1199
|
*/
|
|
938
1200
|
json<T extends StandardSchemaV1.InferOutput<Opts['schema']>>(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, T>, AspiError<TRequest> | (Opts extends {
|
|
@@ -944,14 +1206,45 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
944
1206
|
} ? Opts['error'][keyof Opts['error']] : never) | JSONParseError) | null)
|
|
945
1207
|
]>;
|
|
946
1208
|
/**
|
|
947
|
-
* Executes the request and returns the response as plain text.
|
|
948
|
-
*
|
|
1209
|
+
* Executes the request and returns the response body as plain text.
|
|
1210
|
+
*
|
|
1211
|
+
* The method respects the request mode:
|
|
1212
|
+
*
|
|
1213
|
+
* - **Result mode** (`withResult()`): resolves to a {@link Result.Result}
|
|
1214
|
+
* containing either an {@link AspiResultOk} with the text payload or an
|
|
1215
|
+
* error variant.
|
|
1216
|
+
* - **Throwable mode** (`throwable()`): resolves directly to the text string
|
|
1217
|
+
* and throws on error.
|
|
1218
|
+
* - **Default mode**: resolves to a tuple `[value, error]` where exactly one
|
|
1219
|
+
* element is `null`.
|
|
1220
|
+
*
|
|
1221
|
+
* @returns {Promise<
|
|
1222
|
+
* Opts['withResult'] extends true
|
|
1223
|
+
* ? Result.Result<
|
|
1224
|
+
* AspiResultOk<TRequest, string>,
|
|
1225
|
+
* AspiError<TRequest> |
|
|
1226
|
+
* (Opts extends { error: any } ? Opts['error'][keyof Opts['error']] : never)
|
|
1227
|
+
* >
|
|
1228
|
+
* : Opts['throwable'] extends true
|
|
1229
|
+
* ? AspiPlainResponse<TRequest, string>
|
|
1230
|
+
* : [
|
|
1231
|
+
* AspiResultOk<TRequest, string> | null,
|
|
1232
|
+
* (
|
|
1233
|
+
* | AspiError<TRequest>
|
|
1234
|
+
* | (Opts extends { error: any } ? Opts['error'][keyof Opts['error']] : never)
|
|
1235
|
+
* | null
|
|
1236
|
+
* )
|
|
1237
|
+
* ]
|
|
1238
|
+
* }>
|
|
1239
|
+
* A promise that resolves according to the selected request mode.
|
|
1240
|
+
*
|
|
949
1241
|
* @example
|
|
1242
|
+
* ```ts
|
|
950
1243
|
* const request = new Request('/data.txt', config);
|
|
951
1244
|
* const result = await request
|
|
952
1245
|
* .setQueryParams({ version: '1' })
|
|
953
1246
|
* .withResult()
|
|
954
|
-
* .notFound((
|
|
1247
|
+
* .notFound(() => ({ message: 'Text file not found' }))
|
|
955
1248
|
* .text();
|
|
956
1249
|
*
|
|
957
1250
|
* if (Result.isOk(result)) {
|
|
@@ -959,6 +1252,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
959
1252
|
* } else {
|
|
960
1253
|
* console.error(result.error); // Error handling
|
|
961
1254
|
* }
|
|
1255
|
+
* ```
|
|
962
1256
|
*/
|
|
963
1257
|
text(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, string>, AspiError<TRequest> | (Opts extends {
|
|
964
1258
|
error: any;
|
|
@@ -969,14 +1263,49 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
969
1263
|
} ? Opts['error'][keyof Opts['error']] : never)) | null)
|
|
970
1264
|
]>;
|
|
971
1265
|
/**
|
|
972
|
-
* Executes the request and returns the response as a Blob.
|
|
973
|
-
*
|
|
1266
|
+
* Executes the request and returns the response body as a {@link Blob}.
|
|
1267
|
+
*
|
|
1268
|
+
* The shape of the returned {@link Promise} depends on the request mode:
|
|
1269
|
+
*
|
|
1270
|
+
* - **Result mode** (`withResult()`): resolves to a {@link Result.Result} containing
|
|
1271
|
+
* either an {@link AspiResultOk} with `Blob` data or an error variant.
|
|
1272
|
+
* - **Throwable mode** (`throwable()`): resolves directly to a {@link Blob}
|
|
1273
|
+
* (wrapped in {@link AspiPlainResponse}) and throws on failure.
|
|
1274
|
+
* - **Default mode**: resolves to a tuple `[value, error]` where exactly one element
|
|
1275
|
+
* is `null`.
|
|
1276
|
+
*
|
|
1277
|
+
* @returns {Promise<
|
|
1278
|
+
* Opts['withResult'] extends true
|
|
1279
|
+
* ? Result.Result<
|
|
1280
|
+
* AspiResultOk<TRequest, Blob>,
|
|
1281
|
+
* | AspiError<TRequest>
|
|
1282
|
+
* | (Opts extends { error: any }
|
|
1283
|
+
* ? Opts['error'][keyof Opts['error']]
|
|
1284
|
+
* : never)
|
|
1285
|
+
* >
|
|
1286
|
+
* : Opts['throwable'] extends true
|
|
1287
|
+
* ? AspiPlainResponse<TRequest, Blob>
|
|
1288
|
+
* : [
|
|
1289
|
+
* AspiResultOk<TRequest, Blob> | null,
|
|
1290
|
+
* (
|
|
1291
|
+
* | (
|
|
1292
|
+
* | AspiError<TRequest>
|
|
1293
|
+
* | (Opts extends { error: any }
|
|
1294
|
+
* ? Opts['error'][keyof Opts['error']]
|
|
1295
|
+
* : never)
|
|
1296
|
+
* )
|
|
1297
|
+
* | null
|
|
1298
|
+
* ),
|
|
1299
|
+
* ]
|
|
1300
|
+
* }>
|
|
1301
|
+
*
|
|
974
1302
|
* @example
|
|
1303
|
+
* ```ts
|
|
975
1304
|
* const request = new Request('/image.jpg', config);
|
|
976
1305
|
* const result = await request
|
|
977
1306
|
* .setQueryParams({ size: 'large' })
|
|
978
1307
|
* .withResult()
|
|
979
|
-
* .notFound((
|
|
1308
|
+
* .notFound(() => ({ message: 'Image not found' }))
|
|
980
1309
|
* .blob();
|
|
981
1310
|
*
|
|
982
1311
|
* if (Result.isOk(result)) {
|
|
@@ -984,6 +1313,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
984
1313
|
* } else {
|
|
985
1314
|
* console.error(result.error); // Error handling
|
|
986
1315
|
* }
|
|
1316
|
+
* ```
|
|
987
1317
|
*/
|
|
988
1318
|
blob(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, Blob>, AspiError<TRequest> | (Opts extends {
|
|
989
1319
|
error: any;
|
|
@@ -994,33 +1324,122 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
994
1324
|
} ? Opts['error'][keyof Opts['error']] : never)) | null)
|
|
995
1325
|
]>;
|
|
996
1326
|
/**
|
|
997
|
-
* Returns the
|
|
998
|
-
*
|
|
1327
|
+
* Returns the fully‑qualified URL that will be used for the request.
|
|
1328
|
+
*
|
|
1329
|
+
* The URL is constructed from the configured base URL, the request path,
|
|
1330
|
+
* and any query parameters added via {@link setQueryParams}.
|
|
1331
|
+
*
|
|
1332
|
+
* @returns {string} The complete request URL.
|
|
1333
|
+
*
|
|
999
1334
|
* @example
|
|
1335
|
+
* ```ts
|
|
1000
1336
|
* const request = new Request('/users', config);
|
|
1001
1337
|
* request.setBaseUrl('https://api.example.com');
|
|
1002
1338
|
* request.setQueryParams({ id: '123' });
|
|
1003
|
-
*
|
|
1339
|
+
*
|
|
1340
|
+
* console.log(request.url());
|
|
1341
|
+
* // => 'https://api.example.com/users?id=123'
|
|
1342
|
+
* ```
|
|
1004
1343
|
*/
|
|
1005
1344
|
url(): string;
|
|
1006
1345
|
/**
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
1346
|
+
* Switches the request into **Result** mode.
|
|
1347
|
+
*
|
|
1348
|
+
* In Result mode the response helpers (`json`, `text`, `blob`, …) resolve to a
|
|
1349
|
+
* {@link Result.Result} instance instead of the default tuple
|
|
1350
|
+
* `[value, error]`. This allows callers to use pattern matching
|
|
1351
|
+
* (`Result.isOk`, `Result.isErr`) to handle success and failure.
|
|
1352
|
+
*
|
|
1353
|
+
* Calling `withResult` disables the “throwable” behaviour (see {@link throwable}).
|
|
1354
|
+
*
|
|
1355
|
+
* @returns {Request<
|
|
1356
|
+
* Method,
|
|
1357
|
+
* TRequest,
|
|
1358
|
+
* Merge<
|
|
1359
|
+
* Omit<Opts, 'withResult' | 'throwable'>,
|
|
1360
|
+
* {
|
|
1361
|
+
* withResult: true;
|
|
1362
|
+
* throwable: false;
|
|
1363
|
+
* }
|
|
1364
|
+
* >
|
|
1365
|
+
* >} The same {@link Request} instance, now typed with `withResult: true` and
|
|
1366
|
+
* `throwable: false` for fluent chaining.
|
|
1367
|
+
*
|
|
1009
1368
|
* @example
|
|
1369
|
+
* ```ts
|
|
1010
1370
|
* const request = new Request('/users', config);
|
|
1371
|
+
*
|
|
1011
1372
|
* const result = await request
|
|
1012
|
-
* .withResult()
|
|
1373
|
+
* .withResult() // enable Result mode
|
|
1013
1374
|
* .json<User>();
|
|
1014
1375
|
*
|
|
1015
|
-
* // Returns Result type instead of tuple
|
|
1016
1376
|
* if (Result.isOk(result)) {
|
|
1017
|
-
*
|
|
1377
|
+
* // `result.value` is of type `User`
|
|
1378
|
+
* console.log(result.value);
|
|
1018
1379
|
* }
|
|
1380
|
+
* ```
|
|
1019
1381
|
*/
|
|
1020
1382
|
withResult(): Request<Method, TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
1021
1383
|
withResult: true;
|
|
1022
1384
|
throwable: false;
|
|
1023
1385
|
}>>;
|
|
1386
|
+
/**
|
|
1387
|
+
* Returns the underlying {@link AspiRequest} object that will be used for the fetch call.
|
|
1388
|
+
*
|
|
1389
|
+
* This method does not perform any network activity; it simply builds and returns the
|
|
1390
|
+
* request configuration, including any applied middlewares, query parameters, etc.
|
|
1391
|
+
*
|
|
1392
|
+
* @returns {AspiRequest<TRequest>} The constructed request object.
|
|
1393
|
+
*/
|
|
1394
|
+
getRequest(): AspiRequest<TRequest>;
|
|
1395
|
+
/**
|
|
1396
|
+
* Retrieves the registry of custom error callbacks that have been
|
|
1397
|
+
* registered via {@link error}. The returned object maps HTTP status
|
|
1398
|
+
* codes to their corresponding callback functions and tags.
|
|
1399
|
+
*
|
|
1400
|
+
* @returns {ErrorCallbacks} A shallow copy of the internal error callback registry.
|
|
1401
|
+
*/
|
|
1402
|
+
getErrorCallbackRegistry(): ErrorCallbacks;
|
|
1403
|
+
/**
|
|
1404
|
+
* Returns whether the request is configured to return a {@link Result.Result}
|
|
1405
|
+
* instead of the default tuple or throwing.
|
|
1406
|
+
*
|
|
1407
|
+
* @returns {boolean} `true` when {@link withResult} has been called.
|
|
1408
|
+
*/
|
|
1409
|
+
isResult(): boolean;
|
|
1410
|
+
/**
|
|
1411
|
+
* Returns whether the request is configured to throw on HTTP errors.
|
|
1412
|
+
*
|
|
1413
|
+
* @returns {boolean} `true` when {@link throwable} has been called.
|
|
1414
|
+
*/
|
|
1415
|
+
isThrowable(): boolean;
|
|
1416
|
+
/**
|
|
1417
|
+
* Returns the effective retry configuration for this request, including defaulted values.
|
|
1418
|
+
*
|
|
1419
|
+
* The returned object contains:
|
|
1420
|
+
* - `retries` – number of retry attempts (default 1)
|
|
1421
|
+
* - `retryDelay` – delay between attempts in milliseconds or a function that returns a delay
|
|
1422
|
+
* - `retryOn` – array of HTTP status codes that should trigger a retry
|
|
1423
|
+
* - `retryWhile` – optional custom predicate executed after each response
|
|
1424
|
+
* - `onRetry` – optional callback invoked after a retry attempt
|
|
1425
|
+
*
|
|
1426
|
+
* A shallow copy is returned to avoid accidental mutation of the internal state.
|
|
1427
|
+
*
|
|
1428
|
+
* @returns {{
|
|
1429
|
+
* retries: number;
|
|
1430
|
+
* retryDelay: number | ((attempt: number, maxAttempts: number, request: AspiRequest<TRequest>, response: AspiResponse<any, true>) => number);
|
|
1431
|
+
* retryOn: number[];
|
|
1432
|
+
* retryWhile?: (request: AspiRequest<TRequest>, response: AspiResponse<any, true>) => boolean | Promise<boolean>;
|
|
1433
|
+
* onRetry?: (request: AspiRequest<TRequest>, response: AspiResponse<any, true>) => void;
|
|
1434
|
+
* }}
|
|
1435
|
+
*/
|
|
1436
|
+
getRetryConfig(): {
|
|
1437
|
+
retries: number;
|
|
1438
|
+
retryDelay: number | ((remainingRetries: number, totalRetries: number, request: AspiRequest<TRequest>, response: AspiResponse) => number | Promise<number>);
|
|
1439
|
+
retryOn: HttpErrorCodes[];
|
|
1440
|
+
retryWhile: ((request: AspiRequest<TRequest>, response: AspiResponse) => boolean | Promise<boolean>) | undefined;
|
|
1441
|
+
onRetry: ((request: AspiRequest<TRequest>, response: AspiResponse) => void) | undefined;
|
|
1442
|
+
};
|
|
1024
1443
|
}
|
|
1025
1444
|
|
|
1026
1445
|
/**
|
|
@@ -1040,16 +1459,20 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
1040
1459
|
*/
|
|
1041
1460
|
declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts extends Record<any, any> = {}> {
|
|
1042
1461
|
#private;
|
|
1043
|
-
constructor(config:
|
|
1462
|
+
constructor(config: AspiRequestInitWithoutBodyAndMethod);
|
|
1044
1463
|
/**
|
|
1045
|
-
* Sets the base URL for all API requests
|
|
1046
|
-
*
|
|
1047
|
-
*
|
|
1464
|
+
* Sets or overrides the base URL used for all subsequent API requests.
|
|
1465
|
+
*
|
|
1466
|
+
* Accepts either a string or a `URL` instance. If a `URL` object is provided,
|
|
1467
|
+
* it is converted to its string representation.
|
|
1468
|
+
*
|
|
1469
|
+
* @param url - The new base URL.
|
|
1470
|
+
* @returns The current {@link Aspi} instance for chaining.
|
|
1048
1471
|
* @example
|
|
1049
1472
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1050
1473
|
* api.setBaseUrl('https://api.newdomain.com');
|
|
1051
1474
|
*/
|
|
1052
|
-
setBaseUrl(url: string): this;
|
|
1475
|
+
setBaseUrl(url: string | URL): this;
|
|
1053
1476
|
/**
|
|
1054
1477
|
* Sets the retry configuration for failed requests
|
|
1055
1478
|
* @param {AspiRetryConfig<TRequest>} retry - The retry configuration object
|
|
@@ -1074,35 +1497,34 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1074
1497
|
*/
|
|
1075
1498
|
get(path: string): Request<"GET", TRequest, Opts>;
|
|
1076
1499
|
/**
|
|
1077
|
-
* Makes a POST request to the specified path
|
|
1078
|
-
*
|
|
1079
|
-
* @param {
|
|
1080
|
-
* @returns {Request} A Request instance for chaining
|
|
1500
|
+
* Makes a POST request to the specified path.
|
|
1501
|
+
*
|
|
1502
|
+
* @param {string} path - The path to make the request to.
|
|
1503
|
+
* @returns {Request} A Request instance for chaining.
|
|
1504
|
+
*
|
|
1081
1505
|
* @example
|
|
1082
1506
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1083
|
-
* const response = await api.post('/users'
|
|
1507
|
+
* const response = await api.post('/users').json();
|
|
1084
1508
|
*/
|
|
1085
|
-
post(path: string
|
|
1509
|
+
post(path: string): Request<"POST", TRequest, Opts>;
|
|
1086
1510
|
/**
|
|
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
|
|
1511
|
+
* Makes a PUT request to the specified path.
|
|
1512
|
+
* @param {string} path - The path to make the request to.
|
|
1513
|
+
* @returns {Request} A Request instance for chaining.
|
|
1091
1514
|
* @example
|
|
1092
1515
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1093
|
-
* const response = await api.put('/users/1'
|
|
1516
|
+
* const response = await api.put('/users/1').json();
|
|
1094
1517
|
*/
|
|
1095
|
-
put(path: string
|
|
1518
|
+
put(path: string): Request<"PUT", TRequest, Opts>;
|
|
1096
1519
|
/**
|
|
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
|
|
1520
|
+
* Makes a PATCH request to the specified path.
|
|
1521
|
+
* @param {string} path - The path to make the request to.
|
|
1522
|
+
* @returns {Request} A Request instance for chaining.
|
|
1101
1523
|
* @example
|
|
1102
1524
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1103
|
-
* const response = await api.patch('/users/1'
|
|
1525
|
+
* const response = await api.patch('/users/1').json();
|
|
1104
1526
|
*/
|
|
1105
|
-
patch(path: string
|
|
1527
|
+
patch(path: string): Request<"PATCH", TRequest, Opts>;
|
|
1106
1528
|
/**
|
|
1107
1529
|
* Makes a DELETE request to the specified path
|
|
1108
1530
|
* @param {string} path - The path to make the request to
|
|
@@ -1131,8 +1553,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1131
1553
|
*/
|
|
1132
1554
|
options(path: string): Request<"OPTIONS", TRequest, Opts>;
|
|
1133
1555
|
/**
|
|
1134
|
-
* Sets multiple headers for all API requests
|
|
1135
|
-
*
|
|
1556
|
+
* Sets multiple headers for all API requests. Existing headers are preserved
|
|
1557
|
+
* and new ones are merged, overriding any duplicate keys.
|
|
1558
|
+
* @param {HeadersInit} headers - An object containing header key-value pairs
|
|
1136
1559
|
* @returns {Aspi} The Aspi instance for chaining
|
|
1137
1560
|
* @example
|
|
1138
1561
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
@@ -1141,12 +1564,14 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1141
1564
|
* 'Accept': 'application/json'
|
|
1142
1565
|
* });
|
|
1143
1566
|
*/
|
|
1144
|
-
setHeaders(headers:
|
|
1567
|
+
setHeaders(headers: HeadersInit): this;
|
|
1145
1568
|
/**
|
|
1146
|
-
* Sets a single header for all API requests
|
|
1147
|
-
*
|
|
1148
|
-
* @param
|
|
1149
|
-
* @
|
|
1569
|
+
* Sets a single header for all API requests.
|
|
1570
|
+
*
|
|
1571
|
+
* @param key - The header name.
|
|
1572
|
+
* @param value - The header value.
|
|
1573
|
+
* @returns This {@link Aspi} instance for chaining.
|
|
1574
|
+
*
|
|
1150
1575
|
* @example
|
|
1151
1576
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1152
1577
|
* api.setHeader('Content-Type', 'application/json');
|
|
@@ -1162,21 +1587,31 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1162
1587
|
*/
|
|
1163
1588
|
setBearer(token: string): this;
|
|
1164
1589
|
/**
|
|
1165
|
-
*
|
|
1166
|
-
*
|
|
1167
|
-
*
|
|
1590
|
+
* Register a request‑transformer middleware.
|
|
1591
|
+
*
|
|
1592
|
+
* The supplied function receives the current request initialization object
|
|
1593
|
+
* (`T`) and must return a request initialization of type `U`. The middleware
|
|
1594
|
+
* is added to the internal middleware chain and will be applied to every
|
|
1595
|
+
* request created by this {@link Aspi} instance.
|
|
1596
|
+
*
|
|
1597
|
+
* @template T - The input request type, extending the current {@link Aspi} request init type.
|
|
1598
|
+
* @template U - The output request type after transformation.
|
|
1599
|
+
* @param {RequestTransformer<T, U>} fn - The middleware function that transforms a request configuration.
|
|
1600
|
+
* @returns {Aspi<U>} A new {@link Aspi} instance typed with the transformed request configuration.
|
|
1168
1601
|
* @example
|
|
1169
1602
|
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1170
|
-
* api.use((req) => {
|
|
1171
|
-
* // Add custom headers
|
|
1172
|
-
*
|
|
1173
|
-
* ...req
|
|
1174
|
-
*
|
|
1603
|
+
* const apiWithHeaders = api.use((req) => {
|
|
1604
|
+
* // Add custom headers to every request
|
|
1605
|
+
* return {
|
|
1606
|
+
* ...req,
|
|
1607
|
+
* headers: {
|
|
1608
|
+
* ...req.headers,
|
|
1609
|
+
* 'x-custom-header': 'custom-value',
|
|
1610
|
+
* },
|
|
1175
1611
|
* };
|
|
1176
|
-
* return req;
|
|
1177
1612
|
* });
|
|
1178
1613
|
*/
|
|
1179
|
-
use<T extends TRequest, U extends TRequest>(fn:
|
|
1614
|
+
use<T extends TRequest, U extends TRequest>(fn: RequestTransformer<T, U>): Aspi<U>;
|
|
1180
1615
|
/**
|
|
1181
1616
|
* Registers a custom error handler for a specific HTTP status
|
|
1182
1617
|
* @param {string} tag - The error tag identifier
|
|
@@ -1296,9 +1731,18 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1296
1731
|
* .json();
|
|
1297
1732
|
*
|
|
1298
1733
|
*/
|
|
1299
|
-
throwable(): Aspi<TRequest,
|
|
1734
|
+
throwable(): Aspi<TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
1735
|
+
withResult: false;
|
|
1300
1736
|
throwable: true;
|
|
1301
1737
|
}>>;
|
|
1738
|
+
/**
|
|
1739
|
+
* Configures the request to return a Result object instead of just the response body.
|
|
1740
|
+
* @returns The Aspi instance with result handling enabled.
|
|
1741
|
+
*/
|
|
1742
|
+
withResult(): Aspi<TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
1743
|
+
withResult: true;
|
|
1744
|
+
throwable: false;
|
|
1745
|
+
}>>;
|
|
1302
1746
|
}
|
|
1303
1747
|
|
|
1304
|
-
export { Aspi, type
|
|
1748
|
+
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 };
|