|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| import '../../server/src/env.js';
|
| import crypto from 'node:crypto';
|
| import type { Server } from 'node:http';
|
| import { createApp } from '../../server/src/app.js';
|
| import { initDb, getDb, getUnifiedApiKey } from '../../server/src/db/index.js';
|
| import { startHealthChecker } from '../../server/src/services/health.js';
|
| import { userCount, createUser, createSession } from '../../server/src/services/auth.js';
|
|
|
| export { getDb, getUnifiedApiKey };
|
|
|
| export interface StartOptions {
|
| dbPath: string;
|
| clientDist: string;
|
| host: string;
|
| preferredPort: number;
|
| }
|
|
|
| export interface ServerHandle {
|
| server: Server;
|
| port: number;
|
| }
|
|
|
| export async function startServer(opts: StartOptions): Promise<ServerHandle> {
|
| process.env.CLIENT_DIST = opts.clientDist;
|
| initDb(opts.dbPath);
|
| const app = createApp();
|
| const { server, port } = await listenWithScan(app, opts.host, opts.preferredPort);
|
| startHealthChecker();
|
| return { server, port };
|
| }
|
|
|
|
|
|
|
| export function ensureSessionToken(): string {
|
| if (userCount() === 0) {
|
| createUser('desktop@localhost', crypto.randomBytes(24).toString('hex'));
|
| }
|
| const first = getDb().prepare('SELECT id FROM users ORDER BY id ASC LIMIT 1').get() as { id: number };
|
| return createSession(first.id);
|
| }
|
|
|
| async function listenWithScan(
|
| app: ReturnType<typeof createApp>,
|
| host: string,
|
| start: number,
|
| attempts = 50,
|
| ): Promise<{ server: Server; port: number }> {
|
| for (let port = start; port < start + attempts; port++) {
|
| const server = await tryListen(app, host, port);
|
| if (server) return { server, port };
|
| }
|
| throw new Error(`No free port found in ${start}–${start + attempts - 1}`);
|
| }
|
|
|
| function tryListen(app: ReturnType<typeof createApp>, host: string, port: number): Promise<Server | null> {
|
| return new Promise((resolve) => {
|
| const server = app.listen(port, host);
|
| server.once('listening', () => resolve(server));
|
| server.once('error', (err: NodeJS.ErrnoException) => {
|
| if (err.code === 'EADDRINUSE') resolve(null);
|
| else resolve(null);
|
| });
|
| });
|
| }
|
|
|