diff --git a/src/server.ts b/src/server.ts index a9f6ae8..dfa15cf 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,10 +1,10 @@ import { join } from 'path' -import { unlinkSync } from 'fs' +import { accessSync, chmodSync, constants, mkdirSync, unlinkSync } from 'fs' import type { ServerWebSocket, Subprocess } from 'bun' -const DATA_DIR = process.env.DATA_DIR! +const DATA_DIR = process.env.DATA_DIR const PORT = Number(process.env.PORT) || 3000 -const SOCKET_PATH = join(DATA_DIR, 'tronbyt.sock') +const SOCKET_PATH = DATA_DIR ? join(DATA_DIR, 'tronbyt.sock') : '' const BIN_DIR = join(import.meta.dir, '..', 'bin') let goProcess: Subprocess | undefined @@ -107,13 +107,52 @@ async function waitForHealthy(maxAttempts = 60): Promise { return false } +async function downloadBinary(binPath: string): Promise { + const name = getBinaryName() + const url = `https://github.com/tronbyt/server/releases/latest/download/${name}` + + console.log(`Downloading ${name}...`) + try { + const resp = await fetch(url, { redirect: 'follow' }) + if (!resp.ok) { + console.error(`Download failed: ${resp.status} ${resp.statusText}`) + return false + } + + mkdirSync(BIN_DIR, { recursive: true }) + await Bun.write(binPath, resp) + + chmodSync(binPath, 0o755) + + console.log('Download complete') + return true + } catch (e) { + console.error('Download failed:', e) + return false + } +} + +function validate(): string | undefined { + if (!DATA_DIR) return 'DATA_DIR env var is not set — toes should provide this automatically' + + const binPath = join(BIN_DIR, getBinaryName()) + try { + accessSync(binPath, constants.X_OK) + } catch { + return `Binary not found or not executable: ${binPath}` + } +} + async function spawnGoServer() { const binPath = join(BIN_DIR, getBinaryName()) if (!(await Bun.file(binPath).exists())) { - console.error(`Binary not found: ${binPath}`) - console.error(`Download from https://github.com/tronbyt/server/releases`) - console.error(`Expected: ${getBinaryName()}`) + if (!(await downloadBinary(binPath))) return + } + + const error = validate() + if (error) { + console.error(`Setup error: ${error}`) return } @@ -126,7 +165,7 @@ async function spawnGoServer() { ...process.env, TRONBYT_UNIX_SOCKET: SOCKET_PATH, DATA_DIR, - DB_DSN: join(DATA_DIR, 'tronbyt.db'), + DB_DSN: join(DATA_DIR!, 'tronbyt.db'), PRODUCTION: process.env.PRODUCTION ?? 'false', SINGLE_USER_AUTO_LOGIN: process.env.SINGLE_USER_AUTO_LOGIN ?? 'true', SYSTEM_APPS_AUTO_REFRESH: process.env.SYSTEM_APPS_AUTO_REFRESH ?? 'true',