@bombillazo/error-x 0.1.1 → 0.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.d.cts CHANGED
@@ -167,6 +167,29 @@ type ErrorAction = NotifyAction | LogoutAction | RedirectAction | CustomAction;
167
167
  * Configuration options for creating an ErrorX instance.
168
168
  * All properties are optional with sensible defaults.
169
169
  *
170
+ * @remarks
171
+ * **Note on design:** ErrorXOptions is a `type` instead of a `class` to provide maximum flexibility.
172
+ * This allows you to pass plain objects without instantiation:
173
+ *
174
+ * ```typescript
175
+ * // ✅ Works - plain object
176
+ * new ErrorX({ message: 'Error', code: 'ERR' })
177
+ *
178
+ * // ✅ Works - object literal
179
+ * const opts = { message: 'Error' }
180
+ * new ErrorX(opts)
181
+ * ```
182
+ *
183
+ * If ErrorXOptions were a class, you would need to instantiate it:
184
+ *
185
+ * ```typescript
186
+ * // ❌ Would be required with class
187
+ * new ErrorX(new ErrorXOptions({ message: 'Error' }))
188
+ * ```
189
+ *
190
+ * The current `type` approach provides better ergonomics while still maintaining type safety.
191
+ * The `isErrorXOptions()` validation method ensures only valid option objects are accepted.
192
+ *
170
193
  * @public
171
194
  */
172
195
  type ErrorXOptions = {
@@ -184,6 +207,10 @@ type ErrorXOptions = {
184
207
  metadata?: ErrorMetadata;
185
208
  /** Actions to perform when this error occurs (default: undefined) */
186
209
  actions?: ErrorAction[];
210
+ /** HTTP status code (100-599) for HTTP-related errors (default: undefined) */
211
+ httpStatus?: number | undefined;
212
+ /** Error type for categorization */
213
+ type?: string | undefined;
187
214
  };
188
215
  /**
189
216
  * JSON-serializable representation of an ErrorX instance.
@@ -232,6 +259,10 @@ type SerializableError = {
232
259
  actions?: ErrorAction[];
233
260
  /** Serialized cause error (for error chaining) */
234
261
  cause?: SerializableError;
262
+ /** HTTP status code for HTTP-related errors */
263
+ httpStatus?: number;
264
+ /** Error type for categorization */
265
+ type?: string;
235
266
  };
236
267
 
237
268
  /**
@@ -265,52 +296,75 @@ declare class ErrorX extends Error {
265
296
  readonly timestamp: Date;
266
297
  /** Error actions for UI behavior and handling */
267
298
  readonly actions: ErrorAction[] | undefined;
299
+ /** HTTP status code (100-599) for HTTP-related errors */
300
+ readonly httpStatus: number | undefined;
301
+ /** Error type for categorization */
302
+ readonly type: string | undefined;
268
303
  /**
269
304
  * Creates a new ErrorX instance with enhanced error handling capabilities.
270
305
  *
271
- * @param options - Configuration options for the error (optional)
272
- * @param options.message - Technical error message (defaults to 'An error occurred')
273
- * @param options.name - Error type/name (defaults to 'Error')
274
- * @param options.code - Error identifier code (auto-generated from name if not provided)
275
- * @param options.uiMessage - User-friendly message (defaults to undefined)
276
- * @param options.cause - Original error that caused this error
277
- * @param options.metadata - Additional context data (defaults to undefined)
278
- * @param options.actions - Error actions for UI behavior and handling (defaults to undefined)
306
+ * @param messageOrOptions - Error message string, ErrorXOptions object, or any value to convert to ErrorX
307
+ * @param additionalOptions - Additional options when first parameter is a string (optional)
279
308
  *
280
309
  * @example
281
310
  * ```typescript
282
- * // Create with full options
283
- * const error = new ErrorX({
284
- * message: 'Database query failed',
311
+ * // Create with string message only
312
+ * const error1 = new ErrorX('Database query failed')
313
+ *
314
+ * // Create with string message and additional options
315
+ * const error2 = new ErrorX('Database query failed', {
285
316
  * name: 'DatabaseError',
286
317
  * code: 'DB_QUERY_FAILED',
287
318
  * uiMessage: 'Unable to load data. Please try again.',
288
- * metadata: { query: 'SELECT * FROM users', timeout: 5000 },
319
+ * metadata: { query: 'SELECT * FROM users', timeout: 5000 }
320
+ * })
321
+ *
322
+ * // Create with options object (backward compatible)
323
+ * const error3 = new ErrorX({
324
+ * message: 'Database query failed',
325
+ * name: 'DatabaseError',
326
+ * code: 'DB_QUERY_FAILED',
289
327
  * actions: [
290
- * {
291
- * action: 'notify',
292
- * payload: { targets: [HandlingTargets.TOAST] }
293
- * },
294
- * {
295
- * action: 'redirect',
296
- * payload: { redirectURL: '/dashboard', delay: 1000 }
297
- * }
328
+ * { action: 'notify', payload: { targets: [HandlingTargets.TOAST] } }
298
329
  * ]
299
330
  * })
300
331
  *
301
- * // Create with minimal options
302
- * const simpleError = new ErrorX({ message: 'Something failed' })
332
+ * // Create with unknown input (smart conversion)
333
+ * const apiError = { message: 'User not found', code: 404 }
334
+ * const error4 = new ErrorX(apiError)
303
335
  *
304
336
  * // Create with no options (uses defaults)
305
- * const defaultError = new ErrorX()
337
+ * const error5 = new ErrorX()
306
338
  * ```
307
339
  */
