aspi 1.3.0 → 2.1.0

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