refactor: rewrite on @punktfunk/plugin-kit — contract + plugin workspaces
The framework half of this plugin (engine lifecycle, config/state, host
reconcile, UI server, CLI) was ~80% identical to rom-manager's. That code is
now @punktfunk/plugin-kit; this replaces the local copy with it and adopts the
rom-manager blueprint layout.
contract/ Effect Schemas: the cross-process export contract (the C#
exporter's other half, with the schema-version guard as a decode
check), the config schema (one schema, Encoded = authored file
shape, defaults only via withDecodingDefaultKey), domain DTOs, the
HttpApi contract, API errors.
plugin/ src/domain = the pure core (locate/read, art, reconcile), ported
tests green before any Effect wiring; src/services = the kit's
ConfigService/CacheStore/SyncEngine/ProviderClient; definePluginKit
entry, kit CLI, auth-free dev API.
Preserved, because they are what makes playnite work at all: the ingest inbox
is still read FIRST (the de-privileged LocalService runner cannot reach the
interactive user's %APPDATA%), the host/dataurl/off art modes, and the
playnite:// launch hand-back. The C# exporter is untouched.
New: per-game include/exclude overrides, and an allow-listed /api/art proxy so
the SPA can render local Playnite covers — it serves only paths the currently
ingested export references.
Dropped: the standalone password UI server (console surface + CLI only, as in
rom-manager 0.3.0) and the devEntry flag.
Trap found and fixed here: the HttpApi encoder serialises `undefined` as
`null`, so a `Schema.optional` field the server omits cannot be decoded by the
client — silently in the SSE feed, loudly in the typed client. Every optional
EngineStatus field is `Schema.NullOr` with an explicit value on the wire.
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
// API errors — Schema-backed so they cross the wire typed; status set per-endpoint via
|
||||
// HttpApiSchema.status in api.ts.
|
||||
import { Schema } from "effect";
|
||||
|
||||
/** PUT /api/config body failed schema validation. → 400 */
|
||||
export class ConfigInvalid extends Schema.TaggedErrorClass<ConfigInvalid>()(
|
||||
"ConfigInvalid",
|
||||
{ issues: Schema.String },
|
||||
) {}
|
||||
|
||||
/** A sync pass is already running (the trigger was coalesced). → 409 */
|
||||
export class SyncInProgress extends Schema.TaggedErrorClass<SyncInProgress>()(
|
||||
"SyncInProgress",
|
||||
{},
|
||||
) {}
|
||||
|
||||
/**
|
||||
* No exporter output was found, or the file is unreadable / not a valid export / stamped
|
||||
* with a schema this plugin does not understand. → 503, because it is a "the other half
|
||||
* isn't installed yet" state rather than a server fault: the UI turns it into onboarding.
|
||||
*/
|
||||
export class ExportUnavailable extends Schema.TaggedErrorClass<ExportUnavailable>()(
|
||||
"ExportUnavailable",
|
||||
{ message: Schema.String },
|
||||
) {}
|
||||
Reference in New Issue
Block a user