@ogcio/fastify-error-handler 5.0.2 → 5.2.0
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/__tests__/helpers/build-fastify.ts +16 -15
- package/__tests__/helpers/fastify-test-helpers.ts +3 -3
- package/__tests__/initialize-error-handler.test.ts +81 -79
- package/__tests__/life-events-error-handler.test.ts +72 -57
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/initialize-error-handler.d.ts +3 -2
- package/dist/initialize-error-handler.d.ts.map +1 -1
- package/dist/initialize-error-handler.js +10 -5
- package/dist/initialize-error-handler.js.map +1 -1
- package/package.json +5 -4
- package/src/index.ts +2 -2
- package/src/initialize-error-handler.ts +28 -22
- package/vitest.config.mts +19 -0
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import { FastifyError, createError } from "@fastify/error";
|
|
2
|
-
import { pino, DestinationStream } from "pino";
|
|
3
|
-
import fastify, { FastifyInstance } from "fastify";
|
|
4
|
-
import { initializeErrorHandler } from "../../src/index.js";
|
|
1
|
+
import { type FastifyError, createError } from "@fastify/error";
|
|
5
2
|
import fastifySensible from "@fastify/sensible";
|
|
3
|
+
import fastify, { type FastifyInstance } from "fastify";
|
|
6
4
|
import httpErrors from "http-errors";
|
|
5
|
+
import { type DestinationStream, pino } from "pino";
|
|
6
|
+
import { initializeErrorHandler } from "../../src/index.js";
|
|
7
7
|
export const buildFastify = async (
|
|
8
|
-
loggerDestination?: DestinationStream
|
|
8
|
+
loggerDestination?: DestinationStream,
|
|
9
9
|
): Promise<FastifyInstance> => {
|
|
10
10
|
const server = fastify({ loggerInstance: pino({}, loggerDestination) });
|
|
11
11
|
initializeErrorHandler(server as unknown as FastifyInstance);
|
|
12
12
|
await server.register(fastifySensible);
|
|
13
13
|
server.get("/error", async (request, _reply) => {
|
|
14
14
|
const parsed = request.query as { [x: string]: unknown };
|
|
15
|
-
const requestedStatusCode = Number(parsed
|
|
16
|
-
const requestedMessage = String(parsed
|
|
15
|
+
const requestedStatusCode = Number(parsed.status_code ?? "500");
|
|
16
|
+
const requestedMessage = String(parsed.error_message ?? "WHOOOPS");
|
|
17
17
|
|
|
18
|
-
if (!parsed
|
|
18
|
+
if (!parsed.status_code) {
|
|
19
19
|
throw new Error(requestedMessage);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
throw createError(
|
|
23
23
|
"CUSTOM_CODE",
|
|
24
24
|
requestedMessage as string,
|
|
25
|
-
requestedStatusCode as number
|
|
25
|
+
requestedStatusCode as number,
|
|
26
26
|
)();
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
server.get("/validation", async (request, _reply) => {
|
|
30
30
|
const parsed = request.query as { [x: string]: unknown };
|
|
31
|
-
const requestedMessage = String(parsed
|
|
31
|
+
const requestedMessage = String(parsed.error_message ?? "WHOOOPS");
|
|
32
32
|
|
|
33
33
|
const error = createError(
|
|
34
34
|
"CUSTOM_CODE",
|
|
@@ -56,11 +56,11 @@ export const buildFastify = async (
|
|
|
56
56
|
|
|
57
57
|
server.get("/life-events/custom", async (request, _reply) => {
|
|
58
58
|
const parsed = request.query as { [x: string]: unknown };
|
|
59
|
-
const requestedStatusCode = Number(parsed
|
|
59
|
+
const requestedStatusCode = Number(parsed.status_code ?? "500");
|
|
60
60
|
|
|
61
61
|
throw server.httpErrors.createError(
|
|
62
62
|
requestedStatusCode as number,
|
|
63
|
-
"message"
|
|
63
|
+
"message",
|
|
64
64
|
);
|
|
65
65
|
});
|
|
66
66
|
|
|
@@ -73,12 +73,13 @@ export const buildFastify = async (
|
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
server.get("/life-events/:errorCode", async (request, _reply) => {
|
|
76
|
-
const errorCode =
|
|
77
|
-
.errorCode)
|
|
76
|
+
const errorCode = request.params
|
|
77
|
+
? Number((request.params as { errorCode: string }).errorCode)
|
|
78
|
+
: "DO NOT EXIST";
|
|
78
79
|
if (!httpErrors[errorCode]) {
|
|
79
80
|
throw new Error("Wrong parameter");
|
|
80
81
|
}
|
|
81
|
-
|
|
82
|
+
|
|
82
83
|
const errorObj = httpErrors[errorCode];
|
|
83
84
|
|
|
84
85
|
throw new errorObj("Failed Correctly!");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FastifyInstance } from "fastify";
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
2
|
import { buildFastify } from "./build-fastify.js";
|
|
3
3
|
export const DEFAULT_HOSTNAME = "localhost:80";
|
|
4
4
|
export const DEFAULT_USER_AGENT = "lightMyRequest";
|
|
@@ -34,11 +34,11 @@ export const initializeServer = async (): Promise<{
|
|
|
34
34
|
loggingDestination: TestingLoggerDestination;
|
|
35
35
|
}> => {
|
|
36
36
|
const loggingDestination = getTestingDestinationLogger();
|
|
37
|
-
const server =
|
|
37
|
+
const server = await buildFastify(loggingDestination.loggerDestination);
|
|
38
38
|
|
|
39
39
|
return { server, loggingDestination };
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
//
|
|
42
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
43
43
|
export const parseLogEntry = (logEntry: string): { [x: string]: any } =>
|
|
44
44
|
JSON.parse(logEntry);
|
|
@@ -1,99 +1,101 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { HttpErrorClasses } from "@ogcio/shared-errors";
|
|
2
|
+
import httpErrors from "http-errors";
|
|
3
|
+
import { assert, afterEach, describe, it } from "vitest";
|
|
3
4
|
import {
|
|
4
5
|
DEFAULT_METHOD,
|
|
5
6
|
DEFAULT_PATH,
|
|
6
7
|
initializeServer,
|
|
7
8
|
} from "./helpers/fastify-test-helpers.js";
|
|
8
|
-
import httpErrors from "http-errors";
|
|
9
|
-
import { HttpErrorClasses } from "@ogcio/shared-errors";
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const response = await server.inject({
|
|
16
|
-
method: DEFAULT_METHOD,
|
|
17
|
-
url: DEFAULT_PATH,
|
|
18
|
-
query: { status_code: "500", error_message: "error message" },
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
assert.ok(typeof response !== "undefined");
|
|
22
|
-
assert.equal(response?.statusCode, 500);
|
|
23
|
-
assert.deepStrictEqual(response.json(), {
|
|
24
|
-
code: HttpErrorClasses.ServerError,
|
|
25
|
-
detail: "error message",
|
|
26
|
-
requestId: "req-1",
|
|
27
|
-
name: "FastifyError",
|
|
10
|
+
describe("Error management", () => {
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
const { server } = await initializeServer();
|
|
13
|
+
await server.close();
|
|
28
14
|
});
|
|
29
|
-
});
|
|
30
15
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
16
|
+
it("manages common errors as expected", async () => {
|
|
17
|
+
const { server } = await initializeServer();
|
|
18
|
+
const response = await server.inject({
|
|
19
|
+
method: DEFAULT_METHOD,
|
|
20
|
+
url: DEFAULT_PATH,
|
|
21
|
+
query: { status_code: "500", error_message: "error message" },
|
|
22
|
+
});
|
|
34
23
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
assert.ok(typeof response !== "undefined");
|
|
25
|
+
assert.equal(response?.statusCode, 500);
|
|
26
|
+
assert.deepEqual(response.json(), {
|
|
27
|
+
code: HttpErrorClasses.ServerError,
|
|
28
|
+
detail: "error message",
|
|
29
|
+
requestId: "req-1",
|
|
30
|
+
name: "FastifyError",
|
|
31
|
+
statusCode: 500,
|
|
32
|
+
});
|
|
39
33
|
});
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
35
|
+
it("manages validation errors as expected", async () => {
|
|
36
|
+
const { server } = await initializeServer();
|
|
37
|
+
const response = await server.inject({
|
|
38
|
+
method: DEFAULT_METHOD,
|
|
39
|
+
url: "/validation",
|
|
40
|
+
query: { error_message: "error message" },
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
assert.ok(typeof response !== "undefined");
|
|
44
|
+
assert.equal(response?.statusCode, 422);
|
|
45
|
+
assert.deepEqual(response.json(), {
|
|
46
|
+
code: HttpErrorClasses.ValidationError,
|
|
47
|
+
detail: "error message",
|
|
48
|
+
requestId: "req-1",
|
|
49
|
+
name: "UnprocessableEntityError",
|
|
50
|
+
validation: [
|
|
51
|
+
{
|
|
52
|
+
fieldName: "the.instance.path",
|
|
53
|
+
message: "error message",
|
|
54
|
+
validationRule: "field",
|
|
55
|
+
additionalInfo: {
|
|
56
|
+
field: "one",
|
|
57
|
+
property: "two",
|
|
58
|
+
},
|
|
56
59
|
},
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
],
|
|
61
|
+
statusCode: 422,
|
|
62
|
+
});
|
|
59
63
|
});
|
|
60
|
-
});
|
|
61
64
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
it("manages unknown errors as 500", async () => {
|
|
66
|
+
const { server } = await initializeServer();
|
|
67
|
+
const response = await server.inject({
|
|
68
|
+
method: DEFAULT_METHOD,
|
|
69
|
+
url: DEFAULT_PATH,
|
|
70
|
+
query: { status_code: "200", error_message: "error message" },
|
|
71
|
+
});
|
|
65
72
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
assert.ok(typeof response !== "undefined");
|
|
74
|
+
assert.equal(response?.statusCode, 500);
|
|
75
|
+
assert.deepEqual(response.json(), {
|
|
76
|
+
code: HttpErrorClasses.UnknownError,
|
|
77
|
+
detail: "error message",
|
|
78
|
+
requestId: "req-1",
|
|
79
|
+
name: "FastifyError",
|
|
80
|
+
statusCode: 500,
|
|
81
|
+
});
|
|
70
82
|
});
|
|
71
83
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
name: "FastifyError",
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test("404 error is managed as expected", async (t) => {
|
|
83
|
-
const { server } = await initializeServer();
|
|
84
|
-
t.after(() => server.close());
|
|
85
|
-
|
|
86
|
-
const response = await server.inject({
|
|
87
|
-
method: DEFAULT_METHOD,
|
|
88
|
-
url: "/this-path-does-not-exist",
|
|
89
|
-
});
|
|
84
|
+
it("manages 404 errors as expected", async () => {
|
|
85
|
+
const { server } = await initializeServer();
|
|
86
|
+
const response = await server.inject({
|
|
87
|
+
method: DEFAULT_METHOD,
|
|
88
|
+
url: "/this-path-does-not-exist",
|
|
89
|
+
});
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
assert.ok(typeof response !== "undefined");
|
|
92
|
+
assert.equal(response?.statusCode, 404);
|
|
93
|
+
assert.deepEqual(response.json(), {
|
|
94
|
+
code: HttpErrorClasses.NotFoundError,
|
|
95
|
+
detail: "Route not found: /this-path-does-not-exist",
|
|
96
|
+
requestId: "req-1",
|
|
97
|
+
name: new httpErrors[404]("TEMP").name,
|
|
98
|
+
statusCode: 404,
|
|
99
|
+
});
|
|
98
100
|
});
|
|
99
101
|
});
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import * as sharedErrors from "@ogcio/shared-errors";
|
|
2
|
+
import httpErrors from "http-errors";
|
|
3
|
+
import { assert, afterEach, describe, it } from "vitest";
|
|
3
4
|
import {
|
|
4
5
|
DEFAULT_METHOD,
|
|
5
6
|
initializeServer,
|
|
6
7
|
} from "./helpers/fastify-test-helpers.js";
|
|
7
|
-
import httpErrors from "http-errors";
|
|
8
|
-
import * as sharedErrors from "@ogcio/shared-errors";
|
|
9
8
|
|
|
10
9
|
const errorsProvider = [
|
|
11
10
|
{ errorType: httpErrors[401], expectedStatusCode: 401 },
|
|
@@ -16,67 +15,83 @@ const errorsProvider = [
|
|
|
16
15
|
{ errorType: httpErrors[502], expectedStatusCode: 502 },
|
|
17
16
|
];
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
describe("Error management", () => {
|
|
19
|
+
afterEach(async () => {
|
|
21
20
|
const { server } = await initializeServer();
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const errorInstance = new errorProv.errorType("message");
|
|
21
|
+
await server.close();
|
|
22
|
+
});
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
for (const errorProv of errorsProvider) {
|
|
25
|
+
it(`Error is managed in the correct way - ${errorProv.errorType.name}`, async (_t) => {
|
|
26
|
+
const { server } = await initializeServer();
|
|
27
|
+
await server.close();
|
|
29
28
|
});
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
detail: "Failed Correctly!",
|
|
36
|
-
requestId: "req-1",
|
|
37
|
-
name: errorInstance.name,
|
|
38
|
-
});
|
|
39
|
-
})
|
|
40
|
-
);
|
|
30
|
+
for (const errorProv of errorsProvider) {
|
|
31
|
+
it(`manages ${errorProv.errorType.name} correctly`, async () => {
|
|
32
|
+
const { server } = await initializeServer();
|
|
33
|
+
const errorInstance = new errorProv.errorType("message");
|
|
41
34
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
const response = await server.inject({
|
|
36
|
+
method: DEFAULT_METHOD,
|
|
37
|
+
url: `/life-events/${errorProv.expectedStatusCode}`,
|
|
38
|
+
});
|
|
45
39
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
assert.ok(typeof response !== "undefined");
|
|
41
|
+
assert.equal(response?.statusCode, errorProv.expectedStatusCode);
|
|
42
|
+
const parsedErrorClass = sharedErrors.parseHttpErrorClass(
|
|
43
|
+
errorProv.expectedStatusCode,
|
|
44
|
+
);
|
|
45
|
+
assert.deepEqual(response.json(), {
|
|
46
|
+
code: parsedErrorClass.errorClass,
|
|
47
|
+
detail: "Failed Correctly!",
|
|
48
|
+
requestId: "req-1",
|
|
49
|
+
name: errorInstance.name,
|
|
50
|
+
statusCode: parsedErrorClass.statusCode,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
});
|
|
60
|
-
});
|
|
55
|
+
it("manages custom errors based on parameters", async () => {
|
|
56
|
+
const { server } = await initializeServer();
|
|
57
|
+
const response = await server.inject({
|
|
58
|
+
method: DEFAULT_METHOD,
|
|
59
|
+
url: "/life-events/custom",
|
|
60
|
+
query: { status_code: "503" },
|
|
61
|
+
});
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
assert.ok(typeof response !== "undefined");
|
|
64
|
+
assert.equal(response?.statusCode, 503);
|
|
65
|
+
const parsedErrorClass = sharedErrors.parseHttpErrorClass(503);
|
|
66
|
+
assert.deepEqual(response.json(), {
|
|
67
|
+
code: parsedErrorClass.errorClass,
|
|
68
|
+
detail: "message",
|
|
69
|
+
requestId: "req-1",
|
|
70
|
+
name: new httpErrors[503]("MOCK").name,
|
|
71
|
+
statusCode: parsedErrorClass.statusCode,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
65
74
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
it("manages validation errors as expected", async () => {
|
|
76
|
+
const { server } = await initializeServer();
|
|
77
|
+
const response = await server.inject({
|
|
78
|
+
method: DEFAULT_METHOD,
|
|
79
|
+
url: "/life-events/validation",
|
|
80
|
+
});
|
|
70
81
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
assert.ok(typeof response !== "undefined");
|
|
83
|
+
assert.equal(response?.statusCode, 422);
|
|
84
|
+
const parsedErrorClass = sharedErrors.parseHttpErrorClass(422);
|
|
85
|
+
assert.deepEqual(response.json(), {
|
|
86
|
+
code: parsedErrorClass.errorClass,
|
|
87
|
+
detail: "message",
|
|
88
|
+
requestId: "req-1",
|
|
89
|
+
name: new httpErrors[422]("MOCK").name,
|
|
90
|
+
validation: [
|
|
91
|
+
{ fieldName: "field", message: "error", validationRule: "equal" },
|
|
92
|
+
],
|
|
93
|
+
statusCode: parsedErrorClass.statusCode,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
82
97
|
});
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAM/C,eAAO,MAAM,sBAAsB,WAAY,eAAe,KAAG,IAGhE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { initializeNotFoundHandler, setupErrorHandler } from "./initialize-error-handler.js";
|
|
1
|
+
import { initializeNotFoundHandler, setupErrorHandler, } from "./initialize-error-handler.js";
|
|
2
2
|
export const initializeErrorHandler = (server) => {
|
|
3
3
|
setupErrorHandler(server);
|
|
4
4
|
initializeNotFoundHandler(server);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,yBAAyB,EACzB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,MAAuB,EAAQ,EAAE;IACtE,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,yBAAyB,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { type HttpErrorClasses, type ValidationErrorData } from "@ogcio/shared-errors";
|
|
2
|
+
import type { FastifyInstance } from "fastify";
|
|
3
3
|
export interface OutputHttpError {
|
|
4
4
|
code: HttpErrorClasses;
|
|
5
5
|
detail: string;
|
|
@@ -7,6 +7,7 @@ export interface OutputHttpError {
|
|
|
7
7
|
name: string;
|
|
8
8
|
validation?: ValidationErrorData[];
|
|
9
9
|
process?: string;
|
|
10
|
+
statusCode: number;
|
|
10
11
|
}
|
|
11
12
|
export declare const setupErrorHandler: (server: FastifyInstance) => void;
|
|
12
13
|
export declare const initializeNotFoundHandler: (server: FastifyInstance) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initialize-error-handler.d.ts","sourceRoot":"","sources":["../src/initialize-error-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"initialize-error-handler.d.ts","sourceRoot":"","sources":["../src/initialize-error-handler.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EAEzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAEV,eAAe,EAGhB,MAAM,SAAS,CAAC;AAIjB,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAOD,eAAO,MAAM,iBAAiB,WAAY,eAAe,KAAG,IAyC3D,CAAC;AAIF,eAAO,MAAM,yBAAyB,WAAY,eAAe,KAAG,IAUnE,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { httpErrors } from "@fastify/sensible";
|
|
2
|
+
import { LogMessages, getLoggingContextError, setLoggingContext, } from "@ogcio/fastify-logging-wrapper";
|
|
2
3
|
import { parseHttpErrorClass, } from "@ogcio/shared-errors";
|
|
3
4
|
import { isHttpError } from "http-errors";
|
|
4
|
-
import { httpErrors } from "@fastify/sensible";
|
|
5
5
|
// The error handler below is the same as the original one in Fastify,
|
|
6
6
|
// just without unwanted log entries
|
|
7
7
|
// I've opened an issue to fastify to ask them if we could avoid logging
|
|
@@ -27,7 +27,7 @@ export const setupErrorHandler = (server) => {
|
|
|
27
27
|
res.statusCode = statusCode;
|
|
28
28
|
reply.statusCode = res.statusCode;
|
|
29
29
|
};
|
|
30
|
-
server.setErrorHandler(
|
|
30
|
+
server.setErrorHandler((error, request, reply) => {
|
|
31
31
|
if (isHttpError(error)) {
|
|
32
32
|
manageHttpError(error, request, reply);
|
|
33
33
|
return;
|
|
@@ -77,11 +77,13 @@ const getValidationFromFastifyError = (validationInput) => {
|
|
|
77
77
|
return { validation: output };
|
|
78
78
|
};
|
|
79
79
|
const getResponseFromFastifyError = (error, request) => {
|
|
80
|
+
const errorDetails = parseHttpErrorClass(error.statusCode);
|
|
80
81
|
const output = {
|
|
81
|
-
code:
|
|
82
|
+
code: errorDetails.errorClass,
|
|
82
83
|
detail: error.message,
|
|
83
84
|
requestId: request.id,
|
|
84
85
|
name: error.name,
|
|
86
|
+
statusCode: errorDetails.statusCode,
|
|
85
87
|
};
|
|
86
88
|
if (error.validation && error.validation.length > 0) {
|
|
87
89
|
output.validation = getValidationFromFastifyError(error.validation).validation;
|
|
@@ -91,12 +93,14 @@ const getResponseFromFastifyError = (error, request) => {
|
|
|
91
93
|
const manageHttpError = (error, request, reply) => {
|
|
92
94
|
reply.raw.statusCode = error.statusCode;
|
|
93
95
|
reply.statusCode = error.statusCode;
|
|
96
|
+
const errorDetails = parseHttpErrorClass(error.statusCode);
|
|
94
97
|
const errorResponse = {
|
|
95
|
-
code:
|
|
98
|
+
code: errorDetails.errorClass,
|
|
96
99
|
detail: error.message,
|
|
97
100
|
requestId: request.id,
|
|
98
101
|
name: error.name,
|
|
99
102
|
process: error.errorProcess,
|
|
103
|
+
statusCode: errorDetails.statusCode,
|
|
100
104
|
};
|
|
101
105
|
let validationErrors = error.validationErrors && error.validationErrors.length > 0
|
|
102
106
|
? error.validationErrors
|
|
@@ -107,6 +111,7 @@ const manageHttpError = (error, request, reply) => {
|
|
|
107
111
|
if (validationErrors) {
|
|
108
112
|
errorResponse.validation = validationErrors;
|
|
109
113
|
}
|
|
114
|
+
console.log({ errorResponse, errorDetails });
|
|
110
115
|
reply.status(error.statusCode).send(errorResponse);
|
|
111
116
|
};
|
|
112
117
|
const toOutputHttpValidationError = (error) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initialize-error-handler.js","sourceRoot":"","sources":["../src/initialize-error-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"initialize-error-handler.js","sourceRoot":"","sources":["../src/initialize-error-handler.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ogcio/fastify-error-handler",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "rm -rf dist tsconfig.prod.tsbuildinfo tsconfig.tsbuildinfo && tsc -p tsconfig.prod.json",
|
|
9
|
-
"test": "
|
|
9
|
+
"test": "vitest run --coverage --outputFile=results.xml",
|
|
10
|
+
"prepublishOnly": "npm i && npm run build && npm run test"
|
|
10
11
|
},
|
|
11
12
|
"keywords": [],
|
|
12
13
|
"author": {
|
|
@@ -17,8 +18,8 @@
|
|
|
17
18
|
"description": "Normalize the error handling of errors with related logs",
|
|
18
19
|
"dependencies": {
|
|
19
20
|
"@ogcio/fastify-logging-wrapper": "^5.0.2",
|
|
20
|
-
"@ogcio/shared-errors": "^1.
|
|
21
|
-
"fastify": "^5.
|
|
21
|
+
"@ogcio/shared-errors": "^1.1.0",
|
|
22
|
+
"fastify": "^5.1.0"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@types/http-errors": "^2.0.4"
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { FastifyInstance } from "fastify";
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
2
|
import {
|
|
3
3
|
initializeNotFoundHandler,
|
|
4
|
-
setupErrorHandler
|
|
4
|
+
setupErrorHandler,
|
|
5
5
|
} from "./initialize-error-handler.js";
|
|
6
6
|
|
|
7
7
|
export const initializeErrorHandler = (server: FastifyInstance): void => {
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
+
import { type HttpError, httpErrors } from "@fastify/sensible";
|
|
1
2
|
import {
|
|
2
|
-
FastifyError,
|
|
3
|
-
FastifyRequest,
|
|
4
|
-
FastifyInstance,
|
|
5
|
-
FastifyReply,
|
|
6
|
-
} from "fastify";
|
|
7
|
-
import { FastifySchemaValidationError } from "fastify/types/schema.js";
|
|
8
|
-
import {
|
|
9
|
-
setLoggingContext,
|
|
10
|
-
getLoggingContextError,
|
|
11
3
|
LogMessages,
|
|
4
|
+
getLoggingContextError,
|
|
5
|
+
setLoggingContext,
|
|
12
6
|
} from "@ogcio/fastify-logging-wrapper";
|
|
13
7
|
import {
|
|
14
|
-
HttpErrorClasses,
|
|
15
|
-
ValidationErrorData,
|
|
8
|
+
type HttpErrorClasses,
|
|
9
|
+
type ValidationErrorData,
|
|
16
10
|
parseHttpErrorClass,
|
|
17
11
|
} from "@ogcio/shared-errors";
|
|
12
|
+
import type {
|
|
13
|
+
FastifyError,
|
|
14
|
+
FastifyInstance,
|
|
15
|
+
FastifyReply,
|
|
16
|
+
FastifyRequest,
|
|
17
|
+
} from "fastify";
|
|
18
|
+
import type { FastifySchemaValidationError } from "fastify/types/schema.js";
|
|
18
19
|
import { isHttpError } from "http-errors";
|
|
19
|
-
import { HttpError, httpErrors } from "@fastify/sensible";
|
|
20
20
|
|
|
21
21
|
export interface OutputHttpError {
|
|
22
22
|
code: HttpErrorClasses;
|
|
@@ -25,6 +25,7 @@ export interface OutputHttpError {
|
|
|
25
25
|
name: string;
|
|
26
26
|
validation?: ValidationErrorData[];
|
|
27
27
|
process?: string;
|
|
28
|
+
statusCode: number;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
// The error handler below is the same as the original one in Fastify,
|
|
@@ -39,7 +40,7 @@ export const setupErrorHandler = (server: FastifyInstance): void => {
|
|
|
39
40
|
status?: number;
|
|
40
41
|
statusCode?: number;
|
|
41
42
|
},
|
|
42
|
-
reply: FastifyReply
|
|
43
|
+
reply: FastifyReply,
|
|
43
44
|
) => {
|
|
44
45
|
const res = reply.raw;
|
|
45
46
|
let statusCode = res.statusCode;
|
|
@@ -59,7 +60,7 @@ export const setupErrorHandler = (server: FastifyInstance): void => {
|
|
|
59
60
|
reply.statusCode = res.statusCode;
|
|
60
61
|
};
|
|
61
62
|
|
|
62
|
-
server.setErrorHandler(
|
|
63
|
+
server.setErrorHandler((error, request, reply) => {
|
|
63
64
|
if (isHttpError(error)) {
|
|
64
65
|
manageHttpError(error, request, reply);
|
|
65
66
|
return;
|
|
@@ -90,7 +91,7 @@ export const initializeNotFoundHandler = (server: FastifyInstance): void => {
|
|
|
90
91
|
};
|
|
91
92
|
|
|
92
93
|
const getValidationFromFastifyError = (
|
|
93
|
-
validationInput: FastifySchemaValidationError[]
|
|
94
|
+
validationInput: FastifySchemaValidationError[],
|
|
94
95
|
): { validation: ValidationErrorData[] } => {
|
|
95
96
|
const output: ValidationErrorData[] = [];
|
|
96
97
|
|
|
@@ -121,17 +122,20 @@ const getValidationFromFastifyError = (
|
|
|
121
122
|
|
|
122
123
|
const getResponseFromFastifyError = (
|
|
123
124
|
error: FastifyError,
|
|
124
|
-
request: FastifyRequest
|
|
125
|
+
request: FastifyRequest,
|
|
125
126
|
): OutputHttpError => {
|
|
127
|
+
const errorDetails = parseHttpErrorClass(error.statusCode);
|
|
128
|
+
|
|
126
129
|
const output: OutputHttpError = {
|
|
127
|
-
code:
|
|
130
|
+
code: errorDetails.errorClass,
|
|
128
131
|
detail: error.message,
|
|
129
132
|
requestId: request.id,
|
|
130
133
|
name: error.name,
|
|
134
|
+
statusCode: errorDetails.statusCode,
|
|
131
135
|
};
|
|
132
136
|
if (error.validation && error.validation.length > 0) {
|
|
133
137
|
output.validation = getValidationFromFastifyError(
|
|
134
|
-
error.validation
|
|
138
|
+
error.validation,
|
|
135
139
|
).validation;
|
|
136
140
|
}
|
|
137
141
|
|
|
@@ -141,16 +145,18 @@ const getResponseFromFastifyError = (
|
|
|
141
145
|
const manageHttpError = (
|
|
142
146
|
error: HttpError,
|
|
143
147
|
request: FastifyRequest,
|
|
144
|
-
reply: FastifyReply
|
|
148
|
+
reply: FastifyReply,
|
|
145
149
|
): void => {
|
|
146
150
|
reply.raw.statusCode = error.statusCode;
|
|
147
151
|
reply.statusCode = error.statusCode;
|
|
152
|
+
const errorDetails = parseHttpErrorClass(error.statusCode);
|
|
148
153
|
const errorResponse: OutputHttpError = {
|
|
149
|
-
code:
|
|
154
|
+
code: errorDetails.errorClass,
|
|
150
155
|
detail: error.message,
|
|
151
156
|
requestId: request.id,
|
|
152
157
|
name: error.name,
|
|
153
158
|
process: error.errorProcess,
|
|
159
|
+
statusCode: errorDetails.statusCode,
|
|
154
160
|
};
|
|
155
161
|
let validationErrors =
|
|
156
162
|
error.validationErrors && error.validationErrors.length > 0
|
|
@@ -163,7 +169,7 @@ const manageHttpError = (
|
|
|
163
169
|
if (validationErrors) {
|
|
164
170
|
errorResponse.validation = validationErrors;
|
|
165
171
|
}
|
|
166
|
-
|
|
172
|
+
console.log({ errorResponse, errorDetails });
|
|
167
173
|
reply.status(error.statusCode).send(errorResponse);
|
|
168
174
|
};
|
|
169
175
|
|
|
@@ -175,6 +181,6 @@ const toOutputHttpValidationError = (error: FastifyError): HttpError => {
|
|
|
175
181
|
return httpErrors.createError(
|
|
176
182
|
422,
|
|
177
183
|
error.message,
|
|
178
|
-
getValidationFromFastifyError(error.validation)
|
|
184
|
+
getValidationFromFastifyError(error.validation),
|
|
179
185
|
);
|
|
180
186
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
test: {
|
|
5
|
+
reporters: "default",
|
|
6
|
+
coverage: {
|
|
7
|
+
reporter: ["text", "cobertura"],
|
|
8
|
+
provider: "istanbul",
|
|
9
|
+
},
|
|
10
|
+
include: [
|
|
11
|
+
"**/@(test?(s)|__test?(s)__)/**/*.test.@(js|cjs|mjs|tap|cts|jsx|mts|ts|tsx)",
|
|
12
|
+
"**/*.@(test?(s)|spec).@(js|cjs|mjs|tap|cts|jsx|mts|ts|tsx)",
|
|
13
|
+
"**/test?(s).@(js|cjs|mjs|tap|cts|jsx|mts|ts|tsx)",
|
|
14
|
+
],
|
|
15
|
+
exclude: ["**/@(fixture*(s)|dist|node_modules)/**"],
|
|
16
|
+
maxConcurrency: 1,
|
|
17
|
+
testTimeout: 30000, // Timeout in milliseconds (30 seconds)
|
|
18
|
+
},
|
|
19
|
+
});
|