core-services-sdk 1.3.35 → 1.3.37
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/package.json +1 -1
- package/src/fastify/error-codes.js +2 -4
- package/src/fastify/error-handlers/with-error-handling.js +5 -6
- package/src/http/HttpError.js +10 -29
- package/src/http/http.js +2 -3
- package/src/rabbit-mq/rabbit-mq.js +42 -8
- package/tests/fastify/error-handler.unit.test.js +3 -11
- package/tests/fastify/error-handlers/with-error-handling.test.js +3 -6
- package/tests/http/HttpError.unit.test.js +13 -17
- package/types/fastify/error-codes.d.ts +11 -16
- package/types/http/HttpError.d.ts +68 -76
package/package.json
CHANGED
|
@@ -5,14 +5,12 @@ import httpStatus from 'http-status'
|
|
|
5
5
|
* Useful as a fallback error descriptor for unhandled or unexpected failures.
|
|
6
6
|
*
|
|
7
7
|
* @typedef {Object} GeneralError
|
|
8
|
-
* @property {number}
|
|
9
|
-
* @property {string} httpStatusText - The human-readable status text ("Internal Server Error").
|
|
8
|
+
* @property {number} status - The HTTP status code (500).
|
|
10
9
|
* @property {string} code - An application-specific error code in the format "GENERAL.<StatusText>".
|
|
11
10
|
*/
|
|
12
11
|
|
|
13
12
|
/** @type {GeneralError} */
|
|
14
13
|
export const GENERAL_ERROR = {
|
|
15
|
-
|
|
16
|
-
httpStatusText: httpStatus[httpStatus.INTERNAL_SERVER_ERROR],
|
|
14
|
+
status: httpStatus.INTERNAL_SERVER_ERROR,
|
|
17
15
|
code: `GENERAL.${httpStatus[httpStatus.INTERNAL_SERVER_ERROR]}`,
|
|
18
16
|
}
|
|
@@ -48,8 +48,8 @@ export const withErrorHandlingReply =
|
|
|
48
48
|
try {
|
|
49
49
|
return await withErrorHandling(log, defaultError)(funcToInvoke)
|
|
50
50
|
} catch (error) {
|
|
51
|
-
const { code,
|
|
52
|
-
reply.status(
|
|
51
|
+
const { code, status } = error
|
|
52
|
+
reply.status(status).send({ code })
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -81,12 +81,11 @@ export const replyOnErrorOnly =
|
|
|
81
81
|
errorMerged.stack = error.stack
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
const exposed =
|
|
85
|
-
errorMerged.message ?? errorMerged.code ?? GENERAL_ERROR.httpStatusText
|
|
84
|
+
const exposed = errorMerged.message ?? errorMerged.code
|
|
86
85
|
|
|
87
86
|
const status =
|
|
88
|
-
errorMerged.
|
|
89
|
-
? errorMerged.
|
|
87
|
+
errorMerged.status && errorMerged.status in httpStatus
|
|
88
|
+
? errorMerged.status
|
|
90
89
|
: httpStatus.INTERNAL_SERVER_ERROR
|
|
91
90
|
|
|
92
91
|
reply.status(status).send({ error: exposed })
|
package/src/http/HttpError.js
CHANGED
|
@@ -15,13 +15,7 @@ export class HttpError extends Error {
|
|
|
15
15
|
* @type {number | undefined}
|
|
16
16
|
* HTTP status code associated with the error (e.g., 400, 500).
|
|
17
17
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @type {string | undefined}
|
|
22
|
-
* Human-readable HTTP status text (e.g., "Bad Request").
|
|
23
|
-
*/
|
|
24
|
-
httpStatusText
|
|
18
|
+
status
|
|
25
19
|
|
|
26
20
|
/**
|
|
27
21
|
* @type {object | undefined}
|
|
@@ -35,24 +29,16 @@ export class HttpError extends Error {
|
|
|
35
29
|
* @param {Object} [error] - Optional error object.
|
|
36
30
|
* @param {string | number} [error.code] - Application-specific error code.
|
|
37
31
|
* @param {string} [error.message] - Custom error message.
|
|
38
|
-
* @param {number} [error.
|
|
39
|
-
* @param {string} [error.httpStatusText] - Optional human-readable HTTP status text.
|
|
32
|
+
* @param {number} [error.status] - HTTP status code (e.g., 404, 500).
|
|
40
33
|
* @param {object} [error.extendInfo] - Optional extended metadata for diagnostics.
|
|
41
34
|
*/
|
|
42
35
|
constructor(error = {}) {
|
|
43
|
-
const { code,
|
|
36
|
+
const { code, status, message, extendInfo } = error
|
|
44
37
|
|
|
45
|
-
super(
|
|
46
|
-
message ||
|
|
47
|
-
(httpStatusCode && httpStatus[httpStatusCode]) ||
|
|
48
|
-
code ||
|
|
49
|
-
'Unknown error',
|
|
50
|
-
)
|
|
38
|
+
super(message || (status && httpStatus[status]) || code || 'Unknown error')
|
|
51
39
|
|
|
52
40
|
this.code = code
|
|
53
|
-
this.
|
|
54
|
-
this.httpStatusText =
|
|
55
|
-
httpStatusText || (httpStatusCode && httpStatus[httpStatusCode])
|
|
41
|
+
this.status = status
|
|
56
42
|
this.extendInfo = extendInfo
|
|
57
43
|
|
|
58
44
|
if (typeof Error.captureStackTrace === 'function') {
|
|
@@ -81,8 +67,7 @@ export class HttpError extends Error {
|
|
|
81
67
|
instance &&
|
|
82
68
|
typeof instance === 'object' &&
|
|
83
69
|
'message' in instance &&
|
|
84
|
-
'
|
|
85
|
-
'httpStatusText' in instance
|
|
70
|
+
'status' in instance
|
|
86
71
|
)
|
|
87
72
|
}
|
|
88
73
|
|
|
@@ -92,8 +77,7 @@ export class HttpError extends Error {
|
|
|
92
77
|
* @returns {{
|
|
93
78
|
* code: string | number | undefined,
|
|
94
79
|
* message: string,
|
|
95
|
-
*
|
|
96
|
-
* httpStatusText: string | undefined,
|
|
80
|
+
* status: number | undefined,
|
|
97
81
|
* extendInfo?: object
|
|
98
82
|
* }}
|
|
99
83
|
*/
|
|
@@ -101,8 +85,7 @@ export class HttpError extends Error {
|
|
|
101
85
|
return {
|
|
102
86
|
code: this.code,
|
|
103
87
|
message: this.message,
|
|
104
|
-
|
|
105
|
-
httpStatusText: this.httpStatusText,
|
|
88
|
+
status: this.status,
|
|
106
89
|
...(this.extendInfo ? { extendInfo: this.extendInfo } : {}),
|
|
107
90
|
}
|
|
108
91
|
}
|
|
@@ -118,8 +101,7 @@ export class HttpError extends Error {
|
|
|
118
101
|
error instanceof HttpError ||
|
|
119
102
|
(error &&
|
|
120
103
|
typeof error === 'object' &&
|
|
121
|
-
'
|
|
122
|
-
'httpStatusText' in error &&
|
|
104
|
+
'status' in error &&
|
|
123
105
|
'toJSON' in error)
|
|
124
106
|
)
|
|
125
107
|
}
|
|
@@ -138,8 +120,7 @@ export class HttpError extends Error {
|
|
|
138
120
|
const httpError = new HttpError({
|
|
139
121
|
code: 'UNHANDLED_ERROR',
|
|
140
122
|
message: error.message || 'An unexpected error occurred',
|
|
141
|
-
|
|
142
|
-
httpStatusText: httpStatus[httpStatus.INTERNAL_SERVER_ERROR],
|
|
123
|
+
status: httpStatus.INTERNAL_SERVER_ERROR,
|
|
143
124
|
})
|
|
144
125
|
|
|
145
126
|
httpError.stack = error.stack
|
package/src/http/http.js
CHANGED
|
@@ -36,11 +36,10 @@ const isOkStatus = ({ status }) =>
|
|
|
36
36
|
const checkStatus = async (response) => {
|
|
37
37
|
if (!isOkStatus(response)) {
|
|
38
38
|
const text = await response.text()
|
|
39
|
-
const { status
|
|
39
|
+
const { status } = response
|
|
40
40
|
throw new HttpError({
|
|
41
|
+
status,
|
|
41
42
|
code: status,
|
|
42
|
-
httpStatusCode: status,
|
|
43
|
-
httpStatusText: statusText,
|
|
44
43
|
extendInfo: { text },
|
|
45
44
|
})
|
|
46
45
|
}
|
|
@@ -46,7 +46,7 @@ export const connectQueueService = async ({ host, log }) => {
|
|
|
46
46
|
* Creates a channel from a RabbitMQ connection.
|
|
47
47
|
*
|
|
48
48
|
* @param {{ host: string, log: import('pino').Logger }} options
|
|
49
|
-
* @returns {Promise<amqp.Channel>}
|
|
49
|
+
* @returns {Promise<{ channel: amqp.Channel, connection: amqp.Connection }>}
|
|
50
50
|
*/
|
|
51
51
|
export const createChannel = async ({ host, log }) => {
|
|
52
52
|
const t0 = Date.now()
|
|
@@ -65,7 +65,7 @@ export const createChannel = async ({ host, log }) => {
|
|
|
65
65
|
ms: Date.now() - t0,
|
|
66
66
|
})
|
|
67
67
|
|
|
68
|
-
return channel
|
|
68
|
+
return { channel, connection }
|
|
69
69
|
} catch (err) {
|
|
70
70
|
logger.error(err, {
|
|
71
71
|
event: 'error',
|
|
@@ -96,7 +96,7 @@ const parseMessage = (msgInfo) => {
|
|
|
96
96
|
* @param {boolean} [options.nackOnError=false] - Whether to nack the message on error (default: false)
|
|
97
97
|
* @param {number} [options.prefetch=1] - Max unacked messages per consumer (default: 1)
|
|
98
98
|
*
|
|
99
|
-
* @returns {Promise<
|
|
99
|
+
* @returns {Promise<string>} Returns the consumer tag for later cancellation
|
|
100
100
|
*/
|
|
101
101
|
export const subscribeToQueue = async ({
|
|
102
102
|
log,
|
|
@@ -112,7 +112,7 @@ export const subscribeToQueue = async ({
|
|
|
112
112
|
await channel.assertQueue(queue, { durable: true })
|
|
113
113
|
!!prefetch && (await channel.prefetch(prefetch))
|
|
114
114
|
|
|
115
|
-
channel.consume(queue, async (msgInfo) => {
|
|
115
|
+
const { consumerTag } = await channel.consume(queue, async (msgInfo) => {
|
|
116
116
|
if (!msgInfo) {
|
|
117
117
|
return
|
|
118
118
|
}
|
|
@@ -143,6 +143,9 @@ export const subscribeToQueue = async ({
|
|
|
143
143
|
return
|
|
144
144
|
}
|
|
145
145
|
})
|
|
146
|
+
|
|
147
|
+
logger.debug({ consumerTag }, 'consumer-started')
|
|
148
|
+
return consumerTag
|
|
146
149
|
} catch (err) {
|
|
147
150
|
logger.error(err, {
|
|
148
151
|
event: 'error',
|
|
@@ -164,12 +167,14 @@ export const subscribeToQueue = async ({
|
|
|
164
167
|
* queue: string,
|
|
165
168
|
* onReceive: (data: any, correlationId?: string) => Promise<void>,
|
|
166
169
|
* nackOnError?: boolean
|
|
167
|
-
* }) => Promise<
|
|
168
|
-
* channel: amqp.Channel
|
|
170
|
+
* }) => Promise<string>,
|
|
171
|
+
* channel: amqp.Channel,
|
|
172
|
+
* connection: amqp.Connection,
|
|
173
|
+
* close: () => Promise<void>
|
|
169
174
|
* }>}
|
|
170
175
|
*/
|
|
171
176
|
export const initializeQueue = async ({ host, log }) => {
|
|
172
|
-
const channel = await createChannel({ host, log })
|
|
177
|
+
const { channel, connection } = await createChannel({ host, log })
|
|
173
178
|
const logger = log.child({ op: 'initializeQueue', host: mask(host) })
|
|
174
179
|
|
|
175
180
|
/**
|
|
@@ -224,16 +229,45 @@ export const initializeQueue = async ({ host, log }) => {
|
|
|
224
229
|
* onReceive: (data: any, correlationId?: string) => Promise<void>,
|
|
225
230
|
* nackOnError?: boolean
|
|
226
231
|
* }} options
|
|
227
|
-
* @returns {Promise<
|
|
232
|
+
* @returns {Promise<string>} Returns the consumer tag for later cancellation
|
|
228
233
|
*/
|
|
229
234
|
const subscribe = async ({ queue, onReceive, nackOnError = false }) => {
|
|
230
235
|
return subscribeToQueue({ channel, queue, onReceive, log, nackOnError })
|
|
231
236
|
}
|
|
232
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Gracefully closes the RabbitMQ channel and connection.
|
|
240
|
+
*
|
|
241
|
+
* @returns {Promise<void>}
|
|
242
|
+
*/
|
|
243
|
+
const close = async () => {
|
|
244
|
+
const t0 = Date.now()
|
|
245
|
+
const logChild = logger.child({ op: 'close' })
|
|
246
|
+
|
|
247
|
+
try {
|
|
248
|
+
logChild.debug('closing-channel-and-connection')
|
|
249
|
+
await channel.close()
|
|
250
|
+
await connection.close()
|
|
251
|
+
|
|
252
|
+
logChild.info({
|
|
253
|
+
event: 'ok',
|
|
254
|
+
ms: Date.now() - t0,
|
|
255
|
+
})
|
|
256
|
+
} catch (err) {
|
|
257
|
+
logChild.error(err, {
|
|
258
|
+
event: 'error',
|
|
259
|
+
ms: Date.now() - t0,
|
|
260
|
+
})
|
|
261
|
+
throw err
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
233
265
|
return {
|
|
234
266
|
channel,
|
|
267
|
+
connection,
|
|
235
268
|
publish,
|
|
236
269
|
subscribe,
|
|
270
|
+
close,
|
|
237
271
|
}
|
|
238
272
|
}
|
|
239
273
|
|
|
@@ -5,13 +5,7 @@ import { GENERAL_ERROR } from '../../src/fastify/error-codes.js'
|
|
|
5
5
|
|
|
6
6
|
describe('GENERAL_ERROR', () => {
|
|
7
7
|
it('should have correct status code', () => {
|
|
8
|
-
expect(GENERAL_ERROR.
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
it('should have correct status text', () => {
|
|
12
|
-
expect(GENERAL_ERROR.httpStatusText).toBe(
|
|
13
|
-
httpStatus[httpStatus.INTERNAL_SERVER_ERROR],
|
|
14
|
-
)
|
|
8
|
+
expect(GENERAL_ERROR.status).toBe(httpStatus.INTERNAL_SERVER_ERROR)
|
|
15
9
|
})
|
|
16
10
|
|
|
17
11
|
it('should have correct code format', () => {
|
|
@@ -22,15 +16,13 @@ describe('GENERAL_ERROR', () => {
|
|
|
22
16
|
})
|
|
23
17
|
|
|
24
18
|
it('should have all required properties and types', () => {
|
|
25
|
-
expect(typeof GENERAL_ERROR.
|
|
26
|
-
expect(typeof GENERAL_ERROR.httpStatusText).toBe('string')
|
|
19
|
+
expect(typeof GENERAL_ERROR.status).toBe('number')
|
|
27
20
|
expect(typeof GENERAL_ERROR.code).toBe('string')
|
|
28
21
|
})
|
|
29
22
|
|
|
30
23
|
it('should match full expected structure', () => {
|
|
31
24
|
const expected = {
|
|
32
|
-
|
|
33
|
-
httpStatusText: 'Internal Server Error',
|
|
25
|
+
status: httpStatus.INTERNAL_SERVER_ERROR,
|
|
34
26
|
code: 'GENERAL.Internal Server Error',
|
|
35
27
|
}
|
|
36
28
|
|
|
@@ -25,7 +25,7 @@ describe('withErrorHandling', () => {
|
|
|
25
25
|
it('should rethrow HttpError', async () => {
|
|
26
26
|
const err = new HttpError({
|
|
27
27
|
message: 'Bad',
|
|
28
|
-
|
|
28
|
+
status: httpStatus.BAD_REQUEST,
|
|
29
29
|
})
|
|
30
30
|
const fn = vi.fn().mockRejectedValue(err)
|
|
31
31
|
|
|
@@ -65,8 +65,7 @@ describe('withErrorHandlingReply', () => {
|
|
|
65
65
|
const err = new HttpError({
|
|
66
66
|
message: 'not found',
|
|
67
67
|
code: 'NOT_FOUND',
|
|
68
|
-
|
|
69
|
-
httpStatusText: httpStatus[httpStatus.NOT_FOUND],
|
|
68
|
+
status: httpStatus.NOT_FOUND,
|
|
70
69
|
})
|
|
71
70
|
|
|
72
71
|
const fn = vi.fn().mockRejectedValue(err)
|
|
@@ -75,7 +74,6 @@ describe('withErrorHandlingReply', () => {
|
|
|
75
74
|
expect(reply.status).toHaveBeenCalledWith(httpStatus.NOT_FOUND)
|
|
76
75
|
expect(reply.send).toHaveBeenCalledWith({
|
|
77
76
|
code: 'NOT_FOUND',
|
|
78
|
-
httpStatusText: 'Not Found',
|
|
79
77
|
})
|
|
80
78
|
})
|
|
81
79
|
})
|
|
@@ -112,8 +110,7 @@ describe('replyOnErrorOnly', () => {
|
|
|
112
110
|
const err = new HttpError({
|
|
113
111
|
message: 'forbidden',
|
|
114
112
|
code: 'NO_ACCESS',
|
|
115
|
-
|
|
116
|
-
httpStatusText: httpStatus[httpStatus.FORBIDDEN],
|
|
113
|
+
status: httpStatus.FORBIDDEN,
|
|
117
114
|
})
|
|
118
115
|
|
|
119
116
|
const fn = vi.fn().mockRejectedValue(err)
|
|
@@ -8,26 +8,24 @@ describe('HttpError', () => {
|
|
|
8
8
|
const error = new HttpError({
|
|
9
9
|
code: 'INVALID_INPUT',
|
|
10
10
|
message: 'Invalid input provided',
|
|
11
|
-
|
|
11
|
+
status: httpStatus.BAD_REQUEST,
|
|
12
12
|
extendInfo: { field: 'email', reason: 'missing' },
|
|
13
13
|
})
|
|
14
14
|
|
|
15
15
|
expect(error).toBeInstanceOf(HttpError)
|
|
16
16
|
expect(error.message).toBe('Invalid input provided')
|
|
17
17
|
expect(error.code).toBe('INVALID_INPUT')
|
|
18
|
-
expect(error.
|
|
19
|
-
expect(error.httpStatusText).toBe(httpStatus[400])
|
|
18
|
+
expect(error.status).toBe(httpStatus.BAD_REQUEST)
|
|
20
19
|
expect(error.extendInfo).toEqual({ field: 'email', reason: 'missing' })
|
|
21
20
|
})
|
|
22
21
|
|
|
23
22
|
it('should fallback to default message from status if message is missing', () => {
|
|
24
23
|
const error = new HttpError({
|
|
25
24
|
code: 'BAD_REQUEST',
|
|
26
|
-
|
|
25
|
+
status: httpStatus.BAD_REQUEST,
|
|
27
26
|
})
|
|
28
27
|
|
|
29
|
-
expect(error.message).toBe(httpStatus[
|
|
30
|
-
expect(error.httpStatusText).toBe(httpStatus[400])
|
|
28
|
+
expect(error.message).toBe(httpStatus[httpStatus.BAD_REQUEST])
|
|
31
29
|
expect(error.extendInfo).toBeUndefined()
|
|
32
30
|
})
|
|
33
31
|
|
|
@@ -35,7 +33,7 @@ describe('HttpError', () => {
|
|
|
35
33
|
const error = new HttpError({ code: 'ERROR_CODE_ONLY' })
|
|
36
34
|
|
|
37
35
|
expect(error.message).toBe('ERROR_CODE_ONLY')
|
|
38
|
-
expect(error.
|
|
36
|
+
expect(error.status).toBeUndefined()
|
|
39
37
|
expect(error.extendInfo).toBeUndefined()
|
|
40
38
|
})
|
|
41
39
|
|
|
@@ -50,14 +48,13 @@ describe('HttpError', () => {
|
|
|
50
48
|
const error = new HttpError({
|
|
51
49
|
code: 'NOT_FOUND',
|
|
52
50
|
message: 'Resource not found',
|
|
53
|
-
|
|
51
|
+
status: httpStatus.NOT_FOUND,
|
|
54
52
|
})
|
|
55
53
|
|
|
56
54
|
expect(error.toJSON()).toEqual({
|
|
57
55
|
code: 'NOT_FOUND',
|
|
58
56
|
message: 'Resource not found',
|
|
59
|
-
|
|
60
|
-
httpStatusText: httpStatus[404],
|
|
57
|
+
status: httpStatus.NOT_FOUND,
|
|
61
58
|
})
|
|
62
59
|
})
|
|
63
60
|
|
|
@@ -65,15 +62,14 @@ describe('HttpError', () => {
|
|
|
65
62
|
const error = new HttpError({
|
|
66
63
|
code: 'NOT_FOUND',
|
|
67
64
|
message: 'Resource not found',
|
|
68
|
-
|
|
65
|
+
status: httpStatus.NOT_FOUND,
|
|
69
66
|
extendInfo: { resource: 'user', id: 123 },
|
|
70
67
|
})
|
|
71
68
|
|
|
72
69
|
expect(error.toJSON()).toEqual({
|
|
73
70
|
code: 'NOT_FOUND',
|
|
74
71
|
message: 'Resource not found',
|
|
75
|
-
|
|
76
|
-
httpStatusText: httpStatus[404],
|
|
72
|
+
status: httpStatus.NOT_FOUND,
|
|
77
73
|
extendInfo: { resource: 'user', id: 123 },
|
|
78
74
|
})
|
|
79
75
|
})
|
|
@@ -81,7 +77,7 @@ describe('HttpError', () => {
|
|
|
81
77
|
it('should detect instance using isHttpError', () => {
|
|
82
78
|
const error = new HttpError({
|
|
83
79
|
code: 'TEST',
|
|
84
|
-
|
|
80
|
+
status: httpStatus.INTERNAL_SERVER_ERROR,
|
|
85
81
|
})
|
|
86
82
|
|
|
87
83
|
expect(HttpError.isHttpError(error)).toBe(true)
|
|
@@ -91,7 +87,7 @@ describe('HttpError', () => {
|
|
|
91
87
|
it('FromError should return same instance if already HttpError', () => {
|
|
92
88
|
const original = new HttpError({
|
|
93
89
|
code: 'ALREADY_HTTP',
|
|
94
|
-
|
|
90
|
+
status: httpStatus.UNAUTHORIZED,
|
|
95
91
|
})
|
|
96
92
|
const result = HttpError.FromError(original)
|
|
97
93
|
|
|
@@ -105,8 +101,8 @@ describe('HttpError', () => {
|
|
|
105
101
|
expect(httpError).toBeInstanceOf(HttpError)
|
|
106
102
|
expect(httpError.message).toBe('Boom!')
|
|
107
103
|
expect(httpError.code).toBe('UNHANDLED_ERROR')
|
|
108
|
-
expect(httpError.
|
|
109
|
-
|
|
104
|
+
expect(httpError.status).toBe(httpStatus.INTERNAL_SERVER_ERROR)
|
|
105
|
+
|
|
110
106
|
expect(httpError.extendInfo).toBeUndefined()
|
|
111
107
|
})
|
|
112
108
|
})
|
|
@@ -3,27 +3,22 @@
|
|
|
3
3
|
* Useful as a fallback error descriptor for unhandled or unexpected failures.
|
|
4
4
|
*
|
|
5
5
|
* @typedef {Object} GeneralError
|
|
6
|
-
* @property {number}
|
|
7
|
-
* @property {string} httpStatusText - The human-readable status text ("Internal Server Error").
|
|
6
|
+
* @property {number} status - The HTTP status code (500).
|
|
8
7
|
* @property {string} code - An application-specific error code in the format "GENERAL.<StatusText>".
|
|
9
8
|
*/
|
|
10
9
|
/** @type {GeneralError} */
|
|
11
|
-
export const GENERAL_ERROR: GeneralError
|
|
10
|
+
export const GENERAL_ERROR: GeneralError
|
|
12
11
|
/**
|
|
13
12
|
* A reusable generic error object representing a server-side failure (HTTP 500).
|
|
14
13
|
* Useful as a fallback error descriptor for unhandled or unexpected failures.
|
|
15
14
|
*/
|
|
16
15
|
export type GeneralError = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* - An application-specific error code in the format "GENERAL.<StatusText>".
|
|
27
|
-
*/
|
|
28
|
-
code: string;
|
|
29
|
-
};
|
|
16
|
+
/**
|
|
17
|
+
* - The HTTP status code (500).
|
|
18
|
+
*/
|
|
19
|
+
status: number
|
|
20
|
+
/**
|
|
21
|
+
* - An application-specific error code in the format "GENERAL.<StatusText>".
|
|
22
|
+
*/
|
|
23
|
+
code: string
|
|
24
|
+
}
|
|
@@ -3,80 +3,72 @@
|
|
|
3
3
|
* Useful for consistent error handling across services.
|
|
4
4
|
*/
|
|
5
5
|
export class HttpError extends Error {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
*/
|
|
75
|
-
toJSON(): {
|
|
76
|
-
code: string | number | undefined;
|
|
77
|
-
message: string;
|
|
78
|
-
httpStatusCode: number | undefined;
|
|
79
|
-
httpStatusText: string | undefined;
|
|
80
|
-
extendInfo?: object;
|
|
81
|
-
};
|
|
6
|
+
/**
|
|
7
|
+
* Checks if a given object is an instance of `HttpError`.
|
|
8
|
+
*
|
|
9
|
+
* @param {*} instance - The object to check.
|
|
10
|
+
* @returns {boolean} True if `instance` is an instance of `HttpError`.
|
|
11
|
+
*/
|
|
12
|
+
static isInstanceOf(instance: any): boolean
|
|
13
|
+
/**
|
|
14
|
+
* Checks if the error is an instance of `HttpError` or has similar shape.
|
|
15
|
+
*
|
|
16
|
+
* @param {object} error
|
|
17
|
+
* @returns {error is HttpError}
|
|
18
|
+
*/
|
|
19
|
+
static isHttpError(error: object): error is HttpError
|
|
20
|
+
/**
|
|
21
|
+
* Creates an HttpError from a generic Error instance or returns it if already an HttpError.
|
|
22
|
+
*
|
|
23
|
+
* @param {Error | HttpError} error
|
|
24
|
+
* @returns {HttpError}
|
|
25
|
+
*/
|
|
26
|
+
static FromError(error: Error | HttpError): HttpError
|
|
27
|
+
/**
|
|
28
|
+
* Creates an instance of HttpError.
|
|
29
|
+
*
|
|
30
|
+
* @param {Object} [error] - Optional error object.
|
|
31
|
+
* @param {string | number} [error.code] - Application-specific error code.
|
|
32
|
+
* @param {string} [error.message] - Custom error message.
|
|
33
|
+
* @param {number} [error.status] - HTTP status code (e.g., 404, 500).
|
|
34
|
+
* @param {object} [error.extendInfo] - Optional extended metadata for diagnostics.
|
|
35
|
+
*/
|
|
36
|
+
constructor(error?: {
|
|
37
|
+
code?: string | number
|
|
38
|
+
message?: string
|
|
39
|
+
status?: number
|
|
40
|
+
|
|
41
|
+
extendInfo?: object
|
|
42
|
+
})
|
|
43
|
+
/**
|
|
44
|
+
* @type {string | number | undefined}
|
|
45
|
+
* A short application-specific error code (e.g., "INVALID_INPUT" or a numeric code).
|
|
46
|
+
*/
|
|
47
|
+
code: string | number | undefined
|
|
48
|
+
/**
|
|
49
|
+
* @type {number | undefined}
|
|
50
|
+
* HTTP status code associated with the error (e.g., 400, 500).
|
|
51
|
+
*/
|
|
52
|
+
httpStatusCode: number | undefined
|
|
53
|
+
/**
|
|
54
|
+
* @type {string | undefined}
|
|
55
|
+
* Human-readable HTTP status text (e.g., "Bad Request").
|
|
56
|
+
*/
|
|
57
|
+
extendInfo: object | undefined
|
|
58
|
+
/**
|
|
59
|
+
* Converts the error to a plain object (useful for logging or sending as JSON).
|
|
60
|
+
*
|
|
61
|
+
* @returns {{
|
|
62
|
+
* code: string | number | undefined,
|
|
63
|
+
* message: string,
|
|
64
|
+
* status: number | undefined,
|
|
65
|
+
* extendInfo?: object
|
|
66
|
+
* }}
|
|
67
|
+
*/
|
|
68
|
+
toJSON(): {
|
|
69
|
+
code: string | number | undefined
|
|
70
|
+
message: string
|
|
71
|
+
status: number | undefined
|
|
72
|
+
extendInfo?: object
|
|
73
|
+
}
|
|
82
74
|
}
|