This commit is contained in:
2026-05-10 22:20:54 +08:00
parent d6219f1a0c
commit 192accd796
92 changed files with 7045 additions and 1559 deletions

View File

@@ -1,6 +1,7 @@
import { execFileSync, spawn } from 'node:child_process';
import { existsSync, readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const repoRoot = process.cwd();
const apiServerExePath = resolve(
@@ -8,8 +9,9 @@ const apiServerExePath = resolve(
'server-rs/target/debug/api-server.exe',
);
const shellEnvKeys = new Set(Object.keys(process.env));
const LOCAL_ENV_FILES = ['.env', '.env.local', '.env.secrets.local'];
function loadEnvFile(path, target) {
function loadEnvFile(path, target, protectedKeys = shellEnvKeys) {
if (!existsSync(path)) {
return;
}
@@ -28,8 +30,9 @@ function loadEnvFile(path, target) {
const [, key, rawValue] = match;
// 只保留启动命令行和外层 shell 已显式传入的环境变量优先级;
// `.env.local` 需要能覆盖 `.env`否则本地短信登录会被默认 false 压住。
if (shellEnvKeys.has(key)) {
// `.env.local` 与 `.env.secrets.local` 需要能覆盖 `.env`
// 否则本地短信登录或私密模型密钥会被默认空值压住。
if (protectedKeys.has(key)) {
continue;
}
@@ -37,23 +40,20 @@ function loadEnvFile(path, target) {
}
}
const mergedEnv = { ...process.env };
loadEnvFile(resolve(repoRoot, '.env.secrets.local'), mergedEnv);
loadEnvFile(resolve(repoRoot, '.env.local'), mergedEnv);
loadEnvFile(resolve(repoRoot, '.env'), mergedEnv);
export function loadApiServerEnv(
repoRootPath,
target,
protectedKeys = shellEnvKeys,
) {
for (const fileName of LOCAL_ENV_FILES) {
loadEnvFile(resolve(repoRootPath, fileName), target, protectedKeys);
}
}
mergedEnv.GENARRATIVE_API_HOST = mergedEnv.GENARRATIVE_API_HOST || '127.0.0.1';
mergedEnv.GENARRATIVE_API_PORT = mergedEnv.GENARRATIVE_API_PORT || '3100';
mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL =
mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL || 'http://127.0.0.1:3101';
mergedEnv.GENARRATIVE_SPACETIME_DATABASE = mergedEnv.GENARRATIVE_SPACETIME_DATABASE || '';
mergedEnv.GENARRATIVE_SPACETIME_TOKEN = mergedEnv.GENARRATIVE_SPACETIME_TOKEN || '';
if (!mergedEnv.GENARRATIVE_SPACETIME_DATABASE) {
console.error(
'[api-server] 缺少 GENARRATIVE_SPACETIME_DATABASE。',
);
process.exit(1);
export function mergeApiServerEnv(repoRootPath, baseEnv = process.env) {
const mergedEnv = { ...baseEnv };
loadApiServerEnv(repoRootPath, mergedEnv, new Set(Object.keys(baseEnv)));
return mergedEnv;
}
function stopExistingWindowsApiServer() {
@@ -97,39 +97,63 @@ function stopExistingWindowsApiServer() {
}
}
try {
stopExistingWindowsApiServer();
} catch (error) {
console.error(
`[api-server] 清理旧 api-server 进程失败: ${error.message}`,
);
process.exit(1);
}
function main() {
const mergedEnv = mergeApiServerEnv(repoRoot);
console.log(
`[api-server] SpacetimeDB ${mergedEnv.GENARRATIVE_SPACETIME_DATABASE} @ ${mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL}`,
);
mergedEnv.GENARRATIVE_API_HOST =
mergedEnv.GENARRATIVE_API_HOST || '127.0.0.1';
mergedEnv.GENARRATIVE_API_PORT = mergedEnv.GENARRATIVE_API_PORT || '3100';
mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL =
mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL || 'http://127.0.0.1:3101';
mergedEnv.GENARRATIVE_SPACETIME_DATABASE =
mergedEnv.GENARRATIVE_SPACETIME_DATABASE || '';
mergedEnv.GENARRATIVE_SPACETIME_TOKEN =
mergedEnv.GENARRATIVE_SPACETIME_TOKEN || '';
const child = spawn(
'cargo',
['run', '-p', 'api-server', '--manifest-path', 'server-rs/Cargo.toml'],
{
cwd: repoRoot,
env: mergedEnv,
stdio: 'inherit',
},
);
child.on('error', (error) => {
console.error(`[api-server] 启动 cargo 失败: ${error.message}`);
process.exit(1);
});
child.on('exit', (code, signal) => {
if (signal) {
console.error(`[api-server] api-server 被信号终止: ${signal}`);
if (!mergedEnv.GENARRATIVE_SPACETIME_DATABASE) {
console.error('[api-server] 缺少 GENARRATIVE_SPACETIME_DATABASE。');
process.exit(1);
}
process.exit(code ?? 0);
});
try {
stopExistingWindowsApiServer();
} catch (error) {
console.error(`[api-server] 清理旧 api-server 进程失败: ${error.message}`);
process.exit(1);
}
console.log(
`[api-server] SpacetimeDB ${mergedEnv.GENARRATIVE_SPACETIME_DATABASE} @ ${mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL}`,
);
const child = spawn(
'cargo',
['run', '-p', 'api-server', '--manifest-path', 'server-rs/Cargo.toml'],
{
cwd: repoRoot,
env: mergedEnv,
stdio: 'inherit',
},
);
child.on('error', (error) => {
console.error(`[api-server] 启动 cargo 失败: ${error.message}`);
process.exit(1);
});
child.on('exit', (code, signal) => {
if (signal) {
console.error(`[api-server] api-server 被信号终止: ${signal}`);
process.exit(1);
}
process.exit(code ?? 0);
});
}
if (
process.argv[1] &&
resolve(process.argv[1]) === fileURLToPath(import.meta.url)
) {
main();
}