feat: implement macOS notarization and ad-hoc signing in afterSign script

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
This commit is contained in:
cita
2026-03-06 16:24:41 +08:00
parent acdc846b13
commit 2a810facb8
45 changed files with 6712 additions and 405 deletions
+67
View File
@@ -0,0 +1,67 @@
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;
}