@tsed/terminus 7.0.0-beta.8 → 7.0.0-rc.2

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,23 +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 {
11
+ settings;
12
+ basePath;
13
+ injector;
14
+ httpServer;
15
+ httpsServer;
10
16
  $onInit() {
11
17
  this.mount();
12
18
  }
13
- mount() {
14
- const { terminus } = this.configuration;
15
- const terminusConfig = {
16
- 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
+ }),
17
26
  healthChecks: this.getHealths(),
18
- onSignal: this.execShutdown("onSignal"),
19
- onShutdown: this.execShutdown("onShutdown"),
20
- beforeShutdown: this.execShutdown("beforeShutdown"),
21
- onSendFailureDuringShutdown: this.execShutdown("onSendFailureDuringShutdown"),
22
- ...terminus
27
+ onSignal: this.createEmitter("$onSignal"),
28
+ onShutdown: this.createEmitter("$onShutdown"),
29
+ beforeShutdown: this.createEmitter("$beforeShutdown"),
30
+ onSendFailureDuringShutdown: this.createEmitter("$onSendFailureDuringShutdown"),
31
+ ...props
23
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();
24
62
  if (this.httpServer) {
25
63
  (0, terminus_1.createTerminus)(this.httpServer, terminusConfig);
26
64
  }
@@ -28,37 +66,61 @@ let TerminusModule = class TerminusModule {
28
66
  (0, terminus_1.createTerminus)(this.httpsServer, terminusConfig);
29
67
  }
30
68
  }
31
- getProviders(name) {
32
- return this.injector.getProviders().filter((provider) => {
33
- 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 [];
34
82
  });
35
83
  }
36
- getStore(name) {
37
- return this.injector
38
- .getProviders()
39
- .map((provider) => provider.store.get(name))
40
- .filter((x) => !!x)
41
- .flat();
42
- }
43
84
  getHealths() {
44
- const healths = {};
45
- this.getProviders("terminus").forEach((provider) => {
46
- Object.keys(provider.store.get("terminus")).forEach((name) => {
47
- healths[`${provider.path}${name}`] = provider.store.get("terminus")[name];
48
- });
49
- });
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
+ };
50
104
  return healths;
51
105
  }
52
- execShutdown(name) {
53
- return async () => {
54
- this.getStore(name).forEach((func) => func());
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);
55
113
  };
56
114
  }
57
115
  };
