refactor: workspace restructure — contract package + pure domain ported, tests green
- bun workspaces: contract/ (Schemas = source of truth: config raw↔resolved,
domain DTOs, HttpApi contract, API errors) + plugin/ + ui/
- pure domain moved src/{engine,art}→plugin/src/{domain,art}, types now
imported from @rom-manager/contract and @punktfunk/plugin-kit/wire (the
hand-copied wire.ts dies), loggers injected instead of module-global
- ui.* and devEntry dropped from the config shape (standalone server is
gone; stale keys tolerated on decode, dropped by the next save)
- all 48 domain tests ported and green BEFORE any Effect wiring
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
// 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";
|
||||
|
||||
export const Os = Schema.Literals(["linux", "windows", "mac"]);
|
||||
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.optionalKey(Schema.Boolean),
|
||||
exeToken: Schema.String,
|
||||
exePath: Schema.optionalKey(Schema.String),
|
||||
appId: Schema.optionalKey(Schema.String),
|
||||
via: Schema.Literals(["path", "file", "flatpak"]),
|
||||
coresDir: Schema.optionalKey(Schema.String),
|
||||
cores: Schema.optionalKey(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.optionalKey(LastSync),
|
||||
lastReport: Schema.optionalKey(SyncReport),
|
||||
detectedAt: Schema.optionalKey(Schema.Number),
|
||||
paths: Schema.Struct({
|
||||
dir: Schema.String,
|
||||
config: Schema.String,
|
||||
cache: Schema.String,
|
||||
}),
|
||||
});
|
||||
export type EngineStatus = typeof EngineStatus.Type;
|
||||
Reference in New Issue
Block a user