Files
punktfunk-plugin-rom-manager/plugin/src/services/cache.ts
T
enricobuehler 899028e20f feat: Effect services + HttpApi implementation + kit entry/CLI/dev server
- 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>
2026-07-20 19:04:25 +02:00

47 lines
1.4 KiB
TypeScript

// The plugin's disposable derived state (cache.json), on the kit's CacheStore: art
// verdicts keyed by external_id, the last detection result, and the last-sync
// fingerprint. Corrupt/absent → empty; every mutation is write-through.
import {
type CacheStore,
makeCacheStore,
type PluginInfo,
} from "@punktfunk/plugin-kit";
import { Artwork } from "@punktfunk/plugin-kit/wire";
import { DetectedEmulator, LastSync, Os } from "@rom-manager/contract";
import { Context, Effect, Layer, Schema } from "effect";
export const ArtVerdictSchema = Schema.Struct({
art: Schema.NullOr(Artwork),
provider: Schema.String,
matcher: Schema.Number,
});
export const CacheSchema = Schema.Struct({
art: Schema.Record(Schema.String, ArtVerdictSchema).pipe(
Schema.withDecodingDefaultKey(Effect.succeed({}), {
encodingStrategy: "passthrough",
}),
),
detect: Schema.optionalKey(
Schema.Struct({
at: Schema.Number,
os: Os,
emulators: Schema.Array(DetectedEmulator),
}),
),
lastSync: Schema.optionalKey(LastSync),
});
export type Cache = typeof CacheSchema.Type;
export const emptyCache: Cache = { art: {} };
export class RomCache extends Context.Service<
RomCache,
CacheStore<typeof CacheSchema>
>()("rom-manager/RomCache") {
static readonly layer: Layer.Layer<RomCache, never, PluginInfo> =
Layer.effect(RomCache)(
makeCacheStore({ schema: CacheSchema, empty: emptyCache }),
);
}