@tsed/terminus 6.126.1 → 6.128.1

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/jest.config.js ADDED
@@ -0,0 +1,14 @@
1
+ // For a detailed explanation regarding each configuration property, visit:
2
+ // https://jestjs.io/docs/en/configuration.html
3
+
4
+ module.exports = {
5
+ ...require("@tsed/jest-config")(__dirname, "terminus"),
6
+ coverageThreshold: {
7
+ global: {
8
+ statements: 100,
9
+ branches: 100,
10
+ functions: 100,
11
+ lines: 100
12
+ }
13
+ }
14
+ };
@@ -4,27 +4,61 @@ exports.TerminusModule = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const terminus_1 = require("@godaddy/terminus");
6
6
  const di_1 = require("@tsed/di");
7
- const https_1 = tslib_1.__importDefault(require("https"));
7
+ const schema_1 = require("@tsed/schema");
8
8
  const http_1 = tslib_1.__importDefault(require("http"));
9
+ const https_1 = tslib_1.__importDefault(require("https"));
9
10
  let TerminusModule = class TerminusModule {
10
- configuration;
11
+ settings;
12
+ basePath;
11
13
  injector;
12
14
  httpServer;
13
15
  httpsServer;
14
16
  $onInit() {
15
17
  this.mount();
16
18
  }
17
- mount() {
18
- const { terminus } = this.configuration;
19
- const terminusConfig = {
20
- logger: this.injector.logger,
19
+ getConfiguration() {
20
+ const { path, ...props } = this.settings;
21
+ return {
22
+ logger: (event, error) => this.injector.logger.info({
23
+ event: event.toUpperCase(),
24
+ error_message: error.message
25
+ }),
21
26
  healthChecks: this.getHealths(),
22
- onSignal: this.execShutdown("onSignal"),
23
- onShutdown: this.execShutdown("onShutdown"),
24
- beforeShutdown: this.execShutdown("beforeShutdown"),
25
- onSendFailureDuringShutdown: this.execShutdown("onSendFailureDuringShutdown"),
26
- ...terminus
27
+ onSignal: this.createEmitter("$onSignal"),
28
+ onShutdown: this.createEmitter("$onShutdown"),
29
+ beforeShutdown: this.createEmitter("$beforeShutdown"),
30
+ onSendFailureDuringShutdown: this.createEmitter("$onSendFailureDuringShutdown"),
31
+ ...props
27
32
  };
33
+ }
34
+ async $logRoutes(routes) {
35
+ return [
36
+ ...routes,
37
+ {
38
+ toJSON: () => {
39
+ return {
40
+ method: "GET",
41
+ name: `TerminusModule.dispatch`,
42
+ url: this.basePath
43
+ };
44
+ }
45
+ },
46
+ ...this.getAll("health").map(({ provider, propertyKey, options }) => {
47
+ const path = this.getPath(provider, options.name);
48
+ return {
49
+ toJSON() {
50
+ return {
51
+ method: "GET",
52
+ name: `${provider.className}.${propertyKey}`,
53
+ url: path
54
+ };
55
+ }
56
+ };
57
+ })
58
+ ];
59
+ }
60
+ mount() {
61
+ const terminusConfig = this.getConfiguration();
28
62
  if (this.httpServer) {
29
63
  (0, terminus_1.createTerminus)(this.httpServer, terminusConfig);
30
64
  }
@@ -32,39 +66,61 @@ let TerminusModule = class TerminusModule {
32
66
  (0, terminus_1.createTerminus)(this.httpsServer, terminusConfig);
33
67
  }
34
68
  }
35
- getProviders(name) {
36
- return this.injector.getProviders().filter((provider) => {
37
- return provider.store.get(name);
69
+ getAll(name) {
70
+ return this.injector.getProviders().flatMap((provider) => {
71
+ const metadata = provider.store.get(`terminus:${name}`);
72
+ if (metadata) {
73
+ return Object.entries(metadata).map(([propertyKey, options]) => {
74
+ return {
75
+ provider,
76
+ propertyKey,
77
+ options
78
+ };
79
+ });
80
+ }
81
+ return [];
38
82
  });
39
83
  }
40
- getStore(name) {
41
- return this.injector
42
- .getProviders()
43
- .map((provider) => provider.store.get(name))
44
- .filter((x) => !!x)
45
- .flat();
46
- }
47
84
  getHealths() {
48
- const healths = {};
49
- this.getProviders("terminus").forEach((provider) => {
50
- Object.keys(provider.store.get("terminus")).forEach((name) => {
51
- healths[`${provider.path}${name}`] = provider.store.get("terminus")[name];
52
- });
53
- });
85
+ const subHealths = this.getAll("health").reduce((healths, { provider, propertyKey, options: { name } }) => {
86
+ const instance = this.injector.get(provider.token);
87
+ const callback = async (...args) => {
88
+ const result = await instance[propertyKey](...args);
89
+ return { [name]: result };
90
+ };
91
+ let path = this.getPath(provider, name);
92
+ return {
93
+ ...healths,
94
+ [path]: callback
95
+ };
96
+ }, {});
97
+ const healths = {
98
+ ...subHealths,
99
+ [this.basePath]: (state) => {
100
+ const promises = Object.entries(subHealths).map(([path, callback]) => callback(state));
101
+ return Promise.all(promises);
102
+ }
103
+ };
54
104
  return healths;
55
105
  }
56
- execShutdown(name) {
57
- return async () => {
58
- for (const func of this.getStore(name)) {
59
- await func();
60
- }
106
+ getPath(provider, name) {
107
+ let path = (0, schema_1.concatPath)(provider.path, name);
108
+ return path.includes("health") ? path : (0, schema_1.concatPath)(path, this.basePath);
109
+ }
110
+ createEmitter(name) {
111
+ return async (...args) => {
112
+ return this.injector.emit(`$${name}`, ...args);
61
113
  };
62
114
  }
63
115
  };
64
116
  tslib_1.__decorate([
65
- (0, di_1.Configuration)(),
117
+ (0, di_1.Constant)("terminus", {}),
66
118
  tslib_1.__metadata("design:type", Object)
67
- ], TerminusModule.prototype, "configuration", void 0);
119
+ ], TerminusModule.prototype, "settings", void 0);
120
+ tslib_1.__decorate([
121
+ (0, di_1.Constant)("terminus.path", "/health"),
122
+ tslib_1.__metadata("design:type", String)
123
+ ], TerminusModule.prototype, "basePath", void 0);
68
124
  tslib_1.__decorate([
69
125
  (0, di_1.Inject)(),
70
126
  tslib_1.__metadata("design:type", di_1.InjectorService)
@@ -1 +1 @@
1
- {"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":"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","sourcesContent":["import {createTerminus} from \"@godaddy/terminus\";\nimport {Configuration, Inject, InjectorService, Module, OnInit} from \"@tsed/di\";\nimport Https from \"https\";\nimport Http from \"http\";\n\n@Module()\nexport class TerminusModule implements OnInit {\n @Configuration()\n private configuration: Configuration;\n\n @Inject()\n private injector: InjectorService;\n\n @Inject(Http.Server)\n private httpServer: Http.Server | null;\n\n @Inject(Https.Server)\n private httpsServer: Https.Server | null;\n\n public $onInit() {\n this.mount();\n }\n\n private mount() {\n const {terminus} = this.configuration;\n const terminusConfig = {\n logger: this.injector.logger as any,\n healthChecks: this.getHealths(),\n onSignal: this.execShutdown(\"onSignal\"),\n onShutdown: this.execShutdown(\"onShutdown\"),\n beforeShutdown: this.execShutdown(\"beforeShutdown\"),\n onSendFailureDuringShutdown: this.execShutdown(\"onSendFailureDuringShutdown\"),\n ...terminus\n };\n\n if (this.httpServer) {\n createTerminus(this.httpServer, terminusConfig);\n }\n\n if (this.httpsServer) {\n createTerminus(this.httpsServer, terminusConfig);\n }\n }\n\n private getProviders(name: string) {\n return this.injector.getProviders().filter((provider) => {\n return provider.store.get(name);\n });\n }\n\n private getStore(name: string) {\n return this.injector\n .getProviders()\n .map((provider) => provider.store.get(name))\n .filter((x) => !!x)\n .flat();\n }\n\n private getHealths() {\n const healths: {[k: string]: () => Promise<any>} = {};\n\n this.getProviders(\"terminus\").forEach((provider) => {\n Object.keys(provider.store.get(\"terminus\")).forEach((name) => {\n healths[`${provider.path}${name}`] = provider.store.get(\"terminus\")[name];\n });\n });\n\n return healths;\n }\n\n private execShutdown(name: string) {\n return async () => {\n for (const func of this.getStore(name)) {\n await func();\n }\n };\n }\n}\n"]}
1
+ {"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":"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","sourcesContent":["import {createTerminus} from \"@godaddy/terminus\";\nimport {Constant, Inject, InjectorService, Module, OnInit, Provider} from \"@tsed/di\";\nimport {concatPath} from \"@tsed/schema\";\nimport Http from \"http\";\nimport Https from \"https\";\nimport {TerminusSettings} from \"./interfaces/TerminusSettings\";\n\n@Module()\nexport class TerminusModule implements OnInit {\n @Constant(\"terminus\", {})\n private settings: TerminusSettings;\n\n @Constant(\"terminus.path\", \"/health\")\n private basePath: string;\n\n @Inject()\n private injector: InjectorService;\n\n @Inject(Http.Server)\n private httpServer: Http.Server | null;\n\n @Inject(Https.Server)\n private httpsServer: Https.Server | null;\n\n public $onInit() {\n this.mount();\n }\n\n getConfiguration() {\n const {path, ...props} = this.settings;\n\n return {\n logger: (event: string, error: any) =>\n this.injector.logger.info({\n event: event.toUpperCase(),\n error_message: error.message\n }),\n healthChecks: this.getHealths(),\n onSignal: this.createEmitter(\"$onSignal\"),\n onShutdown: this.createEmitter(\"$onShutdown\"),\n beforeShutdown: this.createEmitter(\"$beforeShutdown\"),\n onSendFailureDuringShutdown: this.createEmitter(\"$onSendFailureDuringShutdown\"),\n ...props\n };\n }\n\n async $logRoutes(routes: any[]): Promise<any[]> {\n return [\n ...routes,\n {\n toJSON: () => {\n return {\n method: \"GET\",\n name: `TerminusModule.dispatch`,\n url: this.basePath\n };\n }\n },\n ...this.getAll<{name: string}>(\"health\").map(({provider, propertyKey, options}) => {\n const path = this.getPath(provider, options.name);\n\n return {\n toJSON() {\n return {\n method: \"GET\",\n name: `${provider.className}.${propertyKey}`,\n url: path\n };\n }\n } as any;\n })\n ];\n }\n\n private mount() {\n const terminusConfig = this.getConfiguration();\n\n if (this.httpServer) {\n createTerminus(this.httpServer, terminusConfig);\n }\n\n if (this.httpsServer) {\n createTerminus(this.httpsServer, terminusConfig);\n }\n }\n\n private getAll<Opts = any>(\n name: string\n ): {\n provider: Provider;\n propertyKey: string;\n options: Opts;\n }[] {\n return this.injector.getProviders().flatMap((provider) => {\n const metadata = provider.store.get(`terminus:${name}`);\n\n if (metadata) {\n return Object.entries(metadata).map(([propertyKey, options]: [string, Opts]) => {\n return {\n provider,\n propertyKey,\n options\n };\n });\n }\n return [];\n });\n }\n\n private getHealths() {\n const subHealths = this.getAll<{name: string}>(\"health\").reduce((healths, {provider, propertyKey, options: {name}}) => {\n const instance = this.injector.get<any>(provider.token)!;\n const callback = async (...args: any[]) => {\n const result = await instance[propertyKey](...args);\n\n return {[name]: result};\n };\n\n let path = this.getPath(provider, name);\n\n return {\n ...healths,\n [path]: callback\n };\n }, {} as Record<string, (state: any) => Promise<any>>);\n\n const healths: Record<string, any> = {\n ...subHealths,\n [this.basePath]: (state: any) => {\n const promises = Object.entries(subHealths).map(([path, callback]) => callback(state));\n\n return Promise.all(promises);\n }\n };\n\n return healths;\n }\n\n private getPath(provider: Provider<any>, name: string) {\n let path = concatPath(provider.path, name);\n return path.includes(\"health\") ? path : concatPath(path, this.basePath);\n }\n\n private createEmitter(name: string) {\n return async (...args: any[]) => {\n return this.injector.emit(`$${name}`, ...args);\n };\n }\n}\n"]}
@@ -22,12 +22,10 @@ const core_1 = require("@tsed/core");
22
22
  * @terminus
23
23
  */
24
24
  function Health(name) {
25
- return (target, propertyKey, descriptor) => {
26
- if (descriptor.value) {
27
- core_1.Store.from(target).merge("terminus", {
28
- [name]: descriptor.value
29
- });
30
- }
25
+ return (target, propertyKey) => {
26
+ core_1.Store.from(target).merge(`terminus:health`, {
27
+ [propertyKey]: { name }
28
+ });
31
29
  };
32
30
  }
33
31
  exports.Health = Health;
@@ -1 +1 @@
1
- {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/decorators/health.ts"],"names":[],"mappings":";;;AAAA,qCAAiC;AAEjC;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,MAAM,CAAC,IAAY;IACjC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,UAA6C,EAAE,EAAE;QACtG,IAAI,UAAU,CAAC,KAAK,EAAE;YACpB,YAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE;gBACnC,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,KAAK;aACzB,CAAC,CAAC;SACJ;IACH,CAAC,CAAC;AACJ,CAAC;AARD,wBAQC","sourcesContent":["import {Store} from \"@tsed/core\";\n\n/**\n * Create a readiness / liveness checks.\n *\n * ```ts\n * import { Health } from \"@tsed/terminus\";\n *\n * @Controller(\"/mongo\")\n * class MongoCtrl {\n * @Health(\"/health\")\n * health() {\n * // Here check the mongo health\n * return Promise.resolve();\n * }\n * }\n *\n * @param name\n * @decorator\n * @terminus\n */\nexport function Health(name: string): MethodDecorator {\n return <Function>(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<Function>) => {\n if (descriptor.value) {\n Store.from(target).merge(\"terminus\", {\n [name]: descriptor.value\n });\n }\n };\n}\n"]}
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/decorators/health.ts"],"names":[],"mappings":";;;AAAA,qCAAiC;AAEjC;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,MAAM,CAAC,IAAY;IACjC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,EAAE;QACvD,YAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,iBAAiB,EAAE;YAC1C,CAAC,WAAW,CAAC,EAAE,EAAC,IAAI,EAAC;SACtB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAND,wBAMC","sourcesContent":["import {Store} from \"@tsed/core\";\n\n/**\n * Create a readiness / liveness checks.\n *\n * ```ts\n * import { Health } from \"@tsed/terminus\";\n *\n * @Controller(\"/mongo\")\n * class MongoCtrl {\n * @Health(\"/health\")\n * health() {\n * // Here check the mongo health\n * return Promise.resolve();\n * }\n * }\n *\n * @param name\n * @decorator\n * @terminus\n */\nexport function Health(name: string): MethodDecorator {\n return <Function>(target: Object, propertyKey: string) => {\n Store.from(target).merge(`terminus:health`, {\n [propertyKey]: {name}\n });\n };\n}\n"]}
@@ -1,21 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OnSendFailureDuringShutdown = exports.OnShutdown = exports.OnSignal = exports.BeforeShutdown = void 0;
4
- const core_1 = require("@tsed/core");
5
- function register(name) {
6
- return (target, propertyKey, descriptor) => {
7
- if (descriptor.value) {
8
- const store = core_1.Store.from(target);
9
- const values = store.get(name) || [];
10
- store.merge(name, [...values, descriptor.value]);
11
- }
3
+ exports.OnSendFailureDuringShutdown = exports.OnShutdown = exports.OnSignal = exports.BeforeShutdown = exports.register = void 0;
4
+ function register(event) {
5
+ return (target, propertyKey, description) => {
6
+ Object.defineProperty(target, `$${event}`, {
7
+ value: description.value
8
+ });
12
9
  };
13
10
  }
11
+ exports.register = register;
14
12
  /**
15
13
  * Listen the `beforeShutdown` terminus event.
16
14
  *
17
15
  * @decorator
18
16
  * @terminus
17
+ * @deprecated Use $BeforeShutdown hook
19
18
  */
20
19
  function BeforeShutdown() {
21
20
  return register("beforeShutdown");
@@ -26,6 +25,7 @@ exports.BeforeShutdown = BeforeShutdown;
26
25
  *
27
26
  * @decorator
28
27
  * @terminus
28
+ * @deprecated Use $onSignal hook
29
29
  */
30
30
  function OnSignal() {
31
31
  return register("onSignal");
@@ -36,6 +36,7 @@ exports.OnSignal = OnSignal;
36
36
  *
37
37
  * @decorator
38
38
  * @terminus
39
+ * @deprecated Use $onShutdown hook
39
40
  */
40
41
  function OnShutdown() {
41
42
  return register("onShutdown");
@@ -46,9 +47,10 @@ exports.OnShutdown = OnShutdown;
46
47
  *
47
48
  * @decorator
48
49
  * @terminus
50
+ * @deprecated Use $onSendFailureDuringShutdown hook
49
51
  */
50
52
  function OnSendFailureDuringShutdown() {
51
- return register("onSendFailureDuringShutdown");
53
+ return register("OnSendFailureDuringShutdown");
52
54
  }
53
55
  exports.OnSendFailureDuringShutdown = OnSendFailureDuringShutdown;
54
56
  //# sourceMappingURL=shutdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../../src/decorators/shutdown.ts"],"names":[],"mappings":";;;AAAA,qCAAiC;AAEjC,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,UAA6C,EAAE,EAAE;QACtG,IAAI,UAAU,CAAC,KAAK,EAAE;YACpB,MAAM,KAAK,GAAG,YAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAErC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;SAClD;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,cAAc;IAC5B,OAAO,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACpC,CAAC;AAFD,wCAEC;AAED;;;;;GAKG;AACH,SAAgB,QAAQ;IACtB,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC;AAFD,4BAEC;AAED;;;;;GAKG;AACH,SAAgB,UAAU;IACxB,OAAO,QAAQ,CAAC,YAAY,CAAC,CAAC;AAChC,CAAC;AAFD,gCAEC;AAED;;;;;GAKG;AACH,SAAgB,2BAA2B;IACzC,OAAO,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AACjD,CAAC;AAFD,kEAEC","sourcesContent":["import {Store} from \"@tsed/core\";\n\nfunction register(name: string) {\n return <Function>(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<Function>) => {\n if (descriptor.value) {\n const store = Store.from(target);\n const values = store.get(name) || [];\n\n store.merge(name, [...values, descriptor.value]);\n }\n };\n}\n\n/**\n * Listen the `beforeShutdown` terminus event.\n *\n * @decorator\n * @terminus\n */\nexport function BeforeShutdown(): MethodDecorator {\n return register(\"beforeShutdown\");\n}\n\n/**\n * Listen the `onSignal` terminus event.\n *\n * @decorator\n * @terminus\n */\nexport function OnSignal(): MethodDecorator {\n return register(\"onSignal\");\n}\n\n/**\n * Listen the `onShutdown` terminus event.\n *\n * @decorator\n * @terminus\n */\nexport function OnShutdown(): MethodDecorator {\n return register(\"onShutdown\");\n}\n\n/**\n * Listen the `onSendFailureDuringShutdown` terminus event.\n *\n * @decorator\n * @terminus\n */\nexport function OnSendFailureDuringShutdown(): MethodDecorator {\n return register(\"onSendFailureDuringShutdown\");\n}\n"]}
1
+ {"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../../src/decorators/shutdown.ts"],"names":[],"mappings":";;;AAAA,SAAgB,QAAQ,CAAC,KAAa;IACpC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,WAA+B,EAAE,EAAE;QACxF,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,KAAK,EAAE,EAAE;YACzC,KAAK,EAAE,WAAW,CAAC,KAAK;SACzB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAND,4BAMC;AAED;;;;;;GAMG;AACH,SAAgB,cAAc;IAC5B,OAAO,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACpC,CAAC;AAFD,wCAEC;AAED;;;;;;GAMG;AACH,SAAgB,QAAQ;IACtB,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC;AAFD,4BAEC;AAED;;;;;;GAMG;AACH,SAAgB,UAAU;IACxB,OAAO,QAAQ,CAAC,YAAY,CAAC,CAAC;AAChC,CAAC;AAFD,gCAEC;AAED;;;;;;GAMG;AACH,SAAgB,2BAA2B;IACzC,OAAO,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AACjD,CAAC;AAFD,kEAEC","sourcesContent":["export function register(event: string) {\n return <Function>(target: Object, propertyKey: string, description: PropertyDescriptor) => {\n Object.defineProperty(target, `$${event}`, {\n value: description.value\n });\n };\n}\n\n/**\n * Listen the `beforeShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $BeforeShutdown hook\n */\nexport function BeforeShutdown(): MethodDecorator {\n return register(\"beforeShutdown\");\n}\n\n/**\n * Listen the `onSignal` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onSignal hook\n */\nexport function OnSignal(): MethodDecorator {\n return register(\"onSignal\");\n}\n\n/**\n * Listen the `onShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onShutdown hook\n */\nexport function OnShutdown(): MethodDecorator {\n return register(\"onShutdown\");\n}\n\n/**\n * Listen the `onSendFailureDuringShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onSendFailureDuringShutdown hook\n */\nexport function OnSendFailureDuringShutdown(): MethodDecorator {\n return register(\"OnSendFailureDuringShutdown\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"TerminusSettings.js","sourceRoot":"","sources":["../../../src/interfaces/TerminusSettings.ts"],"names":[],"mappings":"","sourcesContent":["import {TerminusOptions} from \"@godaddy/terminus\";\n\nexport type TerminusSettings = Omit<\n TerminusOptions,\n \"healthChecks\" | \"onSignal\" | \"onSendFailureDuringShutdown\" | \"onShutdown\" | \"beforeShutdown\" | \"onSigterm\"\n>;\n"]}
1
+ {"version":3,"file":"TerminusSettings.js","sourceRoot":"","sources":["../../../src/interfaces/TerminusSettings.ts"],"names":[],"mappings":"","sourcesContent":["import {TerminusOptions} from \"@godaddy/terminus\";\n\nexport type TerminusSettings = Omit<\n TerminusOptions,\n \"healthChecks\" | \"onSignal\" | \"onSendFailureDuringShutdown\" | \"onShutdown\" | \"beforeShutdown\" | \"onSigterm\"\n> & {path?: string};\n"]}
@@ -1,27 +1,61 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
2
  import { createTerminus } from "@godaddy/terminus";
3
- import { Configuration, Inject, InjectorService, Module } from "@tsed/di";
4
- import Https from "https";
3
+ import { Constant, Inject, InjectorService, Module } from "@tsed/di";
4
+ import { concatPath } from "@tsed/schema";
5
5
  import Http from "http";
6
+ import Https from "https";
6
7
  let TerminusModule = class TerminusModule {
7
- configuration;
8
+ settings;
9
+ basePath;
8
10
  injector;
9
11
  httpServer;
10
12
  httpsServer;
11
13
  $onInit() {
12
14
  this.mount();
13
15
  }
14
- mount() {
15
- const { terminus } = this.configuration;
16
- const terminusConfig = {
17
- logger: this.injector.logger,
16
+ getConfiguration() {
17
+ const { path, ...props } = this.settings;
18
+ return {
19
+ logger: (event, error) => this.injector.logger.info({
20
+ event: event.toUpperCase(),
21
+ error_message: error.message
22
+ }),
18
23
  healthChecks: this.getHealths(),
19
- onSignal: this.execShutdown("onSignal"),
20
- onShutdown: this.execShutdown("onShutdown"),
21
- beforeShutdown: this.execShutdown("beforeShutdown"),
22
- onSendFailureDuringShutdown: this.execShutdown("onSendFailureDuringShutdown"),
23
- ...terminus
24
+ onSignal: this.createEmitter("$onSignal"),
25
+ onShutdown: this.createEmitter("$onShutdown"),
26
+ beforeShutdown: this.createEmitter("$beforeShutdown"),
27
+ onSendFailureDuringShutdown: this.createEmitter("$onSendFailureDuringShutdown"),
28
+ ...props
24
29
  };
30
+ }
31
+ async $logRoutes(routes) {
32
+ return [
33
+ ...routes,
34
+ {
35
+ toJSON: () => {
36
+ return {
37
+ method: "GET",
38
+ name: `TerminusModule.dispatch`,
39
+ url: this.basePath
40
+ };
41
+ }
42
+ },
43
+ ...this.getAll("health").map(({ provider, propertyKey, options }) => {
44
+ const path = this.getPath(provider, options.name);
45
+ return {
46
+ toJSON() {
47
+ return {
48
+ method: "GET",
49
+ name: `${provider.className}.${propertyKey}`,
50
+ url: path
51
+ };
52
+ }
53
+ };
54
+ })
55
+ ];
56
+ }
57
+ mount() {
58
+ const terminusConfig = this.getConfiguration();
25
59
  if (this.httpServer) {
26
60
  createTerminus(this.httpServer, terminusConfig);
27
61
  }
@@ -29,39 +63,61 @@ let TerminusModule = class TerminusModule {
29
63
  createTerminus(this.httpsServer, terminusConfig);
30
64
  }
31
65
  }
32
- getProviders(name) {
33
- return this.injector.getProviders().filter((provider) => {
34
- return provider.store.get(name);
66
+ getAll(name) {
67
+ return this.injector.getProviders().flatMap((provider) => {
68
+ const metadata = provider.store.get(`terminus:${name}`);
69
+ if (metadata) {
70
+ return Object.entries(metadata).map(([propertyKey, options]) => {
71
+ return {
72
+ provider,
73
+ propertyKey,
74
+ options
75
+ };
76
+ });
77
+ }
78
+ return [];
35
79
  });
36
80
  }
37
- getStore(name) {
38
- return this.injector
39
- .getProviders()
40
- .map((provider) => provider.store.get(name))
41
- .filter((x) => !!x)
42
- .flat();
43
- }
44
81
  getHealths() {
45
- const healths = {};
46
- this.getProviders("terminus").forEach((provider) => {
47
- Object.keys(provider.store.get("terminus")).forEach((name) => {
48
- healths[`${provider.path}${name}`] = provider.store.get("terminus")[name];
49
- });
50
- });
82
+ const subHealths = this.getAll("health").reduce((healths, { provider, propertyKey, options: { name } }) => {
83
+ const instance = this.injector.get(provider.token);
84
+ const callback = async (...args) => {
85
+ const result = await instance[propertyKey](...args);
86
+ return { [name]: result };
87
+ };
88
+ let path = this.getPath(provider, name);
89
+ return {
90
+ ...healths,
91
+ [path]: callback
92
+ };
93
+ }, {});
94
+ const healths = {
95
+ ...subHealths,
96
+ [this.basePath]: (state) => {
97
+ const promises = Object.entries(subHealths).map(([path, callback]) => callback(state));
98
+ return Promise.all(promises);
99
+ }
100
+ };
51
101
  return healths;
52
102
  }
53
- execShutdown(name) {
54
- return async () => {
55
- for (const func of this.getStore(name)) {
56
- await func();
57
- }
103
+ getPath(provider, name) {
104
+ let path = concatPath(provider.path, name);
105
+ return path.includes("health") ? path : concatPath(path, this.basePath);
106
+ }
107
+ createEmitter(name) {
108
+ return async (...args) => {
109
+ return this.injector.emit(`$${name}`, ...args);
58
110
  };
59
111
  }
60
112
  };
61
113
  __decorate([
62
- Configuration(),
114
+ Constant("terminus", {}),
63
115
  __metadata("design:type", Object)
64
- ], TerminusModule.prototype, "configuration", void 0);
116
+ ], TerminusModule.prototype, "settings", void 0);
117
+ __decorate([
118
+ Constant("terminus.path", "/health"),
119
+ __metadata("design:type", String)
120
+ ], TerminusModule.prototype, "basePath", void 0);
65
121
  __decorate([
66
122
  Inject(),
67
123
  __metadata("design:type", InjectorService)
@@ -1 +1 @@
1
- {"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":"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","sourcesContent":["import {createTerminus} from \"@godaddy/terminus\";\nimport {Configuration, Inject, InjectorService, Module, OnInit} from \"@tsed/di\";\nimport Https from \"https\";\nimport Http from \"http\";\n\n@Module()\nexport class TerminusModule implements OnInit {\n @Configuration()\n private configuration: Configuration;\n\n @Inject()\n private injector: InjectorService;\n\n @Inject(Http.Server)\n private httpServer: Http.Server | null;\n\n @Inject(Https.Server)\n private httpsServer: Https.Server | null;\n\n public $onInit() {\n this.mount();\n }\n\n private mount() {\n const {terminus} = this.configuration;\n const terminusConfig = {\n logger: this.injector.logger as any,\n healthChecks: this.getHealths(),\n onSignal: this.execShutdown(\"onSignal\"),\n onShutdown: this.execShutdown(\"onShutdown\"),\n beforeShutdown: this.execShutdown(\"beforeShutdown\"),\n onSendFailureDuringShutdown: this.execShutdown(\"onSendFailureDuringShutdown\"),\n ...terminus\n };\n\n if (this.httpServer) {\n createTerminus(this.httpServer, terminusConfig);\n }\n\n if (this.httpsServer) {\n createTerminus(this.httpsServer, terminusConfig);\n }\n }\n\n private getProviders(name: string) {\n return this.injector.getProviders().filter((provider) => {\n return provider.store.get(name);\n });\n }\n\n private getStore(name: string) {\n return this.injector\n .getProviders()\n .map((provider) => provider.store.get(name))\n .filter((x) => !!x)\n .flat();\n }\n\n private getHealths() {\n const healths: {[k: string]: () => Promise<any>} = {};\n\n this.getProviders(\"terminus\").forEach((provider) => {\n Object.keys(provider.store.get(\"terminus\")).forEach((name) => {\n healths[`${provider.path}${name}`] = provider.store.get(\"terminus\")[name];\n });\n });\n\n return healths;\n }\n\n private execShutdown(name: string) {\n return async () => {\n for (const func of this.getStore(name)) {\n await func();\n }\n };\n }\n}\n"]}
1
+ {"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":"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","sourcesContent":["import {createTerminus} from \"@godaddy/terminus\";\nimport {Constant, Inject, InjectorService, Module, OnInit, Provider} from \"@tsed/di\";\nimport {concatPath} from \"@tsed/schema\";\nimport Http from \"http\";\nimport Https from \"https\";\nimport {TerminusSettings} from \"./interfaces/TerminusSettings\";\n\n@Module()\nexport class TerminusModule implements OnInit {\n @Constant(\"terminus\", {})\n private settings: TerminusSettings;\n\n @Constant(\"terminus.path\", \"/health\")\n private basePath: string;\n\n @Inject()\n private injector: InjectorService;\n\n @Inject(Http.Server)\n private httpServer: Http.Server | null;\n\n @Inject(Https.Server)\n private httpsServer: Https.Server | null;\n\n public $onInit() {\n this.mount();\n }\n\n getConfiguration() {\n const {path, ...props} = this.settings;\n\n return {\n logger: (event: string, error: any) =>\n this.injector.logger.info({\n event: event.toUpperCase(),\n error_message: error.message\n }),\n healthChecks: this.getHealths(),\n onSignal: this.createEmitter(\"$onSignal\"),\n onShutdown: this.createEmitter(\"$onShutdown\"),\n beforeShutdown: this.createEmitter(\"$beforeShutdown\"),\n onSendFailureDuringShutdown: this.createEmitter(\"$onSendFailureDuringShutdown\"),\n ...props\n };\n }\n\n async $logRoutes(routes: any[]): Promise<any[]> {\n return [\n ...routes,\n {\n toJSON: () => {\n return {\n method: \"GET\",\n name: `TerminusModule.dispatch`,\n url: this.basePath\n };\n }\n },\n ...this.getAll<{name: string}>(\"health\").map(({provider, propertyKey, options}) => {\n const path = this.getPath(provider, options.name);\n\n return {\n toJSON() {\n return {\n method: \"GET\",\n name: `${provider.className}.${propertyKey}`,\n url: path\n };\n }\n } as any;\n })\n ];\n }\n\n private mount() {\n const terminusConfig = this.getConfiguration();\n\n if (this.httpServer) {\n createTerminus(this.httpServer, terminusConfig);\n }\n\n if (this.httpsServer) {\n createTerminus(this.httpsServer, terminusConfig);\n }\n }\n\n private getAll<Opts = any>(\n name: string\n ): {\n provider: Provider;\n propertyKey: string;\n options: Opts;\n }[] {\n return this.injector.getProviders().flatMap((provider) => {\n const metadata = provider.store.get(`terminus:${name}`);\n\n if (metadata) {\n return Object.entries(metadata).map(([propertyKey, options]: [string, Opts]) => {\n return {\n provider,\n propertyKey,\n options\n };\n });\n }\n return [];\n });\n }\n\n private getHealths() {\n const subHealths = this.getAll<{name: string}>(\"health\").reduce((healths, {provider, propertyKey, options: {name}}) => {\n const instance = this.injector.get<any>(provider.token)!;\n const callback = async (...args: any[]) => {\n const result = await instance[propertyKey](...args);\n\n return {[name]: result};\n };\n\n let path = this.getPath(provider, name);\n\n return {\n ...healths,\n [path]: callback\n };\n }, {} as Record<string, (state: any) => Promise<any>>);\n\n const healths: Record<string, any> = {\n ...subHealths,\n [this.basePath]: (state: any) => {\n const promises = Object.entries(subHealths).map(([path, callback]) => callback(state));\n\n return Promise.all(promises);\n }\n };\n\n return healths;\n }\n\n private getPath(provider: Provider<any>, name: string) {\n let path = concatPath(provider.path, name);\n return path.includes(\"health\") ? path : concatPath(path, this.basePath);\n }\n\n private createEmitter(name: string) {\n return async (...args: any[]) => {\n return this.injector.emit(`$${name}`, ...args);\n };\n }\n}\n"]}
@@ -19,12 +19,10 @@ import { Store } from "@tsed/core";
19
19
  * @terminus
20
20
  */
21
21
  export function Health(name) {
22
- return (target, propertyKey, descriptor) => {
23
- if (descriptor.value) {
24
- Store.from(target).merge("terminus", {
25
- [name]: descriptor.value
26
- });
27
- }
22
+ return (target, propertyKey) => {
23
+ Store.from(target).merge(`terminus:health`, {
24
+ [propertyKey]: { name }
25
+ });
28
26
  };
29
27
  }
30
28
  //# sourceMappingURL=health.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/decorators/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEjC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,UAA6C,EAAE,EAAE;QACtG,IAAI,UAAU,CAAC,KAAK,EAAE;YACpB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE;gBACnC,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,KAAK;aACzB,CAAC,CAAC;SACJ;IACH,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import {Store} from \"@tsed/core\";\n\n/**\n * Create a readiness / liveness checks.\n *\n * ```ts\n * import { Health } from \"@tsed/terminus\";\n *\n * @Controller(\"/mongo\")\n * class MongoCtrl {\n * @Health(\"/health\")\n * health() {\n * // Here check the mongo health\n * return Promise.resolve();\n * }\n * }\n *\n * @param name\n * @decorator\n * @terminus\n */\nexport function Health(name: string): MethodDecorator {\n return <Function>(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<Function>) => {\n if (descriptor.value) {\n Store.from(target).merge(\"terminus\", {\n [name]: descriptor.value\n });\n }\n };\n}\n"]}
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/decorators/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEjC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,EAAE;QACvD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,iBAAiB,EAAE;YAC1C,CAAC,WAAW,CAAC,EAAE,EAAC,IAAI,EAAC;SACtB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import {Store} from \"@tsed/core\";\n\n/**\n * Create a readiness / liveness checks.\n *\n * ```ts\n * import { Health } from \"@tsed/terminus\";\n *\n * @Controller(\"/mongo\")\n * class MongoCtrl {\n * @Health(\"/health\")\n * health() {\n * // Here check the mongo health\n * return Promise.resolve();\n * }\n * }\n *\n * @param name\n * @decorator\n * @terminus\n */\nexport function Health(name: string): MethodDecorator {\n return <Function>(target: Object, propertyKey: string) => {\n Store.from(target).merge(`terminus:health`, {\n [propertyKey]: {name}\n });\n };\n}\n"]}
@@ -1,11 +1,8 @@
1
- import { Store } from "@tsed/core";
2
- function register(name) {
3
- return (target, propertyKey, descriptor) => {
4
- if (descriptor.value) {
5
- const store = Store.from(target);
6
- const values = store.get(name) || [];
7
- store.merge(name, [...values, descriptor.value]);
8
- }
1
+ export function register(event) {
2
+ return (target, propertyKey, description) => {
3
+ Object.defineProperty(target, `$${event}`, {
4
+ value: description.value
5
+ });
9
6
  };
10
7
  }
11
8
  /**
@@ -13,6 +10,7 @@ function register(name) {
13
10
  *
14
11
  * @decorator
15
12
  * @terminus
13
+ * @deprecated Use $BeforeShutdown hook
16
14
  */
17
15
  export function BeforeShutdown() {
18
16
  return register("beforeShutdown");
@@ -22,6 +20,7 @@ export function BeforeShutdown() {
22
20
  *
23
21
  * @decorator
24
22
  * @terminus
23
+ * @deprecated Use $onSignal hook
25
24
  */
26
25
  export function OnSignal() {
27
26
  return register("onSignal");
@@ -31,6 +30,7 @@ export function OnSignal() {
31
30
  *
32
31
  * @decorator
33
32
  * @terminus
33
+ * @deprecated Use $onShutdown hook
34
34
  */
35
35
  export function OnShutdown() {
36
36
  return register("onShutdown");
@@ -40,8 +40,9 @@ export function OnShutdown() {
40
40
  *
41
41
  * @decorator
42
42
  * @terminus
43
+ * @deprecated Use $onSendFailureDuringShutdown hook
43
44
  */
44
45
  export function OnSendFailureDuringShutdown() {
45
- return register("onSendFailureDuringShutdown");
46
+ return register("OnSendFailureDuringShutdown");
46
47
  }
47
48
  //# sourceMappingURL=shutdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../../src/decorators/shutdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEjC,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,UAA6C,EAAE,EAAE;QACtG,IAAI,UAAU,CAAC,KAAK,EAAE;YACpB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAErC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;SAClD;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACpC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,QAAQ,CAAC,YAAY,CAAC,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AACjD,CAAC","sourcesContent":["import {Store} from \"@tsed/core\";\n\nfunction register(name: string) {\n return <Function>(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<Function>) => {\n if (descriptor.value) {\n const store = Store.from(target);\n const values = store.get(name) || [];\n\n store.merge(name, [...values, descriptor.value]);\n }\n };\n}\n\n/**\n * Listen the `beforeShutdown` terminus event.\n *\n * @decorator\n * @terminus\n */\nexport function BeforeShutdown(): MethodDecorator {\n return register(\"beforeShutdown\");\n}\n\n/**\n * Listen the `onSignal` terminus event.\n *\n * @decorator\n * @terminus\n */\nexport function OnSignal(): MethodDecorator {\n return register(\"onSignal\");\n}\n\n/**\n * Listen the `onShutdown` terminus event.\n *\n * @decorator\n * @terminus\n */\nexport function OnShutdown(): MethodDecorator {\n return register(\"onShutdown\");\n}\n\n/**\n * Listen the `onSendFailureDuringShutdown` terminus event.\n *\n * @decorator\n * @terminus\n */\nexport function OnSendFailureDuringShutdown(): MethodDecorator {\n return register(\"onSendFailureDuringShutdown\");\n}\n"]}
1
+ {"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../../src/decorators/shutdown.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,WAA+B,EAAE,EAAE;QACxF,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,KAAK,EAAE,EAAE;YACzC,KAAK,EAAE,WAAW,CAAC,KAAK;SACzB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,QAAQ,CAAC,YAAY,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AACjD,CAAC","sourcesContent":["export function register(event: string) {\n return <Function>(target: Object, propertyKey: string, description: PropertyDescriptor) => {\n Object.defineProperty(target, `$${event}`, {\n value: description.value\n });\n };\n}\n\n/**\n * Listen the `beforeShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $BeforeShutdown hook\n */\nexport function BeforeShutdown(): MethodDecorator {\n return register(\"beforeShutdown\");\n}\n\n/**\n * Listen the `onSignal` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onSignal hook\n */\nexport function OnSignal(): MethodDecorator {\n return register(\"onSignal\");\n}\n\n/**\n * Listen the `onShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onShutdown hook\n */\nexport function OnShutdown(): MethodDecorator {\n return register(\"onShutdown\");\n}\n\n/**\n * Listen the `onSendFailureDuringShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onSendFailureDuringShutdown hook\n */\nexport function OnSendFailureDuringShutdown(): MethodDecorator {\n return register(\"OnSendFailureDuringShutdown\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"TerminusSettings.js","sourceRoot":"","sources":["../../../src/interfaces/TerminusSettings.ts"],"names":[],"mappings":"","sourcesContent":["import {TerminusOptions} from \"@godaddy/terminus\";\n\nexport type TerminusSettings = Omit<\n TerminusOptions,\n \"healthChecks\" | \"onSignal\" | \"onSendFailureDuringShutdown\" | \"onShutdown\" | \"beforeShutdown\" | \"onSigterm\"\n>;\n"]}
1
+ {"version":3,"file":"TerminusSettings.js","sourceRoot":"","sources":["../../../src/interfaces/TerminusSettings.ts"],"names":[],"mappings":"","sourcesContent":["import {TerminusOptions} from \"@godaddy/terminus\";\n\nexport type TerminusSettings = Omit<\n TerminusOptions,\n \"healthChecks\" | \"onSignal\" | \"onSendFailureDuringShutdown\" | \"onShutdown\" | \"beforeShutdown\" | \"onSigterm\"\n> & {path?: string};\n"]}
@@ -1,13 +1,33 @@
1
1
  import { OnInit } from "@tsed/di";
2
2
  export declare class TerminusModule implements OnInit {
3
- private configuration;
3
+ private settings;
4
+ private basePath;
4
5
  private injector;
5
6
  private httpServer;
6
7
  private httpsServer;
7
8
  $onInit(): void;
9
+ getConfiguration(): {
10
+ caseInsensitive?: boolean | undefined;
11
+ timeout?: number | undefined;
12
+ signal?: string | undefined;
13
+ signals?: string[] | undefined;
14
+ sendFailuresDuringShutdown?: boolean | undefined;
15
+ statusOk?: number | undefined;
16
+ statusError?: number | undefined;
17
+ logger: (event: string, error: any) => any;
18
+ headers?: {
19
+ [key: string]: string;
20
+ } | undefined;
21
+ healthChecks: Record<string, any>;
22
+ onSignal: (...args: any[]) => Promise<void>;
23
+ onShutdown: (...args: any[]) => Promise<void>;
24
+ beforeShutdown: (...args: any[]) => Promise<void>;
25
+ onSendFailureDuringShutdown: (...args: any[]) => Promise<void>;
26
+ };
27
+ $logRoutes(routes: any[]): Promise<any[]>;
8
28
  private mount;
9
- private getProviders;
10
- private getStore;
29
+ private getAll;
11
30
  private getHealths;
12
- private execShutdown;
31
+ private getPath;
32
+ private createEmitter;
13
33
  }
@@ -1,8 +1,10 @@
1
+ export declare function register(event: string): <Function_1>(target: Object, propertyKey: string, description: PropertyDescriptor) => void;
1
2
  /**
2
3
  * Listen the `beforeShutdown` terminus event.
3
4
  *
4
5
  * @decorator
5
6
  * @terminus
7
+ * @deprecated Use $BeforeShutdown hook
6
8
  */
7
9
  export declare function BeforeShutdown(): MethodDecorator;
8
10
  /**
@@ -10,6 +12,7 @@ export declare function BeforeShutdown(): MethodDecorator;
10
12
  *
11
13
  * @decorator
12
14
  * @terminus
15
+ * @deprecated Use $onSignal hook
13
16
  */
14
17
  export declare function OnSignal(): MethodDecorator;
15
18
  /**
@@ -17,6 +20,7 @@ export declare function OnSignal(): MethodDecorator;
17
20
  *
18
21
  * @decorator
19
22
  * @terminus
23
+ * @deprecated Use $onShutdown hook
20
24
  */
21
25
  export declare function OnShutdown(): MethodDecorator;
22
26
  /**
@@ -24,5 +28,6 @@ export declare function OnShutdown(): MethodDecorator;
24
28
  *
25
29
  * @decorator
26
30
  * @terminus
31
+ * @deprecated Use $onSendFailureDuringShutdown hook
27
32
  */
28
33
  export declare function OnSendFailureDuringShutdown(): MethodDecorator;
@@ -1,2 +1,4 @@
1
1
  import { TerminusOptions } from "@godaddy/terminus";
2
- export declare type TerminusSettings = Omit<TerminusOptions, "healthChecks" | "onSignal" | "onSendFailureDuringShutdown" | "onShutdown" | "beforeShutdown" | "onSigterm">;
2
+ export declare type TerminusSettings = Omit<TerminusOptions, "healthChecks" | "onSignal" | "onSendFailureDuringShutdown" | "onShutdown" | "beforeShutdown" | "onSigterm"> & {
3
+ path?: string;
4
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsed/terminus",
3
- "version": "6.126.1",
3
+ "version": "6.128.1",
4
4
  "description": "Adds graceful shutdown and Kubernetes readiness / liveness checks for any HTTP applications.",
5
5
  "author": "Romain Lenzotti",
6
6
  "private": false,
@@ -19,22 +19,23 @@
19
19
  "build:cjs": "tsc --build tsconfig.compile.json",
20
20
  "build:esm": "tsc --build tsconfig.compile.esm.json",
21
21
  "barrels": "yarn barrelsby --delete -d ./src -e \"\\.spec\\.ts\" -e \"__mock__\" -e \".benchmark.ts\"",
22
- "start": "ts-node -r tsconfig-paths/register test/app/index.ts"
22
+ "start": "ts-node -r tsconfig-paths/register test/app/index.ts",
23
+ "test": "cross-env NODE_ENV=test yarn jest --max-workers=2"
23
24
  },
24
25
  "dependencies": {
25
26
  "tslib": "2.4.0"
26
27
  },
27
28
  "devDependencies": {
28
29
  "@godaddy/terminus": "^4.7.1",
29
- "@tsed/core": "6.126.1",
30
- "@tsed/di": "6.126.1",
31
- "@tsed/schema": "6.126.1"
30
+ "@tsed/core": "6.128.1",
31
+ "@tsed/di": "6.128.1",
32
+ "@tsed/schema": "6.128.1"
32
33
  },
33
34
  "peerDependencies": {
34
35
  "@godaddy/terminus": "^4.7.1",
35
- "@tsed/core": "^6.126.1",
36
- "@tsed/di": "^6.126.1",
37
- "@tsed/schema": "^6.126.1"
36
+ "@tsed/core": "^6.128.1",
37
+ "@tsed/di": "^6.128.1",
38
+ "@tsed/schema": "^6.128.1"
38
39
  },
39
40
  "peerDependenciesMeta": {
40
41
  "@godaddy/terminus": {
package/readme.md CHANGED
@@ -28,7 +28,7 @@
28
28
 
29
29
  <hr />
30
30
 
31
- Adds graceful shutdown and Kubernetes readiness / liveness checks for any HTTP applications.
31
+ Adds graceful shutdown and Kubernetes readiness / liveliness checks for any HTTP applications.
32
32
 
33
33
  ## Installation
34
34
 
@@ -74,19 +74,31 @@ export type TerminusSettings = Omit<
74
74
 
75
75
  ## Usage
76
76
 
77
- ### Readiness / liveness checks
77
+ ### Readiness / liveliness checks
78
78
 
79
- To create a readiness / liveness checks use the `@Health` decorator.
79
+ To create a readiness / liveliness checks use the `@Health` decorator.
80
80
 
81
81
  ```ts
82
82
  import {Health} from "@tsed/terminus";
83
+ import {Injectable, Inject} from "@tsed/di";
84
+ import {HealthCheckError} from "@godaddy/terminus";
85
+ import {REDIS_CONNECTION} from "./RedisConnection";
86
+
87
+ @Injectable()
88
+ class RedisClient {
89
+ @Inject(REDIS_CONNECTION)
90
+ protected redisConnection: REDIS_CONNECTION;
91
+
92
+ @Health("redis")
93
+ async check() {
94
+ if (this.redisConnection.status === "ready") {
95
+ return "OK";
96
+ }
83
97
 
84
- @Controller("/mongo")
85
- class MongoCtrl {
86
- @Health("/health")
87
- health() {
88
- // Here check the mongo health
89
- return Promise.resolve();
98
+ // Here check the redis health
99
+ throw new HealthCheckError("failed", {
100
+ redis: this.redisConnection.status
101
+ });
90
102
  }
91
103
  }
92
104
  ```
@@ -95,56 +107,84 @@ You can also create an `HealthCheckError` when an error appear during your check
95
107
 
96
108
  ```ts
97
109
  import {Health} from "@tsed/terminus";
110
+ import {Injectable, Inject} from "@tsed/di";
98
111
  import {HealthCheckError} from "@godaddy/terminus";
112
+ import {REDIS_CONNECTION} from "./RedisConnection";
113
+
114
+ @Injectable()
115
+ class RedisClient {
116
+ @Inject(REDIS_CONNECTION)
117
+ protected redisConnection: REDIS_CONNECTION;
118
+
119
+ @Health("redis")
120
+ async check() {
121
+ if (this.redisConnection.status === "ready") {
122
+ return "ok";
123
+ }
99
124
 
100
- @Controller("/redis")
101
- class Redis {
102
- @Health("/health")
103
- health() {
104
125
  // Here check the redis health
105
- return Promise.reject(
106
- new HealthCheckError("failed", {
107
- redis: "down"
108
- })
109
- );
126
+ throw new HealthCheckError("failed", {
127
+ redis: this.redisConnection.status
128
+ });
110
129
  }
111
130
  }
112
131
  ```
113
132
 
133
+ Expected result when calling the "/health":
134
+
135
+ ```json
136
+ {
137
+ "status": "ok",
138
+ "info": [
139
+ {
140
+ "mongo": "ok"
141
+ },
142
+ {
143
+ "redis": "ok"
144
+ }
145
+ ],
146
+ "details": [
147
+ {
148
+ "mongo": "ok"
149
+ },
150
+ {
151
+ "redis": "ok"
152
+ }
153
+ ]
154
+ }
155
+ ```
156
+
114
157
  ### Graceful shutdown
115
158
 
116
159
  `@tsed/terminus` package give some decorators to handle Terminus hooks. These hooks allow you to adds graceful shutdown.
117
160
  Here is the list of decorators:
118
161
 
119
- - `BeforeShutdown`: Use this hook if you deploy your application with Kubernetes (see more details [here](https://github.com/godaddy/terminus#how-to-set-terminus-up-with-kubernetes)),
120
- - `OnSignal`: cleanup hook, returning a promise (used to be onSigterm),
121
- - `OnShutdown`: called right before exiting,
122
- - `OnSendFailureDuringShutdown`: called before sending each 503 during shutdowns.
162
+ - `$beforeShutdown`: Use this hook if you deploy your application with Kubernetes (see more
163
+ details [here](https://github.com/godaddy/terminus#how-to-set-terminus-up-with-kubernetes)),
164
+ - `$onSignal`: cleanup hook, returning a promise (used to be onSigterm),
165
+ - `$onShutdown`: called right before exiting,
166
+ - `$onSendFailureDuringShutdown`: called before sending each 503 during shutdowns.
123
167
 
124
168
  **Example:**
125
169
 
126
170
  ```typescript
127
- import {BeforeShutdown, OnSendFailureDuringShutdown, OnShutdown, OnSignal} from "@tsed/terminus";
171
+ import {Injectable} from "@tsed/di";
128
172
 
129
- @Controller("/redis")
173
+ @Injectable()
130
174
  class RedisCtrl {
131
- @BeforeShutdown()
132
- beforeShutdow() {
175
+ $beforeShutdown() {
133
176
  console.log("called before shutdown");
134
177
  }
135
178
 
136
- @OnSignal()
137
- OnSignal() {
179
+ $onSignal() {
138
180
  console.log("called on signal");
139
181
  }
140
182
 
141
- @OnShutdown()
142
- OnShutdown() {
183
+ $onShutdown() {
143
184
  console.log("called on shutdown");
144
185
  }
145
186
 
146
- @OnSendFailureDuringShutdown()
147
- OnSendFailureDuringShutdown() {
187
+ $onSendFailureDuringShutdown() {
148
188
  console.log("on send failure during shutdown");
149
189
  }
150
190
  }