@lokalise/fastify-extras 13.1.1 → 14.0.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/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/publicHealthcheckPlugin.d.ts +7 -1
- package/dist/plugins/publicHealthcheckPlugin.js +18 -10
- package/dist/plugins/publicHealthcheckPlugin.js.map +1 -1
- package/dist/plugins/publicHealthcheckPlugin.spec.js +50 -8
- package/dist/plugins/publicHealthcheckPlugin.spec.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -13,5 +13,5 @@ export type { ErrorObjectResolver, MetricsPluginOptions } from './plugins/metric
|
|
|
13
13
|
export { prismaOtelTracingPlugin } from './plugins/opentelemetry/prismaOtelTracingPlugin';
|
|
14
14
|
export type { PrismaOtelTracingPluginConfig } from './plugins/opentelemetry/prismaOtelTracingPlugin';
|
|
15
15
|
export { publicHealthcheckPlugin } from './plugins/publicHealthcheckPlugin';
|
|
16
|
-
export type { PublicHealthcheckPluginOptions, HealthCheck } from './plugins/publicHealthcheckPlugin';
|
|
16
|
+
export type { PublicHealthcheckPluginOptions, HealthCheck, HealthChecker, } from './plugins/publicHealthcheckPlugin';
|
|
17
17
|
export { amplitudePlugin, Amplitude, type AmplitudeConfig, type CreateApiTrackingEventFn, } from './plugins/amplitudePlugin';
|
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,+EAA6E;AAApE,oIAAA,wBAAwB,OAAA;AAOjC,yDAAuD;AAA9C,8GAAA,aAAa,OAAA;AAGtB,2FAAyF;AAAhF,kIAAA,uBAAuB,OAAA;AAGhC,6EAA2E;AAAlE,kIAAA,uBAAuB,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,+EAA6E;AAApE,oIAAA,wBAAwB,OAAA;AAOjC,yDAAuD;AAA9C,8GAAA,aAAa,OAAA;AAGtB,2FAAyF;AAAhF,kIAAA,uBAAuB,OAAA;AAGhC,6EAA2E;AAAlE,kIAAA,uBAAuB,OAAA;AAOhC,6DAKkC;AAJhC,kHAAA,eAAe,OAAA;AACf,4GAAA,SAAS,OAAA"}
|
|
@@ -2,9 +2,15 @@ import type { Either } from '@lokalise/node-core';
|
|
|
2
2
|
import type { FastifyInstance } from 'fastify';
|
|
3
3
|
export interface PublicHealthcheckPluginOptions {
|
|
4
4
|
responsePayload?: Record<string, unknown>;
|
|
5
|
+
url?: string;
|
|
6
|
+
logLevel?: 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent';
|
|
5
7
|
healthChecks: readonly HealthCheck[];
|
|
6
8
|
}
|
|
7
|
-
export type
|
|
9
|
+
export type HealthChecker = (app: FastifyInstance) => Promise<Either<Error, true>>;
|
|
10
|
+
export type HealthCheck = {
|
|
11
|
+
isMandatory: boolean;
|
|
12
|
+
checker: HealthChecker;
|
|
13
|
+
};
|
|
8
14
|
declare function plugin(app: FastifyInstance, opts: PublicHealthcheckPluginOptions, done: () => void): void;
|
|
9
15
|
export declare const publicHealthcheckPlugin: typeof plugin;
|
|
10
16
|
export {};
|
|
@@ -6,29 +6,37 @@ const fastify_plugin_1 = tslib_1.__importDefault(require("fastify-plugin"));
|
|
|
6
6
|
function plugin(app, opts, done) {
|
|
7
7
|
const responsePayload = opts.responsePayload ?? {};
|
|
8
8
|
app.route({
|
|
9
|
-
url: '/',
|
|
9
|
+
url: opts.url ?? '/health',
|
|
10
10
|
method: 'GET',
|
|
11
|
-
logLevel: '
|
|
11
|
+
logLevel: opts.logLevel ?? 'info',
|
|
12
12
|
schema: {
|
|
13
13
|
// hide route from swagger plugins
|
|
14
14
|
// @ts-expect-error
|
|
15
15
|
hide: true,
|
|
16
16
|
},
|
|
17
17
|
handler: async (_, reply) => {
|
|
18
|
-
let
|
|
18
|
+
let isFullyHealthy = true;
|
|
19
|
+
let isPartiallyHealthy = false;
|
|
19
20
|
if (opts.healthChecks.length) {
|
|
20
21
|
const results = await Promise.all(opts.healthChecks.map((healthcheck) => {
|
|
21
|
-
return healthcheck(app);
|
|
22
|
+
return healthcheck.checker(app);
|
|
22
23
|
}));
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
for (let i = 0; i < results.length; i++) {
|
|
25
|
+
const entry = results[i];
|
|
26
|
+
if (entry.error && opts.healthChecks[i].isMandatory) {
|
|
27
|
+
isFullyHealthy = false;
|
|
28
|
+
isPartiallyHealthy = false;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
if (entry.error && !opts.healthChecks[i].isMandatory) {
|
|
32
|
+
isFullyHealthy = false;
|
|
33
|
+
isPartiallyHealthy = true;
|
|
34
|
+
}
|
|
27
35
|
}
|
|
28
36
|
}
|
|
29
|
-
return reply.status(
|
|
37
|
+
return reply.status(isFullyHealthy || isPartiallyHealthy ? 200 : 500).send({
|
|
30
38
|
...responsePayload,
|
|
31
|
-
heartbeat:
|
|
39
|
+
heartbeat: isFullyHealthy ? 'HEALTHY' : isPartiallyHealthy ? 'PARTIALLY_HEALTHY' : 'FAIL',
|
|
32
40
|
});
|
|
33
41
|
},
|
|
34
42
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publicHealthcheckPlugin.js","sourceRoot":"","sources":["../../lib/plugins/publicHealthcheckPlugin.ts"],"names":[],"mappings":";;;;AAEA,4EAA+B;
|
|
1
|
+
{"version":3,"file":"publicHealthcheckPlugin.js","sourceRoot":"","sources":["../../lib/plugins/publicHealthcheckPlugin.ts"],"names":[],"mappings":";;;;AAEA,4EAA+B;AAgB/B,SAAS,MAAM,CAAC,GAAoB,EAAE,IAAoC,EAAE,IAAgB;IAC1F,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,IAAI,EAAE,CAAA;IAClD,GAAG,CAAC,KAAK,CAAC;QACR,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,SAAS;QAC1B,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,MAAM;QACjC,MAAM,EAAE;YACN,kCAAkC;YAClC,mBAAmB;YACnB,IAAI,EAAE,IAAI;SACX;QACD,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE;YAC1B,IAAI,cAAc,GAAG,IAAI,CAAA;YACzB,IAAI,kBAAkB,GAAG,KAAK,CAAA;YAC9B,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;gBAC5B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE;oBACpC,OAAO,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;gBACjC,CAAC,CAAC,CACH,CAAA;gBAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBACvC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;oBACxB,IAAI,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;wBACnD,cAAc,GAAG,KAAK,CAAA;wBACtB,kBAAkB,GAAG,KAAK,CAAA;wBAC1B,MAAK;qBACN;oBACD,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;wBACpD,cAAc,GAAG,KAAK,CAAA;wBACtB,kBAAkB,GAAG,IAAI,CAAA;qBAC1B;iBACF;aACF;YAED,OAAO,KAAK,CAAC,MAAM,CAAC,cAAc,IAAI,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACzE,GAAG,eAAe;gBAClB,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM;aAC1F,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;IACF,IAAI,EAAE,CAAA;AACR,CAAC;AAEY,QAAA,uBAAuB,GAAG,IAAA,wBAAE,EAAC,MAAM,EAAE;IAChD,OAAO,EAAE,KAAK;IACd,IAAI,EAAE,2BAA2B;CAClC,CAAC,CAAA"}
|
|
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const fastify_1 = tslib_1.__importDefault(require("fastify"));
|
|
5
5
|
const publicHealthcheckPlugin_1 = require("./publicHealthcheckPlugin");
|
|
6
|
-
const
|
|
6
|
+
const positiveHealthcheckChecker = () => {
|
|
7
7
|
return Promise.resolve({ result: true });
|
|
8
8
|
};
|
|
9
|
-
const
|
|
9
|
+
const negativeHealthcheckChecker = () => {
|
|
10
10
|
return Promise.resolve({ error: new Error('Something exploded') });
|
|
11
11
|
};
|
|
12
12
|
async function initApp(opts) {
|
|
@@ -22,31 +22,73 @@ describe('publicHealthcheckPlugin', () => {
|
|
|
22
22
|
});
|
|
23
23
|
it('returns a heartbeat', async () => {
|
|
24
24
|
app = await initApp({ healthChecks: [] });
|
|
25
|
+
const response = await app.inject().get('/health').end();
|
|
26
|
+
expect(response.statusCode).toBe(200);
|
|
27
|
+
expect(response.json()).toEqual({ heartbeat: 'HEALTHY' });
|
|
28
|
+
});
|
|
29
|
+
it('returns a heartbeat on a custom endpoint', async () => {
|
|
30
|
+
app = await initApp({ healthChecks: [], url: '/' });
|
|
25
31
|
const response = await app.inject().get('/').end();
|
|
26
32
|
expect(response.statusCode).toBe(200);
|
|
27
33
|
expect(response.json()).toEqual({ heartbeat: 'HEALTHY' });
|
|
28
34
|
});
|
|
29
35
|
it('returns custom heartbeat', async () => {
|
|
30
36
|
app = await initApp({ responsePayload: { version: 1 }, healthChecks: [] });
|
|
31
|
-
const response = await app.inject().get('/').end();
|
|
37
|
+
const response = await app.inject().get('/health').end();
|
|
32
38
|
expect(response.statusCode).toBe(200);
|
|
33
39
|
expect(response.json()).toEqual({ heartbeat: 'HEALTHY', version: 1 });
|
|
34
40
|
});
|
|
35
|
-
it('returns false if one healthcheck fails', async () => {
|
|
41
|
+
it('returns false if one mandatory healthcheck fails', async () => {
|
|
36
42
|
app = await initApp({
|
|
37
43
|
responsePayload: { version: 1 },
|
|
38
|
-
healthChecks: [
|
|
44
|
+
healthChecks: [
|
|
45
|
+
{
|
|
46
|
+
isMandatory: true,
|
|
47
|
+
checker: negativeHealthcheckChecker,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
isMandatory: true,
|
|
51
|
+
checker: positiveHealthcheckChecker,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
39
54
|
});
|
|
40
|
-
const response = await app.inject().get('/').end();
|
|
55
|
+
const response = await app.inject().get('/health').end();
|
|
41
56
|
expect(response.statusCode).toBe(500);
|
|
42
57
|
expect(response.json()).toEqual({ heartbeat: 'FAIL', version: 1 });
|
|
43
58
|
});
|
|
59
|
+
it('returns partial if optional healthcheck fails', async () => {
|
|
60
|
+
app = await initApp({
|
|
61
|
+
responsePayload: { version: 1 },
|
|
62
|
+
healthChecks: [
|
|
63
|
+
{
|
|
64
|
+
isMandatory: false,
|
|
65
|
+
checker: negativeHealthcheckChecker,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
isMandatory: true,
|
|
69
|
+
checker: positiveHealthcheckChecker,
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
const response = await app.inject().get('/health').end();
|
|
74
|
+
expect(response.statusCode).toBe(200);
|
|
75
|
+
expect(response.json()).toEqual({ heartbeat: 'PARTIALLY_HEALTHY', version: 1 });
|
|
76
|
+
});
|
|
44
77
|
it('returns true if all healthchecks pass', async () => {
|
|
45
78
|
app = await initApp({
|
|
46
79
|
responsePayload: { version: 1 },
|
|
47
|
-
healthChecks: [
|
|
80
|
+
healthChecks: [
|
|
81
|
+
{
|
|
82
|
+
isMandatory: true,
|
|
83
|
+
checker: positiveHealthcheckChecker,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
isMandatory: true,
|
|
87
|
+
checker: positiveHealthcheckChecker,
|
|
88
|
+
},
|
|
89
|
+
],
|
|
48
90
|
});
|
|
49
|
-
const response = await app.inject().get('/').end();
|
|
91
|
+
const response = await app.inject().get('/health').end();
|
|
50
92
|
expect(response.statusCode).toBe(200);
|
|
51
93
|
expect(response.json()).toEqual({ heartbeat: 'HEALTHY', version: 1 });
|
|
52
94
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publicHealthcheckPlugin.spec.js","sourceRoot":"","sources":["../../lib/plugins/publicHealthcheckPlugin.spec.ts"],"names":[],"mappings":";;;AACA,8DAA6B;AAG7B,uEAAmE;AAEnE,MAAM,
|
|
1
|
+
{"version":3,"file":"publicHealthcheckPlugin.spec.js","sourceRoot":"","sources":["../../lib/plugins/publicHealthcheckPlugin.spec.ts"],"names":[],"mappings":"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"}
|