@bombillazo/error-x 0.2.0 → 0.2.2

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.js CHANGED
@@ -20,7 +20,9 @@ var ERROR_X_OPTION_FIELDS = [
20
20
  "uiMessage",
21
21
  "cause",
22
22
  "metadata",
23
- "actions"
23
+ "actions",
24
+ "httpStatus",
25
+ "type"
24
26
  ];
25
27
 
26
28
  // src/error.ts
@@ -36,6 +38,10 @@ var ErrorX = class _ErrorX extends Error {
36
38
  timestamp;
37
39
  /** Error actions for UI behavior and handling */
38
40
  actions;
41
+ /** HTTP status code (100-599) for HTTP-related errors */
42
+ httpStatus;
43
+ /** Error type for categorization */
44
+ type;
39
45
  /**
40
46
  * Creates a new ErrorX instance with enhanced error handling capabilities.
41
47
  *
@@ -92,6 +98,8 @@ var ErrorX = class _ErrorX extends Error {
92
98
  this.uiMessage = options.uiMessage;
93
99
  this.metadata = options.metadata;
94
100
  this.actions = options.actions;
101
+ this.httpStatus = _ErrorX.validateHttpStatus(options.httpStatus);
102
+ this.type = _ErrorX.validateType(options.type);
95
103
  this.timestamp = /* @__PURE__ */ new Date();
96
104
  if (options.cause instanceof Error) {
97
105
  this.stack = _ErrorX.preserveOriginalStack(options.cause, this);
@@ -109,6 +117,38 @@ var ErrorX = class _ErrorX extends Error {
109
117
  static getDefaultName() {
110
118
  return "Error";
111
119
  }
120
+ /**
121
+ * Validates HTTP status code to ensure it's within valid range (100-599)
122
+ *
123
+ * @param status - Status code to validate
124
+ * @returns Valid status code or undefined if invalid/not provided
125
+ */
126
+ static validateHttpStatus(status) {
127
+ if (status === void 0 || status === null) {
128
+ return void 0;
129
+ }
130
+ const statusNum = Number(status);
131
+ if (Number.isNaN(statusNum) || statusNum < 100 || statusNum > 599) {
132
+ return void 0;
133
+ }
134
+ return Math.floor(statusNum);
135
+ }
136
+ /**
137
+ * Validates and normalizes the type field
138
+ *
139
+ * @param type - Type value to validate
140
+ * @returns Validated type string or undefined if invalid/empty
141
+ */
142
+ static validateType(type) {
143
+ if (type === void 0 || type === null) {
144
+ return void 0;
145
+ }
146
+ const typeStr = String(type).trim();
147
+ if (typeStr === "") {
148
+ return void 0;
149
+ }
150
+ return typeStr;
151
+ }
112
152
  /**
113
153
  * Validates if an object is a valid ErrorXOptions object.
114
154
  * Checks that the object only contains accepted ErrorXOptions fields.
@@ -262,7 +302,9 @@ var ErrorX = class _ErrorX extends Error {
262
302
  code: this.code,
263
303
  uiMessage: this.uiMessage,
264
304
  cause: this.cause,
265
- metadata: { ...this.metadata ?? {}, ...additionalMetadata }
305
+ metadata: { ...this.metadata ?? {}, ...additionalMetadata },
306
+ httpStatus: this.httpStatus,
307
+ type: this.type
266
308
  };
267
309
  if (this.actions) {
268
310
  options.actions = this.actions;
@@ -311,6 +353,8 @@ var ErrorX = class _ErrorX extends Error {
311
353
  let cause;
312
354
  let metadata = {};
313
355
  let actions;
356
+ let httpStatus;
357
+ let type;
314
358
  if (error) {
315
359
  if (typeof error === "string") {
316
360
  message = error;
@@ -328,13 +372,29 @@ var ErrorX = class _ErrorX extends Error {
328
372
  else if ("info" in error && error.info) message = String(error.info);
329
373
  else if ("statusText" in error && error.statusText) message = String(error.statusText);
330
374
  else if ("error" in error && error.error) message = String(error.error);
331
- else if ("errorMessage" in error && error.errorMessage) message = String(error.errorMessage);
375
+ else if ("errorMessage" in error && error.errorMessage)
376
+ message = String(error.errorMessage);
332
377
  if ("code" in error && error.code) code = String(error.code);
333
378
  if ("uiMessage" in error && error.uiMessage) uiMessage = String(error.uiMessage);
334
379
  else if ("userMessage" in error && error.userMessage) uiMessage = String(error.userMessage);
335
380
  if ("actions" in error && Array.isArray(error.actions)) {
336
381
  actions = error.actions;
337
382
  }
383
+ let _httpStatus;
384
+ if ("httpStatus" in error) {
385
+ _httpStatus = error.httpStatus;
386
+ } else if ("status" in error) {
387
+ _httpStatus = error.status;
388
+ } else if ("statusCode" in error) {
389
+ _httpStatus = error.statusCode;
390
+ }
391
+ if (_httpStatus !== void 0 && _httpStatus !== null) {
392
+ const num = typeof _httpStatus === "number" ? _httpStatus : Number(_httpStatus);
393
+ httpStatus = _ErrorX.validateHttpStatus(num);
394
+ }
395
+ if ("type" in error && error.type) {
396
+ type = _ErrorX.validateType(String(error.type));
397
+ }
338
398
  metadata = { originalError: error };
339
399
  }
340
400
  }
@@ -347,6 +407,8 @@ var ErrorX = class _ErrorX extends Error {
347
407
  if (cause) options.cause = cause;
348
408
  if (Object.keys(metadata).length > 0) options.metadata = metadata;
349
409
  if (actions && actions.length > 0) options.actions = actions;
410
+ if (httpStatus) options.httpStatus = httpStatus;
411
+ if (type) options.type = type;
350
412
  return options;
351
413
  }
352
414
  /**
@@ -417,7 +479,9 @@ var ErrorX = class _ErrorX extends Error {
417
479
  name: this.name,
418
480
  code: this.code,
419
481
  uiMessage: this.uiMessage,
420
- cause: this.cause
482
+ cause: this.cause,
483
+ httpStatus: this.httpStatus,
484
+ type: this.type
421
485
  };
422
486
  if (this.metadata !== void 0) {
423
487
  options.metadata = this.metadata;
@@ -500,6 +564,12 @@ ${this.stack}`;
500
564
  const stringified = safeStringify(this.actions);
501
565
  serialized.actions = JSON.parse(stringified);
502
566
  }
567
+ if (this.httpStatus !== void 0) {
568
+ serialized.httpStatus = this.httpStatus;
569
+ }
570
+ if (this.type !== void 0) {
571
+ serialized.type = this.type;
572
+ }
503
573
  if (this.stack) {
504
574
  serialized.stack = this.stack;
505
575
  }
@@ -550,7 +620,9 @@ ${this.stack}`;
550
620
  message: serialized.message,
551
621
  name: serialized.name,
552
622
  code: serialized.code,
553
- uiMessage: serialized.uiMessage
623
+ uiMessage: serialized.uiMessage,
624
+ httpStatus: serialized.httpStatus,
625
+ type: serialized.type
554
626
  };
555
627
  if (serialized.metadata !== void 0) {
556
628
  options.metadata = serialized.metadata;
@@ -576,6 +648,330 @@ ${this.stack}`;
576
648
  }
577
649
  };
578
650
 
579
- export { ErrorX, HandlingTargets };
651
+ // src/presets.ts
652
+ var PRESETS = {
653
+ /**
654
+ * HTTP error presets for common HTTP status codes.
655
+ * Includes both 4xx client errors and 5xx server errors.
656
+ */
657
+ HTTP: {
658
+ // 4xx Client Errors
659
+ BAD_REQUEST: {
660
+ httpStatus: 400,
661
+ code: "BAD_REQUEST",
662
+ name: "BadRequestError",
663
+ message: "Bad request",
664
+ uiMessage: "The request could not be processed. Please check your input and try again.",
665
+ type: "http"
666
+ },
667
+ UNAUTHORIZED: {
668
+ httpStatus: 401,
669
+ code: "UNAUTHORIZED",
670
+ name: "UnauthorizedError",
671
+ message: "Unauthorized",
672
+ uiMessage: "Authentication required. Please log in to continue.",
673
+ type: "http"
674
+ },
675
+ PAYMENT_REQUIRED: {
676
+ httpStatus: 402,
677
+ code: "PAYMENT_REQUIRED",
678
+ name: "PaymentRequiredError",
679
+ message: "Payment required",
680
+ uiMessage: "Payment is required to access this resource.",
681
+ type: "http"
682
+ },
683
+ FORBIDDEN: {
684
+ httpStatus: 403,
685
+ code: "FORBIDDEN",
686
+ name: "ForbiddenError",
687
+ message: "Forbidden",
688
+ uiMessage: "You do not have permission to access this resource.",
689
+ type: "http"
690
+ },
691
+ NOT_FOUND: {
692
+ httpStatus: 404,
693
+ code: "NOT_FOUND",
694
+ name: "NotFoundError",
695
+ message: "Not found",
696
+ uiMessage: "The requested resource could not be found.",
697
+ type: "http"
698
+ },
699
+ METHOD_NOT_ALLOWED: {
700
+ httpStatus: 405,
701
+ code: "METHOD_NOT_ALLOWED",
702
+ name: "MethodNotAllowedError",
703
+ message: "Method not allowed",
704
+ uiMessage: "This action is not allowed for the requested resource.",
705
+ type: "http"
706
+ },
707
+ NOT_ACCEPTABLE: {
708
+ httpStatus: 406,
709
+ code: "NOT_ACCEPTABLE",
710
+ name: "NotAcceptableError",
711
+ message: "Not acceptable",
712
+ uiMessage: "The requested format is not supported.",
713
+ type: "http"
714
+ },
715
+ PROXY_AUTHENTICATION_REQUIRED: {
716
+ httpStatus: 407,
717
+ code: "PROXY_AUTHENTICATION_REQUIRED",
718
+ name: "ProxyAuthenticationRequiredError",
719
+ message: "Proxy authentication required",
720
+ uiMessage: "Proxy authentication is required to access this resource.",
721
+ type: "http"
722
+ },
723
+ REQUEST_TIMEOUT: {
724
+ httpStatus: 408,
725
+ code: "REQUEST_TIMEOUT",
726
+ name: "RequestTimeoutError",
727
+ message: "Request timeout",
728
+ uiMessage: "The request took too long to complete. Please try again.",
729
+ type: "http"
730
+ },
731
+ CONFLICT: {
732
+ httpStatus: 409,
733
+ code: "CONFLICT",
734
+ name: "ConflictError",
735
+ message: "Conflict",
736
+ uiMessage: "The request conflicts with the current state. Please refresh and try again.",
737
+ type: "http"
738
+ },
739
+ GONE: {
740
+ httpStatus: 410,
741
+ code: "GONE",
742
+ name: "GoneError",
743
+ message: "Gone",
744
+ uiMessage: "This resource is no longer available.",
745
+ type: "http"
746
+ },
747
+ LENGTH_REQUIRED: {
748
+ httpStatus: 411,
749
+ code: "LENGTH_REQUIRED",
750
+ name: "LengthRequiredError",
751
+ message: "Length required",
752
+ uiMessage: "The request is missing required length information.",
753
+ type: "http"
754
+ },
755
+ PRECONDITION_FAILED: {
756
+ httpStatus: 412,
757
+ code: "PRECONDITION_FAILED",
758
+ name: "PreconditionFailedError",
759
+ message: "Precondition failed",
760
+ uiMessage: "A required condition was not met. Please try again.",
761
+ type: "http"
762
+ },
763
+ PAYLOAD_TOO_LARGE: {
764
+ httpStatus: 413,
765
+ code: "PAYLOAD_TOO_LARGE",
766
+ name: "PayloadTooLargeError",
767
+ message: "Payload too large",
768
+ uiMessage: "The request is too large. Please reduce the size and try again.",
769
+ type: "http"
770
+ },
771
+ URI_TOO_LONG: {
772
+ httpStatus: 414,
773
+ code: "URI_TOO_LONG",
774
+ name: "URITooLongError",
775
+ message: "URI too long",
776
+ uiMessage: "The request URL is too long.",
777
+ type: "http"
778
+ },
779
+ UNSUPPORTED_MEDIA_TYPE: {
780
+ httpStatus: 415,
781
+ code: "UNSUPPORTED_MEDIA_TYPE",
782
+ name: "UnsupportedMediaTypeError",
783
+ message: "Unsupported media type",
784
+ uiMessage: "The file type is not supported.",
785
+ type: "http"
786
+ },
787
+ RANGE_NOT_SATISFIABLE: {
788
+ httpStatus: 416,
789
+ code: "RANGE_NOT_SATISFIABLE",
790
+ name: "RangeNotSatisfiableError",
791
+ message: "Range not satisfiable",
792
+ uiMessage: "The requested range cannot be satisfied.",
793
+ type: "http"
794
+ },
795
+ EXPECTATION_FAILED: {
796
+ httpStatus: 417,
797
+ code: "EXPECTATION_FAILED",
798
+ name: "ExpectationFailedError",
799
+ message: "Expectation failed",
800
+ uiMessage: "The server cannot meet the requirements of the request.",
801
+ type: "http"
802
+ },
803
+ IM_A_TEAPOT: {
804
+ httpStatus: 418,
805
+ code: "IM_A_TEAPOT",
806
+ name: "ImATeapotError",
807
+ message: "I'm a teapot",
808
+ uiMessage: "I'm a teapot and cannot brew coffee.",
809
+ type: "http"
810
+ },
811
+ UNPROCESSABLE_ENTITY: {
812
+ httpStatus: 422,
813
+ code: "UNPROCESSABLE_ENTITY",
814
+ name: "UnprocessableEntityError",
815
+ message: "Unprocessable entity",
816
+ uiMessage: "The request contains invalid data. Please check your input.",
817
+ type: "http"
818
+ },
819
+ LOCKED: {
820
+ httpStatus: 423,
821
+ code: "LOCKED",
822
+ name: "LockedError",
823
+ message: "Locked",
824
+ uiMessage: "This resource is locked and cannot be modified.",
825
+ type: "http"
826
+ },
827
+ FAILED_DEPENDENCY: {
828
+ httpStatus: 424,
829
+ code: "FAILED_DEPENDENCY",
830
+ name: "FailedDependencyError",
831
+ message: "Failed dependency",
832
+ uiMessage: "The request failed due to a dependency error.",
833
+ type: "http"
834
+ },
835
+ TOO_EARLY: {
836
+ httpStatus: 425,
837
+ code: "TOO_EARLY",
838
+ name: "TooEarlyError",
839
+ message: "Too early",
840
+ uiMessage: "The request was sent too early. Please try again later.",
841
+ type: "http"
842
+ },
843
+ UPGRADE_REQUIRED: {
844
+ httpStatus: 426,
845
+ code: "UPGRADE_REQUIRED",
846
+ name: "UpgradeRequiredError",
847
+ message: "Upgrade required",
848
+ uiMessage: "Please upgrade to continue using this service.",
849
+ type: "http"
850
+ },
851
+ PRECONDITION_REQUIRED: {
852
+ httpStatus: 428,
853
+ code: "PRECONDITION_REQUIRED",
854
+ name: "PreconditionRequiredError",
855
+ message: "Precondition required",
856
+ uiMessage: "Required conditions are missing from the request.",
857
+ type: "http"
858
+ },
859
+ TOO_MANY_REQUESTS: {
860
+ httpStatus: 429,
861
+ code: "TOO_MANY_REQUESTS",
862
+ name: "TooManyRequestsError",
863
+ message: "Too many requests",
864
+ uiMessage: "You have made too many requests. Please wait and try again.",
865
+ type: "http"
866
+ },
867
+ REQUEST_HEADER_FIELDS_TOO_LARGE: {
868
+ httpStatus: 431,
869
+ code: "REQUEST_HEADER_FIELDS_TOO_LARGE",
870
+ name: "RequestHeaderFieldsTooLargeError",
871
+ message: "Request header fields too large",
872
+ uiMessage: "The request headers are too large.",
873
+ type: "http"
874
+ },
875
+ UNAVAILABLE_FOR_LEGAL_REASONS: {
876
+ httpStatus: 451,
877
+ code: "UNAVAILABLE_FOR_LEGAL_REASONS",
878
+ name: "UnavailableForLegalReasonsError",
879
+ message: "Unavailable for legal reasons",
880
+ uiMessage: "This content is unavailable for legal reasons.",
881
+ type: "http"
882
+ },
883
+ // 5xx Server Errors
884
+ INTERNAL_SERVER_ERROR: {
885
+ httpStatus: 500,
886
+ code: "INTERNAL_SERVER_ERROR",
887
+ name: "InternalServerError",
888
+ message: "Internal server error",
889
+ uiMessage: "An unexpected error occurred. Please try again later.",
890
+ type: "http"
891
+ },
892
+ NOT_IMPLEMENTED: {
893
+ httpStatus: 501,
894
+ code: "NOT_IMPLEMENTED",
895
+ name: "NotImplementedError",
896
+ message: "Not implemented",
897
+ uiMessage: "This feature is not yet available.",
898
+ type: "http"
899
+ },
900
+ BAD_GATEWAY: {
901
+ httpStatus: 502,
902
+ code: "BAD_GATEWAY",
903
+ name: "BadGatewayError",
904
+ message: "Bad gateway",
905
+ uiMessage: "Unable to connect to the server. Please try again later.",
906
+ type: "http"
907
+ },
908
+ SERVICE_UNAVAILABLE: {
909
+ httpStatus: 503,
910
+ code: "SERVICE_UNAVAILABLE",
911
+ name: "ServiceUnavailableError",
912
+ message: "Service unavailable",
913
+ uiMessage: "The service is temporarily unavailable. Please try again later.",
914
+ type: "http"
915
+ },
916
+ GATEWAY_TIMEOUT: {
917
+ httpStatus: 504,
918
+ code: "GATEWAY_TIMEOUT",
919
+ name: "GatewayTimeoutError",
920
+ message: "Gateway timeout",
921
+ uiMessage: "The server took too long to respond. Please try again.",
922
+ type: "http"
923
+ },
924
+ HTTP_VERSION_NOT_SUPPORTED: {
925
+ httpStatus: 505,
926
+ code: "HTTP_VERSION_NOT_SUPPORTED",
927
+ name: "HTTPVersionNotSupportedError",
928
+ message: "HTTP version not supported",
929
+ uiMessage: "Your browser version is not supported.",
930
+ type: "http"
931
+ },
932
+ VARIANT_ALSO_NEGOTIATES: {
933
+ httpStatus: 506,
934
+ code: "VARIANT_ALSO_NEGOTIATES",
935
+ name: "VariantAlsoNegotiatesError",
936
+ message: "Variant also negotiates",
937
+ uiMessage: "The server has an internal configuration error.",
938
+ type: "http"
939
+ },
940
+ INSUFFICIENT_STORAGE: {
941
+ httpStatus: 507,
942
+ code: "INSUFFICIENT_STORAGE",
943
+ name: "InsufficientStorageError",
944
+ message: "Insufficient storage",
945
+ uiMessage: "The server has insufficient storage to complete the request.",
946
+ type: "http"
947
+ },
948
+ LOOP_DETECTED: {
949
+ httpStatus: 508,
950
+ code: "LOOP_DETECTED",
951
+ name: "LoopDetectedError",
952
+ message: "Loop detected",
953
+ uiMessage: "The server detected an infinite loop.",
954
+ type: "http"
955
+ },
956
+ NOT_EXTENDED: {
957
+ httpStatus: 510,
958
+ code: "NOT_EXTENDED",
959
+ name: "NotExtendedError",
960
+ message: "Not extended",
961
+ uiMessage: "Additional extensions are required.",
962
+ type: "http"
963
+ },
964
+ NETWORK_AUTHENTICATION_REQUIRED: {
965
+ httpStatus: 511,
966
+ code: "NETWORK_AUTHENTICATION_REQUIRED",
967
+ name: "NetworkAuthenticationRequiredError",
968
+ message: "Network authentication required",
969
+ uiMessage: "Network authentication is required to access this resource.",
970
+ type: "http"
971
+ }
972
+ }
973
+ };
974
+
975
+ export { ErrorX, HandlingTargets, PRESETS };
580
976
  //# sourceMappingURL=index.js.map
581
977
  //# sourceMappingURL=index.js.map