aspi 1.1.0-beta.1 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -20,13 +20,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- Aspi: () => Aspi,
23
+ Aspi: () => Aspi2,
24
24
  AspiError: () => AspiError,
25
25
  CustomError: () => CustomError,
26
26
  Request: () => Request,
27
27
  Result: () => result_exports,
28
28
  getHttpErrorStatus: () => getHttpErrorStatus,
29
- httpErrors: () => httpErrors
29
+ httpErrors: () => httpErrors,
30
+ isAspiError: () => isAspiError,
31
+ isCustomError: () => isCustomError
30
32
  });
31
33
  module.exports = __toCommonJS(index_exports);
32
34
 
@@ -100,6 +102,12 @@ var CustomError = class extends Error {
100
102
  this.data = data;
101
103
  }
102
104
  };
105
+ var isAspiError = (error) => {
106
+ return error instanceof AspiError;
107
+ };
108
+ var isCustomError = (error) => {
109
+ return error instanceof CustomError;
110
+ };
103
111
 
104
112
  // src/result.ts
105
113
  var result_exports = {};
@@ -306,17 +314,20 @@ var Request = class {
306
314
  #retryConfig;
307
315
  #shouldBeResult = false;
308
316
  #bodySchemaIssues = [];
317
+ #throwOnError = false;
309
318
  constructor(method, path, {
310
319
  requestConfig,
311
320
  retryConfig,
312
321
  middlewares,
313
- errorCbs
322
+ errorCbs,
323
+ throwOnError
314
324
  }) {
315
325
  this.#path = path;
316
326
  this.#middlewares = middlewares || [];
317
327
  this.#localRequestInit = { ...requestConfig, method };
318
328
  this.#retryConfig = retryConfig;
319
329
  this.#customErrorCbs = errorCbs || {};
330
+ this.#throwOnError = throwOnError || false;
320
331
  }
321
332
  /**
322
333
  * Sets the base URL for the request.
@@ -646,6 +657,22 @@ var Request = class {
646
657
  this.#schema = schema;
647
658
  return this;
648
659
  }
660
+ /**
661
+ * Sets the request to throw an error if the response status is not successful.
662
+ * @returns The request instance for chaining
663
+ * @example
664
+ * const request = new Request('/users', config);
665
+ * const result = await request
666
+ * .withResult()
667
+ * .throwable()
668
+ * .json();
669
+ *
670
+ */
671
+ throwable() {
672
+ this.#shouldBeResult = false;
673
+ this.#throwOnError = true;
674
+ return this;
675
+ }
649
676
  /**
650
677
  * Executes the request and returns the JSON response.
651
678
  * @returns A Promise containing the Result type with either successful data or error information
@@ -653,7 +680,8 @@ var Request = class {
653
680
  * const request = new Request('/users', config);
654
681
  * const result = await request
655
682
  * .setQueryParams({ id: '123' })
656
- * .withResult()
683
+ * .
684
+ withResult()
657
685
  * .notFound((error) => ({ message: 'User not found' }))
658
686
  * .json<User>();
659
687
  *
@@ -752,6 +780,7 @@ var Request = class {
752
780
  * }
753
781
  */
754
782
  withResult() {
783
+ this.#throwOnError = false;
755
784
  this.#shouldBeResult = true;
756
785
  return this;
757
786
  }
@@ -759,6 +788,9 @@ var Request = class {
759
788
  if (this.#shouldBeResult) {
760
789
  return value;
761
790
  }
791
+ if (this.#throwOnError) {
792
+ return getOrThrow(value);
793
+ }
762
794
  if (isOk(value)) {
763
795
  return [getOrNull(value), null];
764
796
  } else {
@@ -936,11 +968,12 @@ var Request = class {
936
968
  };
937
969
 
938
970
  // src/aspi.ts
939
- var Aspi = class {
971
+ var Aspi2 = class {
940
972
  #globalRequestInit;
941
973
  #middlewares = [];
942
974
  #retryConfig;
943
975
  #customErrorCbs = {};
976
+ #throwOnError = false;
944
977
  constructor(config) {
945
978
  const { retryConfig, ...requestConfig } = config;
946
979
  this.#globalRequestInit = requestConfig;
@@ -987,7 +1020,8 @@ var Aspi = class {
987
1020
  },
988
1021
  retryConfig: this.#retryConfig,
989
1022
  middlewares: this.#middlewares,
990
- errorCbs: this.#customErrorCbs
1023
+ errorCbs: this.#customErrorCbs,
1024
+ throwOnError: this.#throwOnError
991
1025
  });
992
1026
  }
993
1027
  /**
@@ -1243,6 +1277,21 @@ var Aspi = class {
1243
1277
  internalServerError(cb) {
1244
1278
  return this.error("internalServerErrorError", "INTERNAL_SERVER_ERROR", cb);
1245
1279
  }
1280
+ /**
1281
+ * Sets the aspi to throw an error if the response status is not successful.
1282
+ * @returns The request instance for chaining
1283
+ * @example
1284
+ * const aspi = new Aspi({baseUrl: 'https://example.com'});
1285
+ * const result = await aspi.get('/users')
1286
+ * .withResult()
1287
+ * .throwable()
1288
+ * .json();
1289
+ *
1290
+ */
1291
+ throwable() {
1292
+ this.#throwOnError = true;
1293
+ return this;
1294
+ }
1246
1295
  };
1247
1296
  // Annotate the CommonJS export names for ESM import in node:
1248
1297
  0 && (module.exports = {
@@ -1252,5 +1301,7 @@ var Aspi = class {
1252
1301
  Request,
1253
1302
  Result,
1254
1303
  getHttpErrorStatus,
1255
- httpErrors
1304
+ httpErrors,
1305
+ isAspiError,
1306
+ isCustomError
1256
1307
  });
package/dist/index.d.cts CHANGED
@@ -67,6 +67,10 @@ declare const getHttpErrorStatus: (status: HttpErrorCodes) => HttpErrorStatus;
67
67
  */
68
68
  type HttpMethods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'TRACE' | 'CONNECT';
69
69
 
70
+ type Prettify<Type> = Type extends Function ? Type : Extract<{
71
+ [Key in keyof Type]: Type[Key];
72
+ }, Type>;
73
+ type Merge<Object1, Object2> = Prettify<Omit<Object1, keyof Object2> & Object2>;
70
74
  type AspiConfigBase = {
71
75
  baseUrl: string;
72
76
  retryConfig?: AspiRetryConfig<AspiRequestInit>;
@@ -91,6 +95,7 @@ type RequestOptions<TRequest extends AspiRequestInit> = {
91
95
  retryConfig?: AspiRetryConfig<TRequest>;
92
96
  middlewares?: Middleware<TRequest, TRequest>[];
93
97
  errorCbs?: ErrorCallbacks;
98
+ throwOnError?: boolean;
94
99
  };
95
100
  type ErrorCallbacks = Record<number, {
96
101
  cb: (input: {
@@ -104,6 +109,7 @@ type AspiResultOk<TRequest extends AspiRequestInit, TData> = {
104
109
  request: AspiRequest<TRequest>;
105
110
  response: AspiResponse;
106
111
  };
112
+ type AspiPlainResponse<TRequest extends AspiRequestInit, TData> = AspiResultOk<TRequest, TData>;
107
113
 
108
114
  /**
109
115
  * Response interface used in error handling
@@ -195,6 +201,8 @@ interface JSONParseError extends CustomError<'jsonParseError', {
195
201
  message: string;
196
202
  }> {
197
203
  }
204
+ declare const isAspiError: <TReq extends AspiRequestInit>(error: unknown) => error is AspiError<TReq>;
205
+ declare const isCustomError: <Tag extends string, A>(error: unknown) => error is CustomError<Tag, A>;
198
206
 
199
207
  type Ok<T> = {
200
208
  __tag: 'ok';
@@ -598,7 +606,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
598
606
  error: {};
599
607
  }> {
600
608
  #private;
601
- constructor(method: HttpMethods, path: string, { requestConfig, retryConfig, middlewares, errorCbs, }: RequestOptions<TRequest>);
609
+ constructor(method: HttpMethods, path: string, { requestConfig, retryConfig, middlewares, errorCbs, throwOnError, }: RequestOptions<TRequest>);
602
610
  /**
603
611
  * Sets the base URL for the request.
604
612
  * @param url The base URL to set
@@ -690,9 +698,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
690
698
  * age: 30
691
699
  * });
692
700
  */
693
- bodyJson<Body extends StandardSchemaV1.InferInput<Opts['bodySchema']>>(body: Body): Request<Method, TRequest, Omit<Opts, "body"> & {
701
+ bodyJson<Body extends StandardSchemaV1.InferInput<Opts['bodySchema']>>(body: Body): Request<Method, TRequest, Merge<Omit<Opts, "body">, {
694
702
  body: Body;
695
- }>;
703
+ }>>;
696
704
  /**
697
705
  * Sets the raw request body (unsafe, use with caution).
698
706
  * @param body The body content to send with the request
@@ -707,9 +715,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
707
715
  * // or with URLSearchParams
708
716
  * request.unsafeBody(new URLSearchParams({ key: 'value' }));
709
717
  */
710
- unsafeBody(body: BodyInit): Request<Method, TRequest, Omit<Opts, "body"> & {
718
+ unsafeBody(body: BodyInit): Request<Method, TRequest, Merge<Omit<Opts, "body">, {
711
719
  body: BodyInit;
712
- }>;
720
+ }>>;
713
721
  /**
714
722
  * Handles 404 Not Found errors with a custom callback.
715
723
  * @param cb The callback function to handle the error
@@ -721,9 +729,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
721
729
  * return { message: 'Custom not found message' };
722
730
  * });
723
731
  */
724
- notFound<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
732
+ notFound<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
725
733
  error: { [K in "notFoundError" | keyof Opts["error"]]: K extends "notFoundError" ? CustomError<"notFoundError", A> : Opts["error"][K]; };
726
- }>;
734
+ }>>;
727
735
  /**
728
736
  * Handles 429 Too Many Requests errors with a custom callback.
729
737
  * @param cb The callback function to handle the error
@@ -735,9 +743,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
735
743
  * return { message: 'Please try again later' };
736
744
  * });
737
745
  */
738
- tooManyRequests<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
746
+ tooManyRequests<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
739
747
  error: { [K in keyof Opts["error"] | "tooManyRequestsError"]: K extends "tooManyRequestsError" ? CustomError<"tooManyRequestsError", A> : Opts["error"][K]; };
740
- }>;
748
+ }>>;
741
749
  /**
742
750
  * Handles 400 Bad Request errors with a custom callback.
743
751
  * @param cb The callback function to handle the error
@@ -749,9 +757,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
749
757
  * return { message: 'Invalid request parameters' };
750
758
  * });
751
759
  */
752
- badRequest<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
760
+ badRequest<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
753
761
  error: { [K in keyof Opts["error"] | "badRequestError"]: K extends "badRequestError" ? CustomError<"badRequestError", A> : Opts["error"][K]; };
754
- }>;
762
+ }>>;
755
763
  /**
756
764
  * Handles 409 Conflict errors with a custom callback.
757
765
  * @param cb The callback function to handle the error
@@ -763,9 +771,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
763
771
  * return { message: 'Resource conflict detected' };
764
772
  * });
765
773
  */
766
- conflict<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
774
+ conflict<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
767
775
  error: { [K in keyof Opts["error"] | "conflictError"]: K extends "conflictError" ? CustomError<"conflictError", A> : Opts["error"][K]; };
768
- }>;
776
+ }>>;
769
777
  /**
770
778
  * Handles 401 Unauthorized errors with a custom callback.
771
779
  * @param cb The callback function to handle the error
@@ -777,9 +785,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
777
785
  * return { message: 'Please login first' };
778
786
  * });
779
787
  */
