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 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
- if (!apiModule[ctx.method] || typeof apiModule[ctx.method] !== 'function') {
78
+ const handler = apiModule[ctx.method];
79
+ if (!handler || typeof handler !== 'function') {
113
80
  ctx.status = 405;
114
81
  return;
115
82
  }
116
- await apiModule[ctx.method](ctx);
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 'route/${ctx.path}' 未找到。`,
218
- data: null
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
- if (!apiModule[ctx.method] || typeof apiModule[ctx.method] !== 'function') {
191
+ const handler = apiModule[ctx.method];
192
+ if (!handler || typeof handler !== 'function') {
224
193
  ctx.status = 405;
225
194
  return;
226
195
  }
227
- await apiModule[ctx.method](ctx);
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
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alemonjs",
3
- "version": "2.1.0-alpha.45",
3
+ "version": "2.1.0-alpha.46",
4
4
  "description": "bot script",
5
5
  "author": "lemonade",
6
6
  "license": "MIT",