chore: stabilize Zhinian pilot delivery

This commit is contained in:
inman
2026-05-12 19:44:44 +08:00
parent 45389855e1
commit 20b5aff4ad
174 changed files with 41428 additions and 784 deletions

View File

@@ -65,6 +65,14 @@ function getNpmCommand(): string {
return process.platform === 'win32' ? 'npm.cmd' : 'npm';
}
function getBundledNodeCommand(): string | undefined {
const binName = process.platform === 'win32' ? 'node.exe' : 'node';
const candidate = app.isPackaged
? join(process.resourcesPath, 'bin', binName)
: join(process.cwd(), 'resources', 'bin', `${process.platform}-${process.arch}`, binName);
return existsSync(candidate) ? candidate : undefined;
}
function getScriptName(): string {
return process.env.NIANXX_PLAY_SCRIPT?.trim() || (process.env.NODE_ENV === 'production' ? 'start' : 'dev');
}
@@ -209,14 +217,6 @@ function getRuntimeDataDirs() {
return { runtimeRoot, dataDir, uploadDir, resultDir };
}
function hasDirectoryEntries(dir: string): boolean {
try {
return readdirSync(dir).length > 0;
} catch {
return false;
}
}
function copyFileIfMissing(sourcePath: string, targetPath: string): void {
if (!existsSync(sourcePath) || existsSync(targetPath)) return;
mkdirSync(dirname(targetPath), { recursive: true });
@@ -256,18 +256,25 @@ function migrateStateFile(sourcePath: string, targetPath: string): void {
}
}
function copyDirectoryIfEmpty(sourceDir: string, targetDir: string): void {
function copyDirectoryMissing(sourceDir: string, targetDir: string): void {
if (!existsSync(sourceDir) || !statSync(sourceDir).isDirectory()) return;
if (hasDirectoryEntries(targetDir)) return;
mkdirSync(targetDir, { recursive: true });
cpSync(sourceDir, targetDir, { recursive: true, dereference: true });
for (const entry of readdirSync(sourceDir)) {
const sourcePath = join(sourceDir, entry);
const targetPath = join(targetDir, entry);
if (statSync(sourcePath).isDirectory()) {
copyDirectoryMissing(sourcePath, targetPath);
continue;
}
copyFileIfMissing(sourcePath, targetPath);
}
}
function migrateExistingRuntimeData(runtime: NianxxPlayRuntime, dirs: ReturnType<typeof getRuntimeDataDirs>): void {
try {
migrateStateFile(join(runtime.dir, '.data', 'app-state.json'), join(dirs.dataDir, 'app-state.json'));
copyDirectoryIfEmpty(join(runtime.dir, 'public', 'uploads'), dirs.uploadDir);
copyDirectoryIfEmpty(join(runtime.dir, 'public', 'generated-results'), dirs.resultDir);
copyDirectoryMissing(join(runtime.dir, 'public', 'uploads'), dirs.uploadDir);
copyDirectoryMissing(join(runtime.dir, 'public', 'generated-results'), dirs.resultDir);
} catch (error) {
logger.warn('[nianxx-play] Failed to migrate existing local runtime data:', error);
}
@@ -343,12 +350,14 @@ function spawnStandaloneRuntime(runtime: NianxxPlayRuntime, port: number): Child
if (!runtime.serverPath) {
throw new Error('NianxxPlay standalone server path is missing.');
}
logger.info(`[nianxx-play] Starting bundled service: ${runtime.serverPath} (port=${port})`);
return spawn(process.execPath, [runtime.serverPath], {
const bundledNode = getBundledNodeCommand();
const command = bundledNode ?? process.execPath;
logger.info(`[nianxx-play] Starting bundled service: ${runtime.serverPath} (port=${port}, runner=${bundledNode ? 'bundled-node' : 'electron-node'})`);
return spawn(command, [runtime.serverPath], {
cwd: runtime.dir,
env: {
...createRuntimeEnv(port, runtime),
ELECTRON_RUN_AS_NODE: '1',
...(bundledNode ? {} : { ELECTRON_RUN_AS_NODE: '1' }),
NODE_ENV: 'production',
},
stdio: ['ignore', 'pipe', 'pipe'],