899028e20f
- RomConfig/RomCache on the kit's ConfigService/CacheStore; RomSync wires the pure domain into the kit SyncEngine (poll/watch/coalesce/fingerprint) and ProviderClient; EngineStatus assembly shared by REST + SSE - makeApi: HttpApiBuilder groups over live service values (handler runtime shares the plugin runtime's singletons) + sseRoute status feed - index.ts: definePluginKit entry (async-main boundary); headless-first (UI serve failure logged, engine continues) - cli.ts on the kit dispatcher: scan/detect/preview offline, sync/uninstall online; set-password is gone with the standalone server - dev.ts: auth-free loopback API server (:5885) — the dev:live proxy target; never bundled - verified live host-less: raw config round-trip on disk, status/platforms/ preview endpoints, soft-fail reconcile without a host - CI: workspace install, per-package typecheck, publish from plugin/ Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
110 lines
3.6 KiB
TypeScript
110 lines
3.6 KiB
TypeScript
// Domain DTOs shared by the plugin server and the UI — Schemas are the source of truth,
|
|
// the derived types keep the original domain names so the pure core reads unchanged.
|
|
import { Schema } from "effect";
|
|
|
|
/** Host OS as the launch/quoting domain sees it (macOS hosts use the linux lane). */
|
|
export const Os = Schema.Literals(["linux", "windows"]);
|
|
export type Os = typeof Os.Type;
|
|
|
|
/** Default emulator + core for a platform (operator-overridable per platform / per game). */
|
|
export const DefaultLaunch = Schema.Struct({
|
|
emulator: Schema.String,
|
|
core: Schema.optionalKey(Schema.String),
|
|
extraArgs: Schema.optionalKey(Schema.String),
|
|
});
|
|
export type DefaultLaunch = typeof DefaultLaunch.Type;
|
|
|
|
/** A console platform: extension set, art key, default launch (design §5). */
|
|
export const Platform = Schema.Struct({
|
|
id: Schema.String,
|
|
name: Schema.String,
|
|
extensions: Schema.Array(Schema.String),
|
|
libretroSystem: Schema.optionalKey(Schema.String),
|
|
defaultLaunch: DefaultLaunch,
|
|
disc: Schema.optionalKey(Schema.Boolean),
|
|
});
|
|
export type Platform = typeof Platform.Type;
|
|
|
|
/** An emulator definition: per-OS detection, launch template, archive support. */
|
|
export const EmulatorDef = Schema.Struct({
|
|
id: Schema.String,
|
|
name: Schema.String,
|
|
detect: Schema.Struct({
|
|
linux: Schema.Array(Schema.String),
|
|
windows: Schema.Array(Schema.String),
|
|
}),
|
|
coresDir: Schema.optionalKey(
|
|
Schema.Struct({
|
|
linux: Schema.Array(Schema.String),
|
|
windows: Schema.Array(Schema.String),
|
|
}),
|
|
),
|
|
template: Schema.String,
|
|
supportsArchives: Schema.Boolean,
|
|
contested: Schema.optionalKey(Schema.Boolean),
|
|
});
|
|
export type EmulatorDef = typeof EmulatorDef.Type;
|
|
|
|
/** A detected emulator install (UI's Emulators page + launch resolution). */
|
|
export const DetectedEmulator = Schema.Struct({
|
|
id: Schema.String,
|
|
name: Schema.String,
|
|
template: Schema.String,
|
|
supportsArchives: Schema.Boolean,
|
|
contested: Schema.optional(Schema.Boolean),
|
|
exeToken: Schema.String,
|
|
exePath: Schema.optional(Schema.String),
|
|
appId: Schema.optional(Schema.String),
|
|
via: Schema.Literals(["path", "file", "flatpak"]),
|
|
coresDir: Schema.optional(Schema.String),
|
|
cores: Schema.optional(Schema.Array(Schema.String)),
|
|
});
|
|
export type DetectedEmulator = typeof DetectedEmulator.Type;
|
|
|
|
/** A candidate the compute rejected, with a human reason (Library page, CLI). */
|
|
export const Skipped = Schema.Struct({
|
|
external_id: Schema.String,
|
|
title: Schema.String,
|
|
reason: Schema.String,
|
|
});
|
|
export type Skipped = typeof Skipped.Type;
|
|
|
|
/** A summary of one desired-state compute (Overview + Library pages). */
|
|
export const SyncReport = Schema.Struct({
|
|
considered: Schema.Number,
|
|
included: Schema.Number,
|
|
skipped: Schema.Array(Skipped),
|
|
excluded: Schema.Array(
|
|
Schema.Struct({ external_id: Schema.String, title: Schema.String }),
|
|
),
|
|
warnings: Schema.Array(Schema.String),
|
|
truncated: Schema.Number,
|
|
perPlatform: Schema.Record(Schema.String, Schema.Number),
|
|
overWarn: Schema.Boolean,
|
|
});
|
|
export type SyncReport = typeof SyncReport.Type;
|
|
|
|
export const LastSync = Schema.Struct({
|
|
fingerprint: Schema.String,
|
|
count: Schema.Number,
|
|
at: Schema.Number,
|
|
});
|
|
export type LastSync = typeof LastSync.Type;
|
|
|
|
/** The engine status the Overview page renders and the SSE feed streams. */
|
|
export const EngineStatus = Schema.Struct({
|
|
rootsConfigured: Schema.Number,
|
|
os: Os,
|
|
artProvider: Schema.NullOr(Schema.String),
|
|
syncing: Schema.Boolean,
|
|
lastSync: Schema.optional(LastSync),
|
|
lastReport: Schema.optional(SyncReport),
|
|
detectedAt: Schema.optional(Schema.Number),
|
|
paths: Schema.Struct({
|
|
dir: Schema.String,
|
|
config: Schema.String,
|
|
cache: Schema.String,
|
|
}),
|
|
});
|
|
export type EngineStatus = typeof EngineStatus.Type;
|