780
- unauthorised<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
788
+ unauthorised<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
781
789
  error: { [K in keyof Opts["error"] | "unauthorisedError"]: K extends "unauthorisedError" ? CustomError<"unauthorisedError", A> : Opts["error"][K]; };
782
- }>;
790
+ }>>;
783
791
  /**
784
792
  * Handles 403 Forbidden errors with a custom callback.
785
793
  * @param cb The callback function to handle the error
@@ -791,9 +799,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
791
799
  * return { message: 'You do not have permission' };
792
800
  * });
793
801
  */
794
- forbidden<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
802
+ forbidden<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
795
803
  error: { [K in keyof Opts["error"] | "forbiddenError"]: K extends "forbiddenError" ? CustomError<"forbiddenError", A> : Opts["error"][K]; };
796
- }>;
804
+ }>>;
797
805
  /**
798
806
  * Handles 501 Not Implemented errors with a custom callback.
799
807
  * @param cb The callback function to handle the error
@@ -805,9 +813,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
805
813
  * return { message: 'This feature is not implemented yet' };
806
814
  * });
807
815
  */
808
- notImplemented<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
816
+ notImplemented<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
809
817
  error: { [K in keyof Opts["error"] | "notImplementedError"]: K extends "notImplementedError" ? CustomError<"notImplementedError", A> : Opts["error"][K]; };
