@aalis/runtime 0.1.1
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/LICENSE +21 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/node-modules-loader.d.ts +18 -0
- package/dist/node-modules-loader.d.ts.map +1 -0
- package/dist/node-modules-loader.js +107 -0
- package/dist/node-modules-loader.js.map +1 -0
- package/dist/providers.d.ts +40 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +270 -0
- package/dist/providers.js.map +1 -0
- package/dist/start.d.ts +15 -0
- package/dist/start.d.ts.map +1 -0
- package/dist/start.js +34 -0
- package/dist/start.js.map +1 -0
- package/package.json +34 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ace Nyan <ace@acenyan.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { createNodeModulesPluginLoader } from './node-modules-loader.js';
|
|
2
|
+
export { createFsPluginLoader, createFsYamlConfigProvider, createProcessRespawnStrategy, } from './providers.js';
|
|
3
|
+
export { type StartAalisOptions, startAalis } from './start.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @aalis/runtime —— Aalis 独立部署运行时(node 宿主层)
|
|
2
|
+
//
|
|
3
|
+
// 提供两种部署模型的加载器与 YAML 配置/重启策略,以及一行启动 startAalis:
|
|
4
|
+
// - createNodeModulesPluginLoader:纯 npm 独立部署(从 node_modules 解析插件)
|
|
5
|
+
// - createFsPluginLoader:monorepo 自托管(扫描 packages/ 目录)
|
|
6
|
+
// - createFsYamlConfigProvider / createProcessRespawnStrategy:YAML 配置 + 进程级重启
|
|
7
|
+
// - startAalis:组装以上为独立实例并启动
|
|
8
|
+
//
|
|
9
|
+
// monorepo 的 src/runtime/providers.ts 从本包再导出 FS 系列,单一事实来源、零重复。
|
|
10
|
+
export { createNodeModulesPluginLoader } from './node-modules-loader.js';
|
|
11
|
+
export { createFsPluginLoader, createFsYamlConfigProvider, createProcessRespawnStrategy, } from './providers.js';
|
|
12
|
+
export { startAalis } from './start.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,EAAE;AACF,gDAAgD;AAChD,oEAAoE;AACpE,yDAAyD;AACzD,gFAAgF;AAChF,8BAA8B;AAC9B,EAAE;AACF,+DAA+D;AAE/D,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAA0B,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PluginLoader } from '@aalis/core';
|
|
2
|
+
/**
|
|
3
|
+
* 判定一个已装依赖是否为可加载的 Aalis 插件。纯函数,便于单测。
|
|
4
|
+
* 排除核心/契约/前端/工具链标记;收录有 aalis-plugin 关键词或 @aalis/plugin-* 名或 service/subsystem。
|
|
5
|
+
*/
|
|
6
|
+
export declare function isLoadablePlugin(name: string, meta: Record<string, unknown>): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* 创建一个从项目 node_modules 解析插件的 PluginLoader。
|
|
9
|
+
*
|
|
10
|
+
* @param projectDir 项目根目录(含 package.json 与 node_modules),默认 process.cwd()
|
|
11
|
+
*
|
|
12
|
+
* - `discover()`:读 projectDir/package.json 的 dependencies + optionalDependencies,
|
|
13
|
+
* 用 require.resolve 定位每个依赖的 package.json,按标记过滤出可加载插件。
|
|
14
|
+
* - `load()`:用 `pathToFileURL(entry).href` 动态 import(entry = require.resolve(包名))。
|
|
15
|
+
* - `reload()`:用入口文件 mtime 作 import URL query 强制 ESM 缓存失效。
|
|
16
|
+
*/
|
|
17
|
+
export declare function createNodeModulesPluginLoader(projectDir?: string): PluginLoader;
|
|
18
|
+
//# sourceMappingURL=node-modules-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-modules-loader.d.ts","sourceRoot":"","sources":["../src/node-modules-loader.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAoB,YAAY,EAAgB,MAAM,aAAa,CAAC;AAyBhF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAUrF;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,GAAE,MAAsB,GAAG,YAAY,CAqD9F"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
|
+
import { pathToFileURL } from 'node:url';
|
|
6
|
+
// ============================================================
|
|
7
|
+
// NodeModulesPluginLoader —— 从 node_modules 解析并加载插件
|
|
8
|
+
// ============================================================
|
|
9
|
+
//
|
|
10
|
+
// 独立部署(纯 npm 装 Aalis)用的加载器:不扫描 packages/ 目录,而是读项目
|
|
11
|
+
// package.json 的 dependencies,逐个用 node 模块解析(require.resolve)定位已装的
|
|
12
|
+
// @aalis 插件并 dynamic import。与 monorepo 的 createFsPluginLoader 是「两种部署
|
|
13
|
+
// 模型的两个加载器」,非重复:前者扫目录,后者走 node 解析。
|
|
14
|
+
//
|
|
15
|
+
// 插件识别(正信号 + 排除标记):
|
|
16
|
+
// - 排除:package.json 的 aalis.{core,types,client,tooling} 标记(核心/契约/前端/工具链)
|
|
17
|
+
// - 收录:keywords 含 'aalis-plugin'(市场约定)∪ 名称匹配 @aalis/plugin-* ∪ 有 aalis.service/subsystem
|
|
18
|
+
// 这样 @aalis/core、各 *-api(types)、webui-client(client)、@aalis/runtime(tooling)
|
|
19
|
+
// 与 express/yaml 等普通依赖都不会被误当插件加载。
|
|
20
|
+
function readJson(path) {
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 判定一个已装依赖是否为可加载的 Aalis 插件。纯函数,便于单测。
|
|
30
|
+
* 排除核心/契约/前端/工具链标记;收录有 aalis-plugin 关键词或 @aalis/plugin-* 名或 service/subsystem。
|
|
31
|
+
*/
|
|
32
|
+
export function isLoadablePlugin(name, meta) {
|
|
33
|
+
const aalis = (meta.aalis ?? {});
|
|
34
|
+
if (aalis.core || aalis.types || aalis.client || aalis.tooling)
|
|
35
|
+
return false;
|
|
36
|
+
const keywords = Array.isArray(meta.keywords) ? meta.keywords : [];
|
|
37
|
+
return (keywords.includes('aalis-plugin') ||
|
|
38
|
+
/^@aalis\/plugin-/.test(name) ||
|
|
39
|
+
aalis.service !== undefined ||
|
|
40
|
+
aalis.subsystem !== undefined);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 创建一个从项目 node_modules 解析插件的 PluginLoader。
|
|
44
|
+
*
|
|
45
|
+
* @param projectDir 项目根目录(含 package.json 与 node_modules),默认 process.cwd()
|
|
46
|
+
*
|
|
47
|
+
* - `discover()`:读 projectDir/package.json 的 dependencies + optionalDependencies,
|
|
48
|
+
* 用 require.resolve 定位每个依赖的 package.json,按标记过滤出可加载插件。
|
|
49
|
+
* - `load()`:用 `pathToFileURL(entry).href` 动态 import(entry = require.resolve(包名))。
|
|
50
|
+
* - `reload()`:用入口文件 mtime 作 import URL query 强制 ESM 缓存失效。
|
|
51
|
+
*/
|
|
52
|
+
export function createNodeModulesPluginLoader(projectDir = process.cwd()) {
|
|
53
|
+
const root = resolve(projectDir);
|
|
54
|
+
// 以项目 package.json 为基准创建 require,确保从项目 node_modules 解析
|
|
55
|
+
const req = createRequire(pathToFileURL(resolve(root, 'package.json')));
|
|
56
|
+
return {
|
|
57
|
+
async discover() {
|
|
58
|
+
const rootPkg = readJson(resolve(root, 'package.json'));
|
|
59
|
+
if (!rootPkg)
|
|
60
|
+
return [];
|
|
61
|
+
const deps = {
|
|
62
|
+
...(rootPkg.dependencies ?? {}),
|
|
63
|
+
...(rootPkg.optionalDependencies ?? {}),
|
|
64
|
+
};
|
|
65
|
+
const discovered = [];
|
|
66
|
+
for (const dep of Object.keys(deps)) {
|
|
67
|
+
let metaPath;
|
|
68
|
+
try {
|
|
69
|
+
metaPath = req.resolve(`${dep}/package.json`);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
continue; // 未安装或无法解析,跳过
|
|
73
|
+
}
|
|
74
|
+
const meta = readJson(metaPath);
|
|
75
|
+
if (!meta || !isLoadablePlugin(dep, meta))
|
|
76
|
+
continue;
|
|
77
|
+
let entry;
|
|
78
|
+
try {
|
|
79
|
+
entry = req.resolve(dep);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
continue; // 解析不到入口(如缺 main/exports),跳过
|
|
83
|
+
}
|
|
84
|
+
discovered.push({
|
|
85
|
+
name: meta.name ?? dep,
|
|
86
|
+
source: entry,
|
|
87
|
+
metadata: { dir: dirname(metaPath) },
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return discovered;
|
|
91
|
+
},
|
|
92
|
+
async load(desc) {
|
|
93
|
+
return (await import(pathToFileURL(desc.source).href));
|
|
94
|
+
},
|
|
95
|
+
async reload(desc) {
|
|
96
|
+
let cacheKey = '';
|
|
97
|
+
try {
|
|
98
|
+
cacheKey = `?t=${(await stat(desc.source)).mtimeMs}`;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
/* stat 失败时用空 key,让 import 自己报错 */
|
|
102
|
+
}
|
|
103
|
+
return (await import(pathToFileURL(desc.source).href + cacheKey));
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=node-modules-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-modules-loader.js","sourceRoot":"","sources":["../src/node-modules-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AalisConfig, ConfigProvider, PluginLoader, RestartStrategy } from '@aalis/core';
|
|
2
|
+
interface FsYamlConfigProviderResult {
|
|
3
|
+
/** 当前快照(用于 `new App({ config })`) */
|
|
4
|
+
config: AalisConfig;
|
|
5
|
+
/** Provider 实例(用于 `new App({ configProvider })`) */
|
|
6
|
+
provider: ConfigProvider;
|
|
7
|
+
/** 配置文件所在目录(用于 `new App({ dataDir })`) */
|
|
8
|
+
dataDir: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 创建一个基于 YAML 文件的 ConfigProvider。
|
|
12
|
+
*
|
|
13
|
+
* - 同步读取 + 解析 + 环境变量插值
|
|
14
|
+
* - `save()` 同步写回,并保护 `${ENV}` 占位符
|
|
15
|
+
* - `watch()` 用 `fs.watch` + 300ms debounce,并通过 lastWrittenYaml 去重避免自激
|
|
16
|
+
*
|
|
17
|
+
* 调用时一次性返回 config 快照、provider 和 dataDir 三件套,方便 src/index.ts 组装。
|
|
18
|
+
*/
|
|
19
|
+
export declare function createFsYamlConfigProvider(configPath?: string): FsYamlConfigProviderResult;
|
|
20
|
+
/**
|
|
21
|
+
* 创建一个基于 packages 目录扫描的 PluginLoader。
|
|
22
|
+
*
|
|
23
|
+
* - `discover()`:读 dir 下每个子目录的 package.json,按 `aalis.{core,client,types}` 标记过滤
|
|
24
|
+
* - `load()`:用 `pathToFileURL(entry).href` 动态 import
|
|
25
|
+
* - `reload()`:用入口文件 mtime 作为 import URL 的 query 强制 ESM 缓存失效
|
|
26
|
+
*/
|
|
27
|
+
export declare function createFsPluginLoader(packagesDir?: string): PluginLoader;
|
|
28
|
+
/**
|
|
29
|
+
* Node 进程重启策略:spawn 一个 detached 子进程沿用当前 argv,然后 `process.exit(0)`。
|
|
30
|
+
*
|
|
31
|
+
* 时序:
|
|
32
|
+
* 1. 等 500ms 让正在飞行的 HTTP/WS 响应有机会先返回客户端
|
|
33
|
+
* 2. 调 `stop()` 优雅停掉当前 App(关闭网关、断开适配器等)
|
|
34
|
+
* 3. spawn 新进程 + `process.exit(0)`
|
|
35
|
+
*
|
|
36
|
+
* 对 .ts 入口(开发模式)会优先使用本地 `tsx` 二进制。
|
|
37
|
+
*/
|
|
38
|
+
export declare function createProcessRespawnStrategy(): RestartStrategy;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAEd,YAAY,EAEZ,eAAe,EAChB,MAAM,aAAa,CAAC;AA6FrB,UAAU,0BAA0B;IAClC,qCAAqC;IACrC,MAAM,EAAE,WAAW,CAAC;IACpB,oDAAoD;IACpD,QAAQ,EAAE,cAAc,CAAC;IACzB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,0BAA0B,CAmE1F;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,CAkDvE;AAMD;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,IAAI,eAAe,CAyB9D"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { existsSync, watch as fsWatch, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { readdir, stat } from 'node:fs/promises';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
|
+
import { pathToFileURL } from 'node:url';
|
|
6
|
+
import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
|
|
7
|
+
// ============================================================
|
|
8
|
+
// FsYamlConfigProvider —— 从 YAML 文件加载+持久化配置
|
|
9
|
+
// ============================================================
|
|
10
|
+
const DEFAULT_CONFIG_FILE = 'aalis.config.yaml';
|
|
11
|
+
/**
|
|
12
|
+
* 把 `${ENV_VAR}` 替换为环境变量值(兼容老配置)。
|
|
13
|
+
*/
|
|
14
|
+
function interpolateEnvVars(text) {
|
|
15
|
+
return text.replace(/\$\{([^}]+)}/g, (_, varName) => {
|
|
16
|
+
return process.env[varName.trim()] ?? '';
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
const CORE_TOP_LEVEL_KEYS = new Set(['name', 'logLevel', 'plugins', 'disabledPlugins', 'servicePreferences']);
|
|
20
|
+
/**
|
|
21
|
+
* 恢复 ${ENV} 占位符:对比当前值与原始 raw 值,若相等则保留 raw。
|
|
22
|
+
*/
|
|
23
|
+
function restoreEnvVars(current, raw) {
|
|
24
|
+
const result = {};
|
|
25
|
+
for (const [key, value] of Object.entries(current)) {
|
|
26
|
+
const rawVal = raw[key];
|
|
27
|
+
if (typeof rawVal === 'string' && /\$\{[^}]+}/.test(rawVal)) {
|
|
28
|
+
const expanded = interpolateEnvVars(rawVal);
|
|
29
|
+
if (expanded === value) {
|
|
30
|
+
result[key] = rawVal;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (value &&
|
|
35
|
+
typeof value === 'object' &&
|
|
36
|
+
!Array.isArray(value) &&
|
|
37
|
+
rawVal &&
|
|
38
|
+
typeof rawVal === 'object' &&
|
|
39
|
+
!Array.isArray(rawVal)) {
|
|
40
|
+
result[key] = restoreEnvVars(value, rawVal);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
result[key] = value;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 把 AalisConfig 序列化为 YAML 文本,按固定顺序输出 core 字段,
|
|
50
|
+
* 透传其余顶层字段(业务字段,宿主不解释)。
|
|
51
|
+
*/
|
|
52
|
+
function buildSaveYaml(config, rawYaml) {
|
|
53
|
+
const obj = {
|
|
54
|
+
name: config.name,
|
|
55
|
+
logLevel: config.logLevel,
|
|
56
|
+
};
|
|
57
|
+
if (rawYaml) {
|
|
58
|
+
const rawParsed = parseYaml(rawYaml);
|
|
59
|
+
const rawPlugins = (rawParsed?.plugins ?? {});
|
|
60
|
+
const plugins = {};
|
|
61
|
+
for (const [name, conf] of Object.entries(config.plugins)) {
|
|
62
|
+
plugins[name] = restoreEnvVars(conf, rawPlugins[name] ?? {});
|
|
63
|
+
}
|
|
64
|
+
obj.plugins = plugins;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
obj.plugins = config.plugins;
|
|
68
|
+
}
|
|
69
|
+
obj.disabledPlugins = config.disabledPlugins ?? [];
|
|
70
|
+
const prefs = config.servicePreferences ?? {};
|
|
71
|
+
if (Object.keys(prefs).length > 0) {
|
|
72
|
+
obj.servicePreferences = prefs;
|
|
73
|
+
}
|
|
74
|
+
for (const [key, value] of Object.entries(config)) {
|
|
75
|
+
if (CORE_TOP_LEVEL_KEYS.has(key))
|
|
76
|
+
continue;
|
|
77
|
+
if (value === undefined)
|
|
78
|
+
continue;
|
|
79
|
+
if (Array.isArray(value)) {
|
|
80
|
+
if (value.length > 0)
|
|
81
|
+
obj[key] = value;
|
|
82
|
+
}
|
|
83
|
+
else if (value && typeof value === 'object') {
|
|
84
|
+
if (Object.keys(value).length > 0)
|
|
85
|
+
obj[key] = value;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
obj[key] = value;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return stringifyYaml(obj, { lineWidth: 0 });
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* 创建一个基于 YAML 文件的 ConfigProvider。
|
|
95
|
+
*
|
|
96
|
+
* - 同步读取 + 解析 + 环境变量插值
|
|
97
|
+
* - `save()` 同步写回,并保护 `${ENV}` 占位符
|
|
98
|
+
* - `watch()` 用 `fs.watch` + 300ms debounce,并通过 lastWrittenYaml 去重避免自激
|
|
99
|
+
*
|
|
100
|
+
* 调用时一次性返回 config 快照、provider 和 dataDir 三件套,方便 src/index.ts 组装。
|
|
101
|
+
*/
|
|
102
|
+
export function createFsYamlConfigProvider(configPath) {
|
|
103
|
+
const absPath = configPath ? resolve(configPath) : resolve(process.cwd(), DEFAULT_CONFIG_FILE);
|
|
104
|
+
const dataDir = dirname(absPath);
|
|
105
|
+
let rawYaml = null;
|
|
106
|
+
let lastWrittenYaml = null;
|
|
107
|
+
let watcher = null;
|
|
108
|
+
let debounceTimer = null;
|
|
109
|
+
function loadFromDisk() {
|
|
110
|
+
if (existsSync(absPath)) {
|
|
111
|
+
rawYaml = readFileSync(absPath, 'utf-8');
|
|
112
|
+
const interpolated = interpolateEnvVars(rawYaml);
|
|
113
|
+
const parsed = (parseYaml(interpolated) ?? {});
|
|
114
|
+
return parsed;
|
|
115
|
+
}
|
|
116
|
+
rawYaml = null;
|
|
117
|
+
return { name: 'Aalis', logLevel: 'info', plugins: {} };
|
|
118
|
+
}
|
|
119
|
+
const initialConfig = loadFromDisk();
|
|
120
|
+
const provider = {
|
|
121
|
+
save(config) {
|
|
122
|
+
const yaml = buildSaveYaml(config, rawYaml);
|
|
123
|
+
lastWrittenYaml = yaml;
|
|
124
|
+
writeFileSync(absPath, yaml, 'utf-8');
|
|
125
|
+
rawYaml = yaml;
|
|
126
|
+
},
|
|
127
|
+
watch(onChange) {
|
|
128
|
+
if (watcher)
|
|
129
|
+
return () => { };
|
|
130
|
+
if (!existsSync(absPath))
|
|
131
|
+
return () => { };
|
|
132
|
+
try {
|
|
133
|
+
watcher = fsWatch(absPath, () => {
|
|
134
|
+
if (debounceTimer)
|
|
135
|
+
clearTimeout(debounceTimer);
|
|
136
|
+
debounceTimer = setTimeout(() => {
|
|
137
|
+
debounceTimer = null;
|
|
138
|
+
try {
|
|
139
|
+
const current = readFileSync(absPath, 'utf-8');
|
|
140
|
+
if (lastWrittenYaml !== null && current === lastWrittenYaml)
|
|
141
|
+
return;
|
|
142
|
+
lastWrittenYaml = null;
|
|
143
|
+
rawYaml = current;
|
|
144
|
+
const interpolated = interpolateEnvVars(current);
|
|
145
|
+
const parsed = (parseYaml(interpolated) ?? {});
|
|
146
|
+
onChange(parsed);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
/* 文件可能被部分写入,忽略 */
|
|
150
|
+
}
|
|
151
|
+
}, 300);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
/* 平台不支持 watch */
|
|
156
|
+
}
|
|
157
|
+
return () => {
|
|
158
|
+
if (debounceTimer) {
|
|
159
|
+
clearTimeout(debounceTimer);
|
|
160
|
+
debounceTimer = null;
|
|
161
|
+
}
|
|
162
|
+
watcher?.close();
|
|
163
|
+
watcher = null;
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
return { config: initialConfig, provider, dataDir };
|
|
168
|
+
}
|
|
169
|
+
// ============================================================
|
|
170
|
+
// FsPluginLoader —— 扫描目录 + dynamic import
|
|
171
|
+
// ============================================================
|
|
172
|
+
/**
|
|
173
|
+
* 创建一个基于 packages 目录扫描的 PluginLoader。
|
|
174
|
+
*
|
|
175
|
+
* - `discover()`:读 dir 下每个子目录的 package.json,按 `aalis.{core,client,types}` 标记过滤
|
|
176
|
+
* - `load()`:用 `pathToFileURL(entry).href` 动态 import
|
|
177
|
+
* - `reload()`:用入口文件 mtime 作为 import URL 的 query 强制 ESM 缓存失效
|
|
178
|
+
*/
|
|
179
|
+
export function createFsPluginLoader(packagesDir) {
|
|
180
|
+
const rootDir = packagesDir ?? resolve(process.cwd(), 'packages');
|
|
181
|
+
return {
|
|
182
|
+
async discover() {
|
|
183
|
+
let entries;
|
|
184
|
+
try {
|
|
185
|
+
const dirents = await readdir(rootDir, { withFileTypes: true });
|
|
186
|
+
entries = dirents.filter(d => d.isDirectory() || d.isSymbolicLink()).map(d => d.name);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return [];
|
|
190
|
+
}
|
|
191
|
+
const discovered = [];
|
|
192
|
+
for (const entry of entries) {
|
|
193
|
+
const pkgJsonPath = resolve(rootDir, entry, 'package.json');
|
|
194
|
+
let pkgJson;
|
|
195
|
+
try {
|
|
196
|
+
pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
const aalisMeta = pkgJson.aalis;
|
|
202
|
+
if (aalisMeta?.core || aalisMeta?.client || aalisMeta?.types || aalisMeta?.tooling)
|
|
203
|
+
continue;
|
|
204
|
+
const main = pkgJson.main || 'dist/index.js';
|
|
205
|
+
discovered.push({
|
|
206
|
+
name: pkgJson.name,
|
|
207
|
+
source: resolve(rootDir, entry, main),
|
|
208
|
+
metadata: { dir: resolve(rootDir, entry) },
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return discovered;
|
|
212
|
+
},
|
|
213
|
+
async load(desc) {
|
|
214
|
+
const mod = (await import(pathToFileURL(desc.source).href));
|
|
215
|
+
return mod;
|
|
216
|
+
},
|
|
217
|
+
async reload(desc) {
|
|
218
|
+
let cacheKey = '';
|
|
219
|
+
try {
|
|
220
|
+
cacheKey = `?t=${(await stat(desc.source)).mtimeMs}`;
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
/* stat 失败时用空 key,让 import 自己报错 */
|
|
224
|
+
}
|
|
225
|
+
const mod = (await import(pathToFileURL(desc.source).href + cacheKey));
|
|
226
|
+
return mod;
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
// ============================================================
|
|
231
|
+
// ProcessRespawnStrategy —— spawn 新 Node 进程然后退出当前
|
|
232
|
+
// ============================================================
|
|
233
|
+
/**
|
|
234
|
+
* Node 进程重启策略:spawn 一个 detached 子进程沿用当前 argv,然后 `process.exit(0)`。
|
|
235
|
+
*
|
|
236
|
+
* 时序:
|
|
237
|
+
* 1. 等 500ms 让正在飞行的 HTTP/WS 响应有机会先返回客户端
|
|
238
|
+
* 2. 调 `stop()` 优雅停掉当前 App(关闭网关、断开适配器等)
|
|
239
|
+
* 3. spawn 新进程 + `process.exit(0)`
|
|
240
|
+
*
|
|
241
|
+
* 对 .ts 入口(开发模式)会优先使用本地 `tsx` 二进制。
|
|
242
|
+
*/
|
|
243
|
+
export function createProcessRespawnStrategy() {
|
|
244
|
+
return {
|
|
245
|
+
async restart({ stop }) {
|
|
246
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
247
|
+
await stop();
|
|
248
|
+
const scriptFile = process.argv[1];
|
|
249
|
+
let exec;
|
|
250
|
+
let args;
|
|
251
|
+
if (scriptFile?.endsWith('.ts')) {
|
|
252
|
+
const tsxBin = resolve(process.cwd(), 'node_modules', '.bin', 'tsx');
|
|
253
|
+
exec = existsSync(tsxBin) ? tsxBin : 'tsx';
|
|
254
|
+
args = process.argv.slice(1);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
[exec, ...args] = process.argv;
|
|
258
|
+
}
|
|
259
|
+
const child = spawn(exec, args, {
|
|
260
|
+
cwd: process.cwd(),
|
|
261
|
+
stdio: 'inherit',
|
|
262
|
+
detached: true,
|
|
263
|
+
env: process.env,
|
|
264
|
+
});
|
|
265
|
+
child.unref();
|
|
266
|
+
process.exit(0);
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"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"}
|
package/dist/start.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { App } from '@aalis/core';
|
|
2
|
+
export interface StartAalisOptions {
|
|
3
|
+
/** aalis.config.yaml 路径,默认 cwd 下的 aalis.config.yaml */
|
|
4
|
+
configPath?: string;
|
|
5
|
+
/** 项目根目录(含 package.json + node_modules),默认 process.cwd() */
|
|
6
|
+
projectDir?: string;
|
|
7
|
+
/** 应用层声明的必需服务(缺失则启动告警),默认空 */
|
|
8
|
+
requiredServices?: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 启动一个独立部署的 Aalis 实例:YAML 配置 + node_modules 插件加载 + 进程级重启。
|
|
12
|
+
* 返回已启动的 App(便于测试或进一步操作)。
|
|
13
|
+
*/
|
|
14
|
+
export declare function startAalis(opts?: StartAalisOptions): Promise<App>;
|
|
15
|
+
//# sourceMappingURL=start.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAalC,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,GAAG,CAAC,CA4B3E"}
|
package/dist/start.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { App } from '@aalis/core';
|
|
2
|
+
import { createNodeModulesPluginLoader } from './node-modules-loader.js';
|
|
3
|
+
import { createFsYamlConfigProvider, createProcessRespawnStrategy } from './providers.js';
|
|
4
|
+
/**
|
|
5
|
+
* 启动一个独立部署的 Aalis 实例:YAML 配置 + node_modules 插件加载 + 进程级重启。
|
|
6
|
+
* 返回已启动的 App(便于测试或进一步操作)。
|
|
7
|
+
*/
|
|
8
|
+
export async function startAalis(opts = {}) {
|
|
9
|
+
const { config, provider, dataDir } = createFsYamlConfigProvider(opts.configPath);
|
|
10
|
+
const app = new App({
|
|
11
|
+
config,
|
|
12
|
+
configProvider: provider,
|
|
13
|
+
dataDir,
|
|
14
|
+
pluginLoader: createNodeModulesPluginLoader(opts.projectDir),
|
|
15
|
+
restartStrategy: createProcessRespawnStrategy(),
|
|
16
|
+
// 宿主层决定 dev/prod;core 不读 process.env
|
|
17
|
+
devMode: process.env.NODE_ENV !== 'production',
|
|
18
|
+
requiredServices: opts.requiredServices ?? [],
|
|
19
|
+
});
|
|
20
|
+
await app.autoLoadPlugins();
|
|
21
|
+
await app.start();
|
|
22
|
+
let stopping = false;
|
|
23
|
+
const shutdown = async () => {
|
|
24
|
+
if (stopping)
|
|
25
|
+
return;
|
|
26
|
+
stopping = true;
|
|
27
|
+
await app.stop();
|
|
28
|
+
process.exit(0);
|
|
29
|
+
};
|
|
30
|
+
process.on('SIGINT', shutdown);
|
|
31
|
+
process.on('SIGTERM', shutdown);
|
|
32
|
+
return app;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAoB1F;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAA0B,EAAE;IAC3D,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAElF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC;QAClB,MAAM;QACN,cAAc,EAAE,QAAQ;QACxB,OAAO;QACP,YAAY,EAAE,6BAA6B,CAAC,IAAI,CAAC,UAAU,CAAC;QAC5D,eAAe,EAAE,4BAA4B,EAAE;QAC/C,qCAAqC;QACrC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;QAC9C,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,IAAI,EAAE;KAC9C,CAAC,CAAC;IAEH,MAAM,GAAG,CAAC,eAAe,EAAE,CAAC;IAC5B,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;IAElB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QAC1B,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEhC,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aalis/runtime",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Aalis 独立部署运行时:node_modules 插件加载 + YAML 配置 + 一行启动 startAalis",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"aalis",
|
|
9
|
+
"aalis-runtime"
|
|
10
|
+
],
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"yaml": "^2.7.0"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"@aalis/core": "^0.1.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"typescript": "^5.7.0",
|
|
24
|
+
"@types/node": "^22.0.0",
|
|
25
|
+
"@aalis/core": "0.1.1"
|
|
26
|
+
},
|
|
27
|
+
"aalis": {
|
|
28
|
+
"tooling": true
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc",
|
|
32
|
+
"dev": "tsc --watch"
|
|
33
|
+
}
|
|
34
|
+
}
|