feat: add run-server script to manage server execution and compatibility checks feat: create main application logic for desktop with window management, server handling, and auto-updater test: add unit tests for desktop runtime helpers feat: implement desktop server environment configuration and health check test: add tests for server configuration and desktop routes feat: add native module guard for better-sqlite3 compatibility test: add tests for native module guard functionality test: add comprehensive tests for account verification feedback handling feat: implement account verification feedback helpers chore: add TypeScript configuration for desktop builds
68 lines
1.8 KiB
TypeScript
68 lines
1.8 KiB
TypeScript
type DesktopServerEnvInput = {
|
|
inheritedEnv?: NodeJS.ProcessEnv;
|
|
userDataDir: string;
|
|
logsDir: string;
|
|
port: number;
|
|
};
|
|
|
|
type WaitForServerReadyInput = {
|
|
url: string;
|
|
fetcher?: (input: string, init?: RequestInit) => Promise<{ ok: boolean }>;
|
|
timeoutMs?: number;
|
|
intervalMs?: number;
|
|
};
|
|
|
|
type ServerExitState = {
|
|
code: number | null;
|
|
signal: NodeJS.Signals | null;
|
|
};
|
|
|
|
const DEFAULT_READY_TIMEOUT_MS = 30_000;
|
|
const DEFAULT_READY_INTERVAL_MS = 250;
|
|
|
|
function delay(ms: number) {
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
}
|
|
|
|
export function buildDesktopServerEnv(input: DesktopServerEnvInput): NodeJS.ProcessEnv {
|
|
return {
|
|
...(input.inheritedEnv || {}),
|
|
HOST: '127.0.0.1',
|
|
PORT: String(input.port),
|
|
DATA_DIR: input.userDataDir,
|
|
METAPI_DESKTOP: '1',
|
|
METAPI_LOG_DIR: input.logsDir,
|
|
};
|
|
}
|
|
|
|
export function createDesktopServerUrl(port: number): string {
|
|
return `http://127.0.0.1:${port}`;
|
|
}
|
|
|
|
export function createDesktopHealthUrl(port: number): string {
|
|
return `${createDesktopServerUrl(port)}/api/desktop/health`;
|
|
}
|
|
|
|
export async function waitForServerReady(input: WaitForServerReadyInput): Promise<void> {
|
|
const fetcher = input.fetcher || ((url: string, init?: RequestInit) => fetch(url, init));
|
|
const timeoutMs = input.timeoutMs ?? DEFAULT_READY_TIMEOUT_MS;
|
|
const intervalMs = input.intervalMs ?? DEFAULT_READY_INTERVAL_MS;
|
|
const startedAt = Date.now();
|
|
|
|
while (Date.now() - startedAt <= timeoutMs) {
|
|
try {
|
|
const response = await fetcher(input.url, { method: 'GET' });
|
|
if (response.ok) return;
|
|
} catch {
|
|
// Retry until timeout.
|
|
}
|
|
await delay(intervalMs);
|
|
}
|
|
|
|
throw new Error('Timed out waiting for metapi desktop server');
|
|
}
|
|
|
|
export function isFatalServerExit(exitState: ServerExitState): boolean {
|
|
return exitState.code !== null && exitState.code !== 0 && !exitState.signal;
|
|
}
|