58
116
  tslib_1.__decorate([
59
- (0, di_1.Configuration)(),
117
+ (0, di_1.Constant)("terminus", {}),
60
118
  tslib_1.__metadata("design:type", Object)
61
- ], 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);
62
124
  tslib_1.__decorate([
63
125
  (0, di_1.Inject)(),
64
126
  tslib_1.__metadata("design:type", di_1.InjectorService)
@@ -1 +1 @@
1
- {"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":";;;;AAAA,gDAAiD;AACjD,iCAAgF;AAChF,0DAA0B;AAC1B,wDAAwB;AAGxB,IAAa,cAAc,GAA3B,MAAa,cAAc;IAalB,OAAO;QACZ,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAEO,KAAK;QACX,MAAM,EAAC,QAAQ,EAAC,GAAG,IAAI,CAAC,aAAa,CAAC;QACtC,MAAM,cAAc,GAAG;YACrB,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAa;YACnC,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE;YAC/B,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC;YACvC,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;YAC3C,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC;YACnD,2BAA2B,EAAE,IAAI,CAAC,YAAY,CAAC,6BAA6B,CAAC;YAC7E,GAAG,QAAQ;SACZ,CAAC;QAEF,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,IAAA,yBAAc,EAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;SACjD;QAED,IAAI,IAAI,CAAC,WAAW,EAAE;YACpB,IAAA,yBAAc,EAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;SAClD;IACH,CAAC;IAEO,YAAY,CAAC,IAAY;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE;YACtD,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,QAAQ,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,QAAQ;aACjB,YAAY,EAAE;aACd,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;aAC3C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;aAClB,IAAI,EAAE,CAAC;IACZ,CAAC;IAEO,UAAU;QAChB,MAAM,OAAO,GAAsC,EAAE,CAAC;QAEtD,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YACjD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC3D,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;YAC5E,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,YAAY,CAAC,IAAY;QAC/B,OAAO,KAAK,IAAI,EAAE;YAChB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC,CAAC;IACJ,CAAC;CACF,CAAA;AAnEC;IADC,IAAA,kBAAa,GAAE;;qDACqB;AAGrC;IADC,IAAA,WAAM,GAAE;sCACS,oBAAe;gDAAC;AAGlC;IADC,IAAA,WAAM,EAAC,cAAI,CAAC,MAAM,CAAC;;kDACmB;AAGvC;IADC,IAAA,WAAM,EAAC,eAAK,CAAC,MAAM,CAAC;;mDACoB;AAX9B,cAAc;IAD1B,IAAA,WAAM,GAAE;GACI,cAAc,CAqE1B;AArEY,wCAAc","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 this.getStore(name).forEach((func) => func());\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,23 +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 {
8
+ settings;
9
+ basePath;
10
+ injector;
11
+ httpServer;
12
+ httpsServer;
7
13
  $onInit() {
8
14
  this.mount();
9
15
  }
10
- mount() {
11
- const { terminus } = this.configuration;
12
- const terminusConfig = {
13
- 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
+ }),
14
23
  healthChecks: this.getHealths(),
15
- onSignal: this.execShutdown("onSignal"),
16
- onShutdown: this.execShutdown("onShutdown"),
17
- beforeShutdown: this.execShutdown("beforeShutdown"),
18
- onSendFailureDuringShutdown: this.execShutdown("onSendFailureDuringShutdown"),
19
- ...terminus
24
+ onSignal: this.createEmitter("$onSignal"),
25
+ onShutdown: this.createEmitter("$onShutdown"),
26
+ beforeShutdown: this.createEmitter("$beforeShutdown"),
27
+ onSendFailureDuringShutdown: this.createEmitter("$onSendFailureDuringShutdown"),
28
+ ...props
20
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();
21
59
  if (this.httpServer) {
22
60
  createTerminus(this.httpServer, terminusConfig);
23
61
  }
@@ -25,37 +63,61 @@ let TerminusModule = class TerminusModule {
25
63
  createTerminus(this.httpsServer, terminusConfig);
26
64
  }
27
65
  }
28
- getProviders(name) {
29
- return this.injector.getProviders().filter((provider) => {
30
- 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 [];
31
79
  });
32
80
  }
33
- getStore(name) {
34
- return this.injector
35
- .getProviders()
36
- .map((provider) => provider.store.get(name))
37
- .filter((x) => !!x)
38
- .flat();
39
- }
40
81
  getHealths() {
41
- const healths = {};
42
- this.getProviders("terminus").forEach((provider) => {
43
- Object.keys(provider.store.get("terminus")).forEach((name) => {
44
- healths[`${provider.path}${name}`] = provider.store.get("terminus")[name];
45
- });
46
- });
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
+ };
47
101
  return healths;
48
102
  }
49
- execShutdown(name) {
50
- return async () => {
51
- this.getStore(name).forEach((func) => func());
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);
52
110
  };
53
111
  }
54
112
  };
