alemonjs 2.1.80 → 2.1.82
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/app/index.js +1 -1
- package/lib/app/load_modules/load.js +27 -4
- package/lib/app/load_modules/loadChild.js +76 -1
- package/lib/app/store.d.ts +116 -0
- package/lib/app/store.js +198 -2
- package/lib/client.js +17 -2
- package/lib/global.d.ts +8 -0
- package/lib/index.js +1 -1
- package/lib/main.js +3 -3
- package/lib/server/routers/router.js +164 -23
- package/lib/types/event/index.d.ts +2 -0
- package/package.json +1 -1
package/lib/app/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { ChildrenApp, Core, Logger, Middleware, MiddlewareRouter, MiddlewareTree, ProcessorEventAutoClearMap, ProcessorEventUserAutoClearMap, Response, ResponseMiddleware, ResponseRouter, ResponseTree, State, StateSubscribe, SubscribeList, bumpStoreVersion, core, getSubscribeList, logger } from './store.js';
|
|
1
|
+
export { ChildrenApp, Core, Logger, Middleware, MiddlewareRouter, MiddlewareTree, ProcessorEventAutoClearMap, ProcessorEventUserAutoClearMap, Response, ResponseMiddleware, ResponseRouter, ResponseTree, State, StateSubscribe, SubscribeList, bumpStoreVersion, clearRuntimeAppKoaRouters, core, disposeAllRuntimeApps, disposeRuntimeApp, getRuntimeApp, getRuntimeAppKoaRouters, getSubscribeList, hasRuntimeAppCapability, listRuntimeAppKoaRouters, listRuntimeApps, logger, registerRuntimeApp, setRuntimeAppKoaRouters, toRuntimeAppSnapshot, updateRuntimeAppCapabilities, updateRuntimeAppStatus } from './store.js';
|
|
2
2
|
export { Expose, clearAllExpose, disposeExpose, registerExpose } from './expose.js';
|
|
3
3
|
export { loadModels, run } from './load_modules/load.js';
|
|
4
4
|
export { loadChildren, loadChildrenFile } from './load_modules/loadChild.js';
|
|
@@ -1,21 +1,36 @@
|
|
|
1
1
|
import { getConfig } from '../../core/config.js';
|
|
2
2
|
import { loadChildren, loadChildrenFile } from './loadChild.js';
|
|
3
|
-
import { join } from 'path';
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
4
|
import { existsSync } from 'fs';
|
|
5
5
|
import { ResultCode } from '../../core/variable.js';
|
|
6
|
+
import { registerRuntimeApp } from '../store.js';
|
|
6
7
|
|
|
7
8
|
const loadApps = () => {
|
|
8
9
|
const cfg = getConfig();
|
|
9
|
-
const apps = Array.isArray(cfg.value?.apps)
|
|
10
|
+
const apps = Array.isArray(cfg.value?.apps)
|
|
11
|
+
? cfg.value.apps.filter(Boolean)
|
|
12
|
+
: Object.entries(cfg.value?.apps ?? {})
|
|
13
|
+
.filter(([, enabled]) => Boolean(enabled))
|
|
14
|
+
.map(([name]) => name);
|
|
10
15
|
const uniqueApps = Array.from(new Set(apps));
|
|
11
|
-
uniqueApps.forEach(app =>
|
|
16
|
+
uniqueApps.forEach(app => {
|
|
17
|
+
registerRuntimeApp({
|
|
18
|
+
name: app,
|
|
19
|
+
kind: 'plugin',
|
|
20
|
+
enabled: true,
|
|
21
|
+
status: 'discovered',
|
|
22
|
+
rootDir: '',
|
|
23
|
+
mainPath: ''
|
|
24
|
+
});
|
|
25
|
+
void loadChildrenFile(app);
|
|
26
|
+
});
|
|
12
27
|
};
|
|
13
28
|
const run = (input) => {
|
|
14
29
|
if (!input) {
|
|
15
30
|
return;
|
|
16
31
|
}
|
|
17
32
|
const mainPath = join(process.cwd(), input);
|
|
18
|
-
if (!existsSync(
|
|
33
|
+
if (!existsSync(mainPath)) {
|
|
19
34
|
logger.warn({
|
|
20
35
|
code: ResultCode.Warn,
|
|
21
36
|
message: '未找到主要入口文件',
|
|
@@ -23,6 +38,14 @@ const run = (input) => {
|
|
|
23
38
|
});
|
|
24
39
|
return;
|
|
25
40
|
}
|
|
41
|
+
registerRuntimeApp({
|
|
42
|
+
name: 'main',
|
|
43
|
+
kind: 'main',
|
|
44
|
+
enabled: true,
|
|
45
|
+
status: 'discovered',
|
|
46
|
+
rootDir: join(process.cwd(), dirname(input)),
|
|
47
|
+
mainPath
|
|
48
|
+
});
|
|
26
49
|
void loadChildren(mainPath, 'main');
|
|
27
50
|
};
|
|
28
51
|
function loadModels() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { dirname, join } from 'path';
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
3
|
import { showErrorModule, getRecursiveDirFiles, createEventName } from '../../core/utils.js';
|
|
4
|
-
import { ChildrenApp } from '../store.js';
|
|
4
|
+
import { registerRuntimeApp, updateRuntimeAppStatus, ChildrenApp, clearRuntimeAppKoaRouters, setRuntimeAppKoaRouters, updateRuntimeAppCapabilities } from '../store.js';
|
|
5
5
|
import { registerExpose } from '../expose.js';
|
|
6
6
|
import { ResultCode, fileSuffixMiddleware } from '../../core/variable.js';
|
|
7
7
|
import { registerAppDir, scheduleCancelByApp, unregisterAppDir } from '../schedule-store.js';
|
|
@@ -10,6 +10,33 @@ import module$1 from 'module';
|
|
|
10
10
|
const initRequire = () => { };
|
|
11
11
|
initRequire.resolve = () => '';
|
|
12
12
|
const require$1 = module$1?.createRequire?.(import.meta.url) ?? initRequire;
|
|
13
|
+
const resolvePackageRoot = (startDir) => {
|
|
14
|
+
let currentDir = startDir;
|
|
15
|
+
while (currentDir && currentDir !== dirname(currentDir)) {
|
|
16
|
+
if (existsSync(join(currentDir, 'package.json'))) {
|
|
17
|
+
return currentDir;
|
|
18
|
+
}
|
|
19
|
+
currentDir = dirname(currentDir);
|
|
20
|
+
}
|
|
21
|
+
return startDir;
|
|
22
|
+
};
|
|
23
|
+
const detectWebCapability = (startDir) => {
|
|
24
|
+
const packageRoot = resolvePackageRoot(startDir);
|
|
25
|
+
const packageJsonPath = join(packageRoot, 'package.json');
|
|
26
|
+
if (!existsSync(packageJsonPath)) {
|
|
27
|
+
return existsSync(join(packageRoot, 'index.html'));
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const pkg = require$1(packageJsonPath) ?? {};
|
|
31
|
+
const root = pkg?.alemonjs?.web?.root;
|
|
32
|
+
if (typeof root === 'string' && root.trim()) {
|
|
33
|
+
return existsSync(join(packageRoot, root));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
}
|
|
38
|
+
return existsSync(join(packageRoot, 'index.html'));
|
|
39
|
+
};
|
|
13
40
|
const loadChildren = async (mainPath, appName) => {
|
|
14
41
|
if (!mainPath || typeof mainPath !== 'string') {
|
|
15
42
|
logger.error({
|
|
@@ -21,6 +48,24 @@ const loadChildren = async (mainPath, appName) => {
|
|
|
21
48
|
}
|
|
22
49
|
const mainDir = dirname(mainPath);
|
|
23
50
|
const App = new ChildrenApp(appName);
|
|
51
|
+
const kind = appName === 'main' ? 'main' : 'plugin';
|
|
52
|
+
const baseCapabilities = {
|
|
53
|
+
event: false,
|
|
54
|
+
httpApi: existsSync(join(mainDir, 'route', 'api')),
|
|
55
|
+
web: detectWebCapability(mainDir),
|
|
56
|
+
schedule: false,
|
|
57
|
+
expose: false
|
|
58
|
+
};
|
|
59
|
+
registerRuntimeApp({
|
|
60
|
+
name: appName,
|
|
61
|
+
kind,
|
|
62
|
+
enabled: true,
|
|
63
|
+
status: 'discovered',
|
|
64
|
+
rootDir: mainDir,
|
|
65
|
+
mainPath,
|
|
66
|
+
capabilities: baseCapabilities
|
|
67
|
+
});
|
|
68
|
+
updateRuntimeAppStatus(appName, 'loading');
|
|
24
69
|
registerAppDir(appName, mainDir);
|
|
25
70
|
try {
|
|
26
71
|
const moduleApp = await import(`file://${mainPath}`);
|
|
@@ -46,6 +91,8 @@ const loadChildren = async (mainPath, appName) => {
|
|
|
46
91
|
App.pushCycle(app);
|
|
47
92
|
const unMounted = async (e) => {
|
|
48
93
|
showErrorModule(e);
|
|
94
|
+
clearRuntimeAppKoaRouters(appName);
|
|
95
|
+
updateRuntimeAppStatus(appName, 'failed', e);
|
|
49
96
|
scheduleCancelByApp(appName);
|
|
50
97
|
unregisterAppDir(appName);
|
|
51
98
|
App.un();
|
|
@@ -69,17 +116,28 @@ const loadChildren = async (mainPath, appName) => {
|
|
|
69
116
|
}
|
|
70
117
|
const registerMounted = async () => {
|
|
71
118
|
const res = await app?.register();
|
|
119
|
+
const hasEventCapability = Boolean(res && (res?.response || res?.middleware || res?.responseRouter || res?.middlewareRouter));
|
|
120
|
+
const hasExposeCapability = Boolean(res?.expose);
|
|
121
|
+
const hasKoaRouterCapability = Boolean(res?.koaRouter);
|
|
72
122
|
if (res && (res?.response || res?.middleware || res?.responseRouter || res?.middlewareRouter)) {
|
|
73
123
|
App.register(res);
|
|
74
124
|
}
|
|
125
|
+
setRuntimeAppKoaRouters(appName, res?.koaRouter);
|
|
75
126
|
if (res?.expose) {
|
|
76
127
|
registerExpose(appName, res.expose.getConfigs());
|
|
77
128
|
}
|
|
129
|
+
updateRuntimeAppCapabilities(appName, {
|
|
130
|
+
...baseCapabilities,
|
|
131
|
+
httpApi: baseCapabilities.httpApi || hasKoaRouterCapability,
|
|
132
|
+
event: hasEventCapability,
|
|
133
|
+
expose: hasExposeCapability
|
|
134
|
+
});
|
|
78
135
|
App.on();
|
|
79
136
|
try {
|
|
80
137
|
if (app?.onMounted) {
|
|
81
138
|
await app.onMounted({ response: [], responseMiddleware: {}, middleware: [] });
|
|
82
139
|
}
|
|
140
|
+
updateRuntimeAppStatus(appName, 'ready');
|
|
83
141
|
}
|
|
84
142
|
catch (e) {
|
|
85
143
|
void unMounted(e);
|
|
@@ -139,11 +197,16 @@ const loadChildren = async (mainPath, appName) => {
|
|
|
139
197
|
mwData.push(middleware);
|
|
140
198
|
}
|
|
141
199
|
App.pushMiddleware(mwData);
|
|
200
|
+
updateRuntimeAppCapabilities(appName, {
|
|
201
|
+
...baseCapabilities,
|
|
202
|
+
event: resData.length > 0 || Object.keys(resAndMwData).length > 0 || mwData.length > 0
|
|
203
|
+
});
|
|
142
204
|
App.on();
|
|
143
205
|
try {
|
|
144
206
|
if (app?.onMounted) {
|
|
145
207
|
await app.onMounted({ response: resData, responseMiddleware: resAndMwData, middleware: mwData });
|
|
146
208
|
}
|
|
209
|
+
updateRuntimeAppStatus(appName, 'ready');
|
|
147
210
|
}
|
|
148
211
|
catch (e) {
|
|
149
212
|
void unMounted(e);
|
|
@@ -163,6 +226,8 @@ const loadChildren = async (mainPath, appName) => {
|
|
|
163
226
|
}
|
|
164
227
|
catch (e) {
|
|
165
228
|
showErrorModule(e);
|
|
229
|
+
clearRuntimeAppKoaRouters(appName);
|
|
230
|
+
updateRuntimeAppStatus(appName, 'failed', e);
|
|
166
231
|
App.un();
|
|
167
232
|
}
|
|
168
233
|
};
|
|
@@ -178,6 +243,7 @@ const loadChildrenFile = (appName) => {
|
|
|
178
243
|
try {
|
|
179
244
|
const mainPath = require$1.resolve(appName);
|
|
180
245
|
if (!existsSync(mainPath)) {
|
|
246
|
+
updateRuntimeAppStatus(appName, 'failed', new Error('The main file does not exist,' + mainPath));
|
|
181
247
|
logger.error({
|
|
182
248
|
code: ResultCode.FailParams,
|
|
183
249
|
message: 'The main file does not exist,' + mainPath,
|
|
@@ -185,9 +251,18 @@ const loadChildrenFile = (appName) => {
|
|
|
185
251
|
});
|
|
186
252
|
return;
|
|
187
253
|
}
|
|
254
|
+
registerRuntimeApp({
|
|
255
|
+
name: appName,
|
|
256
|
+
kind: 'plugin',
|
|
257
|
+
enabled: true,
|
|
258
|
+
status: 'discovered',
|
|
259
|
+
rootDir: dirname(mainPath),
|
|
260
|
+
mainPath
|
|
261
|
+
});
|
|
188
262
|
void loadChildren(mainPath, appName);
|
|
189
263
|
}
|
|
190
264
|
catch (e) {
|
|
265
|
+
updateRuntimeAppStatus(appName, 'failed', e);
|
|
191
266
|
showErrorModule(e);
|
|
192
267
|
}
|
|
193
268
|
};
|
package/lib/app/store.d.ts
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
import { SinglyLinkedList } from './SinglyLinkedList';
|
|
2
2
|
import { childrenCallbackRes, ChildrenCycle, EventCycleEnum, EventKeys, FileTreeNode, StoreMiddlewareItem, StoreResponseItem, SubscribeValue } from '../types';
|
|
3
|
+
import type KoaRouter from 'koa-router';
|
|
4
|
+
export type RuntimeAppStatus = 'discovered' | 'loading' | 'ready' | 'failed' | 'disposed';
|
|
5
|
+
export type RuntimeAppCapability = {
|
|
6
|
+
event: boolean;
|
|
7
|
+
httpApi: boolean;
|
|
8
|
+
web: boolean;
|
|
9
|
+
schedule: boolean;
|
|
10
|
+
expose: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type RuntimeAppError = {
|
|
13
|
+
message: string;
|
|
14
|
+
stack?: string;
|
|
15
|
+
time: number;
|
|
16
|
+
};
|
|
17
|
+
export type RuntimeAppRecord = {
|
|
18
|
+
name: string;
|
|
19
|
+
kind: 'main' | 'plugin';
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
status: RuntimeAppStatus;
|
|
22
|
+
rootDir: string;
|
|
23
|
+
mainPath: string;
|
|
24
|
+
error?: RuntimeAppError;
|
|
25
|
+
capabilities: RuntimeAppCapability;
|
|
26
|
+
createdAt: number;
|
|
27
|
+
updatedAt: number;
|
|
28
|
+
};
|
|
3
29
|
export declare class Logger {
|
|
4
30
|
#private;
|
|
5
31
|
constructor();
|
|
@@ -14,8 +40,92 @@ export declare class Core {
|
|
|
14
40
|
storeChildrenApp: {
|
|
15
41
|
[key: string]: import("../types").StoreChildrenApp;
|
|
16
42
|
};
|
|
43
|
+
runtimeApps?: {
|
|
44
|
+
[key: string]: RuntimeAppRecord;
|
|
45
|
+
};
|
|
46
|
+
runtimeAppKoaRouters?: {
|
|
47
|
+
[key: string]: KoaRouter[];
|
|
48
|
+
};
|
|
17
49
|
};
|
|
18
50
|
}
|
|
51
|
+
export declare const registerRuntimeApp: (record: Omit<RuntimeAppRecord, "createdAt" | "updatedAt" | "capabilities"> & {
|
|
52
|
+
capabilities?: Partial<RuntimeAppCapability>;
|
|
53
|
+
}) => RuntimeAppRecord;
|
|
54
|
+
export declare const updateRuntimeAppStatus: (name: string, status: RuntimeAppStatus, error?: unknown) => RuntimeAppRecord;
|
|
55
|
+
export declare const updateRuntimeAppCapabilities: (name: string, capabilities: Partial<RuntimeAppCapability>) => RuntimeAppRecord;
|
|
56
|
+
export declare const setRuntimeAppKoaRouters: (name: string, koaRouters?: KoaRouter | KoaRouter[]) => KoaRouter<any, {}>[];
|
|
57
|
+
export declare const getRuntimeAppKoaRouters: (name: string) => KoaRouter<any, {}>[];
|
|
58
|
+
export declare const clearRuntimeAppKoaRouters: (name: string) => void;
|
|
59
|
+
export declare const listRuntimeAppKoaRouters: () => {
|
|
60
|
+
name: string;
|
|
61
|
+
routers: KoaRouter<any, {}>[];
|
|
62
|
+
}[];
|
|
63
|
+
export declare const getRuntimeApp: (name: string) => RuntimeAppRecord;
|
|
64
|
+
export declare const toRuntimeAppSnapshot: (item: RuntimeAppRecord) => {
|
|
65
|
+
capabilities: {
|
|
66
|
+
event: boolean;
|
|
67
|
+
httpApi: boolean;
|
|
68
|
+
web: boolean;
|
|
69
|
+
schedule: boolean;
|
|
70
|
+
expose: boolean;
|
|
71
|
+
};
|
|
72
|
+
error: {
|
|
73
|
+
message: string;
|
|
74
|
+
time: number;
|
|
75
|
+
};
|
|
76
|
+
name: string;
|
|
77
|
+
kind: "main" | "plugin";
|
|
78
|
+
enabled: boolean;
|
|
79
|
+
status: RuntimeAppStatus;
|
|
80
|
+
rootDir: string;
|
|
81
|
+
mainPath: string;
|
|
82
|
+
createdAt: number;
|
|
83
|
+
updatedAt: number;
|
|
84
|
+
};
|
|
85
|
+
export declare const listRuntimeApps: () => {
|
|
86
|
+
capabilities: {
|
|
87
|
+
event: boolean;
|
|
88
|
+
httpApi: boolean;
|
|
89
|
+
web: boolean;
|
|
90
|
+
schedule: boolean;
|
|
91
|
+
expose: boolean;
|
|
92
|
+
};
|
|
93
|
+
error: {
|
|
94
|
+
message: string;
|
|
95
|
+
time: number;
|
|
96
|
+
};
|
|
97
|
+
name: string;
|
|
98
|
+
kind: "main" | "plugin";
|
|
99
|
+
enabled: boolean;
|
|
100
|
+
status: RuntimeAppStatus;
|
|
101
|
+
rootDir: string;
|
|
102
|
+
mainPath: string;
|
|
103
|
+
createdAt: number;
|
|
104
|
+
updatedAt: number;
|
|
105
|
+
}[];
|
|
106
|
+
export declare const disposeRuntimeApp: (name: string) => RuntimeAppRecord;
|
|
107
|
+
export declare const disposeAllRuntimeApps: () => {
|
|
108
|
+
capabilities: {
|
|
109
|
+
event: boolean;
|
|
110
|
+
httpApi: boolean;
|
|
111
|
+
web: boolean;
|
|
112
|
+
schedule: boolean;
|
|
113
|
+
expose: boolean;
|
|
114
|
+
};
|
|
115
|
+
error: {
|
|
116
|
+
message: string;
|
|
117
|
+
time: number;
|
|
118
|
+
};
|
|
119
|
+
name: string;
|
|
120
|
+
kind: "main" | "plugin";
|
|
121
|
+
enabled: boolean;
|
|
122
|
+
status: RuntimeAppStatus;
|
|
123
|
+
rootDir: string;
|
|
124
|
+
mainPath: string;
|
|
125
|
+
createdAt: number;
|
|
126
|
+
updatedAt: number;
|
|
127
|
+
}[];
|
|
128
|
+
export declare const hasRuntimeAppCapability: (name: string, capability: keyof RuntimeAppCapability) => boolean;
|
|
19
129
|
export declare const bumpStoreVersion: () => void;
|
|
20
130
|
export declare class Response {
|
|
21
131
|
#private;
|
|
@@ -87,4 +197,10 @@ export declare const core: {
|
|
|
87
197
|
storeChildrenApp: {
|
|
88
198
|
[key: string]: import("../types").StoreChildrenApp;
|
|
89
199
|
};
|
|
200
|
+
runtimeApps?: {
|
|
201
|
+
[key: string]: RuntimeAppRecord;
|
|
202
|
+
};
|
|
203
|
+
runtimeAppKoaRouters?: {
|
|
204
|
+
[key: string]: KoaRouter[];
|
|
205
|
+
};
|
|
90
206
|
};
|
package/lib/app/store.js
CHANGED
|
@@ -107,7 +107,9 @@ class Core {
|
|
|
107
107
|
mount: new Map(),
|
|
108
108
|
unmount: new Map()
|
|
109
109
|
},
|
|
110
|
-
storeChildrenApp: {}
|
|
110
|
+
storeChildrenApp: {},
|
|
111
|
+
runtimeApps: {},
|
|
112
|
+
runtimeAppKoaRouters: {}
|
|
111
113
|
};
|
|
112
114
|
}
|
|
113
115
|
}
|
|
@@ -116,6 +118,200 @@ class Core {
|
|
|
116
118
|
}
|
|
117
119
|
}
|
|
118
120
|
let _storeVersion = 0;
|
|
121
|
+
const createEmptyRuntimeCapabilities = () => ({
|
|
122
|
+
event: false,
|
|
123
|
+
httpApi: false,
|
|
124
|
+
web: false,
|
|
125
|
+
schedule: false,
|
|
126
|
+
expose: false
|
|
127
|
+
});
|
|
128
|
+
const logRuntimeAppStatus = (level, record) => {
|
|
129
|
+
if (!global.logger?.[level]) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
global.logger[level]({
|
|
133
|
+
message: 'runtime app status',
|
|
134
|
+
data: {
|
|
135
|
+
app: record.name,
|
|
136
|
+
kind: record.kind,
|
|
137
|
+
status: record.status,
|
|
138
|
+
capabilities: record.capabilities,
|
|
139
|
+
error: record.error?.message ?? null
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
const normalizeRuntimeAppError = (error) => {
|
|
144
|
+
if (!error) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
if (error instanceof Error) {
|
|
148
|
+
return {
|
|
149
|
+
message: error.message,
|
|
150
|
+
stack: error.stack,
|
|
151
|
+
time: Date.now()
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
message: typeof error === 'string' ? error : 'Unknown runtime app error',
|
|
156
|
+
time: Date.now()
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
const sameRuntimeAppCapabilities = (left, right) => {
|
|
160
|
+
return (left.event === right.event && left.httpApi === right.httpApi && left.web === right.web && left.schedule === right.schedule && left.expose === right.expose);
|
|
161
|
+
};
|
|
162
|
+
const sameRuntimeAppError = (left, right) => {
|
|
163
|
+
if (!left && !right) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
if (!left || !right) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
return left.message === right.message && left.stack === right.stack;
|
|
170
|
+
};
|
|
171
|
+
const getRuntimeAppStore = () => {
|
|
172
|
+
if (!global.alemonjsCore.runtimeApps) {
|
|
173
|
+
global.alemonjsCore.runtimeApps = {};
|
|
174
|
+
}
|
|
175
|
+
return global.alemonjsCore.runtimeApps;
|
|
176
|
+
};
|
|
177
|
+
const getRuntimeAppKoaRouterStore = () => {
|
|
178
|
+
if (!global.alemonjsCore.runtimeAppKoaRouters) {
|
|
179
|
+
global.alemonjsCore.runtimeAppKoaRouters = {};
|
|
180
|
+
}
|
|
181
|
+
return global.alemonjsCore.runtimeAppKoaRouters;
|
|
182
|
+
};
|
|
183
|
+
const registerRuntimeApp = (record) => {
|
|
184
|
+
const runtimeApps = getRuntimeAppStore();
|
|
185
|
+
const current = runtimeApps[record.name];
|
|
186
|
+
const now = Date.now();
|
|
187
|
+
const nextCapabilities = {
|
|
188
|
+
...(current?.capabilities ?? createEmptyRuntimeCapabilities()),
|
|
189
|
+
...(record.capabilities ?? {})
|
|
190
|
+
};
|
|
191
|
+
runtimeApps[record.name] = {
|
|
192
|
+
name: record.name,
|
|
193
|
+
kind: record.kind,
|
|
194
|
+
enabled: record.enabled,
|
|
195
|
+
status: record.status,
|
|
196
|
+
rootDir: record.rootDir,
|
|
197
|
+
mainPath: record.mainPath,
|
|
198
|
+
error: record.error,
|
|
199
|
+
capabilities: nextCapabilities,
|
|
200
|
+
createdAt: current?.createdAt ?? now,
|
|
201
|
+
updatedAt: now
|
|
202
|
+
};
|
|
203
|
+
if (!current || current.status !== record.status) {
|
|
204
|
+
logRuntimeAppStatus(record.status === 'failed' ? 'warn' : 'debug', runtimeApps[record.name]);
|
|
205
|
+
}
|
|
206
|
+
return runtimeApps[record.name];
|
|
207
|
+
};
|
|
208
|
+
const updateRuntimeAppStatus = (name, status, error) => {
|
|
209
|
+
const runtimeApps = getRuntimeAppStore();
|
|
210
|
+
const current = runtimeApps[name];
|
|
211
|
+
if (!current) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const normalizedError = normalizeRuntimeAppError(error);
|
|
215
|
+
if (current.status === status && sameRuntimeAppError(current.error, normalizedError)) {
|
|
216
|
+
return current;
|
|
217
|
+
}
|
|
218
|
+
current.status = status;
|
|
219
|
+
current.updatedAt = Date.now();
|
|
220
|
+
current.error = normalizedError;
|
|
221
|
+
const level = status === 'failed' ? 'warn' : status === 'disposed' ? 'info' : 'debug';
|
|
222
|
+
logRuntimeAppStatus(level, current);
|
|
223
|
+
return current;
|
|
224
|
+
};
|
|
225
|
+
const updateRuntimeAppCapabilities = (name, capabilities) => {
|
|
226
|
+
const runtimeApps = getRuntimeAppStore();
|
|
227
|
+
const current = runtimeApps[name];
|
|
228
|
+
if (!current) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const nextCapabilities = {
|
|
232
|
+
...current.capabilities,
|
|
233
|
+
...capabilities
|
|
234
|
+
};
|
|
235
|
+
if (sameRuntimeAppCapabilities(current.capabilities, nextCapabilities)) {
|
|
236
|
+
return current;
|
|
237
|
+
}
|
|
238
|
+
current.capabilities = nextCapabilities;
|
|
239
|
+
current.updatedAt = Date.now();
|
|
240
|
+
return current;
|
|
241
|
+
};
|
|
242
|
+
const setRuntimeAppKoaRouters = (name, koaRouters) => {
|
|
243
|
+
const koaRouterStore = getRuntimeAppKoaRouterStore();
|
|
244
|
+
if (!koaRouters) {
|
|
245
|
+
delete koaRouterStore[name];
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
const normalizedRouters = (Array.isArray(koaRouters) ? koaRouters : [koaRouters]).filter(Boolean);
|
|
249
|
+
koaRouterStore[name] = normalizedRouters;
|
|
250
|
+
return normalizedRouters;
|
|
251
|
+
};
|
|
252
|
+
const getRuntimeAppKoaRouters = (name) => {
|
|
253
|
+
return getRuntimeAppKoaRouterStore()[name] ?? [];
|
|
254
|
+
};
|
|
255
|
+
const clearRuntimeAppKoaRouters = (name) => {
|
|
256
|
+
const koaRouterStore = getRuntimeAppKoaRouterStore();
|
|
257
|
+
delete koaRouterStore[name];
|
|
258
|
+
};
|
|
259
|
+
const listRuntimeAppKoaRouters = () => {
|
|
260
|
+
return Object.entries(getRuntimeAppKoaRouterStore())
|
|
261
|
+
.sort(([left], [right]) => {
|
|
262
|
+
if (left === 'main' && right !== 'main') {
|
|
263
|
+
return -1;
|
|
264
|
+
}
|
|
265
|
+
if (left !== 'main' && right === 'main') {
|
|
266
|
+
return 1;
|
|
267
|
+
}
|
|
268
|
+
return left.localeCompare(right);
|
|
269
|
+
})
|
|
270
|
+
.map(([name, routers]) => ({
|
|
271
|
+
name,
|
|
272
|
+
routers: [...routers]
|
|
273
|
+
}));
|
|
274
|
+
};
|
|
275
|
+
const getRuntimeApp = (name) => {
|
|
276
|
+
return getRuntimeAppStore()[name];
|
|
277
|
+
};
|
|
278
|
+
const toRuntimeAppSnapshot = (item) => ({
|
|
279
|
+
...item,
|
|
280
|
+
capabilities: { ...item.capabilities },
|
|
281
|
+
error: item.error
|
|
282
|
+
? {
|
|
283
|
+
message: item.error.message,
|
|
284
|
+
time: item.error.time
|
|
285
|
+
}
|
|
286
|
+
: undefined
|
|
287
|
+
});
|
|
288
|
+
const listRuntimeApps = () => {
|
|
289
|
+
return Object.values(getRuntimeAppStore())
|
|
290
|
+
.sort((left, right) => {
|
|
291
|
+
if (left.name === 'main' && right.name !== 'main') {
|
|
292
|
+
return -1;
|
|
293
|
+
}
|
|
294
|
+
if (left.name !== 'main' && right.name === 'main') {
|
|
295
|
+
return 1;
|
|
296
|
+
}
|
|
297
|
+
return left.name.localeCompare(right.name);
|
|
298
|
+
})
|
|
299
|
+
.map(toRuntimeAppSnapshot);
|
|
300
|
+
};
|
|
301
|
+
const disposeRuntimeApp = (name) => {
|
|
302
|
+
clearRuntimeAppKoaRouters(name);
|
|
303
|
+
return updateRuntimeAppStatus(name, 'disposed');
|
|
304
|
+
};
|
|
305
|
+
const disposeAllRuntimeApps = () => {
|
|
306
|
+
const runtimeApps = listRuntimeApps();
|
|
307
|
+
runtimeApps.forEach(app => {
|
|
308
|
+
disposeRuntimeApp(app.name);
|
|
309
|
+
});
|
|
310
|
+
return runtimeApps;
|
|
311
|
+
};
|
|
312
|
+
const hasRuntimeAppCapability = (name, capability) => {
|
|
313
|
+
return Boolean(getRuntimeApp(name)?.capabilities?.[capability]);
|
|
314
|
+
};
|
|
119
315
|
const bumpStoreVersion = () => {
|
|
120
316
|
_storeVersion++;
|
|
121
317
|
};
|
|
@@ -449,4 +645,4 @@ process?.on?.('exit', code => {
|
|
|
449
645
|
logger.info?.(`[alemonjs][exit] 进程退出,code=${code}`);
|
|
450
646
|
});
|
|
451
647
|
|
|
452
|
-
export { ChildrenApp, Core, Logger, Middleware, MiddlewareRouter, MiddlewareTree, ProcessorEventAutoClearMap, ProcessorEventUserAutoClearMap, Response, ResponseMiddleware, ResponseRouter, ResponseTree, State, StateSubscribe, SubscribeList, bumpStoreVersion, core, getSubscribeList, logger };
|
|
648
|
+
export { ChildrenApp, Core, Logger, Middleware, MiddlewareRouter, MiddlewareTree, ProcessorEventAutoClearMap, ProcessorEventUserAutoClearMap, Response, ResponseMiddleware, ResponseRouter, ResponseTree, State, StateSubscribe, SubscribeList, bumpStoreVersion, clearRuntimeAppKoaRouters, core, disposeAllRuntimeApps, disposeRuntimeApp, getRuntimeApp, getRuntimeAppKoaRouters, getSubscribeList, hasRuntimeAppCapability, listRuntimeAppKoaRouters, listRuntimeApps, logger, registerRuntimeApp, setRuntimeAppKoaRouters, toRuntimeAppSnapshot, updateRuntimeAppCapabilities, updateRuntimeAppStatus };
|
package/lib/client.js
CHANGED
|
@@ -16,7 +16,7 @@ import '@koa/cors';
|
|
|
16
16
|
import './cbp/routers/router.js';
|
|
17
17
|
import 'lodash';
|
|
18
18
|
import 'fs/promises';
|
|
19
|
-
import './app/store.js';
|
|
19
|
+
import { disposeAllRuntimeApps } from './app/store.js';
|
|
20
20
|
import { loadModels } from './app/load_modules/load.js';
|
|
21
21
|
import './app/load_modules/loadChild.js';
|
|
22
22
|
import './app/define-children.js';
|
|
@@ -28,7 +28,7 @@ import './app/event-processor.js';
|
|
|
28
28
|
import './app/event-response.js';
|
|
29
29
|
import './app/hook-event-context.js';
|
|
30
30
|
import './app/message-format-old.js';
|
|
31
|
-
import '
|
|
31
|
+
import { scheduleCancelByApp, unregisterAppDir } from './app/schedule-store.js';
|
|
32
32
|
import './app/event-utils.js';
|
|
33
33
|
import './app/message-api.js';
|
|
34
34
|
import './process/platform.js';
|
|
@@ -36,6 +36,18 @@ import './process/module.js';
|
|
|
36
36
|
import { createServer } from './server/main.js';
|
|
37
37
|
|
|
38
38
|
global.__client_loaded = true;
|
|
39
|
+
let runtimeDisposed = false;
|
|
40
|
+
const disposeRuntime = () => {
|
|
41
|
+
if (runtimeDisposed) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
runtimeDisposed = true;
|
|
45
|
+
const apps = disposeAllRuntimeApps();
|
|
46
|
+
apps.forEach(app => {
|
|
47
|
+
scheduleCancelByApp(app.name);
|
|
48
|
+
unregisterAppDir(app.name);
|
|
49
|
+
});
|
|
50
|
+
};
|
|
39
51
|
const mainServer = () => {
|
|
40
52
|
const port = process.env.serverPort;
|
|
41
53
|
if (!port) {
|
|
@@ -72,10 +84,12 @@ const mainProcess = () => {
|
|
|
72
84
|
['SIGINT', 'SIGTERM', 'SIGQUIT', 'disconnect'].forEach(sig => {
|
|
73
85
|
process?.on?.(sig, () => {
|
|
74
86
|
logger.info?.(`[alemonjs][${sig}] 收到信号,正在关闭...`);
|
|
87
|
+
disposeRuntime();
|
|
75
88
|
setImmediate(() => process.exit(0));
|
|
76
89
|
});
|
|
77
90
|
});
|
|
78
91
|
process?.on?.('exit', code => {
|
|
92
|
+
disposeRuntime();
|
|
79
93
|
logger.info?.(`[alemonjs][exit] 进程退出,code=${code}`);
|
|
80
94
|
});
|
|
81
95
|
process.on('message', msg => {
|
|
@@ -86,6 +100,7 @@ const mainProcess = () => {
|
|
|
86
100
|
mainServer();
|
|
87
101
|
}
|
|
88
102
|
else if (data?.type === 'stop') {
|
|
103
|
+
disposeRuntime();
|
|
89
104
|
process.exit(0);
|
|
90
105
|
}
|
|
91
106
|
}
|
package/lib/global.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { DefineChildrenFunc, OnResponseReversalFunc, OnMiddlewareReversalFunc, OnSelectsFunc, OnDataFormatFunc, OnResponseReversalFuncBack, OnGroupFunc, OnMiddlewareReversalFuncBack, DefineResponseFunc, defineMiddlewareFunc, StoreChildrenApp, StateSubscribeMap, SubscribeKeysMap, LoggerUtils, ResponseState, StartOptions } from './types';
|
|
2
2
|
import WebSocket, { Server } from 'ws';
|
|
3
3
|
import { IncomingMessage } from 'http';
|
|
4
|
+
import type KoaRouter from 'koa-router';
|
|
5
|
+
import type { RuntimeAppRecord } from './app/store.js';
|
|
4
6
|
declare global {
|
|
5
7
|
var __config: any;
|
|
6
8
|
var __options: StartOptions;
|
|
@@ -12,6 +14,12 @@ declare global {
|
|
|
12
14
|
storeChildrenApp: {
|
|
13
15
|
[key: string]: StoreChildrenApp;
|
|
14
16
|
};
|
|
17
|
+
runtimeApps?: {
|
|
18
|
+
[key: string]: RuntimeAppRecord;
|
|
19
|
+
};
|
|
20
|
+
runtimeAppKoaRouters?: {
|
|
21
|
+
[key: string]: KoaRouter[];
|
|
22
|
+
};
|
|
15
23
|
};
|
|
16
24
|
var chatbotServer: Server<typeof WebSocket, typeof IncomingMessage>;
|
|
17
25
|
var chatbotPlatform: WebSocket;
|
package/lib/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export { createEventName, createHash, createResult, createUserHashKey, fastHash,
|
|
|
5
5
|
export { cbpClient } from './cbp/connects/client.js';
|
|
6
6
|
export { cbpPlatform } from './cbp/connects/platform.js';
|
|
7
7
|
export { cbpServer } from './cbp/server/main.js';
|
|
8
|
-
export { ChildrenApp, Core, Logger, Middleware, MiddlewareRouter, MiddlewareTree, ProcessorEventAutoClearMap, ProcessorEventUserAutoClearMap, Response, ResponseMiddleware, ResponseRouter, ResponseTree, State, StateSubscribe, SubscribeList, bumpStoreVersion, core, getSubscribeList, logger } from './app/store.js';
|
|
8
|
+
export { ChildrenApp, Core, Logger, Middleware, MiddlewareRouter, MiddlewareTree, ProcessorEventAutoClearMap, ProcessorEventUserAutoClearMap, Response, ResponseMiddleware, ResponseRouter, ResponseTree, State, StateSubscribe, SubscribeList, bumpStoreVersion, clearRuntimeAppKoaRouters, core, disposeAllRuntimeApps, disposeRuntimeApp, getRuntimeApp, getRuntimeAppKoaRouters, getSubscribeList, hasRuntimeAppCapability, listRuntimeAppKoaRouters, listRuntimeApps, logger, registerRuntimeApp, setRuntimeAppKoaRouters, toRuntimeAppSnapshot, updateRuntimeAppCapabilities, updateRuntimeAppStatus } from './app/store.js';
|
|
9
9
|
export { Expose, clearAllExpose, disposeExpose, registerExpose } from './app/expose.js';
|
|
10
10
|
export { loadModels, run } from './app/load_modules/load.js';
|
|
11
11
|
export { loadChildren, loadChildrenFile } from './app/load_modules/loadChild.js';
|
package/lib/main.js
CHANGED
|
@@ -58,8 +58,8 @@ const start = (options = {}) => {
|
|
|
58
58
|
cbpServer(port, () => {
|
|
59
59
|
const httpURL = `http://127.0.0.1:${port}`;
|
|
60
60
|
const wsURL = `ws://127.0.0.1:${port}`;
|
|
61
|
-
logger.info(`[CBP
|
|
62
|
-
logger.info(`[CBP
|
|
61
|
+
logger.info(`[CBP-Server] ${httpURL}`);
|
|
62
|
+
logger.info(`[CBP-Server] ${wsURL}]`);
|
|
63
63
|
startClient(options);
|
|
64
64
|
startPlatform(options);
|
|
65
65
|
});
|
|
@@ -67,7 +67,7 @@ const start = (options = {}) => {
|
|
|
67
67
|
else {
|
|
68
68
|
const sockPath = generateSocketPath();
|
|
69
69
|
process.env.__ALEMON_DIRECT_SOCK = sockPath;
|
|
70
|
-
logger.info('[Direct-IPC
|
|
70
|
+
logger.info('[Direct-IPC] 平台↔客户端直连');
|
|
71
71
|
startClient(options);
|
|
72
72
|
startPlatform(options);
|
|
73
73
|
}
|
|
@@ -9,14 +9,113 @@ import module$1 from 'module';
|
|
|
9
9
|
import { ResultCode } from '../../core/variable.js';
|
|
10
10
|
import 'yaml';
|
|
11
11
|
import '../../core/utils.js';
|
|
12
|
+
import { listRuntimeApps, getRuntimeApp, toRuntimeAppSnapshot, listRuntimeAppKoaRouters, hasRuntimeAppCapability, getRuntimeAppKoaRouters } from '../../app/store.js';
|
|
12
13
|
|
|
13
14
|
const initRequire = () => { };
|
|
14
15
|
initRequire.resolve = () => '';
|
|
15
16
|
const require$1 = module$1?.createRequire?.(import.meta.url) ?? initRequire;
|
|
16
|
-
const mainDirMap = new Map();
|
|
17
17
|
const router = new KoaRouter({
|
|
18
18
|
prefix: '/'
|
|
19
19
|
});
|
|
20
|
+
const resolvePackageRoot = (startDir) => {
|
|
21
|
+
let currentDir = startDir;
|
|
22
|
+
while (currentDir && currentDir !== path__default.dirname(currentDir)) {
|
|
23
|
+
if (existsSync(path__default.join(currentDir, 'package.json'))) {
|
|
24
|
+
return currentDir;
|
|
25
|
+
}
|
|
26
|
+
currentDir = path__default.dirname(currentDir);
|
|
27
|
+
}
|
|
28
|
+
return startDir;
|
|
29
|
+
};
|
|
30
|
+
const readWebRootConfig = (packageRoot) => {
|
|
31
|
+
const packageJsonPath = path__default.join(packageRoot, 'package.json');
|
|
32
|
+
if (!existsSync(packageJsonPath)) {
|
|
33
|
+
return '';
|
|
34
|
+
}
|
|
35
|
+
const pkg = require$1(packageJsonPath) ?? {};
|
|
36
|
+
return pkg?.alemonjs?.web?.root ?? '';
|
|
37
|
+
};
|
|
38
|
+
const denyRuntimeAppAccess = (ctx, appName, capability) => {
|
|
39
|
+
const runtimeApp = getRuntimeApp(appName);
|
|
40
|
+
if (!runtimeApp || !runtimeApp.enabled) {
|
|
41
|
+
ctx.status = 404;
|
|
42
|
+
ctx.body = {
|
|
43
|
+
code: 404,
|
|
44
|
+
message: '应用未注册或未启用',
|
|
45
|
+
data: null
|
|
46
|
+
};
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
if (runtimeApp.status === 'discovered' || runtimeApp.status === 'loading') {
|
|
50
|
+
ctx.status = 503;
|
|
51
|
+
ctx.body = {
|
|
52
|
+
code: 503,
|
|
53
|
+
message: '应用正在初始化',
|
|
54
|
+
data: {
|
|
55
|
+
app: appName,
|
|
56
|
+
status: runtimeApp.status
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
if (runtimeApp.status === 'failed') {
|
|
62
|
+
ctx.status = 500;
|
|
63
|
+
ctx.body = {
|
|
64
|
+
code: 500,
|
|
65
|
+
message: '应用生命周期失败',
|
|
66
|
+
data: {
|
|
67
|
+
app: appName,
|
|
68
|
+
status: runtimeApp.status,
|
|
69
|
+
lifecycle: 'failed'
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
if (runtimeApp.status === 'disposed') {
|
|
75
|
+
ctx.status = 410;
|
|
76
|
+
ctx.body = {
|
|
77
|
+
code: 410,
|
|
78
|
+
message: '应用已卸载或已结束服务',
|
|
79
|
+
data: {
|
|
80
|
+
app: appName,
|
|
81
|
+
status: runtimeApp.status,
|
|
82
|
+
lifecycle: 'disposed'
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
if (runtimeApp.status !== 'ready' || !hasRuntimeAppCapability(appName, capability)) {
|
|
88
|
+
ctx.status = 404;
|
|
89
|
+
ctx.body = {
|
|
90
|
+
code: 404,
|
|
91
|
+
message: '应用未提供对应服务能力',
|
|
92
|
+
data: null
|
|
93
|
+
};
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
return runtimeApp;
|
|
97
|
+
};
|
|
98
|
+
const dispatchRegisteredKoaRouters = async (ctx) => {
|
|
99
|
+
const registeredRouters = listRuntimeAppKoaRouters();
|
|
100
|
+
for (const item of registeredRouters) {
|
|
101
|
+
const runtimeApp = getRuntimeApp(item.name);
|
|
102
|
+
if (!runtimeApp || !runtimeApp.enabled || runtimeApp.status !== 'ready' || !hasRuntimeAppCapability(item.name, 'httpApi')) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const routers = getRuntimeAppKoaRouters(item.name);
|
|
106
|
+
for (const koaRouter of routers) {
|
|
107
|
+
const beforeMatched = Array.isArray(ctx.matched) ? ctx.matched.length : 0;
|
|
108
|
+
await koaRouter.routes()(ctx, async () => { });
|
|
109
|
+
const afterMatched = Array.isArray(ctx.matched) ? ctx.matched.length : 0;
|
|
110
|
+
if (afterMatched <= beforeMatched) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
await koaRouter.allowedMethods()(ctx, async () => { });
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
};
|
|
20
119
|
router.get('/', ctx => {
|
|
21
120
|
ctx.status = 200;
|
|
22
121
|
ctx.set('Content-Type', 'text/html; charset=utf-8');
|
|
@@ -30,6 +129,47 @@ router.get('api/online', ctx => {
|
|
|
30
129
|
data: null
|
|
31
130
|
};
|
|
32
131
|
});
|
|
132
|
+
router.get('api/runtime/apps', ctx => {
|
|
133
|
+
const status = String(ctx.query?.status ?? '').trim();
|
|
134
|
+
const data = listRuntimeApps().filter(item => {
|
|
135
|
+
if (!status) {
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
return item.status === status;
|
|
139
|
+
});
|
|
140
|
+
ctx.status = 200;
|
|
141
|
+
ctx.body = {
|
|
142
|
+
code: 200,
|
|
143
|
+
message: 'runtime apps',
|
|
144
|
+
data
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
router.get('api/runtime/apps/:app', ctx => {
|
|
148
|
+
const appName = ctx.params.app;
|
|
149
|
+
const runtimeApp = getRuntimeApp(appName);
|
|
150
|
+
if (!runtimeApp) {
|
|
151
|
+
ctx.status = 404;
|
|
152
|
+
ctx.body = {
|
|
153
|
+
code: 404,
|
|
154
|
+
message: '应用未注册',
|
|
155
|
+
data: null
|
|
156
|
+
};
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
ctx.status = 200;
|
|
160
|
+
ctx.body = {
|
|
161
|
+
code: 200,
|
|
162
|
+
message: 'runtime app',
|
|
163
|
+
data: toRuntimeAppSnapshot(runtimeApp)
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
router.use(async (ctx, next) => {
|
|
167
|
+
const handled = await dispatchRegisteredKoaRouters(ctx);
|
|
168
|
+
if (handled) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
await next();
|
|
172
|
+
});
|
|
33
173
|
router.all('app/{*path}', async (ctx) => {
|
|
34
174
|
if (!process.env.input) {
|
|
35
175
|
ctx.status = 400;
|
|
@@ -43,6 +183,10 @@ router.all('app/{*path}', async (ctx) => {
|
|
|
43
183
|
const rootPath = process.cwd();
|
|
44
184
|
const apiPath = '/app/api';
|
|
45
185
|
if (ctx.path.startsWith(apiPath)) {
|
|
186
|
+
const runtimeApp = denyRuntimeAppAccess(ctx, 'main', 'httpApi');
|
|
187
|
+
if (!runtimeApp) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
46
190
|
const mainPath = join(rootPath, process.env.input);
|
|
47
191
|
if (!existsSync(mainPath)) {
|
|
48
192
|
ctx.status = 400;
|
|
@@ -111,9 +255,13 @@ router.all('app/{*path}', async (ctx) => {
|
|
|
111
255
|
}
|
|
112
256
|
let root = '';
|
|
113
257
|
const resourcePath = formatPath(ctx.params?.path);
|
|
258
|
+
const runtimeApp = denyRuntimeAppAccess(ctx, 'main', 'web');
|
|
259
|
+
if (!runtimeApp) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const packageRoot = resolvePackageRoot(runtimeApp.rootDir);
|
|
114
263
|
try {
|
|
115
|
-
|
|
116
|
-
root = pkg.alemonjs?.web?.root ?? '';
|
|
264
|
+
root = readWebRootConfig(packageRoot);
|
|
117
265
|
}
|
|
118
266
|
catch (err) {
|
|
119
267
|
ctx.status = 500;
|
|
@@ -124,7 +272,7 @@ router.all('app/{*path}', async (ctx) => {
|
|
|
124
272
|
};
|
|
125
273
|
return;
|
|
126
274
|
}
|
|
127
|
-
const webRoot = root ? path__default.join(
|
|
275
|
+
const webRoot = root ? path__default.join(packageRoot, root) : packageRoot;
|
|
128
276
|
const fullPath = safePath(webRoot, resourcePath);
|
|
129
277
|
if (!fullPath) {
|
|
130
278
|
ctx.status = 403;
|
|
@@ -177,22 +325,12 @@ router.all('apps/:app/{*path}', async (ctx) => {
|
|
|
177
325
|
}
|
|
178
326
|
const apiPath = `/apps/${appName}/api`;
|
|
179
327
|
if (ctx.path.startsWith(apiPath)) {
|
|
328
|
+
const runtimeApp = denyRuntimeAppAccess(ctx, appName, 'httpApi');
|
|
329
|
+
if (!runtimeApp) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
180
332
|
try {
|
|
181
|
-
|
|
182
|
-
const mainPath = require$1.resolve(appName);
|
|
183
|
-
if (!existsSync(mainPath)) {
|
|
184
|
-
ctx.status = 400;
|
|
185
|
-
ctx.body = {
|
|
186
|
-
code: 400,
|
|
187
|
-
message: '未找到主要入口文件',
|
|
188
|
-
data: null
|
|
189
|
-
};
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
const mainDir = dirname(mainPath);
|
|
193
|
-
mainDirMap.set(appName, mainDir);
|
|
194
|
-
}
|
|
195
|
-
const routeBase = join(mainDirMap.get(appName), 'route');
|
|
333
|
+
const routeBase = join(runtimeApp.rootDir, 'route');
|
|
196
334
|
const dir = safePath(routeBase, ctx.path?.replace(apiPath, '/api') || '');
|
|
197
335
|
if (!dir) {
|
|
198
336
|
ctx.status = 403;
|
|
@@ -250,12 +388,15 @@ router.all('apps/:app/{*path}', async (ctx) => {
|
|
|
250
388
|
ctx.status = 405;
|
|
251
389
|
return;
|
|
252
390
|
}
|
|
253
|
-
const
|
|
391
|
+
const runtimeApp = denyRuntimeAppAccess(ctx, appName, 'web');
|
|
392
|
+
if (!runtimeApp) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
const packageRoot = resolvePackageRoot(runtimeApp.rootDir);
|
|
254
396
|
const resourcePath = formatPath(ctx.params?.path);
|
|
255
397
|
let root = '';
|
|
256
398
|
try {
|
|
257
|
-
|
|
258
|
-
root = pkg?.alemonjs?.web?.root ?? '';
|
|
399
|
+
root = readWebRootConfig(packageRoot);
|
|
259
400
|
}
|
|
260
401
|
catch (err) {
|
|
261
402
|
ctx.status = 500;
|
|
@@ -266,7 +407,7 @@ router.all('apps/:app/{*path}', async (ctx) => {
|
|
|
266
407
|
};
|
|
267
408
|
return;
|
|
268
409
|
}
|
|
269
|
-
const webRoot = root ? path__default.join(
|
|
410
|
+
const webRoot = root ? path__default.join(packageRoot, root) : packageRoot;
|
|
270
411
|
const fullPath = safePath(webRoot, resourcePath);
|
|
271
412
|
if (!fullPath) {
|
|
272
413
|
ctx.status = 403;
|
|
@@ -3,6 +3,7 @@ import { ClientAPI } from '../client';
|
|
|
3
3
|
import { EventKeys, Events } from './map';
|
|
4
4
|
import { DataEnums } from '../message';
|
|
5
5
|
import { Expose } from '../../app/expose';
|
|
6
|
+
import type KoaRouter from 'koa-router';
|
|
6
7
|
export type Current<T extends EventKeys> = (event: Events[T], next: Next) => Promise<boolean | void | undefined> | boolean | void | undefined;
|
|
7
8
|
export type OnResponseValue<C, T extends EventKeys> = {
|
|
8
9
|
current: C;
|
|
@@ -56,6 +57,7 @@ export type childrenCallbackRes = {
|
|
|
56
57
|
middleware?: ReturnType<defineMiddlewareFunc>;
|
|
57
58
|
responseRouter?: ReturnType<DefineRouterFunc>;
|
|
58
59
|
middlewareRouter?: ReturnType<DefineRouterFunc>;
|
|
60
|
+
koaRouter?: KoaRouter | KoaRouter[];
|
|
59
61
|
expose?: Expose;
|
|
60
62
|
} | undefined;
|
|
61
63
|
export type childrenCallback = ChildrenCycle & {
|