@lokalise/fastify-extras 30.1.0 → 30.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/README.md +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/healthcheck/commonHealthcheckPlugin.d.ts +13 -0
- package/dist/plugins/healthcheck/commonHealthcheckPlugin.js +1 -1
- package/dist/plugins/healthcheck/commonHealthcheckPlugin.js.map +1 -1
- package/dist/plugins/healthcheck/startupHealthcheckPlugin.d.ts +7 -0
- package/dist/plugins/healthcheck/startupHealthcheckPlugin.js +48 -0
- package/dist/plugins/healthcheck/startupHealthcheckPlugin.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -152,6 +152,35 @@ The key differences from the async version:
|
|
|
152
152
|
- Better suited for checks that are already running in the background or are inherently synchronous
|
|
153
153
|
- Supports mandatory vs optional healthchecks (optional failures result in `PARTIALLY_HEALTHY` status)
|
|
154
154
|
|
|
155
|
+
### Startup Healthcheck Plugin
|
|
156
|
+
|
|
157
|
+
Plugin to monitor app startup status, doing potentially more expensive checks than what is reasonable through periodic healthchecks.
|
|
158
|
+
|
|
159
|
+
Add the plugin to your Fastify instance by registering it with the following options:
|
|
160
|
+
|
|
161
|
+
- `healthChecks`, a list of asynchronous healthchecks to run at the app startup;
|
|
162
|
+
- `resultsLogLevel`, at what log level to report healthcheck results - default is INFO;
|
|
163
|
+
|
|
164
|
+
This is the structure of the log:
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"heartbeat": "PARTIALLY_HEALTHY",
|
|
168
|
+
"checks": {
|
|
169
|
+
"check1": "HEALTHY",
|
|
170
|
+
"check2": "HEALTHY",
|
|
171
|
+
"check3": "FAIL"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
In case a non-optional healthcheck fails, an application startup will throw an error. In order to ensure that the error is thrown correctly, make sure to await the app startup:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
const app = fastify()
|
|
180
|
+
await app.register(startupHealthcheckPlugin, opts)
|
|
181
|
+
await app.ready()
|
|
182
|
+
```
|
|
183
|
+
|
|
155
184
|
### Split IO Plugin
|
|
156
185
|
|
|
157
186
|
Plugin to handle feature flags in Split IO.
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export { wrapHealthCheck } from './plugins/healthcheck/healthcheckCommons.js';
|
|
|
21
21
|
export type { HealthChecker, HealthCheckerSync } from './plugins/healthcheck/healthcheckCommons.js';
|
|
22
22
|
export { commonHealthcheckPlugin } from './plugins/healthcheck/commonHealthcheckPlugin.js';
|
|
23
23
|
export type { CommonHealthcheckPluginOptions } from './plugins/healthcheck/commonHealthcheckPlugin.js';
|
|
24
|
+
export { startupHealthcheckPlugin } from './plugins/healthcheck/startupHealthcheckPlugin.js';
|
|
25
|
+
export type { StartupHealthcheckPluginOptions } from './plugins/healthcheck/startupHealthcheckPlugin.js';
|
|
24
26
|
export { commonSyncHealthcheckPlugin } from './plugins/healthcheck/commonSyncHealthcheckPlugin.ts';
|
|
25
27
|
export type { CommonSyncHealthcheckPluginOptions } from './plugins/healthcheck/commonSyncHealthcheckPlugin.ts';
|
|
26
28
|
export { amplitudePlugin, type AmplitudeConfig, type CreateApiTrackingEventFn, } from './plugins/amplitude/amplitudePlugin.js';
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export { metricsPlugin } from './plugins/metricsPlugin.js';
|
|
|
10
10
|
export { publicHealthcheckPlugin } from './plugins/healthcheck/publicHealthcheckPlugin.js';
|
|
11
11
|
export { wrapHealthCheck } from './plugins/healthcheck/healthcheckCommons.js';
|
|
12
12
|
export { commonHealthcheckPlugin } from './plugins/healthcheck/commonHealthcheckPlugin.js';
|
|
13
|
+
export { startupHealthcheckPlugin } from './plugins/healthcheck/startupHealthcheckPlugin.js';
|
|
13
14
|
export { commonSyncHealthcheckPlugin } from "./plugins/healthcheck/commonSyncHealthcheckPlugin.js";
|
|
14
15
|
export { amplitudePlugin, } from './plugins/amplitude/amplitudePlugin.js';
|
|
15
16
|
export { Amplitude } from './plugins/amplitude/Amplitude.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,GACf,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,2CAA2C,CAAA;AAGlD,OAAO,EACL,gCAAgC,EAChC,0BAA0B,GAC3B,MAAM,+CAA+C,CAAA;AAGtD,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,0CAA0C,CAAA;AAGjD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,mDAAmD,CAAA;AAO1D,OAAO,EAAE,mCAAmC,EAAE,MAAM,6DAA6D,CAAA;AAEjH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AAEtE,OAAO,EACL,yBAAyB,EACzB,kCAAkC,GACnC,MAAM,+CAA+C,CAAA;AAGtD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAM1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAA;AAO1F,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAA;AAG7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAA;AAG1F,OAAO,EAAE,2BAA2B,EAAE,MAAM,sDAAsD,CAAA;AAGlG,OAAO,EACL,eAAe,GAGhB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AAC5D,OAAO,EACL,gBAAgB,EAChB,6BAA6B,GAG9B,MAAM,yCAAyC,CAAA;AAIhD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAA;AAEhF,OAAO,EACL,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,uCAAuC,CAAA;AAG9C,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAA4B,MAAM,0BAA0B,CAAA;AAGnG,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAE5E,OAAO,EAAE,+BAA+B,EAAE,MAAM,kCAAkC,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,GACf,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,2CAA2C,CAAA;AAGlD,OAAO,EACL,gCAAgC,EAChC,0BAA0B,GAC3B,MAAM,+CAA+C,CAAA;AAGtD,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,0CAA0C,CAAA;AAGjD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,mDAAmD,CAAA;AAO1D,OAAO,EAAE,mCAAmC,EAAE,MAAM,6DAA6D,CAAA;AAEjH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AAEtE,OAAO,EACL,yBAAyB,EACzB,kCAAkC,GACnC,MAAM,+CAA+C,CAAA;AAGtD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAM1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAA;AAO1F,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAA;AAG7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAA;AAG1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,mDAAmD,CAAA;AAG5F,OAAO,EAAE,2BAA2B,EAAE,MAAM,sDAAsD,CAAA;AAGlG,OAAO,EACL,eAAe,GAGhB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AAC5D,OAAO,EACL,gBAAgB,EAChB,6BAA6B,GAG9B,MAAM,yCAAyC,CAAA;AAIhD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAA;AAEhF,OAAO,EACL,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,uCAAuC,CAAA;AAG9C,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAA4B,MAAM,0BAA0B,CAAA;AAGnG,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAE5E,OAAO,EAAE,+BAA+B,EAAE,MAAM,kCAAkC,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Either } from '@lokalise/node-core';
|
|
1
2
|
import type { FastifyPluginCallback } from 'fastify';
|
|
2
3
|
import type { HealthChecker } from './healthcheckCommons.js';
|
|
3
4
|
export interface CommonHealthcheckPluginOptions {
|
|
@@ -7,6 +8,16 @@ export interface CommonHealthcheckPluginOptions {
|
|
|
7
8
|
infoProviders?: readonly InfoProvider[];
|
|
8
9
|
isRootRouteEnabled?: boolean;
|
|
9
10
|
}
|
|
11
|
+
type HealthcheckResult = {
|
|
12
|
+
name: string;
|
|
13
|
+
isMandatory: boolean;
|
|
14
|
+
result: Either<Error, true>;
|
|
15
|
+
};
|
|
16
|
+
type ResolvedHealthcheckResponse = {
|
|
17
|
+
isFullyHealthy: boolean;
|
|
18
|
+
isPartiallyHealthy: boolean;
|
|
19
|
+
healthChecks: Record<string, string>;
|
|
20
|
+
};
|
|
10
21
|
export type InfoProvider = {
|
|
11
22
|
name: string;
|
|
12
23
|
dataResolver: () => Record<string, unknown>;
|
|
@@ -16,4 +27,6 @@ export type HealthCheck = {
|
|
|
16
27
|
isMandatory: boolean;
|
|
17
28
|
checker: HealthChecker;
|
|
18
29
|
};
|
|
30
|
+
export declare function resolveHealthcheckResults(results: HealthcheckResult[], opts: CommonHealthcheckPluginOptions): ResolvedHealthcheckResponse;
|
|
19
31
|
export declare const commonHealthcheckPlugin: FastifyPluginCallback<CommonHealthcheckPluginOptions>;
|
|
32
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commonHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/commonHealthcheckPlugin.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAwC/B,
|
|
1
|
+
{"version":3,"file":"commonHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/commonHealthcheckPlugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FastifyPluginCallback } from 'fastify';
|
|
2
|
+
import { type HealthCheck } from './commonHealthcheckPlugin.js';
|
|
3
|
+
export interface StartupHealthcheckPluginOptions {
|
|
4
|
+
resultsLogLevel?: 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent';
|
|
5
|
+
healthChecks: readonly HealthCheck[];
|
|
6
|
+
}
|
|
7
|
+
export declare const startupHealthcheckPlugin: FastifyPluginCallback<StartupHealthcheckPluginOptions>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import fp from 'fastify-plugin';
|
|
2
|
+
import { stdSerializers } from 'pino';
|
|
3
|
+
import { resolveHealthcheckResults } from './commonHealthcheckPlugin.js';
|
|
4
|
+
const plugin = (app, opts, done) => {
|
|
5
|
+
app.addHook('onReady', async () => {
|
|
6
|
+
let isFullyHealthy = true;
|
|
7
|
+
let isPartiallyHealthy = false;
|
|
8
|
+
let healthChecks = {};
|
|
9
|
+
const failedHealthchecks = [];
|
|
10
|
+
if (opts.healthChecks.length) {
|
|
11
|
+
const results = await Promise.all(opts.healthChecks.map(async (healthcheck) => {
|
|
12
|
+
const result = await healthcheck.checker(app);
|
|
13
|
+
if (result.error) {
|
|
14
|
+
app.log.error({
|
|
15
|
+
error: stdSerializers.err(result.error),
|
|
16
|
+
}, `${healthcheck.name} healthcheck has failed`);
|
|
17
|
+
}
|
|
18
|
+
if (result.error) {
|
|
19
|
+
failedHealthchecks.push(healthcheck.name);
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
name: healthcheck.name,
|
|
23
|
+
result,
|
|
24
|
+
isMandatory: healthcheck.isMandatory,
|
|
25
|
+
};
|
|
26
|
+
}));
|
|
27
|
+
const resolvedHealthcheckResponse = resolveHealthcheckResults(results, opts);
|
|
28
|
+
healthChecks = resolvedHealthcheckResponse.healthChecks;
|
|
29
|
+
isFullyHealthy = resolvedHealthcheckResponse.isFullyHealthy;
|
|
30
|
+
isPartiallyHealthy = resolvedHealthcheckResponse.isPartiallyHealthy;
|
|
31
|
+
}
|
|
32
|
+
const heartbeat = isFullyHealthy ? 'HEALTHY' : isPartiallyHealthy ? 'PARTIALLY_HEALTHY' : 'FAIL';
|
|
33
|
+
const resultLog = {
|
|
34
|
+
heartbeat,
|
|
35
|
+
checks: healthChecks,
|
|
36
|
+
};
|
|
37
|
+
app.log[opts.resultsLogLevel ?? 'info'](resultLog, 'Healthcheck finished');
|
|
38
|
+
if (!isPartiallyHealthy && !isFullyHealthy) {
|
|
39
|
+
throw new Error(`Healthchecks failed: ${JSON.stringify(failedHealthchecks)}`);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
done();
|
|
43
|
+
};
|
|
44
|
+
export const startupHealthcheckPlugin = fp(plugin, {
|
|
45
|
+
fastify: '5.x',
|
|
46
|
+
name: 'startup-healthcheck-plugin',
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=startupHealthcheckPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startupHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/startupHealthcheckPlugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AACrC,OAAO,EAAoB,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AAO1F,MAAM,MAAM,GAA2D,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;IACzF,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAChC,IAAI,cAAc,GAAG,IAAI,CAAA;QACzB,IAAI,kBAAkB,GAAG,KAAK,CAAA;QAC9B,IAAI,YAAY,GAA2B,EAAE,CAAA;QAC7C,MAAM,kBAAkB,GAAa,EAAE,CAAA;QAEvC,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;gBAC1C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;gBAC7C,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,GAAG,CAAC,GAAG,CAAC,KAAK,CACX;wBACE,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;qBACxC,EACD,GAAG,WAAW,CAAC,IAAI,yBAAyB,CAC7C,CAAA;gBACH,CAAC;gBACD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;gBAC3C,CAAC;gBACD,OAAO;oBACL,IAAI,EAAE,WAAW,CAAC,IAAI;oBACtB,MAAM;oBACN,WAAW,EAAE,WAAW,CAAC,WAAW;iBACrC,CAAA;YACH,CAAC,CAAC,CACH,CAAA;YAED,MAAM,2BAA2B,GAAG,yBAAyB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAC5E,YAAY,GAAG,2BAA2B,CAAC,YAAY,CAAA;YACvD,cAAc,GAAG,2BAA2B,CAAC,cAAc,CAAA;YAC3D,kBAAkB,GAAG,2BAA2B,CAAC,kBAAkB,CAAA;QACrE,CAAC;QAED,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM,CAAA;QAEhG,MAAM,SAAS,GAAG;YAChB,SAAS;YACT,MAAM,EAAE,YAAY;SACrB,CAAA;QAED,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,IAAI,MAAM,CAAC,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAA;QAE1E,IAAI,CAAC,kBAAkB,IAAI,CAAC,cAAc,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAA;QAC/E,CAAC;IACH,CAAC,CAAC,CAAA;IACF,IAAI,EAAE,CAAA;AACR,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC,MAAM,EAAE;IACjD,OAAO,EAAE,KAAK;IACd,IAAI,EAAE,4BAA4B;CACnC,CAAC,CAAA"}
|