55
113
  __decorate([
56
- Configuration(),
114
+ Constant("terminus", {}),
57
115
  __metadata("design:type", Object)
58
- ], 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);
59
121
  __decorate([
60
122
  Inject(),
61
123
  __metadata("design:type", InjectorService)
@@ -1 +1 @@
1
- {"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":";AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAC,aAAa,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAS,MAAM,UAAU,CAAC;AAChF,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,IAAa,cAAc,GAA3B,MAAa,cAAc;IAalB,OAAO;QACZ,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAEO,KAAK;QACX,MAAM,EAAC,QAAQ,EAAC,GAAG,IAAI,CAAC,aAAa,CAAC;QACtC,MAAM,cAAc,GAAG;YACrB,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAa;YACnC,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE;YAC/B,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC;YACvC,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;YAC3C,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC;YACnD,2BAA2B,EAAE,IAAI,CAAC,YAAY,CAAC,6BAA6B,CAAC;YAC7E,GAAG,QAAQ;SACZ,CAAC;QAEF,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,cAAc,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;SACjD;QAED,IAAI,IAAI,CAAC,WAAW,EAAE;YACpB,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;SAClD;IACH,CAAC;IAEO,YAAY,CAAC,IAAY;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE;YACtD,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,QAAQ,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,QAAQ;aACjB,YAAY,EAAE;aACd,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;aAC3C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;aAClB,IAAI,EAAE,CAAC;IACZ,CAAC;IAEO,UAAU;QAChB,MAAM,OAAO,GAAsC,EAAE,CAAC;QAEtD,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YACjD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC3D,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;YAC5E,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,YAAY,CAAC,IAAY;QAC/B,OAAO,KAAK,IAAI,EAAE;YAChB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC,CAAC;IACJ,CAAC;CACF,CAAA;AAnEC;IADC,aAAa,EAAE;;qDACqB;AAGrC;IADC,MAAM,EAAE;8BACS,eAAe;gDAAC;AAGlC;IADC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;;kDACmB;AAGvC;IADC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;;mDACoB;AAX9B,cAAc;IAD1B,MAAM,EAAE;GACI,cAAc,CAqE1B;SArEY,cAAc","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 this.getStore(name).forEach((func) => func());\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": "7.0.0-beta.8",
3
+ "version": "7.0.0-rc.2",
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,23 +19,28 @@
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
- "@godaddy/terminus": "^4.7.1",
26
- "tslib": "2.3.1"
26
+ "tslib": "2.4.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@tsed/core": "7.0.0-beta.8",
30
- "@tsed/di": "7.0.0-beta.8",
31
- "@tsed/schema": "7.0.0-beta.8"
29
+ "@godaddy/terminus": "^4.7.1",
30
+ "@tsed/core": "7.0.0-rc.2",
31
+ "@tsed/di": "7.0.0-rc.2",
32
+ "@tsed/schema": "7.0.0-rc.2"
32
33
  },
33
34
  "peerDependencies": {
34
- "@tsed/core": "^7.0.0-beta.8",
35
- "@tsed/di": "^7.0.0-beta.8",
36
- "@tsed/schema": "^7.0.0-beta.8"
35
+ "@godaddy/terminus": "^4.7.1",
36
+ "@tsed/core": "^7.0.0-rc.2",
37
+ "@tsed/di": "^7.0.0-rc.2",
38
+ "@tsed/schema": "^7.0.0-rc.2"
37
39
  },
38
40
  "peerDependenciesMeta": {
41
+ "@godaddy/terminus": {
42
+ "optional": false
43
+ },
39
44
  "@tsed/core": {
40
45
  "optional": false
41
46
  },
@@ -50,6 +55,9 @@
50
55
  "bugs": {
51
56
  "url": "https://github.com/tsedio/tsed/issues"
52
57
  },
53
- "homepage": "https://github.com/tsedio/tsed/tree/beta/packages/third-parties/terminus",
54
- "license": "MIT"
58
+ "homepage": "https://github.com/tsedio/tsed/tree/rc/packages/third-parties/terminus",
59
+ "license": "MIT",
60
+ "publishConfig": {
61
+ "tag": "rc"
62
+ }
55
63
  }
package/readme.md CHANGED
@@ -11,7 +11,8 @@
11
11
  [![npm version](https://badge.fury.io/js/%40tsed%2Fcommon.svg)](https://badge.fury.io/js/%40tsed%2Fcommon)
12
12
  [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
13
13
  [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
14
- [![backers](https://opencollective.com/tsed/tiers/badge.svg)](https://opencollective.com/tsed)
14
+ [![github](https://img.shields.io/static/v1?label=Github%20sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/romakita)
15
+ [![opencollective](https://img.shields.io/static/v1?label=OpenCollective%20sponsor&message=%E2%9D%A4&logo=OpenCollective&color=%23fe8e86)](https://opencollective.com/tsed)
15
16
 
16
17
  </div>
17
18
 
@@ -27,7 +28,7 @@
27
28
 
28
29
  <hr />
29
30
 
30
- 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.
31
32
 
32
33
  ## Installation
33
34
 
@@ -73,19 +74,31 @@ export type TerminusSettings = Omit<
73
74
 
74
75
  ## Usage
75
76
 
76
- ### Readiness / liveness checks
77
+ ### Readiness / liveliness checks
77
78
 
78
- To create a readiness / liveness checks use the `@Health` decorator.
79
+ To create a readiness / liveliness checks use the `@Health` decorator.
79
80
 
80
81
  ```ts
81
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
+ }
82
97
 
83
- @Controller("/mongo")
84
- class MongoCtrl {
85
- @Health("/health")
86
- health() {
87
- // Here check the mongo health
88
- return Promise.resolve();
98
+ // Here check the redis health
99
+ throw new HealthCheckError("failed", {
100
+ redis: this.redisConnection.status
101
+ });
89
102
  }
90
103
  }
91
104
  ```
@@ -94,56 +107,84 @@ You can also create an `HealthCheckError` when an error appear during your check
94
107
 
95
108
  ```ts
96
109
  import {Health} from "@tsed/terminus";
110
+ import {Injectable, Inject} from "@tsed/di";
97
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
+ }
98
124
 
99
- @Controller("/redis")
100
- class Redis {
101
- @Health("/health")
102
- health() {
103
125
  // Here check the redis health
104
- return Promise.reject(
105
- new HealthCheckError("failed", {
106
- redis: "down"
107
- })
108
- );
126
+ throw new HealthCheckError("failed", {
127
+ redis: this.redisConnection.status
128
+ });
109
129
  }
110
130
  }
111
131
  ```
112
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
+
113
157
  ### Graceful shutdown
114
158
 
115
159
  `@tsed/terminus` package give some decorators to handle Terminus hooks. These hooks allow you to adds graceful shutdown.
116
160
  Here is the list of decorators:
117
161
 
118
- - `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)),
119
- - `OnSignal`: cleanup hook, returning a promise (used to be onSigterm),
120
- - `OnShutdown`: called right before exiting,
121
- - `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.
122
167
 
123
168
  **Example:**
124
169
 
125
170
  ```typescript
126
- import {BeforeShutdown, OnSendFailureDuringShutdown, OnShutdown, OnSignal} from "@tsed/terminus";
171
+ import {Injectable} from "@tsed/di";
127
172
 
128
- @Controller("/redis")
173
+ @Injectable()
129
174
  class RedisCtrl {
130
- @BeforeShutdown()
131
- beforeShutdow() {
175
+ $beforeShutdown() {
132
176
  console.log("called before shutdown");
133
177
  }
134
178
 
135
- @OnSignal()
136
- OnSignal() {
179
+ $onSignal() {
137
180
  console.log("called on signal");
138
181
  }
139
182
 
140
- @OnShutdown()
141
- OnShutdown() {
183
+ $onShutdown() {
142
184
  console.log("called on shutdown");
143
185
  }
144
186
 
145
- @OnSendFailureDuringShutdown()
146
- OnSendFailureDuringShutdown() {
187
+ $onSendFailureDuringShutdown() {
147
188
  console.log("on send failure during shutdown");
148
189
  }
149
190
  }
@@ -169,7 +210,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
169
210
 
170
211
  The MIT License (MIT)
171
212
 
172
- Copyright (c) 2016 - 2018 Romain Lenzotti
213
+ Copyright (c) 2016 - 2022 Romain Lenzotti
173
214
 
174
215
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
175
216