308
- constructor(options?: ErrorXOptions);
340
+ constructor(messageOrOptions?: string | ErrorXOptions | unknown, additionalOptions?: Partial<ErrorXOptions>);
309
341
  /**
310
342
  * Returns the default error name.
311
343
  * @returns Default error name 'Error'
312
344
  */
313
345
  private static getDefaultName;
346
+ /**
347
+ * Validates HTTP status code to ensure it's within valid range (100-599)
348
+ *
349
+ * @param status - Status code to validate
350
+ * @returns Valid status code or undefined if invalid/not provided
351
+ */
352
+ private static validateHttpStatus;
353
+ /**
354
+ * Validates and normalizes the type field
355
+ *
356
+ * @param type - Type value to validate
357
+ * @returns Validated type string or undefined if invalid/empty
358
+ */
359
+ private static validateType;
360
+ /**
361
+ * Validates if an object is a valid ErrorXOptions object.
362
+ * Checks that the object only contains accepted ErrorXOptions fields.
363
+ *
364
+ * @param value - Value to check
365
+ * @returns True if value is a valid ErrorXOptions object
366
+ */
367
+ static isErrorXOptions(value: unknown): value is ErrorXOptions;
314
368
  /**
315
369
  * Generates a default error code from the error name.
316
370
  * Converts camelCase/PascalCase names to UPPER_SNAKE_CASE format.
@@ -414,6 +468,16 @@ declare class ErrorX extends Error {
414
468
  * ```
415
469
  */
416
470
  static isErrorX(value: unknown): value is ErrorX;
