aspi 1.1.0-beta.1 → 1.3.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.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.
@@ -438,6 +449,8 @@ var Request = class {
438
449
  } else {
439
450
  this.#localRequestInit.body = JSON.stringify(body);
440
451
  }
452
+ } else {
453
+ this.#localRequestInit.body = JSON.stringify(body);
441
454
  }
442
455
  return this;
443
456
  }
@@ -646,6 +659,22 @@ var Request = class {
646
659
  this.#schema = schema;
647
660
  return this;
648
661
  }
662
+ /**
663
+ * Sets the request to throw an error if the response status is not successful.
664
+ * @returns The request instance for chaining
665
+ * @example
666
+ * const request = new Request('/users', config);
667
+ * const result = await request
668
+ * .withResult()
669
+ * .throwable()
670
+ * .json();
671
+ *
672
+ */
673
+ throwable() {
674
+ this.#shouldBeResult = false;
675
+ this.#throwOnError = true;
676
+ return this;
677
+ }
649
678
  /**
650
679
  * Executes the request and returns the JSON response.
651
680
  * @returns A Promise containing the Result type with either successful data or error information
@@ -653,7 +682,8 @@ var Request = class {
653
682
  * const request = new Request('/users', config);
654
683
  * const result = await request
655
684
  * .setQueryParams({ id: '123' })
656
- * .withResult()
685
+ * .
686
+ withResult()
657
687
  * .notFound((error) => ({ message: 'User not found' }))
658
688
  * .json<User>();
659
689
  *
@@ -752,6 +782,7 @@ var Request = class {
752
782
  * }
753
783
  */
754
784
  withResult() {
785
+ this.#throwOnError = false;
755
786
  this.#shouldBeResult = true;
756
787
  return this;
757
788
  }
@@ -759,6 +790,9 @@ var Request = class {
759
790
  if (this.#shouldBeResult) {
760
791
  return value;
761
792
  }
793
+ if (this.#throwOnError) {
794
+ return getOrThrow(value);
795
+ }
762
796
  if (isOk(value)) {
763
797
  return [getOrNull(value), null];
764
798
  } else {
@@ -936,11 +970,12 @@ var Request = class {
936
970
  };
937
971
 
938
972
  // src/aspi.ts
939
- var Aspi = class {
973
+ var Aspi2 = class {
940
974
  #globalRequestInit;
941
975
  #middlewares = [];
942
976
  #retryConfig;
943
977
  #customErrorCbs = {};
978
+ #throwOnError = false;
944
979
  constructor(config) {
945
980
  const { retryConfig, ...requestConfig } = config;
946
981
  this.#globalRequestInit = requestConfig;
@@ -987,7 +1022,8 @@ var Aspi = class {
987
1022
  },
988
1023
  retryConfig: this.#retryConfig,
989
1024
  middlewares: this.#middlewares,
990
- errorCbs: this.#customErrorCbs
1025
+ errorCbs: this.#customErrorCbs,
1026
+ throwOnError: this.#throwOnError
991
1027
  });
992
1028
  }
993
1029
  /**
@@ -1243,6 +1279,21 @@ var Aspi = class {
1243
1279
  internalServerError(cb) {
1244
1280
  return this.error("internalServerErrorError", "INTERNAL_SERVER_ERROR", cb);
1245
1281
  }
1282
+ /**
1283
+ * Sets the aspi to throw an error if the response status is not successful.
1284
+ * @returns The request instance for chaining
1285
+ * @example
1286
+ * const aspi = new Aspi({baseUrl: 'https://example.com'});
1287
+ * const result = await aspi.get('/users')
1288
+ * .withResult()
1289
+ * .throwable()
1290
+ * .json();
1291
+ *
1292
+ */
1293
+ throwable() {
1294
+ this.#throwOnError = true;
1295
+ return this;
1296
+ }
1246
1297
  };
1247
1298
  // Annotate the CommonJS export names for ESM import in node:
1248
1299
  0 && (module.exports = {
@@ -1252,5 +1303,7 @@ var Aspi = class {
1252
1303
  Request,
1253
1304
  Result,
1254
1305
  getHttpErrorStatus,
1255
- httpErrors
1306
+ httpErrors,
1307
+ isAspiError,
1308
+ isCustomError
1256
1309
  });
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.
@@ -412,6 +421,8 @@ var Request = class {
412
421
  } else {
413
422
  this.#localRequestInit.body = JSON.stringify(body);
414
423
  }
424
+ } else {
425
+ this.#localRequestInit.body = JSON.stringify(body);
415
426
  }
416
427
  return this;
417
428
  }
