#!/usr/bin/env bun // Dev-only API server: the plugin's HttpApi on a plain loopback port (:5885), no auth, // no static files — the `bun run dev:live` proxy target for the Vite UI. Connects to a // running host when one is up (full sync path); otherwise runs host-less (scan, preview, // detect, and config all work; reconcile fails softly in the engine's safeSync). // This is NOT part of the shipped plugin (never bundled into dist/index.js or cli.js). import { connect, type Punktfunk } from "@punktfunk/host"; import { hostClientFromFacade, loggingLayer, pluginInfoLayer, } from "@punktfunk/plugin-kit"; import { Effect, Layer, ManagedRuntime } from "effect"; import { HttpRouter } from "effect/unstable/http"; import pkg from "../package.json" with { type: "json" }; import { PLUGIN_NAME } from "./index.js"; import { romLayer } from "./layer.js"; import { makeApi } from "./services/api.js"; import { RomCache } from "./services/cache.js"; import { RomConfig } from "./services/config.js"; import { RomSync } from "./services/engine.js"; const PORT = Number(process.env.ROM_MANAGER_DEV_PORT ?? 5885); const offlineFacade = (): Punktfunk => ({ request: async (method: string, path: string) => { throw new Error(`dev: no host running (tried ${method} ${path})`); }, close: () => {}, }) as unknown as Punktfunk; const pf = await connect().catch(() => { console.log("dev: no punktfunk host reachable — running host-less"); return offlineFacade(); }); const base = Layer.mergeAll( hostClientFromFacade(pf), pluginInfoLayer({ name: PLUGIN_NAME, version: pkg.version }), loggingLayer(PLUGIN_NAME), ); const rt = ManagedRuntime.make(Layer.provideMerge(romLayer, base)); // No Effect.scoped here: the engine's loops belong to the runtime's layer scope and // must outlive this acquisition effect (they close on rt.dispose()). const { handler, dispose } = await rt.runPromise( Effect.gen(function* () { const sync = yield* RomSync; const config = yield* RomConfig; const cache = yield* RomCache; yield* sync.engine.start; return HttpRouter.toWebHandler(makeApi({ sync, config, cache })); }), ); const server = Bun.serve({ hostname: "127.0.0.1", port: PORT, idleTimeout: 0, // SSE fetch: (req) => handler(req), }); console.log( `rom-manager dev API on http://127.0.0.1:${server.port}/api/status`, ); process.once("SIGINT", () => { void dispose() .then(() => rt.dispose()) .finally(() => process.exit(0)); });