471
+ /**
472
+ * Converts unknown input into ErrorXOptions with intelligent property extraction.
473
+ * Handles strings, regular Error objects, API response objects, and unknown values.
474
+ * This is a private helper method used by both the constructor and toErrorX.
475
+ *
476
+ * @param error - Value to convert to ErrorXOptions
477
+ * @returns ErrorXOptions object with extracted properties
478
+ * @internal
479
+ */
480
+ private static convertUnknownToOptions;
417
481
  /**
418
482
  * Converts unknown input into an ErrorX instance with intelligent property extraction.
419
483
  * Handles strings, regular Error objects, API response objects, and unknown values.
@@ -534,4 +598,352 @@ declare class ErrorX extends Error {
534
598
  static fromJSON(serialized: SerializableError): ErrorX;
535
599
  }
536
600
 
537
- export { type CustomAction, type ErrorAction, type ErrorMetadata, ErrorX, type ErrorXOptions, type HandlingTarget, HandlingTargets, type LogoutAction, type NotifyAction, type RedirectAction, type SerializableError };
601
+ /**
602
+ * Preset configurations for common errors organized by category.
603
+ * Each preset includes httpStatus (for HTTP errors), code, name, message, and uiMessage.
604
+ *
605
+ * @example
606
+ * ```typescript
607
+ * import { ErrorX, ErrorPresets } from '@bombillazo/error-x'
608
+ *
609
+ * // Use preset directly
610
+ * const error = new ErrorX(ErrorPresets.HTTP.NOT_FOUND)
611
+ *
612
+ * // Override preset values
613
+ * const error = new ErrorX({
614
+ * ...ErrorPresets.HTTP.NOT_FOUND,
615
+ * message: 'User not found',
616
+ * metadata: { userId: 123 }
617
+ * })
618
+ *
619
+ * // Use with additional options
620
+ * const error = new ErrorX({
621
+ * ...ErrorPresets.HTTP.UNAUTHORIZED,
622
+ * actions: [{ action: 'redirect', payload: { redirectURL: '/login' } }]
623
+ * })
624
+ * ```
625
+ *
626
+ * @public
627
+ */
628
+ declare const PRESETS: {
629
+ /**
630
+ * HTTP error presets for common HTTP status codes.
631
+ * Includes both 4xx client errors and 5xx server errors.
632
+ */
633
+ readonly HTTP: {
634
+ readonly BAD_REQUEST: {
635
+ httpStatus: number;
636
+ code: string;
637
+ name: string;
638
+ message: string;
639
+ uiMessage: string;
640
+ type: string;
641
+ };
642
+ readonly UNAUTHORIZED: {
643
+ httpStatus: number;
644
+ code: string;
645
+ name: string;
646
+ message: string;
647
+ uiMessage: string;
648
+ type: string;
649
+ };
650
+ readonly PAYMENT_REQUIRED: {
651
+ httpStatus: number;
652
+ code: string;
653
+ name: string;
654
+ message: string;
655
+ uiMessage: string;
656
+ type: string;
657
+ };
658
+ readonly FORBIDDEN: {
659
+ httpStatus: number;
660
+ code: string;
661
+ name: string;
662
+ message: string;
663
+ uiMessage: string;
664
+ type: string;
665
+ };
666
+ readonly NOT_FOUND: {
667
+ httpStatus: number;
668
+ code: string;
669
+ name: string;
670
+ message: string;
671
+ uiMessage: string;
672
+ type: string;
673
+ };
674
+ readonly METHOD_NOT_ALLOWED: {
675
+ httpStatus: number;
676
+ code: string;
677
+ name: string;
678
+ message: string;
679
+ uiMessage: string;
680
+ type: string;
681
+ };
682
+ readonly NOT_ACCEPTABLE: {
683
+ httpStatus: number;
684
+ code: string;
685
+ name: string;
686
+ message: string;
687
+ uiMessage: string;
688
+ type: string;
689
+ };
690
+ readonly PROXY_AUTHENTICATION_REQUIRED: {
691
+ httpStatus: number;
692
+ code: string;
693
+ name: string;
694
+ message: string;
695
+ uiMessage: string;
696
+ type: string;
697
+ };
698
+ readonly REQUEST_TIMEOUT: {
699
+ httpStatus: number;
700
+ code: string;
701
+ name: string;
702
+ message: string;
703
+ uiMessage: string;
704
+ type: string;
705
+ };
706
+ readonly CONFLICT: {
707
+ httpStatus: number;
708
+ code: string;
709
+ name: string;
710
+ message: string;
711
+ uiMessage: string;
712
+ type: string;
713
+ };
714
+ readonly GONE: {
715
+ httpStatus: number;
716
+ code: string;
717
+ name: string;
718
+ message: string;
719
+ uiMessage: string;
720
+ type: string;
721
+ };
722
+ readonly LENGTH_REQUIRED: {
723
+ httpStatus: number;
724
+ code: string;
725
+ name: string;
726
+ message: string;
727
+ uiMessage: string;
728
+ type: string;
729
+ };
730
+ readonly PRECONDITION_FAILED: {
731
+ httpStatus: number;
732
+ code: string;
733
+ name: string;
734
+ message: string;
735
+ uiMessage: string;
736
+ type: string;
737
+ };
738
+ readonly PAYLOAD_TOO_LARGE: {
739
+ httpStatus: number;
740
+ code: string;
741
+ name: string;
742
+ message: string;
743
+ uiMessage: string;
744
+ type: string;
745
+ };
746
+ readonly URI_TOO_LONG: {
747
+ httpStatus: number;
748
+ code: string;
749
+ name: string;
750
+ message: string;
751
+ uiMessage: string;
752
+ type: string;
753
+ };
754
+ readonly UNSUPPORTED_MEDIA_TYPE: {
755
+ httpStatus: number;
756
+ code: string;
757
+ name: string;
758
+ message: string;
759
+ uiMessage: string;
760
+ type: string;
761
+ };
762
+ readonly RANGE_NOT_SATISFIABLE: {
763
+ httpStatus: number;
764
+ code: string;
765
+ name: string;
766
+ message: string;
767
+ uiMessage: string;
768
+ type: string;
769
+ };
770
+ readonly EXPECTATION_FAILED: {
771
+ httpStatus: number;
772
+ code: string;
773
+ name: string;
774
+ message: string;
775
+ uiMessage: string;
776
+ type: string;
777
+ };
778
+ readonly IM_A_TEAPOT: {
779
+ httpStatus: number;
780
+ code: string;
781
+ name: string;
782
+ message: string;
783
+ uiMessage: string;
784
+ type: string;
785
+ };
786
+ readonly UNPROCESSABLE_ENTITY: {
787
+ httpStatus: number;
788
+ code: string;
789
+ name: string;
790
+ message: string;
791
+ uiMessage: string;
792
+ type: string;
793
+ };
794
+ readonly LOCKED: {
795
+ httpStatus: number;
796
+ code: string;
797
+ name: string;
798
+ message: string;
799
+ uiMessage: string;
800
+ type: string;
801
+ };
802
+ readonly FAILED_DEPENDENCY: {
803
+ httpStatus: number;
804
+ code: string;
805
+ name: string;
806
+ message: string;
807
+ uiMessage: string;
808
+ type: string;
809
+ };
810
+ readonly TOO_EARLY: {
811
+ httpStatus: number;
812
+ code: string;
813
+ name: string;
814
+ message: string;
815
+ uiMessage: string;
816
+ type: string;
817
+ };
818
+ readonly UPGRADE_REQUIRED: {
819
+ httpStatus: number;
820
+ code: string;
821
+ name: string;
822
+ message: string;
823
+ uiMessage: string;
824
+ type: string;
825
+ };
826
+ readonly PRECONDITION_REQUIRED: {
827
+ httpStatus: number;
828
+ code: string;
829
+ name: string;
830
+ message: string;
831
+ uiMessage: string;
832
+ type: string;
833
+ };
834
+ readonly TOO_MANY_REQUESTS: {
835
+ httpStatus: number;
836
+ code: string;
837
+ name: string;
838
+ message: string;
839
+ uiMessage: string;
840
+ type: string;
841
+ };
842
+ readonly REQUEST_HEADER_FIELDS_TOO_LARGE: {
843
+ httpStatus: number;
844
+ code: string;
845
+ name: string;
846
+ message: string;
847
+ uiMessage: string;
848
+ type: string;
849
+ };
850
+ readonly UNAVAILABLE_FOR_LEGAL_REASONS: {
851
+ httpStatus: number;
852
+ code: string;
853
+ name: string;
854
+ message: string;
855
+ uiMessage: string;
856
+ type: string;
857
+ };
858
+ readonly INTERNAL_SERVER_ERROR: {
859
+ httpStatus: number;
860
+ code: string;
861
+ name: string;
862
+ message: string;
863
+ uiMessage: string;
864
+ type: string;
865
+ };
866
+ readonly NOT_IMPLEMENTED: {
867
+ httpStatus: number;
868
+ code: string;
869
+ name: string;
870
+ message: string;
871
+ uiMessage: string;
872
+ type: string;
873
+ };
874
+ readonly BAD_GATEWAY: {
875
+ httpStatus: number;
876
+ code: string;
877
+ name: string;
878
+ message: string;
879
+ uiMessage: string;
880
+ type: string;
881
+ };
882
+ readonly SERVICE_UNAVAILABLE: {
883
+ httpStatus: number;
884
+ code: string;
885
+ name: string;
886
+ message: string;
887
+ uiMessage: string;
888
+ type: string;
889
+ };
890
+ readonly GATEWAY_TIMEOUT: {
891
+ httpStatus: number;
892
+ code: string;
893
+ name: string;
894
+ message: string;
895
+ uiMessage: string;
896
+ type: string;
897
+ };
898
+ readonly HTTP_VERSION_NOT_SUPPORTED: {
899
+ httpStatus: number;
900
+ code: string;
901
+ name: string;
902
+ message: string;
903
+ uiMessage: string;
904
+ type: string;
905
+ };
906
+ readonly VARIANT_ALSO_NEGOTIATES: {
907
+ httpStatus: number;
908
+ code: string;
909
+ name: string;
910
+ message: string;
911
+ uiMessage: string;
912
+ type: string;
913
+ };
914
+ readonly INSUFFICIENT_STORAGE: {
915
+ httpStatus: number;
916
+ code: string;
917
+ name: string;
918
+ message: string;
919
+ uiMessage: string;
920
+ type: string;
921
+ };
922
+ readonly LOOP_DETECTED: {
923
+ httpStatus: number;
924
+ code: string;
925
+ name: string;
926
+ message: string;
927
+ uiMessage: string;
928
+ type: string;
929
+ };
930
+ readonly NOT_EXTENDED: {
931
+ httpStatus: number;
932
+ code: string;
933
+ name: string;
934
+ message: string;
935
+ uiMessage: string;
936
+ type: string;
937
+ };
938
+ readonly NETWORK_AUTHENTICATION_REQUIRED: {
939
+ httpStatus: number;
940
+ code: string;
941
+ name: string;
942
+ message: string;
943
+ uiMessage: string;
944
+ type: string;
945
+ };
946
+ };
947
+ };
948
+
949
+ export { type CustomAction, type ErrorAction, type ErrorMetadata, ErrorX, type ErrorXOptions, type HandlingTarget, HandlingTargets, type LogoutAction, type NotifyAction, PRESETS, type RedirectAction, type SerializableError };