810
- }>;
818
+ }>>;
811
819
  /**
812
820
  * Handles 500 Internal Server Error errors with a custom callback.
813
821
  * @param cb The callback function to handle the error
@@ -819,9 +827,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
819
827
  * return { message: 'An unexpected error occurred' };
820
828
  * });
821
829
  */
822
- internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
830
+ internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
823
831
  error: { [K in keyof Opts["error"] | "internalServerError"]: K extends "internalServerError" ? CustomError<"internalServerError", A> : Opts["error"][K]; };
824
- }>;
832
+ }>>;
825
833
  /**
826
834
  * Sets a custom error handler for a specific HTTP status code.
827
835
  * @param tag A string identifier for the error type
@@ -847,9 +855,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
847
855
  * console.log(result.error.data.message); // 'Invalid input'
848
856
  * }
849
857
  */
850
- error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
858
+ error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Merge<Omit<Opts, "error">, {
851
859
  error: { [K in Tag | keyof Opts["error"]]: K extends Tag ? CustomError<Tag, A> : Opts["error"][K]; };
852
- }>;
860
+ }>>;
853
861
  /**
854
862
  * Sets query parameters for the request URL.
855
863
  * @param params An object containing query parameter key-value pairs
@@ -862,9 +870,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
862
870
  * sort: 'desc'
863
871
  * });
864
872
  */
865
- setQueryParams<T extends Record<string, string> | string[][] | string | URLSearchParams>(params: T): Request<Method, TRequest, Omit<Opts, "queryParams"> & {
866
- qyeryParams: T;
867
- }>;
873
+ setQueryParams<T extends Record<string, string> | string[][] | string | URLSearchParams>(params: T): Request<Method, TRequest, Merge<Omit<Opts, "queryParams">, {
874
+ queryParams: T;
875
+ }>>;
868
876
  /**
869
877
  * Sets the output schema for validating the response data using Zod.
870
878
  * @param schema The Zod schema to validate the response
@@ -888,12 +896,27 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
888
896
  * const user = result.value; // Typed and validated user data
889
897
  * }
890
898
  */
891
- schema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Omit<Opts, "schema"> & {
899
+ schema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Merge<Omit<Opts, "schema">, {
892
900
  schema: TSchema;
893
- error: Opts["error"] & {
901
+ error: Merge<Opts["error"], {
894
902
  parseError: CustomError<"parseError", StandardSchemaV1.FailureResult["issues"]>;
895
- };
896
- }>;
903
+ }>;
904
+ }>>;
905
+ /**
906
+ * Sets the request to throw an error if the response status is not successful.
907
+ * @returns The request instance for chaining
908
+ * @example
909
+ * const request = new Request('/users', config);
910
+ * const result = await request
911
+ * .withResult()
912
+ * .throwable()
913
+ * .json();
914
+ *
915
+ */
916
+ throwable(): Request<Method, TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
917
+ withResult: false;
918
+ throwable: true;
919
+ }>>;
897
920
  /**
898
921
  * Executes the request and returns the JSON response.
899
922
  * @returns A Promise containing the Result type with either successful data or error information
@@ -901,7 +924,8 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
901
924
  * const request = new Request('/users', config);
902
925
  * const result = await request
903
926
  * .setQueryParams({ id: '123' })
904
- * .withResult()
927
+ * .
928
+ withResult()
905
929
  * .notFound((error) => ({ message: 'User not found' }))
906
930
  * .json<User>();
907
931
  *
@@ -913,7 +937,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
913
937
  */
