@notchjs/core 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application.d.ts +6 -0
- package/dist/application.js +51 -5
- package/dist/hook-collector.d.ts +2 -2
- package/dist/hook-collector.js +2 -2
- package/dist/http-adapter-host.d.ts +2 -2
- package/dist/interfaces/application-config.d.ts +2 -0
- package/dist/interfaces/shutdown-options.d.ts +7 -0
- package/dist/interfaces/shutdown-options.js +2 -0
- package/dist/logger-host.d.ts +2 -2
- package/dist/notch.module.js +6 -6
- package/package.json +5 -5
package/dist/application.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
+
/// <reference types="node" />
|
|
3
4
|
import * as http from 'node:http';
|
|
4
5
|
import * as https from 'node:https';
|
|
5
6
|
import type { HttpAdapter } from '@notchjs/types';
|
|
@@ -10,6 +11,8 @@ export declare class Application {
|
|
|
10
11
|
private readonly adapter;
|
|
11
12
|
private readonly hooks;
|
|
12
13
|
private readonly _environment;
|
|
14
|
+
private readonly activeSignals;
|
|
15
|
+
private cleanupRef?;
|
|
13
16
|
private isInitialized;
|
|
14
17
|
private isListening;
|
|
15
18
|
constructor(adapter: HttpAdapter, hooks: HookCollector, environment: ApplicationEnvironment);
|
|
@@ -23,6 +26,9 @@ export declare class Application {
|
|
|
23
26
|
listen(port: string | number, hostname: string, callback?: () => void): Promise<any>;
|
|
24
27
|
close(signal?: string): Promise<void>;
|
|
25
28
|
getUrl(): Promise<string>;
|
|
29
|
+
protected shutdownOnSignal(signals?: (NodeJS.Signals | string)[]): void;
|
|
30
|
+
protected listenToSignals(signals: NodeJS.Signals[]): void;
|
|
31
|
+
protected unsubscribeFromSignals(): void;
|
|
26
32
|
protected dispose(): Promise<void>;
|
|
27
33
|
private formatAddress;
|
|
28
34
|
private getProtocol;
|
package/dist/application.js
CHANGED
|
@@ -3,8 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Application = void 0;
|
|
4
4
|
const node_os_1 = require("node:os");
|
|
5
5
|
const notions_1 = require("@hemjs/notions");
|
|
6
|
+
const iterare_1 = require("iterare");
|
|
6
7
|
class Application {
|
|
7
8
|
constructor(adapter, hooks, environment) {
|
|
9
|
+
this.activeSignals = new Array();
|
|
8
10
|
this.isInitialized = false;
|
|
9
11
|
this.isListening = false;
|
|
10
12
|
this.adapter = adapter;
|
|
@@ -20,11 +22,11 @@ class Application {
|
|
|
20
22
|
return this;
|
|
21
23
|
}
|
|
22
24
|
const startAt = process.hrtime.bigint();
|
|
23
|
-
await this.hooks.
|
|
25
|
+
await this.hooks.onStartup();
|
|
24
26
|
this.isInitialized = true;
|
|
25
27
|
const finishedAt = process.hrtime.bigint();
|
|
26
|
-
const
|
|
27
|
-
this.environment.log?.info(`Application started in ${
|
|
28
|
+
const elapsedTime = (Number(finishedAt - startAt) / 1e9).toFixed(3);
|
|
29
|
+
this.environment.log?.info(`Application started in ${elapsedTime} seconds`);
|
|
28
30
|
return this;
|
|
29
31
|
}
|
|
30
32
|
getHttpAdapter() {
|
|
@@ -43,6 +45,9 @@ class Application {
|
|
|
43
45
|
async listen(port, ...args) {
|
|
44
46
|
if (!this.isInitialized)
|
|
45
47
|
await this.init();
|
|
48
|
+
if (this.environment.config?.shutdown?.enabled === true) {
|
|
49
|
+
this.shutdownOnSignal(this.environment.config?.shutdown?.signals);
|
|
50
|
+
}
|
|
46
51
|
return new Promise((resolve, reject) => {
|
|
47
52
|
const errorHandler = (e) => {
|
|
48
53
|
this.environment.log?.error(e?.toString?.());
|
|
@@ -71,13 +76,14 @@ class Application {
|
|
|
71
76
|
}
|
|
72
77
|
async close(signal) {
|
|
73
78
|
await this.dispose();
|
|
74
|
-
await this.hooks.
|
|
79
|
+
await this.hooks.onShutdown(signal);
|
|
80
|
+
this.unsubscribeFromSignals();
|
|
75
81
|
this.isListening = false;
|
|
76
82
|
}
|
|
77
83
|
async getUrl() {
|
|
78
84
|
return new Promise((resolve, reject) => {
|
|
79
85
|
if (!this.isListening) {
|
|
80
|
-
this.environment.log?.error('app.listen() must be called before
|
|
86
|
+
this.environment.log?.error('app.listen() must be called before app.getUrl()');
|
|
81
87
|
reject('Server not listening!');
|
|
82
88
|
return;
|
|
83
89
|
}
|
|
@@ -85,6 +91,46 @@ class Application {
|
|
|
85
91
|
resolve(this.formatAddress(address));
|
|
86
92
|
});
|
|
87
93
|
}
|
|
94
|
+
shutdownOnSignal(signals = []) {
|
|
95
|
+
signals = (0, iterare_1.iterate)(Array.from(new Set(['SIGTERM', ...signals])))
|
|
96
|
+
.map((signal) => signal.toString().toUpperCase().trim())
|
|
97
|
+
.filter((signal) => !this.activeSignals.includes(signal))
|
|
98
|
+
.toArray();
|
|
99
|
+
this.listenToSignals(signals);
|
|
100
|
+
}
|
|
101
|
+
listenToSignals(signals) {
|
|
102
|
+
let receivedSignal = false;
|
|
103
|
+
const doCleanup = async (signal) => {
|
|
104
|
+
try {
|
|
105
|
+
if (receivedSignal) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
receivedSignal = true;
|
|
109
|
+
this.environment.log?.info(`Received ${signal}. Shutdown initiated...`);
|
|
110
|
+
await this.dispose();
|
|
111
|
+
await this.hooks.onShutdown(signal);
|
|
112
|
+
signals.forEach((sig) => process.removeListener(sig, doCleanup));
|
|
113
|
+
process.kill(process.pid, signal);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
this.environment.log?.error(`Error during shutdown: ${err.stack}`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
this.cleanupRef = doCleanup;
|
|
121
|
+
signals.forEach((signal) => {
|
|
122
|
+
this.activeSignals.push(signal);
|
|
123
|
+
process.on(signal, doCleanup);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
unsubscribeFromSignals() {
|
|
127
|
+
if (!this.cleanupRef) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
this.activeSignals.forEach((signal) => {
|
|
131
|
+
process.removeListener(signal, this.cleanupRef);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
88
134
|
async dispose() {
|
|
89
135
|
this.adapter && (await this.adapter.close());
|
|
90
136
|
}
|
package/dist/hook-collector.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type { HookFactory } from './hook-factory';
|
|
|
3
3
|
export declare class HookCollector {
|
|
4
4
|
private readonly records;
|
|
5
5
|
constructor(factory: HookFactory, hooks?: HookProvider[]);
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
onStartup(): Promise<void>;
|
|
7
|
+
onShutdown(signal?: string): Promise<void>;
|
|
8
8
|
private runStartupHook;
|
|
9
9
|
private runShutdownHook;
|
|
10
10
|
private isStartupHook;
|
package/dist/hook-collector.js
CHANGED
|
@@ -7,10 +7,10 @@ class HookCollector {
|
|
|
7
7
|
constructor(factory, hooks = []) {
|
|
8
8
|
this.records = factory.prepare(hooks);
|
|
9
9
|
}
|
|
10
|
-
async
|
|
10
|
+
async onStartup() {
|
|
11
11
|
await Promise.all(this.runStartupHook(this.records));
|
|
12
12
|
}
|
|
13
|
-
async
|
|
13
|
+
async onShutdown(signal) {
|
|
14
14
|
await Promise.all(this.runShutdownHook(this.records, signal));
|
|
15
15
|
}
|
|
16
16
|
runStartupHook(records) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { HttpAdapter } from '@notchjs/types';
|
|
2
2
|
export declare class HttpAdapterHost {
|
|
3
3
|
private _httpAdapter;
|
|
4
|
-
constructor(httpAdapter
|
|
5
|
-
get httpAdapter(): HttpAdapter
|
|
4
|
+
constructor(httpAdapter: HttpAdapter);
|
|
5
|
+
get httpAdapter(): HttpAdapter;
|
|
6
6
|
}
|
package/dist/logger-host.d.ts
CHANGED
package/dist/notch.module.js
CHANGED
|
@@ -16,10 +16,13 @@ class NotchModule {
|
|
|
16
16
|
{
|
|
17
17
|
provide: http_adapter_host_1.HttpAdapterHost.name,
|
|
18
18
|
useFactory: (container) => {
|
|
19
|
-
const
|
|
19
|
+
const httpAdapter = container.has(constants_1.HTTP_ADAPTER)
|
|
20
20
|
? container.get(constants_1.HTTP_ADAPTER)
|
|
21
21
|
: undefined;
|
|
22
|
-
|
|
22
|
+
if (!httpAdapter) {
|
|
23
|
+
throw new Error('HTTP adapter not found. Please register a compatible HTTP adapter with the "HTTP_ADAPTER" token.');
|
|
24
|
+
}
|
|
25
|
+
return new http_adapter_host_1.HttpAdapterHost(httpAdapter);
|
|
23
26
|
},
|
|
24
27
|
},
|
|
25
28
|
{
|
|
@@ -55,13 +58,10 @@ class NotchModule {
|
|
|
55
58
|
{
|
|
56
59
|
provide: application_1.Application.name,
|
|
57
60
|
useFactory: (container) => {
|
|
58
|
-
const httpAdapterHost = container.get(http_adapter_host_1.HttpAdapterHost.name);
|
|
59
|
-
if (!httpAdapterHost.httpAdapter) {
|
|
60
|
-
throw new Error('HTTP adapter missing');
|
|
61
|
-
}
|
|
62
61
|
const config = container.has('config')
|
|
63
62
|
? container.get('config')
|
|
64
63
|
: {};
|
|
64
|
+
const httpAdapterHost = container.get(http_adapter_host_1.HttpAdapterHost.name);
|
|
65
65
|
const loggerHost = container.get(logger_host_1.LoggerHost.name);
|
|
66
66
|
const hooks = container.get(hook_collector_1.HookCollector.name);
|
|
67
67
|
return new application_1.Application(httpAdapterHost.httpAdapter, hooks, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@notchjs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A dependency injection based web framework (Node.js)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Augustus Kamau",
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
"test": "jest --detectOpenHandles"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@notchjs/util": "^0.
|
|
21
|
+
"@notchjs/util": "^0.4.0",
|
|
22
22
|
"iterare": "1.2.1",
|
|
23
23
|
"tslib": "2.6.2"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@notchjs/express": "^0.
|
|
27
|
-
"@notchjs/types": "^0.
|
|
26
|
+
"@notchjs/express": "^0.4.0",
|
|
27
|
+
"@notchjs/types": "^0.4.0"
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/notchjs/notch",
|
|
30
30
|
"bugs": {
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"publishConfig": {
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "309faca8c971daedad07aff9fdc69383cdeda2b3"
|
|
44
44
|
}
|