@@ -620,6 +631,22 @@ var Request = class {
620
631
  this.#schema = schema;
621
632
  return this;
622
633
  }
634
+ /**
635
+ * Sets the request to throw an error if the response status is not successful.
636
+ * @returns The request instance for chaining
637
+ * @example
638
+ * const request = new Request('/users', config);
639
+ * const result = await request
640
+ * .withResult()
641
+ * .throwable()
642
+ * .json();
643
+ *
644
+ */
645
+ throwable() {
646
+ this.#shouldBeResult = false;
647
+ this.#throwOnError = true;
648
+ return this;
649
+ }
623
650
  /**
624
651
  * Executes the request and returns the JSON response.
625
652
  * @returns A Promise containing the Result type with either successful data or error information
@@ -627,7 +654,8 @@ var Request = class {
627
654
  * const request = new Request('/users', config);
628
655
  * const result = await request
629
656
  * .setQueryParams({ id: '123' })
630
- * .withResult()
657
+ * .
658
+ withResult()
631
659
  * .notFound((error) => ({ message: 'User not found' }))
632
660
  * .json<User>();
633
661
  *
@@ -726,6 +754,7 @@ var Request = class {
726
754
  * }
727
755
  */
728
756
  withResult() {
757
+ this.#throwOnError = false;
729
758
  this.#shouldBeResult = true;
730
759
  return this;
731
760
  }
@@ -733,6 +762,9 @@ var Request = class {
733
762
  if (this.#shouldBeResult) {
734
763
  return value;
735
764
  }
765
+ if (this.#throwOnError) {
766
+ return getOrThrow(value);
767
+ }
736
768
  if (isOk(value)) {
737
769
  return [getOrNull(value), null];
738
770
  } else {
@@ -910,11 +942,12 @@ var Request = class {
910
942
  };
911
943
 
912
944
  // src/aspi.ts
913
- var Aspi = class {
945
+ var Aspi2 = class {
914
946
  #globalRequestInit;
915
947
  #middlewares = [];
916
948
  #retryConfig;
917
949
  #customErrorCbs = {};
950
+ #throwOnError = false;
918
951
  constructor(config) {
919
952
  const { retryConfig, ...requestConfig } = config;
920
953
  this.#globalRequestInit = requestConfig;
@@ -961,7 +994,8 @@ var Aspi = class {
961
994
  },
962
995
  retryConfig: this.#retryConfig,
963
996
  middlewares: this.#middlewares,
964
- errorCbs: this.#customErrorCbs
997
+ errorCbs: this.#customErrorCbs,
998
+ throwOnError: this.#throwOnError
965
999
  });
966
1000
  }
967
1001
  /**
@@ -1217,13 +1251,30 @@ var Aspi = class {
1217
1251
  internalServerError(cb) {
1218
1252
  return this.error("internalServerErrorError", "INTERNAL_SERVER_ERROR", cb);
1219
1253
  }
1254
+ /**
1255
+ * Sets the aspi to throw an error if the response status is not successful.
1256
+ * @returns The request instance for chaining
1257
+ * @example
1258
+ * const aspi = new Aspi({baseUrl: 'https://example.com'});
1259
+ * const result = await aspi.get('/users')
1260
+ * .withResult()
1261
+ * .throwable()
1262
+ * .json();
1263
+ *
1264
+ */
1265
+ throwable() {
1266
+ this.#throwOnError = true;
1267
+ return this;
1268
+ }
1220
1269
  };
1221
1270
  export {
1222
- Aspi,
1271
+ Aspi2 as Aspi,
1223
1272
  AspiError,
1224
1273
  CustomError,
1225
1274
  Request,
1226
1275
  result_exports as Result,
1227
1276
  getHttpErrorStatus,
1228
- httpErrors
1277
+ httpErrors,
1278
+ isAspiError,
1279
+ isCustomError
1229
1280
  };
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.3.0",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",
7
7
  "devDependencies": {