alemonjs 2.1.0-alpha.45 → 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 +0 -9
- 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
|
@@ -109,14 +109,5 @@ function startAdapterWithFallback() {
|
|
|
109
109
|
};
|
|
110
110
|
startByFork();
|
|
111
111
|
}
|
|
112
|
-
['SIGINT', 'SIGTERM', 'SIGQUIT', 'disconnect'].forEach(sig => {
|
|
113
|
-
process?.on?.(sig, () => {
|
|
114
|
-
logger?.info?.(`[${sig}] 收到信号,正在关闭...`);
|
|
115
|
-
setImmediate(() => process.exit(0));
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
process?.on?.('exit', (code) => {
|
|
119
|
-
logger?.info?.(`[exit] 进程退出,code=${code}`);
|
|
120
|
-
});
|
|
121
112
|
|
|
122
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
|
+
});
|