alemonjs 2.1.83-alpha.5 → 2.1.83-alpha.7

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.
@@ -16,7 +16,7 @@ import 'os';
16
16
  import 'flatted';
17
17
  import '../../../../common/cbp/runtime.js';
18
18
  import 'ws';
19
- import { listRuntimeApps, getRuntimeApp, toRuntimeAppSnapshot, listRuntimeAppKoaRouters, hasRuntimeAppCapability, getRuntimeAppKoaRouters } from '../../store.js';
19
+ import { listRuntimeApps, getRuntimeApp, toRuntimeAppSnapshot, listRuntimeAppKoaRouters, hasRuntimeAppCapability, getChildrenApp, getRuntimeAppKoaRouters } from '../../store.js';
20
20
  import { dispatchHttpError } from '../../lifecycle-callbacks.js';
21
21
 
22
22
  const initRequire = () => { };
@@ -38,10 +38,46 @@ const resolvePackageRoot = (startDir) => {
38
38
  const readWebRootConfig = (packageRoot) => {
39
39
  const packageJsonPath = path__default.join(packageRoot, 'package.json');
40
40
  if (!existsSync(packageJsonPath)) {
41
+ if (existsSync(path__default.join(packageRoot, 'dist', 'index.html'))) {
42
+ return 'dist';
43
+ }
41
44
  return '';
42
45
  }
43
46
  const pkg = require$1(packageJsonPath) ?? {};
44
- return pkg?.alemonjs?.web?.root ?? '';
47
+ const configuredRoot = pkg?.alemonjs?.web?.root ?? '';
48
+ if (typeof configuredRoot === 'string' && configuredRoot.trim()) {
49
+ return configuredRoot;
50
+ }
51
+ if (existsSync(path__default.join(packageRoot, 'dist', 'index.html'))) {
52
+ return 'dist';
53
+ }
54
+ return '';
55
+ };
56
+ const matchBasePath = (requestPath, basePath) => {
57
+ if (!basePath) {
58
+ return requestPath;
59
+ }
60
+ if (requestPath === basePath) {
61
+ return '/';
62
+ }
63
+ if (requestPath.startsWith(`${basePath}/`)) {
64
+ return requestPath.slice(basePath.length) || '/';
65
+ }
66
+ return '';
67
+ };
68
+ const rewriteCtxPath = async (ctx, nextPath, handler) => {
69
+ const search = ctx.querystring ? `?${ctx.querystring}` : '';
70
+ const originalUrl = ctx.url;
71
+ const originalReqUrl = ctx.req.url;
72
+ ctx.url = `${nextPath}${search}`;
73
+ ctx.req.url = `${nextPath}${search}`;
74
+ try {
75
+ await handler();
76
+ }
77
+ finally {
78
+ ctx.url = originalUrl;
79
+ ctx.req.url = originalReqUrl;
80
+ }
45
81
  };
46
82
  const denyRuntimeAppAccess = (ctx, appName, capability) => {
47
83
  const runtimeApp = getRuntimeApp(appName);
@@ -105,48 +141,85 @@ const denyRuntimeAppAccess = (ctx, appName, capability) => {
105
141
  };
106
142
  const dispatchRegisteredKoaRouters = async (ctx) => {
107
143
  const registeredRouters = listRuntimeAppKoaRouters();
108
- for (const item of registeredRouters) {
109
- const runtimeApp = getRuntimeApp(item.name);
110
- if (!runtimeApp || !runtimeApp.enabled || runtimeApp.status !== 'ready' || !hasRuntimeAppCapability(item.name, 'httpApi')) {
144
+ const candidates = new Set(registeredRouters.map(item => item.name));
145
+ const runtimeApps = listRuntimeApps();
146
+ runtimeApps.forEach(item => {
147
+ if (item.capabilities?.httpApi) {
148
+ candidates.add(item.name);
149
+ }
150
+ });
151
+ for (const appName of candidates) {
152
+ const runtimeApp = getRuntimeApp(appName);
153
+ if (!runtimeApp || !runtimeApp.enabled || runtimeApp.status !== 'ready' || !hasRuntimeAppCapability(appName, 'httpApi')) {
111
154
  continue;
112
155
  }
113
- const routers = getRuntimeAppKoaRouters(item.name);
156
+ const registerRouters = getChildrenApp(appName)?.register?.koaRouter;
157
+ const storedRouters = getRuntimeAppKoaRouters(appName);
158
+ const routers = (storedRouters.length
159
+ ? storedRouters
160
+ : (Array.isArray(registerRouters) ? registerRouters : registerRouters ? [registerRouters] : [])).filter(Boolean);
161
+ const aliasBases = appName === 'main' ? ['', '/app'] : ['', `/apps/${appName}`];
114
162
  for (const koaRouter of routers) {
115
- try {
116
- const matchedContext = ctx;
117
- const beforeMatched = Array.isArray(matchedContext.matched) ? matchedContext.matched.length : 0;
118
- await koaRouter.routes()(ctx, async () => { });
119
- const afterMatched = Array.isArray(matchedContext.matched) ? matchedContext.matched.length : 0;
120
- if (afterMatched <= beforeMatched) {
163
+ for (const basePath of aliasBases) {
164
+ const rewrittenPath = matchBasePath(ctx.path, basePath);
165
+ if (!rewrittenPath) {
121
166
  continue;
122
167
  }
123
- await koaRouter.allowedMethods()(ctx, async () => { });
124
- return true;
125
- }
126
- catch (error) {
127
- const handled = await dispatchHttpError({
128
- ctx,
129
- error,
130
- appName: item.name,
131
- path: ctx.path,
132
- method: ctx.method,
133
- kind: 'koa-router'
134
- });
135
- if (handled) {
168
+ try {
169
+ const matchedContext = ctx;
170
+ const beforeMatched = Array.isArray(matchedContext.matched) ? matchedContext.matched.length : 0;
171
+ const beforeStatus = ctx.status;
172
+ const beforeBody = ctx.body;
173
+ const beforeMatchedRoute = ctx._matchedRoute;
174
+ const beforeRouterPath = ctx.routerPath;
175
+ let fallthrough = false;
176
+ await rewriteCtxPath(ctx, rewrittenPath, async () => {
177
+ await koaRouter.routes()(ctx, async () => {
178
+ fallthrough = true;
179
+ });
180
+ });
181
+ const afterMatched = Array.isArray(matchedContext.matched) ? matchedContext.matched.length : 0;
182
+ const afterMatchedRoute = ctx._matchedRoute;
183
+ const afterRouterPath = ctx.routerPath;
184
+ const handled = afterMatched > beforeMatched
185
+ || afterMatchedRoute !== beforeMatchedRoute
186
+ || afterRouterPath !== beforeRouterPath
187
+ || ctx.status !== beforeStatus
188
+ || ctx.body !== beforeBody
189
+ || !fallthrough;
190
+ if (!handled) {
191
+ continue;
192
+ }
193
+ await rewriteCtxPath(ctx, rewrittenPath, async () => {
194
+ await koaRouter.allowedMethods()(ctx, async () => { });
195
+ });
196
+ return true;
197
+ }
198
+ catch (error) {
199
+ const handled = await dispatchHttpError({
200
+ ctx,
201
+ error,
202
+ appName,
203
+ path: ctx.path,
204
+ method: ctx.method,
205
+ kind: 'koa-router'
206
+ });
207
+ if (handled) {
208
+ return true;
209
+ }
210
+ logger.warn({
211
+ code: ResultCode.Fail,
212
+ message: `Error request ${ctx.path}:`,
213
+ data: error instanceof Error ? error.message : String(error)
214
+ });
215
+ ctx.status = 500;
216
+ ctx.body = {
217
+ code: 500,
218
+ message: '处理 Koa Router 请求时发生错误。',
219
+ error: error instanceof Error ? error.message : String(error)
220
+ };
136
221
  return true;
137
222
  }
138
- logger.warn({
139
- code: ResultCode.Fail,
140
- message: `Error request ${ctx.path}:`,
141
- data: error instanceof Error ? error.message : String(error)
142
- });
143
- ctx.status = 500;
144
- ctx.body = {
145
- code: 500,
146
- message: '处理 Koa Router 请求时发生错误。',
147
- error: error instanceof Error ? error.message : String(error)
148
- };
149
- return true;
150
223
  }
151
224
  }
152
225
  }
@@ -206,7 +279,7 @@ router.use(async (ctx, next) => {
206
279
  }
207
280
  await next();
208
281
  });
209
- router.all('app/{*path}', async (ctx) => {
282
+ const handleMainAppRequest = async (ctx) => {
210
283
  if (!process.env.input) {
211
284
  ctx.status = 400;
212
285
  ctx.body = {
@@ -376,11 +449,11 @@ router.all('app/{*path}', async (ctx) => {
376
449
  };
377
450
  }
378
451
  }
379
- });
380
- router.all('app', ctx => {
381
- ctx.redirect('/app/');
382
- });
383
- router.all('apps/:app/{*path}', async (ctx) => {
452
+ };
453
+ router.all('app', handleMainAppRequest);
454
+ router.all('app/', handleMainAppRequest);
455
+ router.all('app/{*path}', handleMainAppRequest);
456
+ const handlePluginAppRequest = async (ctx) => {
384
457
  const appName = ctx.params.app;
385
458
  if (!isValidPackageName(appName)) {
386
459
  ctx.status = 400;
@@ -549,11 +622,9 @@ router.all('apps/:app/{*path}', async (ctx) => {
549
622
  };
550
623
  }
551
624
  }
552
- });
553
- router.all('apps/:name', ctx => {
554
- if (ctx.path === `/apps/${ctx.params.name}`) {
555
- ctx.redirect(`/apps/${ctx.params.name}/`);
556
- }
557
- });
625
+ };
626
+ router.all('apps/:app', handlePluginAppRequest);
627
+ router.all('apps/:app/', handlePluginAppRequest);
628
+ router.all('apps/:app/{*path}', handlePluginAppRequest);
558
629
 
559
630
  export { router as default };
@@ -36,7 +36,7 @@ const getModuelFile = (dir) => {
36
36
  };
37
37
  const formatPath = (pathValue) => {
38
38
  if (!pathValue || pathValue === '/') {
39
- return '/index.html';
39
+ return 'index.html';
40
40
  }
41
41
  const pates = pathValue.split('/');
42
42
  const lastPath = pates[pates.length - 1];
@@ -21,11 +21,20 @@ const resolvePackageRoot = (startDir) => {
21
21
  }
22
22
  return startDir;
23
23
  };
24
+ const detectDefaultWebRoot = (packageRoot) => {
25
+ if (existsSync(join(packageRoot, 'dist', 'index.html'))) {
26
+ return 'dist';
27
+ }
28
+ if (existsSync(join(packageRoot, 'index.html'))) {
29
+ return '';
30
+ }
31
+ return null;
32
+ };
24
33
  const detectWebCapability = (startDir) => {
25
34
  const packageRoot = resolvePackageRoot(startDir);
26
35
  const packageJsonPath = join(packageRoot, 'package.json');
27
36
  if (!existsSync(packageJsonPath)) {
28
- return existsSync(join(packageRoot, 'index.html'));
37
+ return Boolean(detectDefaultWebRoot(packageRoot));
29
38
  }
30
39
  try {
31
40
  const pkg = require$1(packageJsonPath) ?? {};
@@ -36,7 +45,7 @@ const detectWebCapability = (startDir) => {
36
45
  }
37
46
  catch {
38
47
  }
39
- return existsSync(join(packageRoot, 'index.html'));
48
+ return Boolean(detectDefaultWebRoot(packageRoot));
40
49
  };
41
50
  const loadChildren = async (mainPath, appName) => {
42
51
  if (!mainPath || typeof mainPath !== 'string') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alemonjs",
3
- "version": "2.1.83-alpha.5",
3
+ "version": "2.1.83-alpha.7",
4
4
  "description": "bot script",
5
5
  "author": "lemonade",
6
6
  "license": "MIT",