@lokalise/fastify-extras 16.0.0 → 16.1.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/dist/errors/errorHandler.d.ts +18 -0
- package/dist/errors/errorHandler.js +91 -0
- package/dist/errors/errorHandler.js.map +1 -0
- package/dist/errors/errorHandler.spec.d.ts +1 -0
- package/dist/errors/errorHandler.spec.js +206 -0
- package/dist/errors/errorHandler.spec.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ErrorReporter } from '@lokalise/node-core';
|
|
2
|
+
import type { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify';
|
|
3
|
+
export type FreeformRecord = Record<string, any>;
|
|
4
|
+
type ResponseObject = {
|
|
5
|
+
statusCode: number;
|
|
6
|
+
payload: {
|
|
7
|
+
message: string;
|
|
8
|
+
errorCode: string;
|
|
9
|
+
details?: FreeformRecord;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export type ErrorHandlerParams = {
|
|
13
|
+
errorReporter: ErrorReporter;
|
|
14
|
+
resolveResponseObject?: (error: FreeformRecord) => ResponseObject | undefined;
|
|
15
|
+
resolveLogObject?: (error: unknown) => FreeformRecord | undefined;
|
|
16
|
+
};
|
|
17
|
+
export declare function createErrorHandler(params: ErrorHandlerParams): (this: FastifyInstance, error: FreeformRecord, request: FastifyRequest, reply: FastifyReply) => void;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createErrorHandler = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const node_core_1 = require("@lokalise/node-core");
|
|
6
|
+
const pino_1 = tslib_1.__importDefault(require("pino"));
|
|
7
|
+
const zod_1 = require("zod");
|
|
8
|
+
const knownAuthErrors = new Set([
|
|
9
|
+
'FST_JWT_NO_AUTHORIZATION_IN_HEADER',
|
|
10
|
+
'FST_JWT_AUTHORIZATION_TOKEN_EXPIRED',
|
|
11
|
+
'FST_JWT_AUTHORIZATION_TOKEN_INVALID',
|
|
12
|
+
]);
|
|
13
|
+
function resolveLogObject(error) {
|
|
14
|
+
if ((0, node_core_1.isInternalError)(error)) {
|
|
15
|
+
return {
|
|
16
|
+
message: error.message,
|
|
17
|
+
code: error.errorCode,
|
|
18
|
+
details: error.details ? JSON.stringify(error.details) : undefined,
|
|
19
|
+
error: pino_1.default.stdSerializers.err({
|
|
20
|
+
name: error.name,
|
|
21
|
+
message: error.message,
|
|
22
|
+
stack: error.stack,
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
message: (0, node_core_1.isObject)(error) ? error.message : JSON.stringify(error),
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
29
|
+
error: error instanceof Error ? pino_1.default.stdSerializers.err(error) : error,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function resolveResponseObject(error) {
|
|
33
|
+
if ((0, node_core_1.isPublicNonRecoverableError)(error)) {
|
|
34
|
+
return {
|
|
35
|
+
statusCode: error.httpStatusCode ?? 500,
|
|
36
|
+
payload: {
|
|
37
|
+
message: error.message,
|
|
38
|
+
errorCode: error.errorCode,
|
|
39
|
+
details: error.details,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (error instanceof zod_1.ZodError) {
|
|
44
|
+
return {
|
|
45
|
+
statusCode: 400,
|
|
46
|
+
payload: {
|
|
47
|
+
message: 'Invalid params',
|
|
48
|
+
errorCode: 'VALIDATION_ERROR',
|
|
49
|
+
details: {
|
|
50
|
+
error: error.issues,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if ((0, node_core_1.isStandardizedError)(error)) {
|
|
56
|
+
if (knownAuthErrors.has(error.code)) {
|
|
57
|
+
const message = error.code === 'FST_JWT_AUTHORIZATION_TOKEN_INVALID'
|
|
58
|
+
? 'Authorization token is invalid'
|
|
59
|
+
: error.message;
|
|
60
|
+
return {
|
|
61
|
+
statusCode: 401,
|
|
62
|
+
payload: {
|
|
63
|
+
message,
|
|
64
|
+
errorCode: 'AUTH_FAILED',
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
statusCode: 500,
|
|
71
|
+
payload: {
|
|
72
|
+
message: 'Internal server error',
|
|
73
|
+
errorCode: 'INTERNAL_SERVER_ERROR',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function createErrorHandler(params) {
|
|
78
|
+
return function errorHandler(error, request, reply) {
|
|
79
|
+
const logObject = params.resolveLogObject?.(error) ?? resolveLogObject(error);
|
|
80
|
+
if ((0, node_core_1.isInternalError)(error)) {
|
|
81
|
+
params.errorReporter.report({ error });
|
|
82
|
+
}
|
|
83
|
+
const responseObject = params.resolveResponseObject?.(error) ?? resolveResponseObject(error);
|
|
84
|
+
if (responseObject.statusCode >= 500) {
|
|
85
|
+
request.log.error(logObject);
|
|
86
|
+
}
|
|
87
|
+
void reply.status(responseObject.statusCode).send(responseObject.payload);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
exports.createErrorHandler = createErrorHandler;
|
|
91
|
+
//# sourceMappingURL=errorHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../lib/errors/errorHandler.ts"],"names":[],"mappings":";;;;AACA,mDAK4B;AAE5B,wDAAuB;AACvB,6BAA8B;AAK9B,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,oCAAoC;IACpC,qCAAqC;IACrC,qCAAqC;CACtC,CAAC,CAAA;AAWF,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,IAAA,2BAAe,EAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,IAAI,EAAE,KAAK,CAAC,SAAS;YACrB,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;YAClE,KAAK,EAAE,cAAI,CAAC,cAAc,CAAC,GAAG,CAAC;gBAC7B,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB,CAAC;SACH,CAAA;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAA,oBAAQ,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QAChE,mEAAmE;QACnE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,cAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK;KACvE,CAAA;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAqB;IAClD,IAAI,IAAA,uCAA2B,EAAC,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO;YACL,UAAU,EAAE,KAAK,CAAC,cAAc,IAAI,GAAG;YACvC,OAAO,EAAE;gBACP,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB;SACF,CAAA;IACH,CAAC;IAED,IAAI,KAAK,YAAY,cAAQ,EAAE,CAAC;QAC9B,OAAO;YACL,UAAU,EAAE,GAAG;YACf,OAAO,EAAE;gBACP,OAAO,EAAE,gBAAgB;gBACzB,SAAS,EAAE,kBAAkB;gBAC7B,OAAO,EAAE;oBACP,KAAK,EAAE,KAAK,CAAC,MAAM;iBACpB;aACF;SACF,CAAA;IACH,CAAC;IAED,IAAI,IAAA,+BAAmB,EAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,MAAM,OAAO,GACX,KAAK,CAAC,IAAI,KAAK,qCAAqC;gBAClD,CAAC,CAAC,gCAAgC;gBAClC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAA;YAEnB,OAAO;gBACL,UAAU,EAAE,GAAG;gBACf,OAAO,EAAE;oBACP,OAAO;oBACP,SAAS,EAAE,aAAa;iBACzB;aACF,CAAA;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,UAAU,EAAE,GAAG;QACf,OAAO,EAAE;YACP,OAAO,EAAE,uBAAuB;YAChC,SAAS,EAAE,uBAAuB;SACnC;KACF,CAAA;AACH,CAAC;AAQD,SAAgB,kBAAkB,CAAC,MAA0B;IAC3D,OAAO,SAAS,YAAY,CAE1B,KAAqB,EACrB,OAAuB,EACvB,KAAmB;QAEnB,MAAM,SAAS,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,IAAI,gBAAgB,CAAC,KAAK,CAAC,CAAA;QAE7E,IAAI,IAAA,2BAAe,EAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;QACxC,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAA;QAC5F,IAAI,cAAc,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAC9B,CAAC;QAED,KAAK,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAA;IAC3E,CAAC,CAAA;AACH,CAAC;AApBD,gDAoBC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const node_core_1 = require("@lokalise/node-core");
|
|
5
|
+
const fastify_1 = tslib_1.__importDefault(require("fastify"));
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const zod_1 = require("zod");
|
|
8
|
+
const errorHandler_1 = require("./errorHandler");
|
|
9
|
+
async function initApp(routeHandler, errorHandlerParams = {}, awaitApp = true) {
|
|
10
|
+
const app = (0, fastify_1.default)({
|
|
11
|
+
logger: true,
|
|
12
|
+
});
|
|
13
|
+
app.setErrorHandler((0, errorHandler_1.createErrorHandler)({
|
|
14
|
+
errorReporter: {
|
|
15
|
+
report: () => { },
|
|
16
|
+
},
|
|
17
|
+
...errorHandlerParams,
|
|
18
|
+
}));
|
|
19
|
+
app.route({
|
|
20
|
+
method: 'GET',
|
|
21
|
+
url: '/',
|
|
22
|
+
handler: routeHandler,
|
|
23
|
+
});
|
|
24
|
+
if (awaitApp) {
|
|
25
|
+
await app.ready();
|
|
26
|
+
}
|
|
27
|
+
return app;
|
|
28
|
+
}
|
|
29
|
+
describe('errorHandler', () => {
|
|
30
|
+
let app;
|
|
31
|
+
afterAll(async () => {
|
|
32
|
+
await app.close();
|
|
33
|
+
});
|
|
34
|
+
it('returns 500 internal error by default', async () => {
|
|
35
|
+
app = await initApp(() => {
|
|
36
|
+
throw new Error('Generic error');
|
|
37
|
+
});
|
|
38
|
+
const response = await app.inject().get('/').end();
|
|
39
|
+
expect(response.statusCode).toBe(500);
|
|
40
|
+
expect(response.json()).toEqual({
|
|
41
|
+
errorCode: 'INTERNAL_SERVER_ERROR',
|
|
42
|
+
message: 'Internal server error',
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
it('can override response resolution', async () => {
|
|
46
|
+
app = await initApp(() => {
|
|
47
|
+
throw new node_core_1.PublicNonRecoverableError({
|
|
48
|
+
message: 'Auth failed',
|
|
49
|
+
errorCode: 'AUTH_FAILED',
|
|
50
|
+
httpStatusCode: 401,
|
|
51
|
+
details: { someDetails: 'details' },
|
|
52
|
+
});
|
|
53
|
+
}, {
|
|
54
|
+
resolveResponseObject: (error) => {
|
|
55
|
+
return {
|
|
56
|
+
statusCode: 502,
|
|
57
|
+
payload: {
|
|
58
|
+
message: error.message + '1',
|
|
59
|
+
errorCode: 'TEST_ERR',
|
|
60
|
+
details: {
|
|
61
|
+
someValues: 1,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
const response = await app.inject().get('/').end();
|
|
68
|
+
expect(response.statusCode).toBe(502);
|
|
69
|
+
expect(response.json()).toEqual({
|
|
70
|
+
details: {
|
|
71
|
+
someValues: 1,
|
|
72
|
+
},
|
|
73
|
+
errorCode: 'TEST_ERR',
|
|
74
|
+
message: 'Auth failed1',
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
it('can override logged object resolution', async () => {
|
|
78
|
+
let logSpy;
|
|
79
|
+
app = await initApp((req) => {
|
|
80
|
+
logSpy = vitest_1.vitest.spyOn(req.log, 'error');
|
|
81
|
+
throw new node_core_1.InternalError({
|
|
82
|
+
message: 'Internal error',
|
|
83
|
+
errorCode: 'INTERNAL',
|
|
84
|
+
});
|
|
85
|
+
}, {
|
|
86
|
+
resolveLogObject: (error) => {
|
|
87
|
+
return {
|
|
88
|
+
message: error.message + '22',
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
const response = await app.inject().get('/').end();
|
|
93
|
+
expect(response.statusCode).toBe(500);
|
|
94
|
+
expect(logSpy.mock.calls).toHaveLength(1);
|
|
95
|
+
expect(logSpy.mock.calls[0]).toEqual([
|
|
96
|
+
{
|
|
97
|
+
message: 'Internal error22',
|
|
98
|
+
},
|
|
99
|
+
]);
|
|
100
|
+
});
|
|
101
|
+
it('sends error to the reporter', async () => {
|
|
102
|
+
const logs = [];
|
|
103
|
+
app = await initApp(() => {
|
|
104
|
+
throw new node_core_1.InternalError({
|
|
105
|
+
message: 'Internal error',
|
|
106
|
+
errorCode: 'INTERNAL',
|
|
107
|
+
});
|
|
108
|
+
}, {
|
|
109
|
+
errorReporter: {
|
|
110
|
+
report: (err) => {
|
|
111
|
+
logs.push(err);
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
const response = await app.inject().get('/').end();
|
|
116
|
+
expect(response.statusCode).toBe(500);
|
|
117
|
+
expect(logs).toHaveLength(1);
|
|
118
|
+
expect(logs[0].error).toMatchObject({
|
|
119
|
+
message: 'Internal error',
|
|
120
|
+
errorCode: 'INTERNAL',
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
it('responds with AUTH_FAILED in case of internal auth failed error', async () => {
|
|
124
|
+
app = await initApp(() => {
|
|
125
|
+
throw new node_core_1.PublicNonRecoverableError({
|
|
126
|
+
message: 'Auth failed',
|
|
127
|
+
errorCode: 'AUTH_FAILED',
|
|
128
|
+
httpStatusCode: 401,
|
|
129
|
+
details: { someDetails: 'details' },
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
const response = await app.inject().get('/').end();
|
|
133
|
+
expect(response.statusCode).toBe(401);
|
|
134
|
+
expect(response.json()).toEqual({
|
|
135
|
+
message: 'Auth failed',
|
|
136
|
+
errorCode: 'AUTH_FAILED',
|
|
137
|
+
details: { someDetails: 'details' },
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
it('responds with 401 for standardized token error with invalid token', async () => {
|
|
141
|
+
app = await initApp(() => {
|
|
142
|
+
const err = new Error('Auth failed');
|
|
143
|
+
// @ts-expect-error
|
|
144
|
+
err.code = 'FST_JWT_AUTHORIZATION_TOKEN_INVALID';
|
|
145
|
+
throw err;
|
|
146
|
+
});
|
|
147
|
+
const response = await app.inject().get('/').end();
|
|
148
|
+
expect(response.statusCode).toBe(401);
|
|
149
|
+
expect(response.json()).toEqual({
|
|
150
|
+
message: 'Authorization token is invalid',
|
|
151
|
+
errorCode: 'AUTH_FAILED',
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
it('responds with 401 for standardized token error with expired token', async () => {
|
|
155
|
+
app = await initApp(() => {
|
|
156
|
+
const err = new Error('Auth failed');
|
|
157
|
+
// @ts-expect-error
|
|
158
|
+
err.code = 'FST_JWT_NO_AUTHORIZATION_IN_HEADER';
|
|
159
|
+
throw err;
|
|
160
|
+
});
|
|
161
|
+
const response = await app.inject().get('/').end();
|
|
162
|
+
expect(response.statusCode).toBe(401);
|
|
163
|
+
expect(response.json()).toEqual({
|
|
164
|
+
message: 'Auth failed',
|
|
165
|
+
errorCode: 'AUTH_FAILED',
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
it('returns 500 for InternalError', async () => {
|
|
169
|
+
app = await initApp(() => {
|
|
170
|
+
throw new node_core_1.InternalError({
|
|
171
|
+
message: 'Auth failed',
|
|
172
|
+
details: { userId: 4 },
|
|
173
|
+
errorCode: 'INT_ERR',
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
const response = await app.inject().get('/').end();
|
|
177
|
+
expect(response.statusCode).toBe(500);
|
|
178
|
+
expect(response.json()).toEqual({
|
|
179
|
+
errorCode: 'INTERNAL_SERVER_ERROR',
|
|
180
|
+
message: 'Internal server error',
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
it('returns 400 for Zod errors', async () => {
|
|
184
|
+
app = await initApp(() => {
|
|
185
|
+
zod_1.z.string().parse(45);
|
|
186
|
+
});
|
|
187
|
+
const response = await app.inject().get('/').end();
|
|
188
|
+
expect(response.statusCode).toBe(400);
|
|
189
|
+
expect(response.json()).toEqual({
|
|
190
|
+
errorCode: 'VALIDATION_ERROR',
|
|
191
|
+
message: 'Invalid params',
|
|
192
|
+
details: {
|
|
193
|
+
error: [
|
|
194
|
+
{
|
|
195
|
+
code: 'invalid_type',
|
|
196
|
+
expected: 'string',
|
|
197
|
+
message: 'Expected string, received number',
|
|
198
|
+
path: [],
|
|
199
|
+
received: 'number',
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
//# sourceMappingURL=errorHandler.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorHandler.spec.js","sourceRoot":"","sources":["../../lib/errors/errorHandler.spec.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,3 +20,5 @@ export { amplitudePlugin, Amplitude, type AmplitudeConfig, type CreateApiTrackin
|
|
|
20
20
|
export type { FastifyReplyWithPayload } from './types';
|
|
21
21
|
export { unhandledExceptionPlugin } from './plugins/unhandledExceptionPlugin';
|
|
22
22
|
export type { UnhandledExceptionPluginOptions } from './plugins/unhandledExceptionPlugin';
|
|
23
|
+
export { createErrorHandler } from './errors/errorHandler';
|
|
24
|
+
export type { ErrorHandlerParams, FreeformRecord } from './errors/errorHandler';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.unhandledExceptionPlugin = exports.Amplitude = exports.amplitudePlugin = exports.wrapHealthCheck = exports.publicHealthcheckPlugin = exports.prismaOtelTracingPlugin = exports.metricsPlugin = exports.wrapHealthCheckForPrometheus = exports.healthcheckMetricsPlugin = exports.SplitIOFeatureManager = exports.splitIOFeatureManagerPlugin = exports.NewRelicTransactionManager = exports.newrelicTransactionManagerPlugin = exports.REQUEST_ID_STORE_KEY = exports.getRequestIdFastifyAppConfig = exports.requestContextProviderPlugin = exports.reportErrorToBugsnag = exports.bugsnagPlugin = void 0;
|
|
3
|
+
exports.createErrorHandler = exports.unhandledExceptionPlugin = exports.Amplitude = exports.amplitudePlugin = exports.wrapHealthCheck = exports.publicHealthcheckPlugin = exports.prismaOtelTracingPlugin = exports.metricsPlugin = exports.wrapHealthCheckForPrometheus = exports.healthcheckMetricsPlugin = exports.SplitIOFeatureManager = exports.splitIOFeatureManagerPlugin = exports.NewRelicTransactionManager = exports.newrelicTransactionManagerPlugin = exports.REQUEST_ID_STORE_KEY = exports.getRequestIdFastifyAppConfig = exports.requestContextProviderPlugin = exports.reportErrorToBugsnag = exports.bugsnagPlugin = void 0;
|
|
4
4
|
var bugsnagPlugin_1 = require("./plugins/bugsnagPlugin");
|
|
5
5
|
Object.defineProperty(exports, "bugsnagPlugin", { enumerable: true, get: function () { return bugsnagPlugin_1.bugsnagPlugin; } });
|
|
6
6
|
Object.defineProperty(exports, "reportErrorToBugsnag", { enumerable: true, get: function () { return bugsnagPlugin_1.reportErrorToBugsnag; } });
|
|
@@ -30,4 +30,6 @@ Object.defineProperty(exports, "amplitudePlugin", { enumerable: true, get: funct
|
|
|
30
30
|
Object.defineProperty(exports, "Amplitude", { enumerable: true, get: function () { return amplitudePlugin_1.Amplitude; } });
|
|
31
31
|
var unhandledExceptionPlugin_1 = require("./plugins/unhandledExceptionPlugin");
|
|
32
32
|
Object.defineProperty(exports, "unhandledExceptionPlugin", { enumerable: true, get: function () { return unhandledExceptionPlugin_1.unhandledExceptionPlugin; } });
|
|
33
|
+
var errorHandler_1 = require("./errors/errorHandler");
|
|
34
|
+
Object.defineProperty(exports, "createErrorHandler", { enumerable: true, get: function () { return errorHandler_1.createErrorHandler; } });
|
|
33
35
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;AAAA,yDAA6E;AAApE,8GAAA,aAAa,OAAA;AAAE,qHAAA,oBAAoB,OAAA;AAG5C,uFAI+C;AAH7C,4IAAA,4BAA4B,OAAA;AAC5B,4IAAA,4BAA4B,OAAA;AAC5B,oIAAA,oBAAoB,OAAA;AAItB,+FAGmD;AAFjD,oJAAA,gCAAgC,OAAA;AAChC,8IAAA,0BAA0B,OAAA;AAI5B,qFAG8C;AAF5C,0IAAA,2BAA2B,OAAA;AAC3B,oIAAA,qBAAqB,OAAA;AAIvB,2FAGuD;AAFrD,oIAAA,wBAAwB,OAAA;AACxB,wIAAA,4BAA4B,OAAA;AAQ9B,yDAAuD;AAA9C,8GAAA,aAAa,OAAA;AAGtB,2FAAyF;AAAhF,kIAAA,uBAAuB,OAAA;AAGhC,yFAAuF;AAA9E,kIAAA,uBAAuB,OAAA;AAMhC,+EAA0E;AAAjE,qHAAA,eAAe,OAAA;AAGxB,6DAKkC;AAJhC,kHAAA,eAAe,OAAA;AACf,4GAAA,SAAS,OAAA;AAOX,+EAA6E;AAApE,oIAAA,wBAAwB,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;AAAA,yDAA6E;AAApE,8GAAA,aAAa,OAAA;AAAE,qHAAA,oBAAoB,OAAA;AAG5C,uFAI+C;AAH7C,4IAAA,4BAA4B,OAAA;AAC5B,4IAAA,4BAA4B,OAAA;AAC5B,oIAAA,oBAAoB,OAAA;AAItB,+FAGmD;AAFjD,oJAAA,gCAAgC,OAAA;AAChC,8IAAA,0BAA0B,OAAA;AAI5B,qFAG8C;AAF5C,0IAAA,2BAA2B,OAAA;AAC3B,oIAAA,qBAAqB,OAAA;AAIvB,2FAGuD;AAFrD,oIAAA,wBAAwB,OAAA;AACxB,wIAAA,4BAA4B,OAAA;AAQ9B,yDAAuD;AAA9C,8GAAA,aAAa,OAAA;AAGtB,2FAAyF;AAAhF,kIAAA,uBAAuB,OAAA;AAGhC,yFAAuF;AAA9E,kIAAA,uBAAuB,OAAA;AAMhC,+EAA0E;AAAjE,qHAAA,eAAe,OAAA;AAGxB,6DAKkC;AAJhC,kHAAA,eAAe,OAAA;AACf,4GAAA,SAAS,OAAA;AAOX,+EAA6E;AAApE,oIAAA,wBAAwB,OAAA;AAGjC,sDAA0D;AAAjD,kHAAA,kBAAkB,OAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lokalise/fastify-extras",
|
|
3
|
-
"version": "16.
|
|
3
|
+
"version": "16.1.0",
|
|
4
4
|
"description": "Opinionated set of fastify plugins, commonly used in Lokalise",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Lokalise",
|
|
@@ -62,7 +62,8 @@
|
|
|
62
62
|
"@fastify/request-context": "^5.0.0",
|
|
63
63
|
"fastify": "^4.24.3",
|
|
64
64
|
"newrelic": "^11.0.0",
|
|
65
|
-
"pino": "^8.16.2"
|
|
65
|
+
"pino": "^8.16.2",
|
|
66
|
+
"zod": "^3.22.4"
|
|
66
67
|
},
|
|
67
68
|
"devDependencies": {
|
|
68
69
|
"@fastify/request-context": "^5.0.0",
|
|
@@ -87,7 +88,8 @@
|
|
|
87
88
|
"ts-node": "^10.9.1",
|
|
88
89
|
"typescript": "^5.3.2",
|
|
89
90
|
"vitest": "^0.34.6",
|
|
90
|
-
"vite": "4.5.0"
|
|
91
|
+
"vite": "4.5.0",
|
|
92
|
+
"zod": "^3.22.4"
|
|
91
93
|
},
|
|
92
94
|
"engines": {
|
|
93
95
|
"node": ">=18"
|