aspi 1.1.0-beta.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/LICENSE +21 -0
- package/README.md +292 -0
- package/dist/index.cjs +1237 -0
- package/dist/index.d.cts +1285 -0
- package/dist/index.d.ts +1285 -0
- package/dist/index.js +1210 -0
- package/package.json +56 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard HTTP /**
|
|
3
|
+
* Common HTTP error status codes with their numeric values.
|
|
4
|
+
* @readonly
|
|
5
|
+
* @enum {number}
|
|
6
|
+
* @property {number} BAD_REQUEST - 400 Bad Request
|
|
7
|
+
* @property {number} UNAUTHORIZED - 401 Unauthorized
|
|
8
|
+
* @property {number} FORBIDDEN - 403 Forbidden
|
|
9
|
+
* @property {number} NOT_FOUND - 404 Not Found
|
|
10
|
+
* @property {number} METHOD_NOT_ALLOWED - 405 Method Not Allowed
|
|
11
|
+
* @property {number} CONFLICT - 409 Conflict
|
|
12
|
+
* @property {number} LARGE - 413 Payload Too Large
|
|
13
|
+
* @property {number} UNS {number} * @property
|
|
14
|
+
- 413Request entity too largeUPPORTED_MEDIA_TYPE - 415 Unsupported Media Type
|
|
15
|
+
*@property {number} } UNPROCESSABLE_ENTITY - 422 Unprocessable Entity
|
|
16
|
+
* @property {number} TO_MANY_REQUESTS - 429 Too Many Requests
|
|
17
|
+
* @property {number} * @property
|
|
18
|
+
Too many requests made - 429 {number} INTERNAL_SERVER_ERROR - 500 Internal Server Error
|
|
19
|
+
* @property {number} *
|
|
20
|
+
500Generic server error -@property {number} NOT_IMPLEMENTED - 501 Not Implemented
|
|
21
|
+
* @property {number} *
|
|
22
|
+
501Functionality not implemented -@property {number} BAD_GATEWAY - 502 Bad Gateway
|
|
23
|
+
* @property {number} UNAVAILABLE - 503 Service Unavailable
|
|
24
|
+
* @property {number} * @property {number
|
|
25
|
+
temporarily unavailable - 503Server} GATEWAY_TIMEOUT - 504 Gateway Timeout
|
|
26
|
+
*/
|
|
27
|
+
declare const httpErrors: {
|
|
28
|
+
readonly BAD_REQUEST: 400;
|
|
29
|
+
readonly UNAUTHORIZED: 401;
|
|
30
|
+
readonly FORBIDDEN: 403;
|
|
31
|
+
readonly NOT_FOUND: 404;
|
|
32
|
+
readonly METHOD_NOT_ALLOWED: 405;
|
|
33
|
+
readonly CONFLICT: 409;
|
|
34
|
+
readonly PAYLOAD_TOO_LARGE: 413;
|
|
35
|
+
readonly UNSUPPORTED_MEDIA_TYPE: 415;
|
|
36
|
+
readonly UNPROCESSABLE_ENTITY: 422;
|
|
37
|
+
readonly TOO_MANY_REQUESTS: 429;
|
|
38
|
+
readonly INTERNAL_SERVER_ERROR: 500;
|
|
39
|
+
readonly NOT_IMPLEMENTED: 501;
|
|
40
|
+
readonly BAD_GATEWAY: 502;
|
|
41
|
+
readonly SERVICE_UNAVAILABLE: 503;
|
|
42
|
+
readonly GATEWAY_TIMEOUT: 504;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Type representing the possible numeric HTTP error codes.
|
|
46
|
+
* Derived from the values in the `httpErrors` const.
|
|
47
|
+
*/
|
|
48
|
+
type HttpErrorCodes = (typeof httpErrors)[keyof typeof httpErrors];
|
|
49
|
+
/**
|
|
50
|
+
* Type representing the possible HTTP error status keys.
|
|
51
|
+
* Derived from the keys in the `httpErrors` const.
|
|
52
|
+
*/
|
|
53
|
+
type HttpErrorStatus = keyof typeof httpErrors;
|
|
54
|
+
/**
|
|
55
|
+
* Gets the string key representation of an HTTP error status code.
|
|
56
|
+
*
|
|
57
|
+
* @param {HttpErrorCodes} status - The numeric HTTP error status code
|
|
58
|
+
* @returns {HttpErrorStatus} The string key representing the status code
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* getHttpErrorStatus(404) // returns 'NOT_FOUND'
|
|
62
|
+
* getHttpErrorStatus(500) // returns 'INTERNAL_SERVER_ERROR'
|
|
63
|
+
*/
|
|
64
|
+
declare const getHttpErrorStatus: (status: HttpErrorCodes) => HttpErrorStatus;
|
|
65
|
+
/**
|
|
66
|
+
* Valid HTTP methods as defined in the HTTP/1.1 specification.
|
|
67
|
+
*/
|
|
68
|
+
type HttpMethods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'TRACE' | 'CONNECT';
|
|
69
|
+
|
|
70
|
+
type AspiConfigBase = {
|
|
71
|
+
baseUrl: string;
|
|
72
|
+
retryConfig?: AspiRetryConfig<AspiRequestInit>;
|
|
73
|
+
};
|
|
74
|
+
type AspiRetryConfig<TRequest extends AspiRequestInit> = {
|
|
75
|
+
retries?: number;
|
|
76
|
+
retryDelay?: number | ((remainingRetries: number, totalRetries: number, request: AspiRequest<TRequest>, response: AspiResponse) => number | Promise<number>);
|
|
77
|
+
retryOn?: Array<HttpErrorCodes>;
|
|
78
|
+
retryWhile?: (request: AspiRequest<TRequest>, response: AspiResponse) => boolean | Promise<boolean>;
|
|
79
|
+
onRetry?: (request: AspiRequest<TRequest>, response: AspiResponse) => void;
|
|
80
|
+
};
|
|
81
|
+
type AspiConfig = Pick<RequestInit, 'headers' | 'mode'> & AspiConfigBase;
|
|
82
|
+
type CustomErrorCb<T extends AspiRequestInit, A extends {}> = (input: {
|
|
83
|
+
request: AspiRequest<T>;
|
|
84
|
+
response: AspiResponse;
|
|
85
|
+
}) => A;
|
|
86
|
+
type Middleware<T extends RequestInit, U extends RequestInit> = (request: T) => U;
|
|
87
|
+
interface AspiRequestInit extends RequestInit, AspiConfigBase {
|
|
88
|
+
}
|
|
89
|
+
type RequestOptions<TRequest extends AspiRequestInit> = {
|
|
90
|
+
requestConfig: TRequest;
|
|
91
|
+
retryConfig?: AspiRetryConfig<TRequest>;
|
|
92
|
+
middlewares?: Middleware<TRequest, TRequest>[];
|
|
93
|
+
errorCbs?: ErrorCallbacks;
|
|
94
|
+
};
|
|
95
|
+
type ErrorCallbacks = Record<number, {
|
|
96
|
+
cb: (input: {
|
|
97
|
+
request: any;
|
|
98
|
+
response: any;
|
|
99
|
+
}) => any;
|
|
100
|
+
tag: unknown;
|
|
101
|
+
}>;
|
|
102
|
+
type AspiResultOk<TRequest extends AspiRequestInit, TData> = {
|
|
103
|
+
data: TData;
|
|
104
|
+
request: AspiRequest<TRequest>;
|
|
105
|
+
response: AspiResponse;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Response interface used in error handling
|
|
110
|
+
* @interface AspiResponse
|
|
111
|
+
* @property {HttpErrorCodes} status - The HTTP status code of the response
|
|
112
|
+
* @property {HttpErrorStatus} statusText - The HTTP status text of the response
|
|
113
|
+
* @property {Response} [response] - Optional raw Response object
|
|
114
|
+
* @property {any} [responseData] - Optional response data content
|
|
115
|
+
*/
|
|
116
|
+
interface AspiResponse {
|
|
117
|
+
status: HttpErrorCodes;
|
|
118
|
+
statusText: HttpErrorStatus;
|
|
119
|
+
response?: Response;
|
|
120
|
+
responseData?: any;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Interface representing an API request configuration
|
|
124
|
+
* @interface AspiRequest
|
|
125
|
+
* @template T - Request initialization options type extending AspiRequestInit
|
|
126
|
+
* @property {string} baseUrl - Base URL for the API request
|
|
127
|
+
* @property {string} path - Request path to append to baseUrl
|
|
128
|
+
* @property {T} requestInit - Request initialization options
|
|
129
|
+
* @property {URLSearchParams | null} queryParams - URL query parameters, if any
|
|
130
|
+
* @property {AspiRetryConfig<T>} retryConfig - Retry configuration for failed requests
|
|
131
|
+
*/
|
|
132
|
+
interface AspiRequest<T extends AspiRequestInit> {
|
|
133
|
+
baseUrl: string;
|
|
134
|
+
path: string;
|
|
135
|
+
requestInit: T;
|
|
136
|
+
queryParams: URLSearchParams | null;
|
|
137
|
+
retryConfig: AspiRetryConfig<T>;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Custom error class for API errors
|
|
141
|
+
* @class AspiError
|
|
142
|
+
* @extends {Error}
|
|
143
|
+
* @property {string} tag - Constant identifier for this error type
|
|
144
|
+
* @property {AspiRe} request - The original request configuration
|
|
145
|
+
* @property {AspiResponse} response - The error response details
|
|
146
|
+
*/
|
|
147
|
+
declare class AspiError<TReq extends AspiRequestInit> extends Error {
|
|
148
|
+
tag: "aspiError";
|
|
149
|
+
request: AspiRequest<TReq>;
|
|
150
|
+
response: AspiResponse;
|
|
151
|
+
/**
|
|
152
|
+
* Creates an instance of AspiError
|
|
153
|
+
* @param {string} message - The error message
|
|
154
|
+
* @param {AspiRe} request - The request configuration
|
|
155
|
+
* @param {AspiResponse} response - The error response
|
|
156
|
+
*/
|
|
157
|
+
constructor(message: string, request: AspiRequest<TReq>, response: AspiResponse);
|
|
158
|
+
/**
|
|
159
|
+
* Conditionally executes callback if status matches
|
|
160
|
+
* @template T
|
|
161
|
+
* @param {HttpErrorStatus} status - The status to match against
|
|
162
|
+
* @param {(args: { request: AspiRequest; response: AspiResponse }) => T} cb - Callback to execute on match
|
|
163
|
+
* @returns {T | undefined} Result of callback if status matches, undefined otherwise
|
|
164
|
+
*/
|
|
165
|
+
ifMatch<T>(status: HttpErrorStatus, cb: (args: {
|
|
166
|
+
request: AspiRequest<TReq>;
|
|
167
|
+
response: AspiResponse;
|
|
168
|
+
}) => T): T | undefined;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Custom error class with generic tag and data fields
|
|
172
|
+
* @class CustomError
|
|
173
|
+
* @extends {Error}
|
|
174
|
+
* @template Tag - String literal type for the error tag
|
|
175
|
+
* @template A - Type of the error data
|
|
176
|
+
* @property {Tag} tag - Tag identifying the error type
|
|
177
|
+
* @property {A} data - Additional error data
|
|
178
|
+
*/
|
|
179
|
+
declare class CustomError<Tag extends string, A> extends Error {
|
|
180
|
+
tag: Tag;
|
|
181
|
+
data: A;
|
|
182
|
+
/**
|
|
183
|
+
* Creates an instance of CustomError
|
|
184
|
+
* @param {Tag} tag - Tag identifying the error type
|
|
185
|
+
* @param {A} data - Additional error data
|
|
186
|
+
*/
|
|
187
|
+
constructor(tag: Tag, data: A);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Interface representing a JSON parsing error
|
|
191
|
+
* @interface JSONParseError
|
|
192
|
+
* @extends {CustomError<'jsonParseError', { message: string }>}
|
|
193
|
+
*/
|
|
194
|
+
interface JSONParseError extends CustomError<'jsonParseError', {
|
|
195
|
+
message: string;
|
|
196
|
+
}> {
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
type Ok<T> = {
|
|
200
|
+
__tag: 'ok';
|
|
201
|
+
value: T;
|
|
202
|
+
};
|
|
203
|
+
type Err<E> = {
|
|
204
|
+
__tag: 'err';
|
|
205
|
+
error: E;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Represents either a successful value of type T or an error of type E
|
|
209
|
+
* @example
|
|
210
|
+
* const success: Result<number, string> = { __tag: "ok", value: 42 };
|
|
211
|
+
* const failure: Result<number, string> = { __tag: "err", error: "not found" };
|
|
212
|
+
*/
|
|
213
|
+
type Result<T, E> = Ok<T> | Err<E>;
|
|
214
|
+
/**
|
|
215
|
+
* Creates a successful Result
|
|
216
|
+
* @example
|
|
217
|
+
* const result = ok(42);
|
|
218
|
+
* // { __tag: "ok", value: 42 }
|
|
219
|
+
*/
|
|
220
|
+
declare const ok: <T>(value: T) => Ok<T>;
|
|
221
|
+
/**
|
|
222
|
+
* Creates a failed Result
|
|
223
|
+
* @example
|
|
224
|
+
* const result = err("not found");
|
|
225
|
+
* // { __tag: "err", error: "not found" }
|
|
226
|
+
*/
|
|
227
|
+
declare const err: <E>(error: E) => Err<E>;
|
|
228
|
+
/**
|
|
229
|
+
* Returns true if the result is a success
|
|
230
|
+
* @example
|
|
231
|
+
* const result = ok(42);
|
|
232
|
+
* isOk(result) // true
|
|
233
|
+
*
|
|
234
|
+
* const error = err("not found");
|
|
235
|
+
* isOk(error) // false
|
|
236
|
+
*/
|
|
237
|
+
declare const isOk: <T, E>(result: Result<T, E>) => result is Ok<T>;
|
|
238
|
+
/**
|
|
239
|
+
* Returns true if the result is a failure
|
|
240
|
+
* @example
|
|
241
|
+
* const result = ok(42);
|
|
242
|
+
* isErr(result) // false
|
|
243
|
+
*
|
|
244
|
+
* const error = err("not found");
|
|
245
|
+
* isErr(error) // true
|
|
246
|
+
*/
|
|
247
|
+
declare const isErr: <T, E>(result: Result<T, E>) => result is Err<E>;
|
|
248
|
+
/**
|
|
249
|
+
* Maps a function over the value of a successful Result
|
|
250
|
+
* @param fn - Function to map over the successful value
|
|
251
|
+
* @param self - The Result to map over
|
|
252
|
+
* @returns A new Result with the mapped value if successful, or the original error if failed
|
|
253
|
+
* @example
|
|
254
|
+
* // Direct style
|
|
255
|
+
* const result = ok(42);
|
|
256
|
+
* map(result, (x) => x * 2) // { __tag: "ok", value: 84 }
|
|
257
|
+
*
|
|
258
|
+
* const error = err("not found");
|
|
259
|
+
* map(error, (x) => x * 2) // { __tag: "err", error: "not found" }
|
|
260
|
+
*
|
|
261
|
+
* // Curried style
|
|
262
|
+
* const double = map((x: number) => x * 2);
|
|
263
|
+
* double(ok(42)) // { __tag: "ok", value: 84 }
|
|
264
|
+
* double(err("not found")) // { __tag: "err", error: "not found" }
|
|
265
|
+
*/
|
|
266
|
+
declare function map<T, E, U>(fn: (value: T) => U): (self: Result<T, E>) => Result<U, E>;
|
|
267
|
+
declare function map<T, E, U>(self: Result<T, E>, fn: (value: T) => U): Result<U, E>;
|
|
268
|
+
/**
|
|
269
|
+
* Maps a function over the error of a failed Result
|
|
270
|
+
* @param fn - Function to map over the error value
|
|
271
|
+
* @param self - The Result to map over
|
|
272
|
+
* @returns A new Result with the mapped error if failed, or the original value if successful
|
|
273
|
+
* @example
|
|
274
|
+
* // Direct style
|
|
275
|
+
* const result = ok(42);
|
|
276
|
+
* mapErr(result, (e) => e.toUpperCase()) // { __tag: "ok", value: 42 }
|
|
277
|
+
*
|
|
278
|
+
* const error = err("not found");
|
|
279
|
+
* mapErr(error, (e) => e.toUpperCase()) // { __tag: "err", error: "NOT FOUND" }
|
|
280
|
+
*
|
|
281
|
+
* // Curried style
|
|
282
|
+
* const toUpper = mapErr((e: string) => e.toUpperCase());
|
|
283
|
+
* toUpper(ok(42)) // { __tag: "ok", value: 42 }
|
|
284
|
+
* toUpper(err("not found")) // { __tag: "err", error: "NOT FOUND" }
|
|
285
|
+
*/
|
|
286
|
+
declare function mapErr<T, E, U>(fn: (error: E) => U): (self: Result<T, E>) => Result<T, U>;
|
|
287
|
+
declare function mapErr<T, E, U>(self: Result<T, E>, fn: (error: E) => U): Result<T, U>;
|
|
288
|
+
/**
|
|
289
|
+
* Pattern matches on a Result, calling onOk if successful or onErr if failed
|
|
290
|
+
* @example
|
|
291
|
+
* const result = ok(42);
|
|
292
|
+
* match(result, {
|
|
293
|
+
* onOk: (x) => `Got ${x}`,
|
|
294
|
+
* onErr: (e) => `Error: ${e}`
|
|
295
|
+
* }) // "Got 42"
|
|
296
|
+
*
|
|
297
|
+
* const error = err("not found");
|
|
298
|
+
* match(error, {
|
|
299
|
+
* onOk: (x) => `Got ${x}`,
|
|
300
|
+
* onErr: (e) => `Error: ${e}`
|
|
301
|
+
* }) // "Error: not found"
|
|
302
|
+
*/
|
|
303
|
+
declare function match<T, E, U>(handlers: {
|
|
304
|
+
onOk: (value: T) => U;
|
|
305
|
+
onErr: (error: E) => U;
|
|
306
|
+
}): (self: Result<T, E>) => U;
|
|
307
|
+
declare function match<T, E, U, V>(self: Result<T, E>, handlers: {
|
|
308
|
+
onOk: (value: T) => U;
|
|
309
|
+
onErr: (error: E) => V;
|
|
310
|
+
}): U | V;
|
|
311
|
+
/**
|
|
312
|
+
* Returns the value of a successful Result, or null if it's a failure
|
|
313
|
+
* @example
|
|
314
|
+
* const result = ok(42);
|
|
315
|
+
* getOrNull(result) // 42
|
|
316
|
+
*
|
|
317
|
+
* const error = err("not found");
|
|
318
|
+
* getOrNull(error) // null
|
|
319
|
+
*/
|
|
320
|
+
declare const getOrNull: <T, E>(result: Result<T, E>) => T | null;
|
|
321
|
+
/**
|
|
322
|
+
* Returns the error of a failed Result, or null if it's a success
|
|
323
|
+
* @example
|
|
324
|
+
* const result = ok(42);
|
|
325
|
+
* getErrorOrNull(result) // null
|
|
326
|
+
*
|
|
327
|
+
* const error = err("not found");
|
|
328
|
+
* getErrorOrNull(error) // "not found"
|
|
329
|
+
*/
|
|
330
|
+
declare const getErrorOrNull: <T, E>(result: Result<T, E>) => E | null;
|
|
331
|
+
/**
|
|
332
|
+
* Returns the value of a successful Result, or a fallback value if it's a failure
|
|
333
|
+
* @example
|
|
334
|
+
* const result = ok(42);
|
|
335
|
+
* getOrElse(result, 0) // 42
|
|
336
|
+
*
|
|
337
|
+
* const error = err("not found");
|
|
338
|
+
* getOrElse(error, 0) // 0
|
|
339
|
+
*/
|
|
340
|
+
declare const getOrElse: <T, E>(result: Result<T, E>, fallback: T) => T;
|
|
341
|
+
/**
|
|
342
|
+
* Returns the value of a successful Result, or throws the error if it's a failure
|
|
343
|
+
* @example
|
|
344
|
+
* const result = ok(42);
|
|
345
|
+
* getOrThrow(result) // 42
|
|
346
|
+
*
|
|
347
|
+
* const error = err("not found");
|
|
348
|
+
* getOrThrow(error) // throws "not found"
|
|
349
|
+
*/
|
|
350
|
+
declare const getOrThrow: <T, E>(result: Result<T, E>) => T;
|
|
351
|
+
/**
|
|
352
|
+
* Returns the value of a successful Result, or throws a transformed error if it's a failure
|
|
353
|
+
* @example
|
|
354
|
+
* const result = ok(42);
|
|
355
|
+
* getOrThrowWith(result, (e) => new Error(e)) // 42
|
|
356
|
+
*
|
|
357
|
+
* const error = err("not found");
|
|
358
|
+
* getOrThrowWith(error, (e) => new Error(e)) // throws Error("not found")
|
|
359
|
+
*/
|
|
360
|
+
declare function getOrThrowWith<T, E, R>(fn: (error: E) => R): (self: Result<T, E>) => T;
|
|
361
|
+
declare function getOrThrowWith<T, E, R>(self: Result<T, E>, fn: (error: E) => R): T;
|
|
362
|
+
/**
|
|
363
|
+
* Handles an error with a specific tag by running a callback function
|
|
364
|
+
* @example
|
|
365
|
+
* type NetworkError = { tag: "timeout"; duration: number } | { tag: "offline" };
|
|
366
|
+
*
|
|
367
|
+
* const error: NetworkError = { tag: "timeout", duration: 5000 };
|
|
368
|
+
* catchError(error, "timeout", (e) => {
|
|
369
|
+
* console.log(`Request timed out after ${e.duration}ms`);
|
|
370
|
+
* });
|
|
371
|
+
*
|
|
372
|
+
* const result = err<number, NetworkError>({ tag: "offline" });
|
|
373
|
+
* catchError(result, "offline", () => {
|
|
374
|
+
* console.log("No internet connection");
|
|
375
|
+
* }); // { __tag: "ok", value: null }
|
|
376
|
+
*/
|
|
377
|
+
declare function catchError<T, E extends {
|
|
378
|
+
tag: string;
|
|
379
|
+
}, Tag extends E['tag']>(result: Result<T, E>, tag: Tag, fn: (error: Extract<E, {
|
|
380
|
+
tag: Tag;
|
|
381
|
+
}>) => void): Result<T, Exclude<E, {
|
|
382
|
+
tag: Tag;
|
|
383
|
+
}>>;
|
|
384
|
+
declare function catchError<T, E extends {
|
|
385
|
+
tag: string;
|
|
386
|
+
}, Tag extends E['tag']>(error: E, tag: Tag, fn: (error: Extract<E, {
|
|
387
|
+
tag: Tag;
|
|
388
|
+
}>) => void): void;
|
|
389
|
+
declare function catchError<T, E extends {
|
|
390
|
+
tag: string;
|
|
391
|
+
}, Tag extends E['tag']>(tag: Tag, fn: (error: Extract<E, {
|
|
392
|
+
tag: Tag;
|
|
393
|
+
}>) => void): (result: Result<T, E>) => Result<T, Exclude<E, {
|
|
394
|
+
tag: Tag;
|
|
395
|
+
}>>;
|
|
396
|
+
declare function catchError<T, E extends {
|
|
397
|
+
tag: string;
|
|
398
|
+
}, Tag extends E['tag']>(tag: Tag, fn: (error: Extract<E, {
|
|
399
|
+
tag: Tag;
|
|
400
|
+
}>) => void): (error: E) => void;
|
|
401
|
+
/**
|
|
402
|
+
* Catches all errors in a Result by running a callback function
|
|
403
|
+
* @param result - The Result to handle errors for
|
|
404
|
+
* @param fn - Function to handle any error
|
|
405
|
+
* @returns The original Result
|
|
406
|
+
* @example
|
|
407
|
+
* const result = err<number, string>("not found");
|
|
408
|
+
*
|
|
409
|
+
* // Direct style
|
|
410
|
+
* catchAllErrors(result, (e) => {
|
|
411
|
+
* console.log(`Error occurred: ${e}`);
|
|
412
|
+
* }); // { __tag: "ok", value: null }
|
|
413
|
+
*
|
|
414
|
+
* // Curried style
|
|
415
|
+
* const handleError = catchAllErrors((e: string) => {
|
|
416
|
+
* console.log(`Error occurred: ${e}`);
|
|
417
|
+
* });
|
|
418
|
+
* handleError(result); // { __tag: "ok", value: null }
|
|
419
|
+
*/
|
|
420
|
+
declare function catchAllErrors<T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, never>;
|
|
421
|
+
declare function catchAllErrors<T, E>(fn: (error: E) => void): (result: Result<T, E>) => Result<T, never>;
|
|
422
|
+
/**
|
|
423
|
+
* Catches specific error tags using handler functions
|
|
424
|
+
* @param result - The Result to handle errors for
|
|
425
|
+
* @param handlers - Object mapping error tags to handler functions
|
|
426
|
+
* @returns Result with handled error tags excluded from error type
|
|
427
|
+
* @example
|
|
428
|
+
* type NetworkError = { tag: "timeout"; duration: number } | { tag: "offline" };
|
|
429
|
+
*
|
|
430
|
+
* const result = err<number, NetworkError>({ tag: "timeout", duration: 5000 });
|
|
431
|
+
* catchErrors(result, {
|
|
432
|
+
* timeout: (e) => console.log(`Timed out after ${e.duration}ms`),
|
|
433
|
+
* offline: () => console.log("No internet connection")
|
|
434
|
+
* }); // { __tag: "ok", value: null }
|
|
435
|
+
*/
|
|
436
|
+
declare function catchErrors<T, E extends {
|
|
437
|
+
tag: string;
|
|
438
|
+
}, Key extends E['tag']>(result: Result<T, E>, handlers: {
|
|
439
|
+
[K in Key]?: (error: Extract<E, {
|
|
440
|
+
tag: K;
|
|
441
|
+
}>) => void;
|
|
442
|
+
}): Result<T, Exclude<E, {
|
|
443
|
+
tag: keyof typeof handlers;
|
|
444
|
+
}>>;
|
|
445
|
+
declare function catchErrors<T, E extends {
|
|
446
|
+
tag: string;
|
|
447
|
+
}, Key extends E['tag']>(handlers: {
|
|
448
|
+
[K in Key]?: (error: Extract<E, {
|
|
449
|
+
tag: K;
|
|
450
|
+
}>) => void;
|
|
451
|
+
}): (result: Result<T, E>) => Result<T, Exclude<E, {
|
|
452
|
+
tag: keyof typeof handlers;
|
|
453
|
+
}>>;
|
|
454
|
+
/**
|
|
455
|
+
* Creates a chainable pipeline to transform a Result through a series of operations.
|
|
456
|
+
* @param result - The initial Result to transform
|
|
457
|
+
* @param ab - First transformation function to apply to the Result
|
|
458
|
+
* @returns A chainable function with pipe() for adding more transformations and execute() to run the pipeline
|
|
459
|
+
* @example
|
|
460
|
+
* pipe(
|
|
461
|
+
* ok(5),
|
|
462
|
+
* (a) => ok(a.value * 2)
|
|
463
|
+
* )
|
|
464
|
+
* .pipe(b => ok(b.value + 1))
|
|
465
|
+
* .execute() // { __tag: "ok", value: 11 }
|
|
466
|
+
*/
|
|
467
|
+
declare const pipe: <AI, AE, BI, BE>(result: Result<AI, AE>, ab: (a: Result<AI, AE>) => Result<BI, BE>) => {
|
|
468
|
+
(a: Result<AI, AE>): Result<BI, BE>;
|
|
469
|
+
pipe<CI, CE>(bc: (b: Result<BI, BE>) => Result<CI, CE>): {
|
|
470
|
+
(a: Result<AI, AE>): Result<CI, CE>;
|
|
471
|
+
pipe<CI_1, CE_1>(bc: (b: Result<CI, CE>) => Result<CI_1, CE_1>): {
|
|
472
|
+
(a: Result<AI, AE>): Result<CI_1, CE_1>;
|
|
473
|
+
pipe<CI_2, CE_2>(bc: (b: Result<CI_1, CE_1>) => Result<CI_2, CE_2>): {
|
|
474
|
+
(a: Result<AI, AE>): Result<CI_2, CE_2>;
|
|
475
|
+
pipe<CI_3, CE_3>(bc: (b: Result<CI_2, CE_2>) => Result<CI_3, CE_3>): {
|
|
476
|
+
(a: Result<AI, AE>): Result<CI_3, CE_3>;
|
|
477
|
+
pipe<CI_4, CE_4>(bc: (b: Result<CI_3, CE_3>) => Result<CI_4, CE_4>): {
|
|
478
|
+
(a: Result<AI, AE>): Result<CI_4, CE_4>;
|
|
479
|
+
pipe<CI_5, CE_5>(bc: (b: Result<CI_4, CE_4>) => Result<CI_5, CE_5>): {
|
|
480
|
+
(a: Result<AI, AE>): Result<CI_5, CE_5>;
|
|
481
|
+
pipe<CI_6, CE_6>(bc: (b: Result<CI_5, CE_5>) => Result<CI_6, CE_6>): {
|
|
482
|
+
(a: Result<AI, AE>): Result<CI_6, CE_6>;
|
|
483
|
+
pipe<CI_7, CE_7>(bc: (b: Result<CI_6, CE_6>) => Result<CI_7, CE_7>): {
|
|
484
|
+
(a: Result<AI, AE>): Result<CI_7, CE_7>;
|
|
485
|
+
pipe<CI_8, CE_8>(bc: (b: Result<CI_7, CE_7>) => Result<CI_8, CE_8>): {
|
|
486
|
+
(a: Result<AI, AE>): Result<CI_8, CE_8>;
|
|
487
|
+
pipe<CI_9, CE_9>(bc: (b: Result<CI_8, CE_8>) => Result<CI_9, CE_9>): {
|
|
488
|
+
(a: Result<AI, AE>): Result<CI_9, CE_9>;
|
|
489
|
+
pipe<CI_10, CE_10>(bc: (b: Result<CI_9, CE_9>) => Result<CI_10, CE_10>): /*elided*/ any;
|
|
490
|
+
execute(): Result<CI_9, CE_9>;
|
|
491
|
+
};
|
|
492
|
+
execute(): Result<CI_8, CE_8>;
|
|
493
|
+
};
|
|
494
|
+
execute(): Result<CI_7, CE_7>;
|
|
495
|
+
};
|
|
496
|
+
execute(): Result<CI_6, CE_6>;
|
|
497
|
+
};
|
|
498
|
+
execute(): Result<CI_5, CE_5>;
|
|
499
|
+
};
|
|
500
|
+
execute(): Result<CI_4, CE_4>;
|
|
501
|
+
};
|
|
502
|
+
execute(): Result<CI_3, CE_3>;
|
|
503
|
+
};
|
|
504
|
+
execute(): Result<CI_2, CE_2>;
|
|
505
|
+
};
|
|
506
|
+
execute(): Result<CI_1, CE_1>;
|
|
507
|
+
};
|
|
508
|
+
execute(): Result<CI, CE>;
|
|
509
|
+
};
|
|
510
|
+
execute(): Result<BI, BE>;
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
type result_Err<E> = Err<E>;
|
|
514
|
+
type result_Ok<T> = Ok<T>;
|
|
515
|
+
type result_Result<T, E> = Result<T, E>;
|
|
516
|
+
declare const result_catchAllErrors: typeof catchAllErrors;
|
|
517
|
+
declare const result_catchError: typeof catchError;
|
|
518
|
+
declare const result_catchErrors: typeof catchErrors;
|
|
519
|
+
declare const result_err: typeof err;
|
|
520
|
+
declare const result_getErrorOrNull: typeof getErrorOrNull;
|
|
521
|
+
declare const result_getOrElse: typeof getOrElse;
|
|
522
|
+
declare const result_getOrNull: typeof getOrNull;
|
|
523
|
+
declare const result_getOrThrow: typeof getOrThrow;
|
|
524
|
+
declare const result_getOrThrowWith: typeof getOrThrowWith;
|
|
525
|
+
declare const result_isErr: typeof isErr;
|
|
526
|
+
declare const result_isOk: typeof isOk;
|
|
527
|
+
declare const result_map: typeof map;
|
|
528
|
+
declare const result_mapErr: typeof mapErr;
|
|
529
|
+
declare const result_match: typeof match;
|
|
530
|
+
declare const result_ok: typeof ok;
|
|
531
|
+
declare const result_pipe: typeof pipe;
|
|
532
|
+
declare namespace result {
|
|
533
|
+
export { type result_Err as Err, type result_Ok as Ok, type result_Result as Result, result_catchAllErrors as catchAllErrors, result_catchError as catchError, result_catchErrors as catchErrors, result_err as err, result_getErrorOrNull as getErrorOrNull, result_getOrElse as getOrElse, result_getOrNull as getOrNull, result_getOrThrow as getOrThrow, result_getOrThrowWith as getOrThrowWith, result_isErr as isErr, result_isOk as isOk, result_map as map, result_mapErr as mapErr, result_match as match, result_ok as ok, result_pipe as pipe };
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Standard Schema is a common interface designed to be implemented by JavaScript and TypeScript schema libraries.
|
|
538
|
+
* Will support multiple schema validators including Zod, Valibot, and ArkType
|
|
539
|
+
* https://standardschema.dev/
|
|
540
|
+
*/
|
|
541
|
+
/** The Standard Schema interface. */
|
|
542
|
+
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
543
|
+
/** The Standard Schema properties. */
|
|
544
|
+
readonly '~standard': StandardSchemaV1.Props<Input, Output>;
|
|
545
|
+
}
|
|
546
|
+
declare namespace StandardSchemaV1 {
|
|
547
|
+
/** The Standard Schema properties interface. */
|
|
548
|
+
interface Props<Input = unknown, Output = Input> {
|
|
549
|
+
/** The version number of the standard. */
|
|
550
|
+
readonly version: 1;
|
|
551
|
+
/** The vendor name of the schema library. */
|
|
552
|
+
readonly vendor: string;
|
|
553
|
+
/** Validates unknown input values. */
|
|
554
|
+
readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
|
|
555
|
+
/** Inferred types associated with the schema. */
|
|
556
|
+
readonly types?: Types<Input, Output> | undefined;
|
|
557
|
+
}
|
|
558
|
+
/** The result interface of the validate function. */
|
|
559
|
+
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
560
|
+
/** The result interface if validation succeeds. */
|
|
561
|
+
interface SuccessResult<Output> {
|
|
562
|
+
/** The typed output value. */
|
|
563
|
+
readonly value: Output;
|
|
564
|
+
/** The non-existent issues. */
|
|
565
|
+
readonly issues?: undefined;
|
|
566
|
+
}
|
|
567
|
+
/** The result interface if validation fails. */
|
|
568
|
+
interface FailureResult {
|
|
569
|
+
/** The issues of failed validation. */
|
|
570
|
+
readonly issues: ReadonlyArray<Issue>;
|
|
571
|
+
}
|
|
572
|
+
/** The issue interface of the failure output. */
|
|
573
|
+
interface Issue {
|
|
574
|
+
/** The error message of the issue. */
|
|
575
|
+
readonly message: string;
|
|
576
|
+
/** The path of the issue, if any. */
|
|
577
|
+
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
578
|
+
}
|
|
579
|
+
/** The path segment interface of the issue. */
|
|
580
|
+
interface PathSegment {
|
|
581
|
+
/** The key representing a path segment. */
|
|
582
|
+
readonly key: PropertyKey;
|
|
583
|
+
}
|
|
584
|
+
/** The Standard Schema types interface. */
|
|
585
|
+
interface Types<Input = unknown, Output = Input> {
|
|
586
|
+
/** The input type of the schema. */
|
|
587
|
+
readonly input: Input;
|
|
588
|
+
/** The output type of the schema. */
|
|
589
|
+
readonly output: Output;
|
|
590
|
+
}
|
|
591
|
+
/** Infers the input type of a Standard Schema. */
|
|
592
|
+
type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
|
|
593
|
+
/** Infers the output type of a Standard Schema. */
|
|
594
|
+
type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* A class for building and executing HTTP requests with customizable options and error handling.
|
|
599
|
+
* @template Method The HTTP method type (GET, POST, etc.)
|
|
600
|
+
* @template TRequest The request configuration type extending RequestInit
|
|
601
|
+
* @template Opts Additional options type for custom configurations
|
|
602
|
+
* @example
|
|
603
|
+
* // Create a new request instance
|
|
604
|
+
* const request = new Request('/api/users', {
|
|
605
|
+
* baseUrl: 'https://example.com',
|
|
606
|
+
* headers: { 'Content-Type': 'application/json' }
|
|
607
|
+
* });
|
|
608
|
+
*
|
|
609
|
+
* // Configure and execute the request
|
|
610
|
+
* const result = await request
|
|
611
|
+
* .setQueryParams({ page: '1' })
|
|
612
|
+
* .setBearer('token123')
|
|
613
|
+
* .notFound(() => ({ message: 'Not found' }))
|
|
614
|
+
* .withResult()
|
|
615
|
+
* .json<User>();
|
|
616
|
+
*/
|
|
617
|
+
declare class Request<Method extends HttpMethods, TRequest extends AspiRequestInit = AspiRequestInit, Opts extends Record<any, any> = {
|
|
618
|
+
error: {};
|
|
619
|
+
}> {
|
|
620
|
+
#private;
|
|
621
|
+
constructor(method: HttpMethods, path: string, { requestConfig, retryConfig, middlewares, errorCbs, }: RequestOptions<TRequest>);
|
|
622
|
+
/**
|
|
623
|
+
* Sets the base URL for the request.
|
|
624
|
+
* @param url The base URL to set
|
|
625
|
+
* @returns The request instance for chaining
|
|
626
|
+
* @example
|
|
627
|
+
* const request = new Request('/users', config);
|
|
628
|
+
* request.setBaseUrl('https://api.example.com');
|
|
629
|
+
*/
|
|
630
|
+
setBaseUrl(url: string): this;
|
|
631
|
+
/**
|
|
632
|
+
* Sets the retry configuration for the request.
|
|
633
|
+
* @param retry The retry configuration object
|
|
634
|
+
* @returns The request instance for chaining
|
|
635
|
+
* @example
|
|
636
|
+
* const request = new Request('/users', config);
|
|
637
|
+
* request.setRetry({
|
|
638
|
+
* retries: 3, // Number of retry attempts
|
|
639
|
+
* retryDelay: 1000, // Delay between retries in ms
|
|
640
|
+
* retryOn: [500, 502, 503], // Status codes to retry on
|
|
641
|
+
* retryWhile: (request, response) => response.status >= 500 // Custom retry condition
|
|
642
|
+
* });
|
|
643
|
+
*/
|
|
644
|
+
setRetry(retry: AspiRetryConfig<TRequest>): this;
|
|
645
|
+
/**
|
|
646
|
+
* Sets multiple headers for the request.
|
|
647
|
+
* @param headers An object containing header key-value pairs
|
|
648
|
+
* @returns The request instance for chaining
|
|
649
|
+
* @example
|
|
650
|
+
* const request = new Request('/users', config);
|
|
651
|
+
* request.setHeaders({
|
|
652
|
+
* 'Content-Type': 'application/json',
|
|
653
|
+
* 'Accept': 'application/json'
|
|
654
|
+
* });
|
|
655
|
+
*/
|
|
656
|
+
setHeaders(headers: Record<string, string>): this;
|
|
657
|
+
/**
|
|
658
|
+
* Sets a single header for the request.
|
|
659
|
+
* @param key The header key
|
|
660
|
+
* @param value The header value
|
|
661
|
+
* @returns The request instance for chaining
|
|
662
|
+
* @example
|
|
663
|
+
* const request = new Request('/users', config);
|
|
664
|
+
* request.setHeader('Content-Type', 'application/json');
|
|
665
|
+
*/
|
|
666
|
+
setHeader(key: string, value: string): this;
|
|
667
|
+
/**
|
|
668
|
+
* Sets the Authorization header with a bearer token.
|
|
669
|
+
* @param token The bearer token to set
|
|
670
|
+
* @returns The request instance for chaining
|
|
671
|
+
* @example
|
|
672
|
+
* const request = new Request('/users', config);
|
|
673
|
+
* request.setBearer('my-auth-token');
|
|
674
|
+
*/
|
|
675
|
+
setBearer(token: string): this;
|
|
676
|
+
/**
|
|
677
|
+
* Sets a validation schema for the request body using a StandardSchemaV1 schema.
|
|
678
|
+
* @template TSchema Type parameter extending StandardSchemaV1
|
|
679
|
+
* @param schema The schema to validate the body against
|
|
680
|
+
* @returns The request instance for chaining with updated error type
|
|
681
|
+
* @example
|
|
682
|
+
* const userSchema = z.object({
|
|
683
|
+
* name: z.string(),
|
|
684
|
+
* email: z.string().email()
|
|
685
|
+
* });
|
|
686
|
+
*
|
|
687
|
+
* const request = new Request('/users', config);
|
|
688
|
+
* request
|
|
689
|
+
* .bodySchema(userSchema)
|
|
690
|
+
* .bodyJson({
|
|
691
|
+
* name: 'John',
|
|
692
|
+
* email: 'john@example.com'
|
|
693
|
+
* });
|
|
694
|
+
*/
|
|
695
|
+
bodySchema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Omit<Opts, "bodySchema"> & {
|
|
696
|
+
bodySchema: TSchema;
|
|
697
|
+
error: Opts["error"] & {
|
|
698
|
+
parseError: CustomError<"parseError", StandardSchemaV1.FailureResult["issues"]>;
|
|
699
|
+
};
|
|
700
|
+
}>;
|
|
701
|
+
/**
|
|
702
|
+
* Sets the request body as JSON by automatically stringifying the provided object.
|
|
703
|
+
* @param body The object to be stringified and sent as the request body
|
|
704
|
+
* @returns The request instance for chaining
|
|
705
|
+
* @example
|
|
706
|
+
* const request = new Request('/users', config);
|
|
707
|
+
* request.bodyJson({
|
|
708
|
+
* name: 'John Doe',
|
|
709
|
+
* email: 'john@example.com',
|
|
710
|
+
* age: 30
|
|
711
|
+
* });
|
|
712
|
+
*/
|
|
713
|
+
bodyJson<Body extends StandardSchemaV1.InferInput<Opts['bodySchema']>>(body: Body): Request<Method, TRequest, Omit<Opts, "body"> & {
|
|
714
|
+
body: Body;
|
|
715
|
+
}>;
|
|
716
|
+
/**
|
|
717
|
+
* Sets the raw request body (unsafe, use with caution).
|
|
718
|
+
* @param body The body content to send with the request
|
|
719
|
+
* @returns The request instance for chaining
|
|
720
|
+
* @example
|
|
721
|
+
* const request = new Request('/users', config);
|
|
722
|
+
* request.unsafeBody(new FormData());
|
|
723
|
+
*
|
|
724
|
+
* // or with raw text
|
|
725
|
+
* request.unsafeBody('Hello World');
|
|
726
|
+
*
|
|
727
|
+
* // or with URLSearchParams
|
|
728
|
+
* request.unsafeBody(new URLSearchParams({ key: 'value' }));
|
|
729
|
+
*/
|
|
730
|
+
unsafeBody(body: BodyInit): Request<Method, TRequest, Omit<Opts, "body"> & {
|
|
731
|
+
body: BodyInit;
|
|
732
|
+
}>;
|
|
733
|
+
/**
|
|
734
|
+
* Handles 404 Not Found errors with a custom callback.
|
|
735
|
+
* @param cb The callback function to handle the error
|
|
736
|
+
* @returns The request instance for chaining
|
|
737
|
+
* @example
|
|
738
|
+
* const request = new Request('/users', config);
|
|
739
|
+
* request.notFound((error) => {
|
|
740
|
+
* console.log('Resource not found:', error);
|
|
741
|
+
* return { message: 'Custom not found message' };
|
|
742
|
+
* });
|
|
743
|
+
*/
|
|
744
|
+
notFound<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
|
|
745
|
+
error: { [K in "notFoundError" | keyof Opts["error"]]: K extends "notFoundError" ? CustomError<"notFoundError", A> : Opts["error"][K]; };
|
|
746
|
+
}>;
|
|
747
|
+
/**
|
|
748
|
+
* Handles 429 Too Many Requests errors with a custom callback.
|
|
749
|
+
* @param cb The callback function to handle the error
|
|
750
|
+
* @returns The request instance for chaining
|
|
751
|
+
* @example
|
|
752
|
+
* const request = new Request('/users', config);
|
|
753
|
+
* request.tooManyRequests((error) => {
|
|
754
|
+
* console.log('Rate limited:', error);
|
|
755
|
+
* return { message: 'Please try again later' };
|
|
756
|
+
* });
|
|
757
|
+
*/
|
|
758
|
+
tooManyRequests<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
|
|
759
|
+
error: { [K in keyof Opts["error"] | "tooManyRequestsError"]: K extends "tooManyRequestsError" ? CustomError<"tooManyRequestsError", A> : Opts["error"][K]; };
|
|
760
|
+
}>;
|
|
761
|
+
/**
|
|
762
|
+
* Handles 400 Bad Request errors with a custom callback.
|
|
763
|
+
* @param cb The callback function to handle the error
|
|
764
|
+
* @returns The request instance for chaining
|
|
765
|
+
* @example
|
|
766
|
+
* const request = new Request('/users', config);
|
|
767
|
+
* request.badRequest((error) => {
|
|
768
|
+
* console.log('Bad request error:', error);
|
|
769
|
+
* return { message: 'Invalid request parameters' };
|
|
770
|
+
* });
|
|
771
|
+
*/
|
|
772
|
+
badRequest<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
|
|
773
|
+
error: { [K in keyof Opts["error"] | "badRequestError"]: K extends "badRequestError" ? CustomError<"badRequestError", A> : Opts["error"][K]; };
|
|
774
|
+
}>;
|
|
775
|
+
/**
|
|
776
|
+
* Handles 409 Conflict errors with a custom callback.
|
|
777
|
+
* @param cb The callback function to handle the error
|
|
778
|
+
* @returns The request instance for chaining
|
|
779
|
+
* @example
|
|
780
|
+
* const request = new Request('/users', config);
|
|
781
|
+
* request.conflict((error) => {
|
|
782
|
+
* console.log('Conflict error:', error);
|
|
783
|
+
* return { message: 'Resource conflict detected' };
|
|
784
|
+
* });
|
|
785
|
+
*/
|
|
786
|
+
conflict<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
|
|
787
|
+
error: { [K in keyof Opts["error"] | "conflictError"]: K extends "conflictError" ? CustomError<"conflictError", A> : Opts["error"][K]; };
|
|
788
|
+
}>;
|
|
789
|
+
/**
|
|
790
|
+
* Handles 401 Unauthorized errors with a custom callback.
|
|
791
|
+
* @param cb The callback function to handle the error
|
|
792
|
+
* @returns The request instance for chaining
|
|
793
|
+
* @example
|
|
794
|
+
* const request = new Request('/users', config);
|
|
795
|
+
* request.unauthorised((error) => {
|
|
796
|
+
* console.log('Unauthorized access:', error);
|
|
797
|
+
* return { message: 'Please login first' };
|
|
798
|
+
* });
|
|
799
|
+
*/
|
|
800
|
+
unauthorised<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
|
|
801
|
+
error: { [K in keyof Opts["error"] | "unauthorisedError"]: K extends "unauthorisedError" ? CustomError<"unauthorisedError", A> : Opts["error"][K]; };
|
|
802
|
+
}>;
|
|
803
|
+
/**
|
|
804
|
+
* Handles 403 Forbidden errors with a custom callback.
|
|
805
|
+
* @param cb The callback function to handle the error
|
|
806
|
+
* @returns The request instance for chaining
|
|
807
|
+
* @example
|
|
808
|
+
* const request = new Request('/users', config);
|
|
809
|
+
* request.forbidden((error) => {
|
|
810
|
+
* console.log('Access forbidden:', error);
|
|
811
|
+
* return { message: 'You do not have permission' };
|
|
812
|
+
* });
|
|
813
|
+
*/
|
|
814
|
+
forbidden<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
|
|
815
|
+
error: { [K in keyof Opts["error"] | "forbiddenError"]: K extends "forbiddenError" ? CustomError<"forbiddenError", A> : Opts["error"][K]; };
|
|
816
|
+
}>;
|
|
817
|
+
/**
|
|
818
|
+
* Handles 501 Not Implemented errors with a custom callback.
|
|
819
|
+
* @param cb The callback function to handle the error
|
|
820
|
+
* @returns The request instance for chaining
|
|
821
|
+
* @example
|
|
822
|
+
* const request = new Request('/users', config);
|
|
823
|
+
* request.notImplemented((error) => {
|
|
824
|
+
* console.log('Not implemented:', error);
|
|
825
|
+
* return { message: 'This feature is not implemented yet' };
|
|
826
|
+
* });
|
|
827
|
+
*/
|
|
828
|
+
notImplemented<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
|
|
829
|
+
error: { [K in keyof Opts["error"] | "notImplementedError"]: K extends "notImplementedError" ? CustomError<"notImplementedError", A> : Opts["error"][K]; };
|
|
830
|
+
}>;
|
|
831
|
+
/**
|
|
832
|
+
* Handles 500 Internal Server Error errors with a custom callback.
|
|
833
|
+
* @param cb The callback function to handle the error
|
|
834
|
+
* @returns The request instance for chaining
|
|
835
|
+
* @example
|
|
836
|
+
* const request = new Request('/users', config);
|
|
837
|
+
* request.internalServerError((error) => {
|
|
838
|
+
* console.log('Server error:', error);
|
|
839
|
+
* return { message: 'An unexpected error occurred' };
|
|
840
|
+
* });
|
|
841
|
+
*/
|
|
842
|
+
internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
|
|
843
|
+
error: { [K in keyof Opts["error"] | "internalServerError"]: K extends "internalServerError" ? CustomError<"internalServerError", A> : Opts["error"][K]; };
|
|
844
|
+
}>;
|
|
845
|
+
/**
|
|
846
|
+
* Sets a custom error handler for a specific HTTP status code.
|
|
847
|
+
* @param tag A string identifier for the error type
|
|
848
|
+
* @param status The HTTP error status to handle
|
|
849
|
+
* @param cb The callback function to handle the error
|
|
850
|
+
* @returns The request instance for chaining
|
|
851
|
+
* @example
|
|
852
|
+
* const request = new Request('/users', config);
|
|
853
|
+
* request
|
|
854
|
+
.withResult()
|
|
855
|
+
.error('customError', 'BAD_REQUEST', (error) => {
|
|
856
|
+
* console.log('Bad request error:', error);
|
|
857
|
+
* return {
|
|
858
|
+
* message: 'Invalid input',
|
|
859
|
+
* details: error.response.responseData
|
|
860
|
+
* };
|
|
861
|
+
* });
|
|
862
|
+
*
|
|
863
|
+
* // Later when making the request:
|
|
864
|
+
* const result = await request.json();
|
|
865
|
+
* if (Result.isErr(result)) {
|
|
866
|
+
* if(result.tag === 'customError') {
|
|
867
|
+
* console.log(result.error.data.message); // 'Invalid input'
|
|
868
|
+
* }
|
|
869
|
+
*/
|
|
870
|
+
error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
|
|
871
|
+
error: { [K in Tag | keyof Opts["error"]]: K extends Tag ? CustomError<Tag, A> : Opts["error"][K]; };
|
|
872
|
+
}>;
|
|
873
|
+
/**
|
|
874
|
+
* Sets query parameters for the request URL.
|
|
875
|
+
* @param params An object containing query parameter key-value pairs
|
|
876
|
+
* @returns The request instance for chaining
|
|
877
|
+
* @example
|
|
878
|
+
* const request = new Request('/users', config);
|
|
879
|
+
* request.setQueryParams({
|
|
880
|
+
* page: '1',
|
|
881
|
+
* limit: '10',
|
|
882
|
+
* sort: 'desc'
|
|
883
|
+
* });
|
|
884
|
+
*/
|
|
885
|
+
setQueryParams<T extends Record<string, string> | string[][] | string | URLSearchParams>(params: T): Request<Method, TRequest, Omit<Opts, "queryParams"> & {
|
|
886
|
+
qyeryParams: T;
|
|
887
|
+
}>;
|
|
888
|
+
/**
|
|
889
|
+
* Sets the output schema for validating the response data using Zod.
|
|
890
|
+
* @param schema The Zod schema to validate the response
|
|
891
|
+
* @returns The request instance for chaining
|
|
892
|
+
* @example
|
|
893
|
+
* import { z } from 'zod';
|
|
894
|
+
*
|
|
895
|
+
* const userSchema = z.object({
|
|
896
|
+
* id: z.number(),
|
|
897
|
+
* name: z.string(),
|
|
898
|
+
* email: z.string().email()
|
|
899
|
+
* });
|
|
900
|
+
*
|
|
901
|
+
* const request = new Request('/users', config);
|
|
902
|
+
* const result = await request
|
|
903
|
+
* .withResult()
|
|
904
|
+
* .output(userSchema)
|
|
905
|
+
* .json();
|
|
906
|
+
*
|
|
907
|
+
* if (Result.isOk(result)) {
|
|
908
|
+
* const user = result.value; // Typed and validated user data
|
|
909
|
+
* }
|
|
910
|
+
*/
|
|
911
|
+
schema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Omit<Opts, "schema"> & {
|
|
912
|
+
schema: TSchema;
|
|
913
|
+
error: Opts["error"] & {
|
|
914
|
+
parseError: CustomError<"parseError", StandardSchemaV1.FailureResult["issues"]>;
|
|
915
|
+
};
|
|
916
|
+
}>;
|
|
917
|
+
/**
|
|
918
|
+
* Executes the request and returns the JSON response.
|
|
919
|
+
* @returns A Promise containing the Result type with either successful data or error information
|
|
920
|
+
* @example
|
|
921
|
+
* const request = new Request('/users', config);
|
|
922
|
+
* const result = await request
|
|
923
|
+
* .setQueryParams({ id: '123' })
|
|
924
|
+
* .withResult()
|
|
925
|
+
* .notFound((error) => ({ message: 'User not found' }))
|
|
926
|
+
* .json<User>();
|
|
927
|
+
*
|
|
928
|
+
* if (Result.isOk(result)) {
|
|
929
|
+
* const user = result.value; // User data
|
|
930
|
+
* } else {
|
|
931
|
+
* console.error(result.error); // Error handling
|
|
932
|
+
* }
|
|
933
|
+
*/
|
|
934
|
+
json<T extends StandardSchemaV1.InferOutput<Opts['schema']>>(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, T>, AspiError<TRequest> | (Opts extends {
|
|
935
|
+
error: any;
|
|
936
|
+
} ? Opts['error'][keyof Opts['error']] : never) | JSONParseError> : [
|
|
937
|
+
AspiResultOk<TRequest, T> | null,
|
|
938
|
+
((AspiError<TRequest> | (Opts extends {
|
|
939
|
+
error: any;
|
|
940
|
+
} ? Opts['error'][keyof Opts['error']] : never) | JSONParseError) | null)
|
|
941
|
+
]>;
|
|
942
|
+
/**
|
|
943
|
+
* Executes the request and returns the response as plain text.
|
|
944
|
+
* @returns A Promise containing the Result type with either successful text data or error information
|
|
945
|
+
* @example
|
|
946
|
+
* const request = new Request('/data.txt', config);
|
|
947
|
+
* const result = await request
|
|
948
|
+
* .setQueryParams({ version: '1' })
|
|
949
|
+
* .withResult()
|
|
950
|
+
* .notFound((error) => ({ message: 'Text file not found' }))
|
|
951
|
+
* .text();
|
|
952
|
+
*
|
|
953
|
+
* if (Result.isOk(result)) {
|
|
954
|
+
* const text = result.value; // Plain text content
|
|
955
|
+
* } else {
|
|
956
|
+
* console.error(result.error); // Error handling
|
|
957
|
+
* }
|
|
958
|
+
*/
|
|
959
|
+
text(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, string>, AspiError<TRequest> | (Opts extends {
|
|
960
|
+
error: any;
|
|
961
|
+
} ? Opts['error'][keyof Opts['error']] : never)> : [
|
|
962
|
+
AspiResultOk<TRequest, string> | null,
|
|
963
|
+
((AspiError<TRequest> | (Opts extends {
|
|
964
|
+
error: any;
|
|
965
|
+
} ? Opts['error'][keyof Opts['error']] : never)) | null)
|
|
966
|
+
]>;
|
|
967
|
+
/**
|
|
968
|
+
* Executes the request and returns the response as a Blob.
|
|
969
|
+
* @returns A Promise containing the Result type with either successful Blob data or error information
|
|
970
|
+
* @example
|
|
971
|
+
* const request = new Request('/image.jpg', config);
|
|
972
|
+
* const result = await request
|
|
973
|
+
* .setQueryParams({ size: 'large' })
|
|
974
|
+
* .withResult()
|
|
975
|
+
* .notFound((error) => ({ message: 'Image not found' }))
|
|
976
|
+
* .blob();
|
|
977
|
+
*
|
|
978
|
+
* if (Result.isOk(result)) {
|
|
979
|
+
* const imageBlob = result.value; // Blob data
|
|
980
|
+
* } else {
|
|
981
|
+
* console.error(result.error); // Error handling
|
|
982
|
+
* }
|
|
983
|
+
*/
|
|
984
|
+
blob(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, Blob>, AspiError<TRequest> | (Opts extends {
|
|
985
|
+
error: any;
|
|
986
|
+
} ? Opts['error'][keyof Opts['error']] : never)> : [
|
|
987
|
+
AspiResultOk<TRequest, Blob> | null,
|
|
988
|
+
((AspiError<TRequest> | (Opts extends {
|
|
989
|
+
error: any;
|
|
990
|
+
} ? Opts['error'][keyof Opts['error']] : never)) | null)
|
|
991
|
+
]>;
|
|
992
|
+
/**
|
|
993
|
+
* Returns the complete URL for the request including base URL, path, and query parameters.
|
|
994
|
+
* @returns The complete URL string
|
|
995
|
+
* @example
|
|
996
|
+
* const request = new Request('/users', config);
|
|
997
|
+
* request.setBaseUrl('https://api.example.com');
|
|
998
|
+
* request.setQueryParams({ id: '123' });
|
|
999
|
+
* console.log(request.url()); // 'https://api.example.com/users?id=123'
|
|
1000
|
+
*/
|
|
1001
|
+
url(): string;
|
|
1002
|
+
/**
|
|
1003
|
+
* Configures the request to return a Result type instead of a tuple.
|
|
1004
|
+
* @returns The request instance for chaining with Result type return value
|
|
1005
|
+
* @example
|
|
1006
|
+
* const request = new Request('/users', config);
|
|
1007
|
+
* const result = await request
|
|
1008
|
+
* .withResult()
|
|
1009
|
+
* .json<User>();
|
|
1010
|
+
*
|
|
1011
|
+
* // Returns Result type instead of tuple
|
|
1012
|
+
* if (Result.isOk(result)) {
|
|
1013
|
+
* const user = result.value;
|
|
1014
|
+
* }
|
|
1015
|
+
*/
|
|
1016
|
+
withResult(): Request<Method, TRequest, Omit<Opts, "withResult"> & {
|
|
1017
|
+
withResult: true;
|
|
1018
|
+
}>;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
/**
|
|
1022
|
+
* A class for making API requests with a base URL and configurable options
|
|
1023
|
+
* @template TRequest - Type extending RequestInit for request configuration
|
|
1024
|
+
* @example
|
|
1025
|
+
* const api = new Aspi({
|
|
1026
|
+
* baseUrl: 'https://api.example.com',
|
|
1027
|
+
* headers: {
|
|
1028
|
+
* 'Content-Type': 'application/json'
|
|
1029
|
+
* }
|
|
1030
|
+
* });
|
|
1031
|
+
*
|
|
1032
|
+
* // Make requests
|
|
1033
|
+
* const users = await api.get('/users').json();
|
|
1034
|
+
* const user = await api.post('/users', { name: 'John' }).json();
|
|
1035
|
+
*/
|
|
1036
|
+
declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts extends Record<any, any> = {}> {
|
|
1037
|
+
#private;
|
|
1038
|
+
constructor(config: AspiConfig);
|
|
1039
|
+
/**
|
|
1040
|
+
* Sets the base URL for all API requests
|
|
1041
|
+
* @param {string} url - The base URL to be set
|
|
1042
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1043
|
+
* @example
|
|
1044
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1045
|
+
* api.setBaseUrl('https://api.newdomain.com');
|
|
1046
|
+
*/
|
|
1047
|
+
setBaseUrl(url: string): this;
|
|
1048
|
+
/**
|
|
1049
|
+
* Sets the retry configuration for failed requests
|
|
1050
|
+
* @param {AspiRetryConfig<TRequest>} retry - The retry configuration object
|
|
1051
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1052
|
+
* @example
|
|
1053
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1054
|
+
* api.setRetry({
|
|
1055
|
+
* retries: 3,
|
|
1056
|
+
* retryDelay: 1000,
|
|
1057
|
+
* retryOn: [500, 502],
|
|
1058
|
+
* retryWhile: (req, res) => res.status === 500
|
|
1059
|
+
* });
|
|
1060
|
+
*/
|
|
1061
|
+
setRetry(retry: AspiRetryConfig<TRequest>): this;
|
|
1062
|
+
/**
|
|
1063
|
+
* Makes a GET request to the specified path
|
|
1064
|
+
* @param {string} path - The path to make the request to
|
|
1065
|
+
* @returns {Request} A Request instance for chaining
|
|
1066
|
+
* @example
|
|
1067
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1068
|
+
* const response = await api.get('/users').json();
|
|
1069
|
+
*/
|
|
1070
|
+
get(path: string): Request<"GET", TRequest, Opts>;
|
|
1071
|
+
/**
|
|
1072
|
+
* Makes a POST request to the specified path with an optional body
|
|
1073
|
+
* @param {string} path - The path to make the request to
|
|
1074
|
+
* @param {BodyInit} [body] - The body of the request
|
|
1075
|
+
* @returns {Request} A Request instance for chaining
|
|
1076
|
+
* @example
|
|
1077
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1078
|
+
* const response = await api.post('/users', { name: 'John' }).json();
|
|
1079
|
+
*/
|
|
1080
|
+
post(path: string, body?: BodyInit): Request<"POST", TRequest, Opts>;
|
|
1081
|
+
/**
|
|
1082
|
+
* Makes a PUT request to the specified path with an optional body
|
|
1083
|
+
* @param {string} path - The path to make the request to
|
|
1084
|
+
* @param {BodyInit} [body] - The body of the request
|
|
1085
|
+
* @returns {Request} A Request instance for chaining
|
|
1086
|
+
* @example
|
|
1087
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1088
|
+
* const response = await api.put('/users/1', { name: 'John' }).json();
|
|
1089
|
+
*/
|
|
1090
|
+
put(path: string, body?: BodyInit): Request<"PUT", TRequest, Opts>;
|
|
1091
|
+
/**
|
|
1092
|
+
* Makes a PATCH request to the specified path with an optional body
|
|
1093
|
+
* @param {string} path - The path to make the request to
|
|
1094
|
+
* @param {BodyInit} [body] - The body of the request
|
|
1095
|
+
* @returns {Request} A Request instance for chaining
|
|
1096
|
+
* @example
|
|
1097
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1098
|
+
* const response = await api.patch('/users/1', { name: 'John' }).json();
|
|
1099
|
+
*/
|
|
1100
|
+
patch(path: string, body?: BodyInit): Request<"PATCH", TRequest, Opts>;
|
|
1101
|
+
/**
|
|
1102
|
+
* Makes a DELETE request to the specified path
|
|
1103
|
+
* @param {string} path - The path to make the request to
|
|
1104
|
+
* @returns {Request} A Request instance for chaining
|
|
1105
|
+
* @example
|
|
1106
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1107
|
+
* const response = await api.delete('/users/1').json();
|
|
1108
|
+
*/
|
|
1109
|
+
delete(path: string): Request<"DELETE", TRequest, Opts>;
|
|
1110
|
+
/**
|
|
1111
|
+
* Makes a HEAD request to the specified path
|
|
1112
|
+
* @param {string} path - The path to make the request to
|
|
1113
|
+
* @returns {Request} A Request instance for chaining
|
|
1114
|
+
* @example
|
|
1115
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1116
|
+
* const response = await api.head('/users').json();
|
|
1117
|
+
*/
|
|
1118
|
+
head(path: string): Request<"HEAD", TRequest, Opts>;
|
|
1119
|
+
/**
|
|
1120
|
+
* Makes an OPTIONS request to the specified path
|
|
1121
|
+
* @param {string} path - The path to make the request to
|
|
1122
|
+
* @returns {Request} A Request instance for chaining
|
|
1123
|
+
* @example
|
|
1124
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1125
|
+
* const response = await api.options('/users').json();
|
|
1126
|
+
*/
|
|
1127
|
+
options(path: string): Request<"OPTIONS", TRequest, Opts>;
|
|
1128
|
+
/**
|
|
1129
|
+
* Sets multiple headers for all API requests
|
|
1130
|
+
* @param {Record<string, string>} headers - An object containing header key-value pairs
|
|
1131
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1132
|
+
* @example
|
|
1133
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1134
|
+
* api.setHeaders({
|
|
1135
|
+
* 'Content-Type': 'application/json',
|
|
1136
|
+
* 'Accept': 'application/json'
|
|
1137
|
+
* });
|
|
1138
|
+
*/
|
|
1139
|
+
setHeaders(headers: Record<string, string>): this;
|
|
1140
|
+
/**
|
|
1141
|
+
* Sets a single header for all API requests
|
|
1142
|
+
* @param {string} key - The header key
|
|
1143
|
+
* @param {string} value - The header value
|
|
1144
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1145
|
+
* @example
|
|
1146
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1147
|
+
* api.setHeader('Content-Type', 'application/json');
|
|
1148
|
+
*/
|
|
1149
|
+
setHeader(key: string, value: string): this;
|
|
1150
|
+
/**
|
|
1151
|
+
* Sets the Authorization header with a Bearer token
|
|
1152
|
+
* @param {string} token - The Bearer token
|
|
1153
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1154
|
+
* @example
|
|
1155
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1156
|
+
* api.setBearer('myAuthToken123');
|
|
1157
|
+
*/
|
|
1158
|
+
setBearer(token: string): this;
|
|
1159
|
+
/**
|
|
1160
|
+
* Use a middleware function to transform requests
|
|
1161
|
+
* @param {Middleware<T, U>} fn - The middleware function to apply
|
|
1162
|
+
* @returns {Aspi<U>} A new Aspi instance with the applied middleware
|
|
1163
|
+
* @example
|
|
1164
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1165
|
+
* api.use((req) => {
|
|
1166
|
+
* // Add custom headers
|
|
1167
|
+
* req.headers = {
|
|
1168
|
+
* ...req.headers,
|
|
1169
|
+
* 'x-custom-header': 'custom-value'
|
|
1170
|
+
* };
|
|
1171
|
+
* return req;
|
|
1172
|
+
* });
|
|
1173
|
+
*/
|
|
1174
|
+
use<T extends TRequest, U extends TRequest>(fn: Middleware<T, U>): Aspi<U>;
|
|
1175
|
+
/**
|
|
1176
|
+
* Registers a custom error handler for a specific HTTP status
|
|
1177
|
+
* @param {string} tag - The error tag identifier
|
|
1178
|
+
* @param {HttpErrorStatus} status - The HTTP status code to handle
|
|
1179
|
+
* @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
|
|
1180
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1181
|
+
* @example
|
|
1182
|
+
* const api = new Aspi({ baseUrl: 'https://api.example.com' });
|
|
1183
|
+
* api.error('customError', 'BAD_REQUEST', (req, res) => {
|
|
1184
|
+
* console.log('Bad request error occurred');
|
|
1185
|
+
* return { message: 'Invalid input' };
|
|
1186
|
+
* });
|
|
1187
|
+
*/
|
|
1188
|
+
error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
|
|
1189
|
+
error: { [K in Tag | keyof Opts["error"]]: K extends Tag ? CustomError<Tag, A> : Opts["error"][K]; };
|
|
1190
|
+
}>;
|
|
1191
|
+
/**
|
|
1192
|
+
* Handles 404 Not Found errors with a custom callback.
|
|
1193
|
+
* @param cb The callback function to handle the error
|
|
1194
|
+
* @returns The request instance for chaining
|
|
1195
|
+
* @example
|
|
1196
|
+
* const request = new Request('/users', config);
|
|
1197
|
+
* request.notFound((error) => {
|
|
1198
|
+
* console.log('Not found:', error);
|
|
1199
|
+
* return { message: 'Resource not found' };
|
|
1200
|
+
* });
|
|
1201
|
+
*/
|
|
1202
|
+
notFound<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
|
|
1203
|
+
error: { [K in "notFoundError" | keyof Opts["error"]]: K extends "notFoundError" ? CustomError<"notFoundError", A> : Opts["error"][K]; };
|
|
1204
|
+
}>;
|
|
1205
|
+
/**
|
|
1206
|
+
* Handles 429 Too Many Requests errors with a custom callback.
|
|
1207
|
+
* @param cb The callback function to handle the error
|
|
1208
|
+
* @returns The request instance for chaining
|
|
1209
|
+
* @example
|
|
1210
|
+
* const request = new Request('/users', config);
|
|
1211
|
+
* request.tooManyRequests((error) => {
|
|
1212
|
+
* console.log('Rate limited:', error);
|
|
1213
|
+
* return { message: 'Please try again later' };
|
|
1214
|
+
* });
|
|
1215
|
+
*/
|
|
1216
|
+
tooManyRequests<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
|
|
1217
|
+
error: { [K in "tooManyRequestsError" | keyof Opts["error"]]: K extends "tooManyRequestsError" ? CustomError<"tooManyRequestsError", A> : Opts["error"][K]; };
|
|
1218
|
+
}>;
|
|
1219
|
+
/**
|
|
1220
|
+
* Handles 409 Conflict errors with a custom callback.
|
|
1221
|
+
* @param cb The callback function to handle the error
|
|
1222
|
+
* @returns The request instance for chaining
|
|
1223
|
+
* @example
|
|
1224
|
+
* const request = new Request('/users', config);
|
|
1225
|
+
* request.conflict((error) => {
|
|
1226
|
+
* console.log('Conflict error:', error);
|
|
1227
|
+
* return { message: 'Resource conflict detected' };
|
|
1228
|
+
* });
|
|
1229
|
+
*/
|
|
1230
|
+
conflict<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
|
|
1231
|
+
error: { [K in "conflictError" | keyof Opts["error"]]: K extends "conflictError" ? CustomError<"conflictError", A> : Opts["error"][K]; };
|
|
1232
|
+
}>;
|
|
1233
|
+
/**
|
|
1234
|
+
* Registers a handler for 400 Bad Request errors
|
|
1235
|
+
* @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
|
|
1236
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1237
|
+
* @example
|
|
1238
|
+
* api.badRequest((req, res) => ({ message: 'Invalid request parameters' }));
|
|
1239
|
+
*/
|
|
1240
|
+
badRequest<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
|
|
1241
|
+
error: { [K in "badRequestError" | keyof Opts["error"]]: K extends "badRequestError" ? CustomError<"badRequestError", A> : Opts["error"][K]; };
|
|
1242
|
+
}>;
|
|
1243
|
+
/**
|
|
1244
|
+
* Registers a handler for 401 Unauthorized errors
|
|
1245
|
+
* @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
|
|
1246
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1247
|
+
* @example
|
|
1248
|
+
* api.unauthorized((req, res) => ({ message: 'Authentication required' }));
|
|
1249
|
+
*/
|
|
1250
|
+
unauthorized<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
|
|
1251
|
+
error: { [K in keyof Opts["error"] | "unauthorizedError"]: K extends "unauthorizedError" ? CustomError<"unauthorizedError", A> : Opts["error"][K]; };
|
|
1252
|
+
}>;
|
|
1253
|
+
/**
|
|
1254
|
+
* Registers a handler for 403 Forbidden errors
|
|
1255
|
+
* @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
|
|
1256
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1257
|
+
* @example
|
|
1258
|
+
* api.forbidden((req, res) => ({ message: 'Access denied' }));
|
|
1259
|
+
*/
|
|
1260
|
+
forbidden<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
|
|
1261
|
+
error: { [K in "forbiddenError" | keyof Opts["error"]]: K extends "forbiddenError" ? CustomError<"forbiddenError", A> : Opts["error"][K]; };
|
|
1262
|
+
}>;
|
|
1263
|
+
/**
|
|
1264
|
+
* Registers a handler for 501 Not Implemented errors
|
|
1265
|
+
* @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
|
|
1266
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1267
|
+
* @example
|
|
1268
|
+
* api.notImplemented((req, res) => ({ message: 'Feature not implemented' }));
|
|
1269
|
+
*/
|
|
1270
|
+
notImplemented<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
|
|
1271
|
+
error: { [K in "notImplementedError" | keyof Opts["error"]]: K extends "notImplementedError" ? CustomError<"notImplementedError", A> : Opts["error"][K]; };
|
|
1272
|
+
}>;
|
|
1273
|
+
/**
|
|
1274
|
+
* Registers a handler for 500 Internal Server errors
|
|
1275
|
+
* @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
|
|
1276
|
+
* @returns {Aspi} The Aspi instance for chaining
|
|
1277
|
+
* @example
|
|
1278
|
+
* api.internalServerError((req, res) => ({ message: 'Server error occurred' }));
|
|
1279
|
+
*/
|
|
1280
|
+
internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
|
|
1281
|
+
error: { [K in keyof Opts["error"] | "internalServerErrorError"]: K extends "internalServerErrorError" ? CustomError<"internalServerErrorError", A> : Opts["error"][K]; };
|
|
1282
|
+
}>;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
export { Aspi, type AspiConfig, type AspiConfigBase, AspiError, type AspiRequest, type AspiRequestInit, type AspiResponse, type AspiResultOk, type AspiRetryConfig, CustomError, type CustomErrorCb, type ErrorCallbacks, type HttpErrorCodes, type HttpErrorStatus, type HttpMethods, type JSONParseError, type Middleware, Request, type RequestOptions, result as Result, getHttpErrorStatus, httpErrors };
|