@@ -16,6 +16,9 @@ export type ErrorObject = {
1616 name : string
1717 message : string
1818 stack ?: string
19+ code : string
20+ status ?: number
21+ originalError ?: unknown
1922}
2023
2124export function success < T > ( value : T ) : Success < T > {
@@ -26,85 +29,52 @@ export function success<T>(value: T): Success<T> {
2629}
2730
2831export function failure ( error : any ) : Failure < ErrorObject > {
32+ if ( error instanceof Error ) {
33+ const base = getErrorObject ( error )
34+
35+ // Safely extract code, status, and originalError if present
36+ const errorWithMetadata = error as Error & {
37+ code ?: string
38+ status ?: number
39+ originalError ?: unknown
40+ }
41+
42+ return {
43+ success : false ,
44+ error : {
45+ ...base ,
46+ code : typeof errorWithMetadata . code === 'string' ? errorWithMetadata . code : 'UNKNOWN_ERROR' ,
47+ ...( typeof errorWithMetadata . status === 'number' && { status : errorWithMetadata . status } ) ,
48+ ...( 'originalError' in errorWithMetadata && { originalError : errorWithMetadata . originalError } ) ,
49+ } ,
50+ }
51+ }
52+
2953 return {
3054 success : false ,
31- error : getErrorObject ( error ) ,
55+ error : {
56+ ...getErrorObject ( error ) ,
57+ code : 'UNKNOWN_ERROR' ,
58+ } ,
3259 }
3360}
3461
3562export function getErrorObject ( error : any ) : ErrorObject {
3663 if ( error instanceof Error ) {
64+ const errorWithCode = error as Error & { code ?: string }
3765 return {
3866 name : error . name ,
3967 message : error . message ,
4068 stack : error . stack ,
69+ code : typeof errorWithCode . code === 'string' ? errorWithCode . code : 'UNKNOWN_ERROR' ,
4170 }
4271 }
4372
4473 return {
4574 name : 'Error' ,
4675 message : `${ error } ` ,
76+ code : 'UNKNOWN_ERROR' ,
4777 }
4878}
4979
50- /**
51- * Extended error object that can preserve additional metadata like code, status, and originalError
52- * from Error instances (e.g., NetworkError, AuthenticationError).
53- */
54- export type ExtendedErrorObject = ErrorObject & {
55- code ?: string
56- status ?: number
57- originalError ?: unknown
58- }
59-
60- /**
61- * Wrap an unknown error into a Failure<ExtendedErrorObject>, preserving `code`, `status`, and `originalError`
62- * when present on Error instances.
63- *
64- * This is useful for converting thrown errors into ErrorOr results while maintaining error metadata.
65- *
66- * @example
67- * ```typescript
68- * try {
69- * await somethingThatMightThrow()
70- * return success(result)
71- * } catch (error) {
72- * return failureWithCode(error)
73- * }
74- * ```
75- */
76- export function failureWithCode ( error : unknown ) : Failure < ExtendedErrorObject > {
77- if ( error instanceof Error ) {
78- const base = getErrorObject ( error )
79- const enriched : ExtendedErrorObject = {
80- ...base ,
81- }
82-
83- // Safely extract code, status, and originalError if present
84- const errorWithMetadata = error as Error & {
85- code ?: string
86- status ?: number
87- originalError ?: unknown
88- }
89-
90- if ( typeof errorWithMetadata . code === 'string' ) {
91- enriched . code = errorWithMetadata . code
92- }
9380
94- if ( typeof errorWithMetadata . status === 'number' ) {
95- enriched . status = errorWithMetadata . status
96- }
97-
98- if ( 'originalError' in errorWithMetadata ) {
99- enriched . originalError = errorWithMetadata . originalError
100- }
101-
102- return {
103- success : false ,
104- error : enriched ,
105- }
106- }
107-
108- // Fallback to base failure, which will still give us an ErrorObject
109- return failure ( error )
110- }
0 commit comments