alemonjs 2.1.0-alpha.44 → 2.1.0-alpha.46
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/lib/adapter.js +90 -197
- package/lib/cbp/router-middleware.js +51 -0
- package/lib/cbp/router-utils.js +40 -0
- package/lib/cbp/router.js +12 -42
- package/lib/index.js +11 -0
- package/package.json +1 -1
package/lib/adapter.js
CHANGED
|
@@ -1,220 +1,113 @@
|
|
|
1
1
|
import { fork } from 'child_process';
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
3
|
|
|
6
4
|
const require = createRequire(import.meta.url);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
let started = false; // 防止重复 start
|
|
15
|
-
let restartAttempts = 0; // 记录连续重启次数
|
|
16
|
-
const RESTART_BASE_DELAY = 3000; // ms
|
|
17
|
-
const RESTART_MAX_DELAY = 20000; // ms
|
|
18
|
-
function calcBackoffDelay() {
|
|
19
|
-
if (restartAttempts <= 1) {
|
|
20
|
-
return RESTART_BASE_DELAY;
|
|
21
|
-
}
|
|
22
|
-
const delay = RESTART_BASE_DELAY * Math.pow(2, restartAttempts - 1);
|
|
23
|
-
return Math.min(delay, RESTART_MAX_DELAY);
|
|
24
|
-
}
|
|
25
|
-
function terminateChild(reason) {
|
|
26
|
-
if (currentChild && !currentChild.killed) {
|
|
27
|
-
try {
|
|
28
|
-
logger?.debug?.(`终止平台子进程 pid=${currentChild.pid}${reason ? ' reason=' + reason : ''}`);
|
|
29
|
-
try {
|
|
30
|
-
currentChild.send?.(JSON.stringify({ type: 'shutdown' }));
|
|
31
|
-
}
|
|
32
|
-
catch { }
|
|
33
|
-
currentChild.removeAllListeners();
|
|
34
|
-
currentChild.kill('SIGTERM');
|
|
35
|
-
setTimeout(() => {
|
|
36
|
-
if (currentChild && !currentChild.killed) {
|
|
37
|
-
try {
|
|
38
|
-
currentChild.kill('SIGKILL');
|
|
39
|
-
}
|
|
40
|
-
catch { }
|
|
41
|
-
}
|
|
42
|
-
}, 2000).unref?.();
|
|
43
|
-
}
|
|
44
|
-
catch (e) {
|
|
45
|
-
logger?.warn?.('终止子进程失败', e);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
currentChild = undefined;
|
|
49
|
-
}
|
|
50
|
-
function setupSignals() {
|
|
51
|
-
['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach(sig => {
|
|
52
|
-
process.once(sig, s => {
|
|
53
|
-
externalSignal = true;
|
|
54
|
-
shuttingDown = true;
|
|
55
|
-
terminateChild(`parent ${s}`);
|
|
56
|
-
setImmediate(() => process.exit(0));
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
process.on('disconnect', () => {
|
|
60
|
-
externalSignal = true;
|
|
61
|
-
shuttingDown = true;
|
|
62
|
-
terminateChild('parent disconnect');
|
|
63
|
-
setTimeout(() => process.exit(0), 10);
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
async function startByImport(modulePath) {
|
|
67
|
-
if (imported) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
imported = true;
|
|
71
|
-
try {
|
|
72
|
-
if (!modulePath.startsWith('file://')) {
|
|
73
|
-
modulePath = 'file://' + modulePath;
|
|
74
|
-
}
|
|
75
|
-
const mod = await import(modulePath);
|
|
76
|
-
if (typeof mod.default === 'function') {
|
|
77
|
-
await mod.default();
|
|
78
|
-
logger?.debug?.('平台连接已就绪(import 模式)');
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
logger?.warn?.('import 启动,但未找到默认导出函数');
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch (err) {
|
|
85
|
-
logger?.error?.('import 启动平台连接失败', err);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
function startByFork(modulePath) {
|
|
89
|
-
if (imported) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
let ready = false;
|
|
93
|
-
const watchdog = path.join(__dirname, 'child-watchdog.cjs');
|
|
94
|
-
const execArgv = Array.from(new Set([...(process.execArgv || []), '--require', watchdog]));
|
|
95
|
-
try {
|
|
96
|
-
currentChild = fork(modulePath, {
|
|
97
|
-
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
|
98
|
-
execArgv,
|
|
99
|
-
env: { ...process.env, ALEMON_PARENT_PID: String(process.pid) }
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
logger?.warn?.('fork 启动失败,降级 import', err);
|
|
104
|
-
void startByImport(modulePath);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
// 超时检测
|
|
108
|
-
const timeout = setTimeout(() => {
|
|
109
|
-
if (!ready && !imported && !shuttingDown) {
|
|
110
|
-
(async () => {
|
|
111
|
-
logger?.warn?.('子进程未及时 ready,降级 import');
|
|
112
|
-
terminateChild('timeout');
|
|
113
|
-
await startByImport(modulePath);
|
|
114
|
-
})().catch(() => { });
|
|
115
|
-
}
|
|
116
|
-
}, 2000);
|
|
117
|
-
currentChild.on('message', msg => {
|
|
118
|
-
try {
|
|
119
|
-
const data = typeof msg === 'string' ? JSON.parse(msg) : msg;
|
|
120
|
-
if (data?.type === 'ready') {
|
|
121
|
-
ready = true;
|
|
122
|
-
clearTimeout(timeout);
|
|
123
|
-
logger?.debug?.('平台连接已就绪(fork 模式)');
|
|
124
|
-
currentChild?.send(JSON.stringify({ type: 'start' }));
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
catch (e) {
|
|
128
|
-
logger?.error?.('子进程消息解析失败', e);
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
currentChild.on('exit', (code, signal) => {
|
|
132
|
-
clearTimeout(timeout);
|
|
133
|
-
if (shuttingDown || externalSignal || imported) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
if (process.env.ALEMON_DISABLE_RESTART === '1') {
|
|
137
|
-
logger?.warn?.(`子进程退出 code=${code} signal=${signal},已禁用自动重启 (ALEMON_DISABLE_RESTART=1)`);
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
if (!restartScheduled) {
|
|
141
|
-
restartScheduled = true;
|
|
142
|
-
restartAttempts++;
|
|
143
|
-
const delay = calcBackoffDelay();
|
|
144
|
-
logger?.warn?.(`子进程退出 code=${code} signal=${signal},${delay / 1000}s 后重启 (attempt=${restartAttempts})`);
|
|
145
|
-
setTimeout(() => {
|
|
146
|
-
if (shuttingDown || externalSignal) {
|
|
147
|
-
restartScheduled = false;
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
restartScheduled = false;
|
|
151
|
-
startByFork(modulePath);
|
|
152
|
-
}, delay);
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
5
|
+
/**
|
|
6
|
+
* 启动平台平台连接,优先使用子进程(fork),如不支持或平台连接未响应,则自动降级为 import 动态加载。
|
|
7
|
+
* 自动兼容新老版本平台连接。
|
|
8
|
+
* @param modulePath 平台连接模块绝对路径(require.resolve 得到的)
|
|
9
|
+
* @param env 环境变量对象
|
|
10
|
+
* @param logger 日志对象(需实现 info/warn/error)
|
|
11
|
+
*/
|
|
156
12
|
function startAdapterWithFallback() {
|
|
157
|
-
if (started) {
|
|
158
|
-
return; // 避免重复调用
|
|
159
|
-
}
|
|
160
|
-
started = true;
|
|
161
13
|
let modulePath = '';
|
|
162
14
|
try {
|
|
163
15
|
modulePath = require.resolve(process.env.platform);
|
|
164
16
|
}
|
|
165
17
|
catch {
|
|
166
18
|
void import(process.env.platform).then(res => res?.default());
|
|
167
|
-
logger?.warn?.('
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
setupSignals();
|
|
171
|
-
if (process.env.ALEMON_NO_FORK === '1') {
|
|
172
|
-
logger?.info?.('ALEMON_NO_FORK=1 -> 直接 import 启动');
|
|
173
|
-
void startByImport(modulePath);
|
|
19
|
+
logger?.warn?.('平台连接包未支持 require,降级为 import 加载, 请升级对应的平台连接包以提高进程稳定性');
|
|
174
20
|
return;
|
|
175
21
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
22
|
+
let imported = false; // 标记 import 是否已成功,避免重复
|
|
23
|
+
const startByFork = () => {
|
|
24
|
+
if (imported) {
|
|
25
|
+
return; // 如果已经 import 成功,不再 fork
|
|
26
|
+
}
|
|
27
|
+
let restarted = false;
|
|
28
|
+
let ready = false;
|
|
29
|
+
let child;
|
|
30
|
+
const restart = () => {
|
|
31
|
+
if (restarted || imported) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
restarted = true;
|
|
35
|
+
if (child) {
|
|
36
|
+
child.removeAllListeners();
|
|
186
37
|
try {
|
|
187
|
-
|
|
38
|
+
child.kill();
|
|
188
39
|
}
|
|
189
40
|
catch { }
|
|
190
|
-
setTimeout(() => process.exit(0), 60);
|
|
191
41
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
buffer = lines.pop() || '';
|
|
205
|
-
for (const line of lines) {
|
|
206
|
-
const text = line.trim().toLowerCase();
|
|
207
|
-
if (['shutdown', 'quit', 'exit'].includes(text)) {
|
|
208
|
-
shuttingDown = true;
|
|
209
|
-
terminateChild('stdin-cmd');
|
|
210
|
-
setTimeout(() => process.exit(0), 30);
|
|
211
|
-
break;
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
startByFork();
|
|
44
|
+
}, 3000);
|
|
45
|
+
};
|
|
46
|
+
try {
|
|
47
|
+
child = fork(modulePath);
|
|
48
|
+
// 超时
|
|
49
|
+
const checkTimeout = async () => {
|
|
50
|
+
if (!ready && !imported) {
|
|
51
|
+
logger?.warn?.('平台连接未及时响应(未发送 ready 消息),降级为 import 加载, 请升级对应的平台连接包以提高进程稳定性');
|
|
52
|
+
try {
|
|
53
|
+
child?.kill();
|
|
212
54
|
}
|
|
55
|
+
catch { }
|
|
56
|
+
await startByImport();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const timer = setTimeout(() => void checkTimeout(), 2000);
|
|
60
|
+
child.on('exit', (code, signal) => {
|
|
61
|
+
clearTimeout(timer);
|
|
62
|
+
if (!imported) {
|
|
63
|
+
logger?.warn?.(`平台连接子进程已退出,code=${code}, signal=${signal},3秒后自动重启`);
|
|
64
|
+
restart();
|
|
213
65
|
}
|
|
66
|
+
});
|
|
67
|
+
child.on('message', msg => {
|
|
68
|
+
try {
|
|
69
|
+
const data = typeof msg === 'string' ? JSON.parse(msg) : msg;
|
|
70
|
+
if (data?.type === 'ready') {
|
|
71
|
+
ready = true;
|
|
72
|
+
clearTimeout(timer);
|
|
73
|
+
logger?.debug?.('平台连接已就绪(子进程 fork 模式)');
|
|
74
|
+
child?.send?.({ type: 'start' });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
logger?.error?.('平台连接进程通信数据格式错误', err);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
logger?.warn?.('fork 启动平台连接失败,将尝试 import 加载', err);
|
|
84
|
+
void startByImport();
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const startByImport = async () => {
|
|
88
|
+
if (imported) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
imported = true;
|
|
92
|
+
try {
|
|
93
|
+
let importPath = modulePath;
|
|
94
|
+
if (!importPath.startsWith('file://')) {
|
|
95
|
+
importPath = 'file://' + importPath;
|
|
214
96
|
}
|
|
215
|
-
|
|
216
|
-
|
|
97
|
+
const mod = await import(importPath);
|
|
98
|
+
if (typeof mod.default === 'function') {
|
|
99
|
+
await mod.default();
|
|
100
|
+
logger?.debug?.('通过 import 启动平台连接完成');
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
logger?.warn?.('通过 import 启动平台连接,但未找到默认导出函数');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
logger?.error?.('import 启动平台连接失败', err);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
startByFork();
|
|
217
111
|
}
|
|
218
|
-
catch { }
|
|
219
112
|
|
|
220
113
|
export { startAdapterWithFallback };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import path, { dirname } from 'path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 递归向上查找所有目录级 _middleware 文件
|
|
6
|
+
* 支持 .ts/.js/.cjs/.mjs/.tsx/.jsx
|
|
7
|
+
* 按目录从上到下顺序合成
|
|
8
|
+
*/
|
|
9
|
+
async function collectMiddlewares(routeFile) {
|
|
10
|
+
const middlewares = [];
|
|
11
|
+
let dir = dirname(routeFile);
|
|
12
|
+
// 支持的后缀
|
|
13
|
+
const suffixes = ['.ts', '.js', '.cjs', '.mjs', '.tsx', '.jsx'];
|
|
14
|
+
while (true) {
|
|
15
|
+
for (const ext of suffixes) {
|
|
16
|
+
const mwPath = path.join(dir, `_middleware${ext}`);
|
|
17
|
+
if (existsSync(mwPath)) {
|
|
18
|
+
const mw = (await import(`file://${mwPath}`)).default;
|
|
19
|
+
if (typeof mw === 'function') {
|
|
20
|
+
middlewares.unshift(mw);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const parent = dirname(dir);
|
|
25
|
+
if (parent === dir) {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
dir = parent;
|
|
29
|
+
}
|
|
30
|
+
return middlewares;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 依次执行中间件链,最后执行 handler
|
|
34
|
+
* 如果有任意中间件或 handler 抛错,自动捕获并处理
|
|
35
|
+
*/
|
|
36
|
+
async function runMiddlewares(middlewares, ctx, handler) {
|
|
37
|
+
let idx = 0;
|
|
38
|
+
async function dispatch() {
|
|
39
|
+
if (idx < middlewares.length) {
|
|
40
|
+
// 执行下一个中间件
|
|
41
|
+
await middlewares[idx++](ctx, dispatch);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// 执行最终 handler
|
|
45
|
+
await handler(ctx);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
await dispatch();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { collectMiddlewares, runMiddlewares };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import fs, { existsSync } from 'fs';
|
|
2
|
+
|
|
3
|
+
// 输入一个文件路径。
|
|
4
|
+
const getModuelFile = (dir) => {
|
|
5
|
+
const dirMap = {
|
|
6
|
+
'.js': `${dir}.js`,
|
|
7
|
+
'.jsx': `${dir}.jsx`,
|
|
8
|
+
'.mjs': `${dir}.mjs`,
|
|
9
|
+
'.cjs': `${dir}.cjs`,
|
|
10
|
+
'/index.js': `${dir}/index.js`,
|
|
11
|
+
'/index.jsx': `${dir}/index.jsx`,
|
|
12
|
+
'/index.mjs': `${dir}/index.mjs`,
|
|
13
|
+
'/index.cjs': `${dir}/index.cjs`,
|
|
14
|
+
'.ts': `${dir}.ts`,
|
|
15
|
+
'.tsx': `${dir}.tsx`,
|
|
16
|
+
'/index.ts': `${dir}/index.ts`,
|
|
17
|
+
'/index.tsx': `${dir}/index.tsx`
|
|
18
|
+
};
|
|
19
|
+
for (const key in dirMap) {
|
|
20
|
+
const filePath = dirMap[key];
|
|
21
|
+
if (existsSync(filePath) && fs.statSync(filePath)) {
|
|
22
|
+
return filePath;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return '';
|
|
26
|
+
};
|
|
27
|
+
const formatPath = (path) => {
|
|
28
|
+
if (!path || path === '/') {
|
|
29
|
+
return '/index.html';
|
|
30
|
+
}
|
|
31
|
+
const pates = path.split('/');
|
|
32
|
+
const lastPath = pates[pates.length - 1];
|
|
33
|
+
if (lastPath.includes('.')) {
|
|
34
|
+
return path;
|
|
35
|
+
}
|
|
36
|
+
path += '.html';
|
|
37
|
+
return path;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { formatPath, getModuelFile };
|
package/lib/cbp/router.js
CHANGED
|
@@ -4,45 +4,11 @@ import path, { join, dirname } from 'path';
|
|
|
4
4
|
import mime from 'mime-types';
|
|
5
5
|
import { createRequire } from 'module';
|
|
6
6
|
import { html } from './hello.html.js';
|
|
7
|
+
import { getModuelFile, formatPath } from './router-utils.js';
|
|
8
|
+
import { collectMiddlewares, runMiddlewares } from './router-middleware.js';
|
|
7
9
|
|
|
8
10
|
const require = createRequire(import.meta.url);
|
|
9
11
|
const mainDirMap = new Map();
|
|
10
|
-
const formatPath = (path) => {
|
|
11
|
-
if (!path || path === '/') {
|
|
12
|
-
return '/index.html';
|
|
13
|
-
}
|
|
14
|
-
const pates = path.split('/');
|
|
15
|
-
const lastPath = pates[pates.length - 1];
|
|
16
|
-
if (lastPath.includes('.')) {
|
|
17
|
-
return path;
|
|
18
|
-
}
|
|
19
|
-
path += '.html';
|
|
20
|
-
return path;
|
|
21
|
-
};
|
|
22
|
-
// 输入一个文件路径。
|
|
23
|
-
const getModuelFile = (dir) => {
|
|
24
|
-
const dirMap = {
|
|
25
|
-
'.js': `${dir}.js`,
|
|
26
|
-
'.jsx': `${dir}.jsx`,
|
|
27
|
-
'.mjs': `${dir}.mjs`,
|
|
28
|
-
'.cjs': `${dir}.cjs`,
|
|
29
|
-
'/index.js': `${dir}/index.js`,
|
|
30
|
-
'/index.jsx': `${dir}/index.jsx`,
|
|
31
|
-
'/index.mjs': `${dir}/index.mjs`,
|
|
32
|
-
'/index.cjs': `${dir}/index.cjs`,
|
|
33
|
-
'.ts': `${dir}.ts`,
|
|
34
|
-
'.tsx': `${dir}.tsx`,
|
|
35
|
-
'/index.ts': `${dir}/index.ts`,
|
|
36
|
-
'/index.tsx': `${dir}/index.tsx`
|
|
37
|
-
};
|
|
38
|
-
for (const key in dirMap) {
|
|
39
|
-
const filePath = dirMap[key];
|
|
40
|
-
if (existsSync(filePath) && fs.statSync(filePath)) {
|
|
41
|
-
return filePath;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return '';
|
|
45
|
-
};
|
|
46
12
|
const router = new KoaRouter({
|
|
47
13
|
prefix: '/'
|
|
48
14
|
});
|
|
@@ -109,11 +75,13 @@ router.all('app/{*path}', async (ctx) => {
|
|
|
109
75
|
return;
|
|
110
76
|
}
|
|
111
77
|
const apiModule = await import(`file://${modulePath}`);
|
|
112
|
-
|
|
78
|
+
const handler = apiModule[ctx.method];
|
|
79
|
+
if (!handler || typeof handler !== 'function') {
|
|
113
80
|
ctx.status = 405;
|
|
114
81
|
return;
|
|
115
82
|
}
|
|
116
|
-
await
|
|
83
|
+
const middlewares = await collectMiddlewares(modulePath);
|
|
84
|
+
await runMiddlewares(middlewares, ctx, handler);
|
|
117
85
|
}
|
|
118
86
|
catch (err) {
|
|
119
87
|
console.error(`Error handling API request ${ctx.path}`);
|
|
@@ -214,17 +182,19 @@ router.all('apps/:app/{*path}', async (ctx) => {
|
|
|
214
182
|
ctx.status = 404;
|
|
215
183
|
ctx.body = {
|
|
216
184
|
code: 404,
|
|
217
|
-
message: `API '
|
|
218
|
-
data:
|
|
185
|
+
message: `API '${ctx.path}' 未找到。`,
|
|
186
|
+
data: 'existsSync modulePath'
|
|
219
187
|
};
|
|
220
188
|
return;
|
|
221
189
|
}
|
|
222
190
|
const apiModule = await import(`file://${modulePath}`);
|
|
223
|
-
|
|
191
|
+
const handler = apiModule[ctx.method];
|
|
192
|
+
if (!handler || typeof handler !== 'function') {
|
|
224
193
|
ctx.status = 405;
|
|
225
194
|
return;
|
|
226
195
|
}
|
|
227
|
-
await
|
|
196
|
+
const middlewares = await collectMiddlewares(modulePath);
|
|
197
|
+
await runMiddlewares(middlewares, ctx, handler);
|
|
228
198
|
}
|
|
229
199
|
catch (err) {
|
|
230
200
|
logger.warn(`Error request ${ctx.path}:`, err?.message || '');
|
package/lib/index.js
CHANGED
|
@@ -23,3 +23,14 @@ export { cbpClient } from './cbp/client.js';
|
|
|
23
23
|
export { cbpServer } from './cbp/server.js';
|
|
24
24
|
export { cbpPlatform } from './cbp/platform.js';
|
|
25
25
|
export { run, start } from './main.js';
|
|
26
|
+
|
|
27
|
+
// 导出类型
|
|
28
|
+
['SIGINT', 'SIGTERM', 'SIGQUIT', 'disconnect'].forEach(sig => {
|
|
29
|
+
process?.on?.(sig, () => {
|
|
30
|
+
logger?.info?.(`[alemonjs][${sig}] 收到信号,正在关闭...`);
|
|
31
|
+
setImmediate(() => process.exit(0));
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
process?.on?.('exit', code => {
|
|
35
|
+
logger?.info?.(`[alemonjs][exit] 进程退出,code=${code}`);
|
|
36
|
+
});
|