914
938
  json<T extends StandardSchemaV1.InferOutput<Opts['schema']>>(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, T>, AspiError<TRequest> | (Opts extends {
915
939
  error: any;
916
- } ? Opts['error'][keyof Opts['error']] : never) | JSONParseError> : [
940
+ } ? Opts['error'][keyof Opts['error']] : never) | JSONParseError> : Opts['throwable'] extends true ? AspiPlainResponse<TRequest, T> : [
917
941
  AspiResultOk<TRequest, T> | null,
918
942
  ((AspiError<TRequest> | (Opts extends {
919
943
  error: any;
@@ -938,7 +962,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
938
962
  */
939
963
  text(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, string>, AspiError<TRequest> | (Opts extends {
940
964
  error: any;
941
- } ? Opts['error'][keyof Opts['error']] : never)> : [
965
+ } ? Opts['error'][keyof Opts['error']] : never)> : Opts['throwable'] extends true ? AspiPlainResponse<TRequest, string> : [
942
966
  AspiResultOk<TRequest, string> | null,
943
967
  ((AspiError<TRequest> | (Opts extends {
944
968
  error: any;
@@ -963,7 +987,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
963
987
  */
964
988
  blob(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, Blob>, AspiError<TRequest> | (Opts extends {
965
989
  error: any;
966
- } ? Opts['error'][keyof Opts['error']] : never)> : [
990
+ } ? Opts['error'][keyof Opts['error']] : never)> : Opts['throwable'] extends true ? AspiPlainResponse<TRequest, Blob> : [
967
991
  AspiResultOk<TRequest, Blob> | null,
968
992
  ((AspiError<TRequest> | (Opts extends {
969
993
  error: any;
@@ -993,9 +1017,10 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
993
1017
  * const user = result.value;
994
1018
  * }
995
1019
  */
996
- withResult(): Request<Method, TRequest, Omit<Opts, "withResult"> & {
1020
+ withResult(): Request<Method, TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
997
1021
  withResult: true;
998
- }>;
1022
+ throwable: false;
1023
+ }>>;
999
1024
  }
1000
1025
 
1001
1026
  /**
@@ -1165,9 +1190,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1165
1190
  * return { message: 'Invalid input' };
1166
1191
  * });
1167
1192
  */
1168
- error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1193
+ error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1169
1194
  error: { [K in Tag | keyof Opts["error"]]: K extends Tag ? CustomError<Tag, A> : Opts["error"][K]; };
1170
- }>;
1195
+ }>>;
1171
1196
  /**
1172
1197
  * Handles 404 Not Found errors with a custom callback.
1173
1198
  * @param cb The callback function to handle the error
@@ -1179,9 +1204,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1179
1204
  * return { message: 'Resource not found' };
1180
1205
  * });
1181
1206
  */
1182
- notFound<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1207
+ notFound<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1183
1208
  error: { [K in "notFoundError" | keyof Opts["error"]]: K extends "notFoundError" ? CustomError<"notFoundError", A> : Opts["error"][K]; };
1184
- }>;
1209
+ }>>;
1185
1210
  /**
1186
1211
  * Handles 429 Too Many Requests errors with a custom callback.
1187
1212
  * @param cb The callback function to handle the error
@@ -1193,9 +1218,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1193
1218
  * return { message: 'Please try again later' };
1194
1219
  * });
1195
1220
  */
1196
- tooManyRequests<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1221
+ tooManyRequests<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1197
1222
  error: { [K in "tooManyRequestsError" | keyof Opts["error"]]: K extends "tooManyRequestsError" ? CustomError<"tooManyRequestsError", A> : Opts["error"][K]; };
1198
- }>;
1223
+ }>>;
1199
1224
  /**
1200
1225
  * Handles 409 Conflict errors with a custom callback.
1201
1226
  * @param cb The callback function to handle the error
@@ -1207,9 +1232,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1207
1232
  * return { message: 'Resource conflict detected' };
1208
1233
  * });
1209
1234
  */
1210
- conflict<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1235
+ conflict<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1211
1236
  error: { [K in "conflictError" | keyof Opts["error"]]: K extends "conflictError" ? CustomError<"conflictError", A> : Opts["error"][K]; };
1212
- }>;
1237
+ }>>;
1213
1238
  /**
1214
1239
  * Registers a handler for 400 Bad Request errors
1215
1240
  * @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
@@ -1217,9 +1242,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1217
1242
  * @example
1218
1243
  * api.badRequest((req, res) => ({ message: 'Invalid request parameters' }));
1219
1244
  */
1220
- badRequest<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1245
+ badRequest<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1221
1246
  error: { [K in "badRequestError" | keyof Opts["error"]]: K extends "badRequestError" ? CustomError<"badRequestError", A> : Opts["error"][K]; };
1222
- }>;
1247
+ }>>;
1223
1248
  /**
1224
1249
  * Registers a handler for 401 Unauthorized errors
1225
1250
  * @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
@@ -1227,9 +1252,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1227
1252
  * @example
1228
1253
  * api.unauthorized((req, res) => ({ message: 'Authentication required' }));
1229
1254
  */
1230
- unauthorized<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1255
+ unauthorized<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1231
1256
  error: { [K in keyof Opts["error"] | "unauthorizedError"]: K extends "unauthorizedError" ? CustomError<"unauthorizedError", A> : Opts["error"][K]; };
1232
- }>;
1257
+ }>>;
1233
1258
  /**
1234
1259
  * Registers a handler for 403 Forbidden errors
1235
1260
  * @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
@@ -1237,9 +1262,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1237
1262
  * @example
1238
1263
  * api.forbidden((req, res) => ({ message: 'Access denied' }));
1239
1264
  */
1240
- forbidden<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1265
+ forbidden<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1241
1266
  error: { [K in "forbiddenError" | keyof Opts["error"]]: K extends "forbiddenError" ? CustomError<"forbiddenError", A> : Opts["error"][K]; };
1242
- }>;
1267
+ }>>;
1243
1268
  /**
1244
1269
  * Registers a handler for 501 Not Implemented errors
1245
1270
  * @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
@@ -1247,9 +1272,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1247
1272
  * @example
1248
1273
  * api.notImplemented((req, res) => ({ message: 'Feature not implemented' }));
1249
1274
  */
1250
- notImplemented<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1275
+ notImplemented<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1251
1276
  error: { [K in "notImplementedError" | keyof Opts["error"]]: K extends "notImplementedError" ? CustomError<"notImplementedError", A> : Opts["error"][K]; };
1252
- }>;
1277
+ }>>;
1253
1278
  /**
1254
1279
  * Registers a handler for 500 Internal Server errors
1255
1280
  * @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
@@ -1257,9 +1282,23 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1257
1282
  * @example
1258
1283
  * api.internalServerError((req, res) => ({ message: 'Server error occurred' }));
1259
1284
  */
1260
- internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1285
+ internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1261
1286
  error: { [K in keyof Opts["error"] | "internalServerErrorError"]: K extends "internalServerErrorError" ? CustomError<"internalServerErrorError", A> : Opts["error"][K]; };
1262
- }>;
1287
+ }>>;
1288
+ /**
1289
+ * Sets the aspi to throw an error if the response status is not successful.
1290
+ * @returns The request instance for chaining
1291
+ * @example
1292
+ * const aspi = new Aspi({baseUrl: 'https://example.com'});
1293
+ * const result = await aspi.get('/users')
1294
+ * .withResult()
1295
+ * .throwable()
1296
+ * .json();
1297
+ *
1298
+ */
1299
+ throwable(): Aspi<TRequest, Prettify<Opts & {
1300
+ throwable: true;
1301
+ }>>;
1263
1302
  }
1264
1303
 
