import fs from "fs" import path from "path" import type { Stream } from "@/types/stream" const DATA_DIR = process.env.DATA_DIR ?? "/app/data" const STREAMS_FILE = path.join(DATA_DIR, "streams", "streams.json") function ensureFile() { if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true }) if (!fs.existsSync(STREAMS_FILE)) fs.writeFileSync(STREAMS_FILE, "[]", "utf-8") } export function readStreams(): Stream[] { ensureFile() const streams = JSON.parse(fs.readFileSync(STREAMS_FILE, "utf-8")) as Stream[] // migration: assign order to streams that don't have it yet let dirty = false streams.forEach((s, i) => { if (s.order === undefined) { s.order = i; dirty = true } }) if (dirty) fs.writeFileSync(STREAMS_FILE, JSON.stringify(streams, null, 2), "utf-8") return streams.sort((a, b) => a.order - b.order) } export function writeStreams(streams: Stream[]): void { ensureFile() fs.writeFileSync(STREAMS_FILE, JSON.stringify(streams, null, 2), "utf-8") } export function getStream(id: string): Stream | undefined { return readStreams().find((s) => s.id === id) } export function saveStream(stream: Stream): void { const streams = readStreams() const idx = streams.findIndex((s) => s.id === stream.id) if (idx >= 0) streams[idx] = stream else streams.push(stream) writeStreams(streams) } export function deleteStream(id: string): void { writeStreams(readStreams().filter((s) => s.id !== id)) } // Allocates display number and VNC/debug ports without conflicting with existing streams export function allocatePorts(): { display: string vncPort: number debugPort: number } { const streams = readStreams() const usedDisplays = new Set(streams.map((s) => s.display)) let n = 1 while (usedDisplays.has(`:${n}`)) n++ return { display: `:${n}`, vncPort: 5900 + n, debugPort: 9221 + n, } }