alemonjs 2.1.89 → 2.1.91
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/bin/README.md +8 -1
- package/bin/alemonc.js +1 -2
- package/bin/publish.js +58 -23
- package/lib/application/runtime/cbp/connects/client.js +11 -1
- package/lib/application/runtime/client-runtime.d.ts +2 -0
- package/lib/application/runtime/client-runtime.js +14 -36
- package/lib/application/runtime/load-modules/load.d.ts +2 -2
- package/lib/application/runtime/load-modules/load.js +8 -8
- package/lib/application/runtime/load-modules/loadChild.d.ts +1 -1
- package/lib/application/runtime/load-modules/loadChild.js +3 -3
- package/lib/client.d.ts +1 -1
- package/lib/client.js +91 -1
- package/lib/core/index.d.ts +3 -0
- package/lib/core/index.js +2 -0
- package/lib/core/process/index.d.ts +1 -0
- package/lib/core/process/index.js +2 -2
- package/lib/core/process/ipc-bridge.js +12 -0
- package/lib/core/process/module.d.ts +3 -0
- package/lib/core/process/module.js +340 -101
- package/lib/core/process/platform.d.ts +3 -0
- package/lib/core/process/platform.js +393 -165
- package/lib/core/process/types.d.ts +22 -0
- package/lib/core/process/types.js +1 -0
- package/lib/global.d.ts +3 -0
- package/lib/index.js +2 -0
- package/lib/main.d.ts +1 -0
- package/lib/main.js +2 -0
- package/lib/platform/cbp-platform.js +11 -1
- package/lib/platform/define-platform.js +3 -0
- package/lib/platform-bootstrap.d.ts +1 -0
- package/lib/platform-bootstrap.js +85 -0
- package/package.json +1 -1
package/bin/README.md
CHANGED
|
@@ -105,17 +105,24 @@ alemonc version update
|
|
|
105
105
|
```sh
|
|
106
106
|
alemonc publish
|
|
107
107
|
alemonc publish patch
|
|
108
|
+
alemonc publish prepatch --preid beta
|
|
109
|
+
alemonc publish v1.0.33-rc.0
|
|
108
110
|
alemonc publish --dry-run
|
|
109
111
|
```
|
|
110
112
|
|
|
111
113
|
行为说明:
|
|
112
114
|
|
|
113
115
|
- 默认会查询 git tag 历史作为版本基线
|
|
116
|
+
- 版本格式严格为:
|
|
117
|
+
- 正式版:`v1.0.33`
|
|
118
|
+
- 预发布版:`v1.0.33-alpha.0`、`v1.0.33-beta.0`、`v1.0.33-rc.0`、`v1.0.33-next.0`
|
|
119
|
+
- `package.json.version` 保存为不带 `v` 的形式,如 `1.0.33`、`1.0.33-beta.0`
|
|
114
120
|
- 不传参数时:
|
|
115
121
|
- 如果本地版本高于最新 tag,直接发布本地版本
|
|
116
122
|
- 否则自动按最新 tag `patch +1`
|
|
117
123
|
- 传 `patch/minor/major/prepatch/preminor/premajor/prerelease` 时会自动递增
|
|
118
|
-
-
|
|
124
|
+
- 传具体版本号时可写 `v1.0.33` 或 `1.0.33`
|
|
125
|
+
- `--preid` 仅允许 `alpha`、`beta`、`rc`、`next`
|
|
119
126
|
- 默认先执行 `npm run build`
|
|
120
127
|
- 默认发布内容是 `lib/`、`package.json`、`README.md`
|
|
121
128
|
- 如果项目配置了 `.npmignore` 或 `package.json.files`,则切换为 npm 文件选择规则
|
package/bin/alemonc.js
CHANGED
|
@@ -78,8 +78,7 @@ program
|
|
|
78
78
|
program
|
|
79
79
|
.command('publish [release]')
|
|
80
80
|
.description('智能发布当前包到 git release 仓库,支持 patch/minor/major 或直接指定版本号')
|
|
81
|
-
.option('--
|
|
82
|
-
.option('--preid <preid>', '预发布标识,默认 beta', 'beta')
|
|
81
|
+
.option('--preid <preid>', '预发布标识,仅允许 alpha/beta/rc/next', 'beta')
|
|
83
82
|
.option('--branch <branch>', '发布目标分支,默认 release')
|
|
84
83
|
.option('--dry-run', '只执行检查和打包,不真正发布')
|
|
85
84
|
.option('--skip-build', '跳过构建')
|
package/bin/publish.js
CHANGED
|
@@ -5,7 +5,9 @@ import os from 'os';
|
|
|
5
5
|
import { execSync, spawnSync } from 'child_process';
|
|
6
6
|
|
|
7
7
|
const RELEASE_TYPES = new Set(['patch', 'minor', 'major', 'prepatch', 'preminor', 'premajor', 'prerelease']);
|
|
8
|
-
const
|
|
8
|
+
const PRERELEASE_IDS = new Set(['alpha', 'beta', 'rc', 'next']);
|
|
9
|
+
const SEMVER_RE = /^\d+\.\d+\.\d+(?:-(alpha|beta|rc|next)\.\d+)?$/;
|
|
10
|
+
const TAG_RE = /^v\d+\.\d+\.\d+(?:-(alpha|beta|rc|next)\.\d+)?$/;
|
|
9
11
|
const DEFAULT_PUBLISH_FILES = ['lib', 'package.json', 'README.md'];
|
|
10
12
|
|
|
11
13
|
function readPackageJson() {
|
|
@@ -70,8 +72,21 @@ function ensureCleanGit() {
|
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
|
|
75
|
+
function normalizeVersionInput(version) {
|
|
76
|
+
return String(version).trim().replace(/^v/, '');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function validatePreid(preid) {
|
|
80
|
+
const value = String(preid || 'beta').trim();
|
|
81
|
+
if (!PRERELEASE_IDS.has(value)) {
|
|
82
|
+
throw new Error(`非法预发布标识: ${value},仅允许 alpha、beta、rc、next`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
|
|
73
88
|
function parseVersion(version) {
|
|
74
|
-
const matched = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-(
|
|
89
|
+
const matched = normalizeVersionInput(version).match(/^(\d+)\.(\d+)\.(\d+)(?:-((alpha|beta|rc|next)\.(\d+)))?$/);
|
|
75
90
|
if (!matched) {
|
|
76
91
|
throw new Error(`非法版本号: ${version}`);
|
|
77
92
|
}
|
|
@@ -80,7 +95,9 @@ function parseVersion(version) {
|
|
|
80
95
|
major: Number(matched[1]),
|
|
81
96
|
minor: Number(matched[2]),
|
|
82
97
|
patch: Number(matched[3]),
|
|
83
|
-
prerelease: matched[4] ?? null
|
|
98
|
+
prerelease: matched[4] ?? null,
|
|
99
|
+
prereleaseId: matched[5] ?? null,
|
|
100
|
+
prereleaseNum: matched[6] ? Number(matched[6]) : null
|
|
84
101
|
};
|
|
85
102
|
}
|
|
86
103
|
|
|
@@ -102,6 +119,7 @@ function compareVersions(a, b) {
|
|
|
102
119
|
|
|
103
120
|
function incrementVersion(baseVersion, releaseType, preid = 'beta') {
|
|
104
121
|
const parsed = parseVersion(baseVersion);
|
|
122
|
+
const safePreid = validatePreid(preid);
|
|
105
123
|
|
|
106
124
|
if (releaseType === 'patch') {
|
|
107
125
|
return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}`;
|
|
@@ -116,28 +134,23 @@ function incrementVersion(baseVersion, releaseType, preid = 'beta') {
|
|
|
116
134
|
}
|
|
117
135
|
|
|
118
136
|
if (releaseType === 'prepatch') {
|
|
119
|
-
return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}-${
|
|
137
|
+
return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}-${safePreid}.0`;
|
|
120
138
|
}
|
|
121
139
|
|
|
122
140
|
if (releaseType === 'preminor') {
|
|
123
|
-
return `${parsed.major}.${parsed.minor + 1}.0-${
|
|
141
|
+
return `${parsed.major}.${parsed.minor + 1}.0-${safePreid}.0`;
|
|
124
142
|
}
|
|
125
143
|
|
|
126
144
|
if (releaseType === 'premajor') {
|
|
127
|
-
return `${parsed.major + 1}.0.0-${
|
|
145
|
+
return `${parsed.major + 1}.0.0-${safePreid}.0`;
|
|
128
146
|
}
|
|
129
147
|
|
|
130
148
|
if (releaseType === 'prerelease') {
|
|
131
|
-
if (parsed.prerelease) {
|
|
132
|
-
|
|
133
|
-
if (next) {
|
|
134
|
-
return `${parsed.major}.${parsed.minor}.${parsed.patch}-${next[1]}${Number(next[2]) + 1}`;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return `${parsed.major}.${parsed.minor}.${parsed.patch}-${parsed.prerelease}.1`;
|
|
149
|
+
if (parsed.prerelease && parsed.prereleaseId === safePreid && parsed.prereleaseNum !== null) {
|
|
150
|
+
return `${parsed.major}.${parsed.minor}.${parsed.patch}-${safePreid}.${parsed.prereleaseNum + 1}`;
|
|
138
151
|
}
|
|
139
152
|
|
|
140
|
-
return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}-${
|
|
153
|
+
return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}-${safePreid}.0`;
|
|
141
154
|
}
|
|
142
155
|
|
|
143
156
|
throw new Error(`不支持的发布类型: ${releaseType}`);
|
|
@@ -161,8 +174,10 @@ function resolveTargetVersion(localVersion, remoteVersion, release, preid) {
|
|
|
161
174
|
return incrementVersion(base, release, preid);
|
|
162
175
|
}
|
|
163
176
|
|
|
164
|
-
|
|
165
|
-
|
|
177
|
+
const normalizedRelease = normalizeVersionInput(release);
|
|
178
|
+
|
|
179
|
+
if (SEMVER_RE.test(normalizedRelease)) {
|
|
180
|
+
return normalizedRelease;
|
|
166
181
|
}
|
|
167
182
|
|
|
168
183
|
throw new Error(`无法识别的发布参数: ${release}`);
|
|
@@ -261,6 +276,22 @@ function ensureGitRepo() {
|
|
|
261
276
|
}
|
|
262
277
|
}
|
|
263
278
|
|
|
279
|
+
function getLatestReleaseVersion() {
|
|
280
|
+
const tags = getCommandOutput('git tag --list --sort=-v:refname');
|
|
281
|
+
if (!tags) {
|
|
282
|
+
return '';
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
for (const tag of tags.split('\n')) {
|
|
286
|
+
const value = tag.trim();
|
|
287
|
+
if (TAG_RE.test(value)) {
|
|
288
|
+
return value.slice(1);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return '';
|
|
293
|
+
}
|
|
294
|
+
|
|
264
295
|
function remoteBranchExists(branch) {
|
|
265
296
|
const result = spawnSync('git', ['ls-remote', '--exit-code', '--heads', 'origin', branch], {
|
|
266
297
|
cwd: process.cwd(),
|
|
@@ -317,7 +348,7 @@ export async function publish(release, options = {}) {
|
|
|
317
348
|
|
|
318
349
|
const { pkgPath, pkg } = readPackageJson();
|
|
319
350
|
const packageName = pkg.name;
|
|
320
|
-
const localVersion = String(pkg.version || '').trim();
|
|
351
|
+
const localVersion = normalizeVersionInput(String(pkg.version || '').trim());
|
|
321
352
|
|
|
322
353
|
if (!packageName) {
|
|
323
354
|
throw new Error('package.json 缺少 name');
|
|
@@ -333,7 +364,7 @@ export async function publish(release, options = {}) {
|
|
|
333
364
|
ensureGitRepo();
|
|
334
365
|
|
|
335
366
|
const releaseBranch = options.branch || 'release';
|
|
336
|
-
const remoteVersion =
|
|
367
|
+
const remoteVersion = getLatestReleaseVersion();
|
|
337
368
|
if (remoteVersion) {
|
|
338
369
|
console.log(`最新 git tag: v${remoteVersion}`);
|
|
339
370
|
} else {
|
|
@@ -344,9 +375,9 @@ export async function publish(release, options = {}) {
|
|
|
344
375
|
ensureCleanGit();
|
|
345
376
|
}
|
|
346
377
|
|
|
347
|
-
const
|
|
348
|
-
const
|
|
349
|
-
const gitTagName =
|
|
378
|
+
const preid = validatePreid(options.preid);
|
|
379
|
+
const targetVersion = resolveTargetVersion(localVersion, remoteVersion, release, preid);
|
|
380
|
+
const gitTagName = `v${targetVersion}`;
|
|
350
381
|
console.log(`目标版本: ${targetVersion}`);
|
|
351
382
|
console.log(`发布分支: ${releaseBranch}`);
|
|
352
383
|
console.log(`git 标签: ${gitTagName}`);
|
|
@@ -383,6 +414,10 @@ export async function publish(release, options = {}) {
|
|
|
383
414
|
console.log(`发布文件数: ${publishFiles.length}`);
|
|
384
415
|
|
|
385
416
|
if (options.dryRun) {
|
|
417
|
+
if (targetVersion !== localVersion) {
|
|
418
|
+
updateVersion(pkgPath, pkg, localVersion);
|
|
419
|
+
console.log(`已回滚 package.json 版本到 ${localVersion}`);
|
|
420
|
+
}
|
|
386
421
|
console.log('dry-run 模式,不会真正推送到 git');
|
|
387
422
|
return;
|
|
388
423
|
}
|
|
@@ -402,8 +437,8 @@ export async function publish(release, options = {}) {
|
|
|
402
437
|
console.log(`已推送到分支: ${releaseBranch}`);
|
|
403
438
|
}
|
|
404
439
|
|
|
405
|
-
runCommand('git', ['tag', '-f', gitTagName]);
|
|
406
|
-
runCommand('git', ['push', 'origin', gitTagName, '--force']);
|
|
440
|
+
runCommand('git', ['-C', worktreeDir, 'tag', '-f', gitTagName]);
|
|
441
|
+
runCommand('git', ['-C', worktreeDir, 'push', 'origin', gitTagName, '--force']);
|
|
407
442
|
console.log(`发布完成: ${packageName}@${targetVersion}`);
|
|
408
443
|
} catch (error) {
|
|
409
444
|
if (targetVersion !== localVersion) {
|
|
@@ -15,6 +15,11 @@ import { normalizeInboundMessage } from '../../../../common/cbp/normalize.js';
|
|
|
15
15
|
import { apiRequestResolves, apiRequestTimeouts, actionRequestResolves, actionRequestTimeouts } from '../processor/request-registry.js';
|
|
16
16
|
import { setDirectSend } from '../processor/transport.js';
|
|
17
17
|
|
|
18
|
+
const notifyTransportReady = (transport) => {
|
|
19
|
+
if (typeof process.send === 'function') {
|
|
20
|
+
process.send({ type: 'transport_ready', protocolVersion: 'v2', transport });
|
|
21
|
+
}
|
|
22
|
+
};
|
|
18
23
|
const handleInboundMessage = (message) => {
|
|
19
24
|
const normalized = normalizeInboundMessage(message);
|
|
20
25
|
if (!normalized) {
|
|
@@ -72,6 +77,7 @@ const cbpClientDirect = (sockPath, open) => {
|
|
|
72
77
|
})
|
|
73
78
|
.then(channel => {
|
|
74
79
|
setDirectSend(channel.send);
|
|
80
|
+
notifyTransportReady('direct');
|
|
75
81
|
open();
|
|
76
82
|
logger.debug({
|
|
77
83
|
code: ResultCode.Ok,
|
|
@@ -104,6 +110,7 @@ const cbpClientIPC = (open) => {
|
|
|
104
110
|
});
|
|
105
111
|
}
|
|
106
112
|
});
|
|
113
|
+
notifyTransportReady('ipc');
|
|
107
114
|
open();
|
|
108
115
|
logger.debug({
|
|
109
116
|
code: ResultCode.Ok,
|
|
@@ -128,7 +135,10 @@ const cbpClient = (url, options = {}) => {
|
|
|
128
135
|
extraHeaders: {
|
|
129
136
|
[FULL_RECEIVE_HEADER]: isFullReceive ? '1' : '0'
|
|
130
137
|
},
|
|
131
|
-
onOpen:
|
|
138
|
+
onOpen: () => {
|
|
139
|
+
notifyTransportReady('ws');
|
|
140
|
+
open();
|
|
141
|
+
},
|
|
132
142
|
onMessage: (messageStr) => {
|
|
133
143
|
try {
|
|
134
144
|
const parsedMessage = flattedJSON.parse(messageStr);
|
|
@@ -28,7 +28,8 @@ import { dispatchDisposeAllApps } from './lifecycle-callbacks.js';
|
|
|
28
28
|
|
|
29
29
|
global.__client_loaded = true;
|
|
30
30
|
let runtimeDisposed = false;
|
|
31
|
-
|
|
31
|
+
let runtimeStarted = false;
|
|
32
|
+
const disposeClientRuntime = async () => {
|
|
32
33
|
if (runtimeDisposed) {
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
@@ -40,11 +41,6 @@ const disposeRuntime = async () => {
|
|
|
40
41
|
unregisterAppDir(app.name);
|
|
41
42
|
});
|
|
42
43
|
};
|
|
43
|
-
const shutdown = async (reason) => {
|
|
44
|
-
logger.info?.(`[alemonjs][${reason}] 收到信号,正在关闭...`);
|
|
45
|
-
await disposeRuntime();
|
|
46
|
-
process.exit(0);
|
|
47
|
-
};
|
|
48
44
|
const mainServer = () => {
|
|
49
45
|
const port = process.env.serverPort;
|
|
50
46
|
if (!port) {
|
|
@@ -68,37 +64,19 @@ const main = () => {
|
|
|
68
64
|
else {
|
|
69
65
|
cbpClient(`http://127.0.0.1:${port}`, { isFullReceive });
|
|
70
66
|
}
|
|
71
|
-
loadModels();
|
|
72
67
|
};
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
});
|
|
83
|
-
process?.on?.('exit', code => {
|
|
84
|
-
void disposeRuntime();
|
|
85
|
-
logger.info?.(`[alemonjs][exit] 进程退出,code=${code}`);
|
|
86
|
-
});
|
|
87
|
-
process.on('message', msg => {
|
|
88
|
-
try {
|
|
89
|
-
const data = typeof msg === 'string' ? JSON.parse(msg) : msg;
|
|
90
|
-
if (data?.type === 'start') {
|
|
91
|
-
main();
|
|
92
|
-
mainServer();
|
|
93
|
-
}
|
|
94
|
-
else if (data?.type === 'stop') {
|
|
95
|
-
void shutdown('stop');
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch { }
|
|
99
|
-
});
|
|
68
|
+
const startClientRuntime = async () => {
|
|
69
|
+
if (runtimeStarted) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
runtimeStarted = true;
|
|
73
|
+
runtimeDisposed = false;
|
|
74
|
+
main();
|
|
75
|
+
mainServer();
|
|
76
|
+
await loadModels();
|
|
100
77
|
if (process.send) {
|
|
101
|
-
process.send({ type: '
|
|
78
|
+
process.send({ type: 'app_ready', protocolVersion: 'v2' });
|
|
102
79
|
}
|
|
103
80
|
};
|
|
104
|
-
|
|
81
|
+
|
|
82
|
+
export { disposeClientRuntime, startClientRuntime };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const run: (input: string) => void
|
|
2
|
-
export declare function loadModels(): void
|
|
1
|
+
export declare const run: (input: string) => Promise<void>;
|
|
2
|
+
export declare function loadModels(): Promise<void>;
|
|
@@ -13,7 +13,7 @@ const loadApps = () => {
|
|
|
13
13
|
.filter(([, enabled]) => Boolean(enabled))
|
|
14
14
|
.map(([name]) => name);
|
|
15
15
|
const uniqueApps = Array.from(new Set(apps));
|
|
16
|
-
uniqueApps.
|
|
16
|
+
return Promise.all(uniqueApps.map(async (app) => {
|
|
17
17
|
registerRuntimeApp({
|
|
18
18
|
name: app,
|
|
19
19
|
kind: 'plugin',
|
|
@@ -22,10 +22,10 @@ const loadApps = () => {
|
|
|
22
22
|
rootDir: '',
|
|
23
23
|
mainPath: ''
|
|
24
24
|
});
|
|
25
|
-
|
|
26
|
-
});
|
|
25
|
+
await loadChildrenFile(app);
|
|
26
|
+
}));
|
|
27
27
|
};
|
|
28
|
-
const run = (input) => {
|
|
28
|
+
const run = async (input) => {
|
|
29
29
|
if (!input) {
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
@@ -46,12 +46,12 @@ const run = (input) => {
|
|
|
46
46
|
rootDir: join(process.cwd(), dirname(input)),
|
|
47
47
|
mainPath
|
|
48
48
|
});
|
|
49
|
-
|
|
49
|
+
await loadChildren(mainPath, 'main');
|
|
50
50
|
};
|
|
51
|
-
function loadModels() {
|
|
51
|
+
async function loadModels() {
|
|
52
52
|
const input = process.env.input ?? '';
|
|
53
|
-
run(input);
|
|
54
|
-
loadApps();
|
|
53
|
+
await run(input);
|
|
54
|
+
await loadApps();
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
export { loadModels, run };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const loadChildren: (mainPath: string, appName: string) => Promise<void>;
|
|
2
|
-
export declare const loadChildrenFile: (appName: string) => void
|
|
2
|
+
export declare const loadChildrenFile: (appName: string) => Promise<void>;
|
|
@@ -287,7 +287,7 @@ const loadChildren = async (mainPath, appName) => {
|
|
|
287
287
|
App.un();
|
|
288
288
|
}
|
|
289
289
|
};
|
|
290
|
-
const loadChildrenFile = (appName) => {
|
|
290
|
+
const loadChildrenFile = async (appName) => {
|
|
291
291
|
if (typeof appName !== 'string') {
|
|
292
292
|
logger.error({
|
|
293
293
|
code: ResultCode.FailParams,
|
|
@@ -322,7 +322,7 @@ const loadChildrenFile = (appName) => {
|
|
|
322
322
|
rootDir: dirname(mainPath),
|
|
323
323
|
mainPath
|
|
324
324
|
});
|
|
325
|
-
|
|
325
|
+
await loadChildren(mainPath, appName);
|
|
326
326
|
}
|
|
327
327
|
catch (e) {
|
|
328
328
|
const packageDir = resolvePackageDir(appName);
|
|
@@ -336,7 +336,7 @@ const loadChildrenFile = (appName) => {
|
|
|
336
336
|
rootDir: dirname(fallbackMainPath),
|
|
337
337
|
mainPath: fallbackMainPath
|
|
338
338
|
});
|
|
339
|
-
|
|
339
|
+
await loadChildren(fallbackMainPath, appName);
|
|
340
340
|
return;
|
|
341
341
|
}
|
|
342
342
|
updateRuntimeAppStatus(appName, 'failed', e);
|
package/lib/client.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
package/lib/client.js
CHANGED
|
@@ -1 +1,91 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import { logger } from './common/logger.js';
|
|
2
|
+
|
|
3
|
+
let runtimeModulePromise = null;
|
|
4
|
+
let runtimeStarted = false;
|
|
5
|
+
let stopping = false;
|
|
6
|
+
const notifyParent = (message) => {
|
|
7
|
+
if (typeof process.send === 'function') {
|
|
8
|
+
process.send(message);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
const normalizeError = (error) => {
|
|
12
|
+
if (error instanceof Error) {
|
|
13
|
+
return {
|
|
14
|
+
message: error.message,
|
|
15
|
+
stack: error.stack
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
message: typeof error === 'string' ? error : 'Unknown client bootstrap error'
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
const loadRuntimeModule = async () => {
|
|
23
|
+
runtimeModulePromise ??= import('./application/runtime/client-runtime.js');
|
|
24
|
+
return runtimeModulePromise;
|
|
25
|
+
};
|
|
26
|
+
const shutdown = async (reason) => {
|
|
27
|
+
if (stopping) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
stopping = true;
|
|
31
|
+
logger.info?.(`[client-bootstrap][${reason}] 收到信号,正在关闭...`);
|
|
32
|
+
try {
|
|
33
|
+
const runtimeModule = runtimeModulePromise ? await runtimeModulePromise : null;
|
|
34
|
+
if (runtimeModule?.disposeClientRuntime) {
|
|
35
|
+
await runtimeModule.disposeClientRuntime();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
logger.error?.('[client-bootstrap] 关闭失败', error);
|
|
40
|
+
}
|
|
41
|
+
process.exit(0);
|
|
42
|
+
};
|
|
43
|
+
const startRuntime = async () => {
|
|
44
|
+
if (runtimeStarted) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
runtimeStarted = true;
|
|
48
|
+
try {
|
|
49
|
+
const runtimeModule = await loadRuntimeModule();
|
|
50
|
+
if (typeof runtimeModule.startClientRuntime !== 'function') {
|
|
51
|
+
throw new Error('Client runtime missing startClientRuntime');
|
|
52
|
+
}
|
|
53
|
+
await runtimeModule.startClientRuntime();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
notifyParent({
|
|
57
|
+
type: 'boot_error',
|
|
58
|
+
protocolVersion: 'v2',
|
|
59
|
+
stage: 'app',
|
|
60
|
+
error: normalizeError(error)
|
|
61
|
+
});
|
|
62
|
+
logger.error?.('[client-bootstrap] 启动失败', error);
|
|
63
|
+
process.exitCode = 1;
|
|
64
|
+
setImmediate(() => process.exit(1));
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
process.on('unhandledRejection', (reason) => {
|
|
68
|
+
logger.error?.('[client-bootstrap][unhandledRejection]', reason);
|
|
69
|
+
});
|
|
70
|
+
process.on('uncaughtException', (error) => {
|
|
71
|
+
logger.error?.('[client-bootstrap][uncaughtException]', error);
|
|
72
|
+
});
|
|
73
|
+
['SIGINT', 'SIGTERM', 'SIGQUIT', 'disconnect'].forEach(sig => {
|
|
74
|
+
process?.on?.(sig, () => void shutdown(sig));
|
|
75
|
+
});
|
|
76
|
+
process?.on?.('exit', code => {
|
|
77
|
+
logger.info?.(`[client-bootstrap][exit] 进程退出,code=${code}`);
|
|
78
|
+
});
|
|
79
|
+
process.on('message', msg => {
|
|
80
|
+
try {
|
|
81
|
+
const data = typeof msg === 'string' ? JSON.parse(msg) : msg;
|
|
82
|
+
if (data?.type === 'start') {
|
|
83
|
+
void startRuntime();
|
|
84
|
+
}
|
|
85
|
+
else if (data?.type === 'stop') {
|
|
86
|
+
void shutdown('stop');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch { }
|
|
90
|
+
});
|
|
91
|
+
notifyParent({ type: 'ready', protocolVersion: 'v2' });
|
package/lib/core/index.d.ts
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
1
|
export { start } from './start.js';
|
|
2
|
+
export { startModuleAdapter, restartModuleAdapter, getModuleAdapterState } from './process/module.js';
|
|
3
|
+
export { startPlatformAdapterWithFallback, restartPlatformAdapter, getPlatformAdapterState } from './process/platform.js';
|
|
4
|
+
export type { ProcessAdapterState, AdapterPhase, AdapterProtocolVersion, AdapterTransportMode, AdapterBootTimings } from './process/types.js';
|
package/lib/core/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { startModuleAdapter } from './module.js';
|
|
2
|
-
export { startPlatformAdapterWithFallback } from './platform.js';
|
|
1
|
+
export { getModuleAdapterState, restartModuleAdapter, startModuleAdapter } from './module.js';
|
|
2
|
+
export { getPlatformAdapterState, restartPlatformAdapter, startPlatformAdapterWithFallback } from './platform.js';
|
|
3
3
|
export { forwardFromClient, forwardFromPlatform, getClientChild, getPlatformChild, setClientChild, setPlatformChild } from './ipc-bridge.js';
|
|
@@ -27,6 +27,12 @@ const forwardFromPlatform = (data) => {
|
|
|
27
27
|
if (clientChild?.connected) {
|
|
28
28
|
clientChild.send({ type: 'ipc:data', data: safeData });
|
|
29
29
|
}
|
|
30
|
+
else if (process.env.NODE_ENV === 'development') {
|
|
31
|
+
logger.debug?.({
|
|
32
|
+
message: 'skip forwarding platform message before client transport ready',
|
|
33
|
+
data: null
|
|
34
|
+
});
|
|
35
|
+
}
|
|
30
36
|
if (fullClient.size > 0) {
|
|
31
37
|
try {
|
|
32
38
|
const messageStr = flattedJSON.stringify(safeData);
|
|
@@ -48,6 +54,12 @@ const forwardFromClient = (data) => {
|
|
|
48
54
|
if (platformChild?.connected) {
|
|
49
55
|
platformChild.send({ type: 'ipc:data', data: safeData });
|
|
50
56
|
}
|
|
57
|
+
else if (process.env.NODE_ENV === 'development') {
|
|
58
|
+
logger.debug?.({
|
|
59
|
+
message: 'skip forwarding client message before platform transport ready',
|
|
60
|
+
data: null
|
|
61
|
+
});
|
|
62
|
+
}
|
|
51
63
|
if (global.__sandbox && global.testoneClient) {
|
|
52
64
|
try {
|
|
53
65
|
const normalized = normalizeInboundMessage(safeData);
|