1265
- 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 };
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 };
package/dist/index.d.ts CHANGED
@@ -67,6 +67,10 @@ declare const getHttpErrorStatus: (status: HttpErrorCodes) => HttpErrorStatus;
67
67
  */
68
68
  type HttpMethods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'TRACE' | 'CONNECT';
69
69
 
70
+ type Prettify<Type> = Type extends Function ? Type : Extract<{
71
+ [Key in keyof Type]: Type[Key];
72
+ }, Type>;
73
+ type Merge<Object1, Object2> = Prettify<Omit<Object1, keyof Object2> & Object2>;
70
74
  type AspiConfigBase = {
71
75
  baseUrl: string;
72
76
  retryConfig?: AspiRetryConfig<AspiRequestInit>;
@@ -91,6 +95,7 @@ type RequestOptions<TRequest extends AspiRequestInit> = {
91
95
  retryConfig?: AspiRetryConfig<TRequest>;
92
96
  middlewares?: Middleware<TRequest, TRequest>[];
93
97
  errorCbs?: ErrorCallbacks;
98
+ throwOnError?: boolean;
94
99
  };
95
100
  type ErrorCallbacks = Record<number, {
96
101
  cb: (input: {
@@ -104,6 +109,7 @@ type AspiResultOk<TRequest extends AspiRequestInit, TData> = {
104
109
  request: AspiRequest<TRequest>;
105
110
  response: AspiResponse;
106
111
  };
112
+ type AspiPlainResponse<TRequest extends AspiRequestInit, TData> = AspiResultOk<TRequest, TData>;
107
113
 
108
114
  /**
109
115
  * Response interface used in error handling
@@ -195,6 +201,8 @@ interface JSONParseError extends CustomError<'jsonParseError', {
195
201
  message: string;
196
202
  }> {
197
203
  }
204
+ declare const isAspiError: <TReq extends AspiRequestInit>(error: unknown) => error is AspiError<TReq>;
205
+ declare const isCustomError: <Tag extends string, A>(error: unknown) => error is CustomError<Tag, A>;
198
206
 
199
207
  type Ok<T> = {
200
208
  __tag: 'ok';
@@ -598,7 +606,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
598
606
  error: {};
599
607
  }> {
600
608
  #private;
601
- constructor(method: HttpMethods, path: string, { requestConfig, retryConfig, middlewares, errorCbs, }: RequestOptions<TRequest>);
609
+ constructor(method: HttpMethods, path: string, { requestConfig, retryConfig, middlewares, errorCbs, throwOnError, }: RequestOptions<TRequest>);
602
610
  /**
603
611
  * Sets the base URL for the request.
604
612
  * @param url The base URL to set
@@ -690,9 +698,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
690
698
  * age: 30
691
699
  * });
692
700
  */
693
- bodyJson<Body extends StandardSchemaV1.InferInput<Opts['bodySchema']>>(body: Body): Request<Method, TRequest, Omit<Opts, "body"> & {
701
+ bodyJson<Body extends StandardSchemaV1.InferInput<Opts['bodySchema']>>(body: Body): Request<Method, TRequest, Merge<Omit<Opts, "body">, {
694
702
  body: Body;
695
- }>;
703
+ }>>;
696
704
  /**
697
705
  * Sets the raw request body (unsafe, use with caution).
698
706
  * @param body The body content to send with the request
@@ -707,9 +715,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
707
715
  * // or with URLSearchParams
708
716
  * request.unsafeBody(new URLSearchParams({ key: 'value' }));
709
717
  */
710
- unsafeBody(body: BodyInit): Request<Method, TRequest, Omit<Opts, "body"> & {
718
+ unsafeBody(body: BodyInit): Request<Method, TRequest, Merge<Omit<Opts, "body">, {
711
719
  body: BodyInit;
712
- }>;
720
+ }>>;
713
721
  /**
714
722
  * Handles 404 Not Found errors with a custom callback.
715
723
  * @param cb The callback function to handle the error
@@ -721,9 +729,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
721
729
  * return { message: 'Custom not found message' };
722
730
  * });
723
731
  */
724
- notFound<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
732
+ notFound<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
725
733
  error: { [K in "notFoundError" | keyof Opts["error"]]: K extends "notFoundError" ? CustomError<"notFoundError", A> : Opts["error"][K]; };
726
- }>;
734
+ }>>;
727
735
  /**
728
736
  * Handles 429 Too Many Requests errors with a custom callback.
729
737
  * @param cb The callback function to handle the error
@@ -735,9 +743,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
735
743
  * return { message: 'Please try again later' };
736
744
  * });
737
745
  */
738
- tooManyRequests<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
746
+ tooManyRequests<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
739
747
  error: { [K in keyof Opts["error"] | "tooManyRequestsError"]: K extends "tooManyRequestsError" ? CustomError<"tooManyRequestsError", A> : Opts["error"][K]; };
740
- }>;
748
+ }>>;
741
749
  /**
742
750
  * Handles 400 Bad Request errors with a custom callback.
743
751
  * @param cb The callback function to handle the error
@@ -749,9 +757,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
749
757
  * return { message: 'Invalid request parameters' };
750
758
  * });
751
759
  */
752
- badRequest<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
760
+ badRequest<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
753
761
  error: { [K in keyof Opts["error"] | "badRequestError"]: K extends "badRequestError" ? CustomError<"badRequestError", A> : Opts["error"][K]; };
754
- }>;
762
+ }>>;
755
763
  /**
756
764
  * Handles 409 Conflict errors with a custom callback.
757
765
  * @param cb The callback function to handle the error
@@ -763,9 +771,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
763
771
  * return { message: 'Resource conflict detected' };
764
772
  * });
765
773
  */
766
- conflict<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
774
+ conflict<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
767
775
  error: { [K in keyof Opts["error"] | "conflictError"]: K extends "conflictError" ? CustomError<"conflictError", A> : Opts["error"][K]; };
768
- }>;
776
+ }>>;
769
777
  /**
770
778
  * Handles 401 Unauthorized errors with a custom callback.
771
779
  * @param cb The callback function to handle the error
@@ -777,9 +785,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
777
785
  * return { message: 'Please login first' };
778
786
  * });
779
787
  */
