#!/usr/bin/env bun // Ops CLI on the kit's dispatcher — the same layer graph as the plugin entry, so every // command sees the exact services the runner runs. scan/detect/preview work offline; // sync/uninstall talk to the host. import { type CliCommand, ProviderClient, runPluginCli, } from "@punktfunk/plugin-kit"; import { Effect } from "effect"; import pkg from "../package.json" with { type: "json" }; import { PLUGIN_NAME } from "./index.js"; import { type RomServices, romLayer } from "./layer.js"; import { PROVIDER_ID, RomSync } from "./services/engine.js"; const print = (line: string) => Effect.sync(() => console.log(line)); const commands: Record> = { scan: { summary: "Scan configured ROM roots and list candidates", offline: true, run: () => Effect.gen(function* () { const sync = yield* RomSync; const { report } = yield* sync.preview; yield* print( `${report.considered} candidate(s), ${report.included} would be included`, ); for (const [platform, n] of Object.entries(report.perPlatform)) { yield* print(` ${platform}: ${n}`); } }), }, detect: { summary: "Probe for installed emulators", offline: true, run: () => Effect.gen(function* () { const sync = yield* RomSync; const detected = yield* sync.detect(true); for (const d of detected) { yield* print( `${d.id.padEnd(14)} ${d.via.padEnd(8)} ${d.exePath ?? d.exeToken}${d.cores ? ` (${d.cores.length} cores)` : ""}`, ); } if (detected.length === 0) yield* print("no emulators found"); }), }, preview: { summary: "Dry-run: show the entries a sync would reconcile", offline: true, run: () => Effect.gen(function* () { const sync = yield* RomSync; const { entries, report } = yield* sync.preview; for (const e of entries) yield* print(`${e.external_id} ${e.title}`); for (const s of report.skipped) { yield* print(`SKIP ${s.external_id}: ${s.reason}`); } yield* print( `${report.included} included, ${report.skipped.length} skipped`, ); }), }, sync: { summary: "Reconcile the library provider now", run: () => Effect.gen(function* () { const sync = yield* RomSync; const outcome = yield* sync.engine.sync("manual"); yield* print( outcome._tag === "AlreadyRunning" ? "a sync is already running" : `${outcome._tag}: ${outcome.report.included} entries`, ); }), }, uninstall: { summary: "Remove every rom-manager entry from the host library", run: () => Effect.gen(function* () { const provider = yield* ProviderClient; yield* provider.remove(PROVIDER_ID); yield* print("provider entries removed"); }), }, }; await runPluginCli({ def: { name: PLUGIN_NAME, version: pkg.version, layer: romLayer, main: Effect.void, }, commands, });