Files
2026-09-03 16:04:44 +08:00

73 lines
2.5 KiB
JavaScript

import { spawn } from 'node:child_process';
import { existsSync, readFileSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const scriptDirectory = dirname(fileURLToPath(import.meta.url));
const repositoryRoot = resolve(scriptDirectory, '../../..');
const environmentFile = resolve(repositoryRoot, '.env');
const localEnvironment = existsSync(environmentFile)
? parseEnvironment(readFileSync(environmentFile, 'utf8'))
: {};
const apiPort = process.env.API_PORT ?? localEnvironment.API_PORT ?? '8200';
const swaggerEnabled =
(process.env.SWAGGER_ENABLED ??
localEnvironment.SWAGGER_ENABLED ??
'true') === 'true';
const nodeEnvironment =
process.env.NODE_ENV ?? localEnvironment.NODE_ENV ?? 'development';
const swaggerUrl = `http://localhost:${apiPort}/api-docs`;
const tsxCommand = process.platform === 'win32' ? 'tsx.cmd' : 'tsx';
const apiProcess = spawn(tsxCommand, ['watch', 'src/main.ts'], {
shell: process.platform === 'win32',
stdio: 'inherit',
});
if (
process.platform === 'darwin' &&
nodeEnvironment === 'development' &&
swaggerEnabled
) {
void openSwaggerAfterApiIsReady();
}
for (const signal of ['SIGINT', 'SIGTERM']) {
process.on(signal, () => apiProcess.kill(signal));
}
apiProcess.on('exit', (code, signal) => {
if (signal) process.exitCode = 1;
else process.exitCode = code ?? 0;
});
function parseEnvironment(content) {
return Object.fromEntries(
content
.split(/\r?\n/)
.map((line) => line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/))
.filter(Boolean)
.map((match) => [match[1], match[2]]),
);
}
async function openSwaggerAfterApiIsReady() {
const deadline = Date.now() + 30_000;
while (Date.now() < deadline) {
try {
const response = await fetch(`http://localhost:${apiPort}/health`);
if (response.ok) {
// 开发启动器进程不会随 tsx watch 的热重启重建,因此只会打开一次。
spawn('open', [swaggerUrl], {
detached: true,
stdio: 'ignore',
}).unref();
return;
}
} catch {
// API 仍在启动或热重启,继续等待到超时为止。
}
await new Promise((resolveDelay) => setTimeout(resolveDelay, 250));
}
console.warn(`Swagger 未在 30 秒内就绪:${swaggerUrl}`);
}