780
- unauthorised<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
788
+ unauthorised<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
781
789
  error: { [K in keyof Opts["error"] | "unauthorisedError"]: K extends "unauthorisedError" ? CustomError<"unauthorisedError", A> : Opts["error"][K]; };
782
- }>;
790
+ }>>;
783
791
  /**
784
792
  * Handles 403 Forbidden errors with a custom callback.
785
793
  * @param cb The callback function to handle the error
@@ -791,9 +799,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
791
799
  * return { message: 'You do not have permission' };
792
800
  * });
793
801
  */
794
- forbidden<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
802
+ forbidden<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
795
803
  error: { [K in keyof Opts["error"] | "forbiddenError"]: K extends "forbiddenError" ? CustomError<"forbiddenError", A> : Opts["error"][K]; };
796
- }>;
804
+ }>>;
797
805
  /**
798
806
  * Handles 501 Not Implemented errors with a custom callback.
799
807
  * @param cb The callback function to handle the error
@@ -805,9 +813,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
805
813
  * return { message: 'This feature is not implemented yet' };
806
814
  * });
807
815
  */
808
- notImplemented<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
816
+ notImplemented<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
809
817
  error: { [K in keyof Opts["error"] | "notImplementedError"]: K extends "notImplementedError" ? CustomError<"notImplementedError", A> : Opts["error"][K]; };
810
- }>;
818
+ }>>;
811
819
  /**
812
820
  * Handles 500 Internal Server Error errors with a custom callback.
813
821
  * @param cb The callback function to handle the error
@@ -819,9 +827,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
819
827
  * return { message: 'An unexpected error occurred' };
820
828
  * });
821
829
  */
822
- internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
830
+ internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Prettify<Omit<Omit<Opts, "error">, "error"> & {
823
831
  error: { [K in keyof Opts["error"] | "internalServerError"]: K extends "internalServerError" ? CustomError<"internalServerError", A> : Opts["error"][K]; };
824
- }>;
832
+ }>>;
825
833
  /**
826
834
  * Sets a custom error handler for a specific HTTP status code.
827
835
  * @param tag A string identifier for the error type
@@ -847,9 +855,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
847
855
  * console.log(result.error.data.message); // 'Invalid input'
848
856
  * }
849
857
  */
850
- error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Omit<Opts, "error"> & {
858
+ error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Request<Method, TRequest, Merge<Omit<Opts, "error">, {
851
859
  error: { [K in Tag | keyof Opts["error"]]: K extends Tag ? CustomError<Tag, A> : Opts["error"][K]; };
852
- }>;
860
+ }>>;
853
861
  /**
854
862
  * Sets query parameters for the request URL.
855
863
  * @param params An object containing query parameter key-value pairs
@@ -862,9 +870,9 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
862
870
  * sort: 'desc'
863
871
  * });
864
872
  */
865
- setQueryParams<T extends Record<string, string> | string[][] | string | URLSearchParams>(params: T): Request<Method, TRequest, Omit<Opts, "queryParams"> & {
866
- qyeryParams: T;
867
- }>;
873
+ setQueryParams<T extends Record<string, string> | string[][] | string | URLSearchParams>(params: T): Request<Method, TRequest, Merge<Omit<Opts, "queryParams">, {
874
+ queryParams: T;
875
+ }>>;
868
876
  /**
869
877
  * Sets the output schema for validating the response data using Zod.
870
878
  * @param schema The Zod schema to validate the response
@@ -888,12 +896,27 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
888
896
  * const user = result.value; // Typed and validated user data
889
897
  * }
890
898
  */
891
- schema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Omit<Opts, "schema"> & {
899
+ schema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Merge<Omit<Opts, "schema">, {
892
900
  schema: TSchema;
893
- error: Opts["error"] & {
901
+ error: Merge<Opts["error"], {
894
902
  parseError: CustomError<"parseError", StandardSchemaV1.FailureResult["issues"]>;
895
- };
896
- }>;
903
+ }>;
904
+ }>>;
905
+ /**
906
+ * Sets the request to throw an error if the response status is not successful.
907
+ * @returns The request instance for chaining
908
+ * @example
909
+ * const request = new Request('/users', config);
910
+ * const result = await request
911
+ * .withResult()
912
+ * .throwable()
913
+ * .json();
914
+ *
915
+ */
916
+ throwable(): Request<Method, TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
917
+ withResult: false;
918
+ throwable: true;
919
+ }>>;
897
920
  /**
898
921
  * Executes the request and returns the JSON response.
899
922
  * @returns A Promise containing the Result type with either successful data or error information
@@ -901,7 +924,8 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
901
924
  * const request = new Request('/users', config);
902
925
  * const result = await request
903
926
  * .setQueryParams({ id: '123' })
904
- * .withResult()
927
+ * .
928
+ withResult()
905
929
  * .notFound((error) => ({ message: 'User not found' }))
906
930
  * .json<User>();
907
931
  *
@@ -913,7 +937,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
913
937
  */
