@tsed/terminus 7.0.0-beta.7 → 7.0.0-rc.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 +14 -0
- package/lib/cjs/TerminusModule.js +93 -31
- package/lib/cjs/TerminusModule.js.map +1 -1
- package/lib/cjs/decorators/health.js +4 -6
- package/lib/cjs/decorators/health.js.map +1 -1
- package/lib/cjs/decorators/shutdown.js +12 -10
- package/lib/cjs/decorators/shutdown.js.map +1 -1
- package/lib/cjs/interfaces/TerminusSettings.js.map +1 -1
- package/lib/esm/TerminusModule.js +94 -32
- package/lib/esm/TerminusModule.js.map +1 -1
- package/lib/esm/decorators/health.js +4 -6
- package/lib/esm/decorators/health.js.map +1 -1
- package/lib/esm/decorators/shutdown.js +10 -9
- package/lib/esm/decorators/shutdown.js.map +1 -1
- package/lib/esm/interfaces/TerminusSettings.js.map +1 -1
- package/lib/types/TerminusModule.d.ts +24 -4
- package/lib/types/decorators/shutdown.d.ts +5 -0
- package/lib/types/interfaces/TerminusSettings.d.ts +3 -1
- package/package.json +20 -12
- package/readme.md +75 -34
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
|
|
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
|
-
|
|
14
|
-
const {
|
|
15
|
-
|
|
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.
|
|
19
|
-
onShutdown: this.
|
|
20
|
-
beforeShutdown: this.
|
|
21
|
-
onSendFailureDuringShutdown: this.
|
|
22
|
-
...
|
|
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
|
-
|
|
32
|
-
return this.injector.getProviders().
|
|
33
|
-
|
|
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
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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.
|
|
117
|
+
(0, di_1.Constant)("terminus", {}),
|
|
60
118
|
tslib_1.__metadata("design:type", Object)
|
|
61
|
-
], TerminusModule.prototype, "
|
|
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,
|
|
1
|
+
{"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":";;;;AAAA,gDAAiD;AACjD,iCAAqF;AACrF,yCAAwC;AACxC,wDAAwB;AACxB,0DAA0B;AAI1B,IAAa,cAAc,GAA3B,MAAa,cAAc;IAEjB,QAAQ,CAAmB;IAG3B,QAAQ,CAAS;IAGjB,QAAQ,CAAkB;IAG1B,UAAU,CAAqB;IAG/B,WAAW,CAAsB;IAElC,OAAO;QACZ,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED,gBAAgB;QACd,MAAM,EAAC,IAAI,EAAE,GAAG,KAAK,EAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;QAEvC,OAAO;YACL,MAAM,EAAE,CAAC,KAAa,EAAE,KAAU,EAAE,EAAE,CACpC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;gBACxB,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE;gBAC1B,aAAa,EAAE,KAAK,CAAC,OAAO;aAC7B,CAAC;YACJ,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE;YAC/B,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC;YACzC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC;YAC7C,cAAc,EAAE,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC;YACrD,2BAA2B,EAAE,IAAI,CAAC,aAAa,CAAC,8BAA8B,CAAC;YAC/E,GAAG,KAAK;SACT,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAa;QAC5B,OAAO;YACL,GAAG,MAAM;YACT;gBACE,MAAM,EAAE,GAAG,EAAE;oBACX,OAAO;wBACL,MAAM,EAAE,KAAK;wBACb,IAAI,EAAE,yBAAyB;wBAC/B,GAAG,EAAE,IAAI,CAAC,QAAQ;qBACnB,CAAC;gBACJ,CAAC;aACF;YACD,GAAG,IAAI,CAAC,MAAM,CAAiB,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,EAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAC,EAAE,EAAE;gBAChF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBAElD,OAAO;oBACL,MAAM;wBACJ,OAAO;4BACL,MAAM,EAAE,KAAK;4BACb,IAAI,EAAE,GAAG,QAAQ,CAAC,SAAS,IAAI,WAAW,EAAE;4BAC5C,GAAG,EAAE,IAAI;yBACV,CAAC;oBACJ,CAAC;iBACK,CAAC;YACX,CAAC,CAAC;SACH,CAAC;IACJ,CAAC;IAEO,KAAK;QACX,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE/C,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,MAAM,CACZ,IAAY;QAMZ,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YACvD,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;YAExD,IAAI,QAAQ,EAAE;gBACZ,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,CAAiB,EAAE,EAAE;oBAC7E,OAAO;wBACL,QAAQ;wBACR,WAAW;wBACX,OAAO;qBACR,CAAC;gBACJ,CAAC,CAAC,CAAC;aACJ;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,UAAU;QAChB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAiB,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,EAAC,IAAI,EAAC,EAAC,EAAE,EAAE;YACpH,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAM,QAAQ,CAAC,KAAK,CAAE,CAAC;YACzD,MAAM,QAAQ,GAAG,KAAK,EAAE,GAAG,IAAW,EAAE,EAAE;gBACxC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;gBAEpD,OAAO,EAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAC,CAAC;YAC1B,CAAC,CAAC;YAEF,IAAI,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAExC,OAAO;gBACL,GAAG,OAAO;gBACV,CAAC,IAAI,CAAC,EAAE,QAAQ;aACjB,CAAC;QACJ,CAAC,EAAE,EAAkD,CAAC,CAAC;QAEvD,MAAM,OAAO,GAAwB;YACnC,GAAG,UAAU;YACb,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAU,EAAE,EAAE;gBAC9B,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;gBAEvF,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC/B,CAAC;SACF,CAAC;QAEF,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,OAAO,CAAC,QAAuB,EAAE,IAAY;QACnD,IAAI,IAAI,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAA,mBAAU,EAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1E,CAAC;IAEO,aAAa,CAAC,IAAY;QAChC,OAAO,KAAK,EAAE,GAAG,IAAW,EAAE,EAAE;YAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;QACjD,CAAC,CAAC;IACJ,CAAC;CACF,CAAA;AA1IC;IADC,IAAA,aAAQ,EAAC,UAAU,EAAE,EAAE,CAAC;;gDACU;AAGnC;IADC,IAAA,aAAQ,EAAC,eAAe,EAAE,SAAS,CAAC;;gDACZ;AAGzB;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;AAd9B,cAAc;IAD1B,IAAA,WAAM,GAAE;GACI,cAAc,CA4I1B;AA5IY,wCAAc","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
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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,
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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("
|
|
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,
|
|
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
|
|
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 {
|
|
4
|
-
import
|
|
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
|
-
|
|
11
|
-
const {
|
|
12
|
-
|
|
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.
|
|
16
|
-
onShutdown: this.
|
|
17
|
-
beforeShutdown: this.
|
|
18
|
-
onSendFailureDuringShutdown: this.
|
|
19
|
-
...
|
|
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
|
-
|
|
29
|
-
return this.injector.getProviders().
|
|
30
|
-
|
|
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
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
114
|
+
Constant("terminus", {}),
|
|
57
115
|
__metadata("design:type", Object)
|
|
58
|
-
], TerminusModule.prototype, "
|
|
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,
|
|
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
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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,
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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("
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
10
|
-
private getStore;
|
|
29
|
+
private getAll;
|
|
11
30
|
private getHealths;
|
|
12
|
-
private
|
|
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-
|
|
3
|
+
"version": "7.0.0-rc.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,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
|
-
"
|
|
26
|
-
"tslib": "2.3.1"
|
|
26
|
+
"tslib": "2.4.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@
|
|
30
|
-
"@tsed/
|
|
31
|
-
"@tsed/
|
|
29
|
+
"@godaddy/terminus": "^4.7.1",
|
|
30
|
+
"@tsed/core": "7.0.0-rc.1",
|
|
31
|
+
"@tsed/di": "7.0.0-rc.1",
|
|
32
|
+
"@tsed/schema": "7.0.0-rc.1"
|
|
32
33
|
},
|
|
33
34
|
"peerDependencies": {
|
|
34
|
-
"@
|
|
35
|
-
"@tsed/
|
|
36
|
-
"@tsed/
|
|
35
|
+
"@godaddy/terminus": "^4.7.1",
|
|
36
|
+
"@tsed/core": "^7.0.0-rc.1",
|
|
37
|
+
"@tsed/di": "^7.0.0-rc.1",
|
|
38
|
+
"@tsed/schema": "^7.0.0-rc.1"
|
|
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/
|
|
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
|
[](https://badge.fury.io/js/%40tsed%2Fcommon)
|
|
12
12
|
[](https://github.com/semantic-release/semantic-release)
|
|
13
13
|
[](https://github.com/prettier/prettier)
|
|
14
|
-
[](https://github.com/sponsors/romakita)
|
|
15
|
+
[](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 /
|
|
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 /
|
|
77
|
+
### Readiness / liveliness checks
|
|
77
78
|
|
|
78
|
-
To create a readiness /
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
-
|
|
119
|
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
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 {
|
|
171
|
+
import {Injectable} from "@tsed/di";
|
|
127
172
|
|
|
128
|
-
@
|
|
173
|
+
@Injectable()
|
|
129
174
|
class RedisCtrl {
|
|
130
|
-
|
|
131
|
-
beforeShutdow() {
|
|
175
|
+
$beforeShutdown() {
|
|
132
176
|
console.log("called before shutdown");
|
|
133
177
|
}
|
|
134
178
|
|
|
135
|
-
|
|
136
|
-
OnSignal() {
|
|
179
|
+
$onSignal() {
|
|
137
180
|
console.log("called on signal");
|
|
138
181
|
}
|
|
139
182
|
|
|
140
|
-
|
|
141
|
-
OnShutdown() {
|
|
183
|
+
$onShutdown() {
|
|
142
184
|
console.log("called on shutdown");
|
|
143
185
|
}
|
|
144
186
|
|
|
145
|
-
|
|
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 -
|
|
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
|
|