@@ -8,6 +8,7 @@ export class BadRequestError extends Error {
88 */
99 constructor ( public apiMessage : string ) {
1010 super ( 'Bad request' )
11+ this . name = 'BadRequestError'
1112 }
1213}
1314
@@ -21,6 +22,7 @@ export class NotFoundError extends Error {
2122 */
2223 constructor ( public apiMessage : string ) {
2324 super ( 'Not found' )
25+ this . name = 'NotFoundError'
2426 }
2527}
2628
@@ -34,6 +36,7 @@ export class UnauthorizedError extends Error {
3436 */
3537 constructor ( public apiMessage : string ) {
3638 super ( 'Unauthorized' )
39+ this . name = 'UnauthorizedError'
3740 }
3841}
3942
@@ -48,6 +51,7 @@ export class ConflictError extends Error {
4851 */
4952 constructor ( public apiMessage : string ) {
5053 super ( 'Conflict' )
54+ this . name = 'ConflictError'
5155 }
5256}
5357
@@ -62,5 +66,109 @@ export class UnprocessableEntityError extends Error {
6266 */
6367 constructor ( public apiMessage : string ) {
6468 super ( 'Unprocessable entity' )
69+ this . name = 'UnprocessableEntityError'
6570 }
6671}
72+
73+ /**
74+ * Sanitizes error response data to prevent leaking sensitive information
75+ * while preserving useful error details for debugging
76+ * @param data - error response data
77+ * @returns error as a string
78+ */
79+ export function sanitizeErrorData ( data : unknown ) : string {
80+ if ( ! data ) {
81+ return 'Unknown error'
82+ }
83+
84+ // If it's already a string, check if it looks like sensitive data
85+ if ( typeof data === 'string' ) {
86+ // Remove potential tokens, API keys, passwords, etc.
87+ return data
88+ . replace (
89+ / (?: t o k e n | k e y | p a s s w o r d | s e c r e t | a u t h ) [ ' " : \s ] * [ " ' ] ? [ A - Z a - z 0 - 9 + / = . _ - ] { 10 , } [ " ' ] ? / gi,
90+ '[REDACTED]'
91+ )
92+ . replace ( / B e a r e r \s + [ A - Z a - z 0 - 9 + / = . _ - ] + / gi, 'Bearer [REDACTED]' )
93+ . trim ( )
94+ }
95+
96+ // If it's an object, extract safe error message
97+ if ( typeof data === 'object' && data !== null ) {
98+ const errorObj = data as Record < string , unknown >
99+
100+ // Common error message fields
101+ const messageFields = [
102+ 'message' ,
103+ 'error' ,
104+ 'detail' ,
105+ 'description' ,
106+ 'reason' ,
107+ ]
108+
109+ for ( const field of messageFields ) {
110+ if ( typeof errorObj [ field ] === 'string' ) {
111+ return sanitizeErrorData ( errorObj [ field ] )
112+ }
113+ }
114+
115+ // If no message field found, return sanitized JSON string
116+ try {
117+ const sanitizedObj = sanitizeObject ( errorObj )
118+ return JSON . stringify ( sanitizedObj )
119+ } catch {
120+ return 'Error parsing server response'
121+ }
122+ }
123+
124+ // For other types, convert to string safely
125+ return String ( data ) . replace ( / [ A - Z a - z 0 - 9 + / = . _ - ] { 32 , } / g, '[REDACTED]' )
126+ }
127+
128+ /**
129+ * Recursively sanitizes an object, removing potentially sensitive values
130+ * @param obj - object to sanitize
131+ * @returns sanitized object
132+ */
133+ function sanitizeObject ( obj : Record < string , unknown > ) : Record < string , unknown > {
134+ const sanitized : Record < string , unknown > = { }
135+
136+ for ( const [ key , value ] of Object . entries ( obj ) ) {
137+ // Skip potentially sensitive keys
138+ const sensitiveKeys = [
139+ 'token' ,
140+ 'key' ,
141+ 'password' ,
142+ 'secret' ,
143+ 'auth' ,
144+ 'authorization' ,
145+ 'credential' ,
146+ ]
147+ if (
148+ sensitiveKeys . some ( sensitiveKey =>
149+ key . toLowerCase ( ) . includes ( sensitiveKey )
150+ )
151+ ) {
152+ sanitized [ key ] = '[REDACTED]'
153+ continue
154+ }
155+
156+ if ( typeof value === 'string' ) {
157+ sanitized [ key ] = sanitizeErrorData ( value )
158+ } else if ( typeof value === 'object' && value !== null ) {
159+ if ( Array . isArray ( value ) ) {
160+ sanitized [ key ] = value . map ( item =>
161+ typeof item === 'object' && item !== null
162+ ? sanitizeObject ( item as Record < string , unknown > )
163+ : sanitizeErrorData ( item )
164+ )
165+ } else {
166+ sanitized [ key ] = sanitizeObject ( value as Record < string , unknown > )
167+ }
168+ } else {
169+ sanitized [ key ] = value
170+ }
171+ }
172+
173+ return sanitized
174+ }
0 commit comments