914
938
  json<T extends StandardSchemaV1.InferOutput<Opts['schema']>>(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, T>, AspiError<TRequest> | (Opts extends {
915
939
  error: any;
916
- } ? Opts['error'][keyof Opts['error']] : never) | JSONParseError> : [
940
+ } ? Opts['error'][keyof Opts['error']] : never) | JSONParseError> : Opts['throwable'] extends true ? AspiPlainResponse<TRequest, T> : [
917
941
  AspiResultOk<TRequest, T> | null,
918
942
  ((AspiError<TRequest> | (Opts extends {
919
943
  error: any;
@@ -938,7 +962,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
938
962
  */
939
963
  text(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, string>, AspiError<TRequest> | (Opts extends {
940
964
  error: any;
941
- } ? Opts['error'][keyof Opts['error']] : never)> : [
965
+ } ? Opts['error'][keyof Opts['error']] : never)> : Opts['throwable'] extends true ? AspiPlainResponse<TRequest, string> : [
942
966
  AspiResultOk<TRequest, string> | null,
943
967
  ((AspiError<TRequest> | (Opts extends {
944
968
  error: any;
@@ -963,7 +987,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
963
987
  */
964
988
  blob(): Promise<Opts['withResult'] extends true ? Result<AspiResultOk<TRequest, Blob>, AspiError<TRequest> | (Opts extends {
965
989
  error: any;
966
- } ? Opts['error'][keyof Opts['error']] : never)> : [
990
+ } ? Opts['error'][keyof Opts['error']] : never)> : Opts['throwable'] extends true ? AspiPlainResponse<TRequest, Blob> : [
967
991
  AspiResultOk<TRequest, Blob> | null,
968
992
  ((AspiError<TRequest> | (Opts extends {
969
993
  error: any;
@@ -993,9 +1017,10 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
993
1017
  * const user = result.value;
994
1018
  * }
995
1019
  */
996
- withResult(): Request<Method, TRequest, Omit<Opts, "withResult"> & {
1020
+ withResult(): Request<Method, TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
997
1021
  withResult: true;
998
- }>;
1022
+ throwable: false;
1023
+ }>>;
999
1024
  }
1000
1025
 
1001
1026
  /**
@@ -1165,9 +1190,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1165
1190
  * return { message: 'Invalid input' };
1166
1191
  * });
1167
1192
  */
1168
- error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1193
+ error<Tag extends string, A extends {}>(tag: Tag, status: HttpErrorStatus, cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1169
1194
  error: { [K in Tag | keyof Opts["error"]]: K extends Tag ? CustomError<Tag, A> : Opts["error"][K]; };
1170
- }>;
1195
+ }>>;
1171
1196
  /**
1172
1197
  * Handles 404 Not Found errors with a custom callback.
1173
1198
  * @param cb The callback function to handle the error
@@ -1179,9 +1204,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1179
1204
  * return { message: 'Resource not found' };
1180
1205
  * });
1181
1206
  */
1182
- notFound<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1207
+ notFound<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1183
1208
  error: { [K in "notFoundError" | keyof Opts["error"]]: K extends "notFoundError" ? CustomError<"notFoundError", A> : Opts["error"][K]; };
1184
- }>;
1209
+ }>>;
1185
1210
  /**
1186
1211
  * Handles 429 Too Many Requests errors with a custom callback.
1187
1212
  * @param cb The callback function to handle the error
@@ -1193,9 +1218,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1193
1218
  * return { message: 'Please try again later' };
1194
1219
  * });
1195
1220
  */
1196
- tooManyRequests<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1221
+ tooManyRequests<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1197
1222
  error: { [K in "tooManyRequestsError" | keyof Opts["error"]]: K extends "tooManyRequestsError" ? CustomError<"tooManyRequestsError", A> : Opts["error"][K]; };
1198
- }>;
1223
+ }>>;
1199
1224
  /**
1200
1225
  * Handles 409 Conflict errors with a custom callback.
1201
1226
  * @param cb The callback function to handle the error
@@ -1207,9 +1232,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1207
1232
  * return { message: 'Resource conflict detected' };
1208
1233
  * });
1209
1234
  */
1210
- conflict<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1235
+ conflict<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1211
1236
  error: { [K in "conflictError" | keyof Opts["error"]]: K extends "conflictError" ? CustomError<"conflictError", A> : Opts["error"][K]; };
1212
- }>;
1237
+ }>>;
1213
1238
  /**
1214
1239
  * Registers a handler for 400 Bad Request errors
1215
1240
  * @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
@@ -1217,9 +1242,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1217
1242
  * @example
1218
1243
  * api.badRequest((req, res) => ({ message: 'Invalid request parameters' }));
1219
1244
  */
1220
- badRequest<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1245
+ badRequest<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1221
1246
  error: { [K in "badRequestError" | keyof Opts["error"]]: K extends "badRequestError" ? CustomError<"badRequestError", A> : Opts["error"][K]; };
1222
- }>;
1247
+ }>>;
1223
1248
  /**
1224
1249
  * Registers a handler for 401 Unauthorized errors
1225
1250
  * @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
@@ -1227,9 +1252,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1227
1252
  * @example
1228
1253
  * api.unauthorized((req, res) => ({ message: 'Authentication required' }));
1229
1254
  */
1230
- unauthorized<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1255
+ unauthorized<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1231
1256
  error: { [K in keyof Opts["error"] | "unauthorizedError"]: K extends "unauthorizedError" ? CustomError<"unauthorizedError", A> : Opts["error"][K]; };
1232
- }>;
1257
+ }>>;
1233
1258
  /**
1234
1259
  * Registers a handler for 403 Forbidden errors
1235
1260
  * @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
@@ -1237,9 +1262,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1237
1262
  * @example
1238
1263
  * api.forbidden((req, res) => ({ message: 'Access denied' }));
1239
1264
  */
1240
- forbidden<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1265
+ forbidden<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1241
1266
  error: { [K in "forbiddenError" | keyof Opts["error"]]: K extends "forbiddenError" ? CustomError<"forbiddenError", A> : Opts["error"][K]; };
1242
- }>;
1267
+ }>>;
1243
1268
  /**
1244
1269
  * Registers a handler for 501 Not Implemented errors
1245
1270
  * @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
@@ -1247,9 +1272,9 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1247
1272
  * @example
1248
1273
  * api.notImplemented((req, res) => ({ message: 'Feature not implemented' }));
1249
1274
  */
1250
- notImplemented<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1275
+ notImplemented<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1251
1276
  error: { [K in "notImplementedError" | keyof Opts["error"]]: K extends "notImplementedError" ? CustomError<"notImplementedError", A> : Opts["error"][K]; };
1252
- }>;
1277
+ }>>;
1253
1278
  /**
1254
1279
  * Registers a handler for 500 Internal Server errors
1255
1280
  * @param {CustomErrorCb<TRequest, A>} cb - The callback function to handle the error
@@ -1257,9 +1282,23 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
1257
1282
  * @example
1258
1283
  * api.internalServerError((req, res) => ({ message: 'Server error occurred' }));
1259
1284
  */
1260
- internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Opts & {
1285
+ internalServerError<A extends {}>(cb: CustomErrorCb<TRequest, A>): Aspi<TRequest, Prettify<Opts & {
1261
1286
  error: { [K in keyof Opts["error"] | "internalServerErrorError"]: K extends "internalServerErrorError" ? CustomError<"internalServerErrorError", A> : Opts["error"][K]; };
1262
- }>;
1287
+ }>>;
1288
+ /**
1289
+ * Sets the aspi to throw an error if the response status is not successful.
1290
+ * @returns The request instance for chaining
1291
+ * @example
1292
+ * const aspi = new Aspi({baseUrl: 'https://example.com'});
1293
+ * const result = await aspi.get('/users')
1294
+ * .withResult()
1295
+ * .throwable()
1296
+ * .json();
1297
+ *
1298
+ */
1299
+ throwable(): Aspi<TRequest, Prettify<Opts & {
1300
+ throwable: true;
1301
+ }>>;
1263
1302
  }
1264
1303
 
1265
- 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 };
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 };
package/dist/index.js CHANGED
@@ -74,6 +74,12 @@ var CustomError = class extends Error {
74
74
  this.data = data;
75
75
  }
76
76
  };
77
+ var isAspiError = (error) => {
78
+ return error instanceof AspiError;
79
+ };
80
+ var isCustomError = (error) => {
81
+ return error instanceof CustomError;
82
+ };
77
83
 
78
84
  // src/result.ts
79
85
  var result_exports = {};
@@ -280,17 +286,20 @@ var Request = class {
280
286
  #retryConfig;
281
287
  #shouldBeResult = false;
282
288
  #bodySchemaIssues = [];
289
+ #throwOnError = false;
283
290
  constructor(method, path, {
284
291
  requestConfig,
285
292
  retryConfig,
286
293
  middlewares,
287
- errorCbs
294
+ errorCbs,
295
+ throwOnError
288
296
  }) {
289
297
  this.#path = path;
290
298
  this.#middlewares = middlewares || [];
291
299
  this.#localRequestInit = { ...requestConfig, method };
292
300
  this.#retryConfig = retryConfig;
293
301
  this.#customErrorCbs = errorCbs || {};
302
+ this.#throwOnError = throwOnError || false;
294
303
  }
295
304
  /**
296
305
  * Sets the base URL for the request.
@@ -620,6 +629,22 @@ var Request = class {
620
629
  this.#schema = schema;
621
630
  return this;
622
631
  }
632
+ /**
633
+ * Sets the request to throw an error if the response status is not successful.
634
+ * @returns The request instance for chaining
635
+ * @example
636
+ * const request = new Request('/users', config);
637
+ * const result = await request
638
+ * .withResult()
639
+ * .throwable()
640
+ * .json();
641
+ *
642
+ */
643
+ throwable() {
644
+ this.#shouldBeResult = false;
645
+ this.#throwOnError = true;
646
+ return this;
647
+ }
623
648
  /**
624
649
  * Executes the request and returns the JSON response.
625
650
  * @returns A Promise containing the Result type with either successful data or error information
@@ -627,7 +652,8 @@ var Request = class {
627
652
  * const request = new Request('/users', config);
628
653
  * const result = await request
629
654
  * .setQueryParams({ id: '123' })
630
- * .withResult()
655
+ * .
656
+ withResult()
631
657
  * .notFound((error) => ({ message: 'User not found' }))
632
658
  * .json<User>();
633
659
  *
@@ -726,6 +752,7 @@ var Request = class {
726
752
  * }
727
753
  */
728
754
  withResult() {
755
+ this.#throwOnError = false;
729
756
  this.#shouldBeResult = true;
730
757
  return this;
731
758
  }
@@ -733,6 +760,9 @@ var Request = class {
733
760
  if (this.#shouldBeResult) {
734
761
  return value;
735
762
  }
763
+ if (this.#throwOnError) {
764
+ return getOrThrow(value);
765
+ }
736
766
  if (isOk(value)) {
737
767
  return [getOrNull(value), null];
738
768
  } else {
@@ -910,11 +940,12 @@ var Request = class {
910
940
  };
911
941
 
912
942
  // src/aspi.ts
913
- var Aspi = class {
943
+ var Aspi2 = class {
914
944
  #globalRequestInit;
915
945
  #middlewares = [];
916
946
  #retryConfig;
917
947
  #customErrorCbs = {};
948
+ #throwOnError = false;
918
949
  constructor(config) {
919
950
  const { retryConfig, ...requestConfig } = config;
920
951
  this.#globalRequestInit = requestConfig;
@@ -961,7 +992,8 @@ var Aspi = class {
961
992
  },
962
993
  retryConfig: this.#retryConfig,
963
994
  middlewares: this.#middlewares,
964
- errorCbs: this.#customErrorCbs
995
+ errorCbs: this.#customErrorCbs,
996
+ throwOnError: this.#throwOnError
965
997
  });
966
998
  }
967
999
  /**
@@ -1217,13 +1249,30 @@ var Aspi = class {
1217
1249
  internalServerError(cb) {
1218
1250
  return this.error("internalServerErrorError", "INTERNAL_SERVER_ERROR", cb);
1219
1251
  }
1252
+ /**
1253
+ * Sets the aspi to throw an error if the response status is not successful.
1254
+ * @returns The request instance for chaining
1255
+ * @example
1256
+ * const aspi = new Aspi({baseUrl: 'https://example.com'});
1257
+ * const result = await aspi.get('/users')
1258
+ * .withResult()
1259
+ * .throwable()
1260
+ * .json();
1261
+ *
1262
+ */
1263
+ throwable() {
1264
+ this.#throwOnError = true;
1265
+ return this;
1266
+ }
1220
1267
  };
1221
1268
  export {
1222
- Aspi,
1269
+ Aspi2 as Aspi,
1223
1270
  AspiError,
1224
1271
  CustomError,
1225
1272
  Request,
1226
1273
  result_exports as Result,
1227
1274
  getHttpErrorStatus,
1228
- httpErrors
1275
+ httpErrors,
1276
+ isAspiError,
1277
+ isCustomError
1229
1278
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aspi",
3
3
  "description": "Rest API client for typescript projects with chain of responsibility design pattern.",
4
- "version": "1.1.0-beta.1",
4
+ "version": "1.2.1",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",
7
7
  "devDependencies": {