6 Commits
Author SHA1 Message Date
enricobuehler c59d845100 Merge pull request 'plugin-kit 0.3.1' (#2) from chore/plugin-kit-0.3.1 into main
CI / build (push) Successful in 18s
CI / publish (push) Successful in 15s
Reviewed-on: #2
v0.1.0
2026-08-06 19:06:25 +00:00
enricobuehler e3514e7f6c chore: plugin-kit 0.3.1
CI / build (pull_request) Successful in 22s
CI / publish (pull_request) Skipped
Picks up punktfunk#78. The headline fix there — the kit's read-only SQLite reader
never opening a database on Linux — does NOT affect this plugin: Heroic's library
is read from the JSON `store_cache`, not a database. The second fix does matter
here, because it is about this plugin's release gate: `parity --compare` set a
non-zero exit code and `runPluginCli` then overwrote it with 0, so a red parity
run always exited 0 and any scripted use of it passed.

The caret range already allowed 0.3.1, but bun.lock pinned 0.3.0 exactly.

Gates: biome clean, tsc clean, 7/7 tests, bundle builds.

⚠ Parity is NOT yet meaningful for this plugin: Heroic is installed on .21 but has
never been launched, so there is no store_cache and no library — both sides of the
comparison are empty and a green run would prove nothing. It needs a signed-in
Heroic before its v0.1.0 tag.
2026-08-06 20:29:17 +02:00
enricobuehler d3ef3494dc Merge pull request 'A tile that opens Heroic itself' (#1) from feat/launcher-tile into main
CI / build (push) Successful in 17s
CI / publish (push) Skipped
Reviewed-on: #1
2026-08-06 17:24:02 +00:00
enricobuehler 85473e15dc feat: a tile that opens Heroic itself
CI / build (pull_request) Successful in 34s
CI / publish (pull_request) Skipped
`defineLibraryPlugin` has taken a `launchers()` hook since kit 0.3.0 — entries that
open the LAUNCHER rather than a title (design D4) — and nothing implemented it. The
host has resolved `launcher_ui` valued `"heroic"` since the same release. So the
whole path existed end to end with no producer at either end.

One entry, config-toggled and on by default: installing, updating or logging in are
exactly the things you cannot do from a game tile.

`launcher_ui` is valued by STORE ID, never a command: the host resolves "heroic" to
the native binary or the Flatpak, minus the `--no-gui` and the URI that game entries
carry, so the window itself opens (D1). That is also the only shape available to a
plugin at all — the 2026-08-05 review made `launch.kind = "command"` operator-only,
so a plugin publishing one has its entire reconcile refused.

CAVEAT carried in the code: Heroic is a single-instance Electron app, so if a window
is ALREADY open the spawned process forwards to it and exits. The host documents the
same caveat for game launches; keeping the session alive across it is a host-side
question (the launcher-tile lease), not this plugin's.

Deliberately art-less — see the lutris plugin: a square app icon cover-cropped into a
2:3 tile looks broken, and every client renders an art-less launcher entry as "opens
Heroic" on purpose.

Gates: tsc --noEmit clean, 7 tests pass (2 new), biome clean.
Needs a host carrying the M2 wire (`role` + `launcher_ui`), which is on main.
2026-08-06 15:17:14 +02:00
enricobuehler 7d4f26e8d1 chore: lock @punktfunk/plugin-kit@0.3.0
CI / build (push) Successful in 16s
CI / publish (push) Skipped
Same as lutris: the kit is on the registry, so the dependency resolves and CI's
`bun install --frozen-lockfile` has something to freeze against. Verified
against the published package: tsc clean, 5 tests.
2026-08-05 19:29:22 +02:00
enricobuehler 5fb6946aa1 feat: the Heroic library source
CI / build (push) Failing after 15s
CI / publish (push) Skipped
The host's in-tree Heroic scanner, lifted out into its own installable plugin
(design/library-scanner-plugins.md M5/WP5.2). One source covers all three of
Heroic's backends — legendary (Epic), gog, nile (Amazon) — because that is how
Heroic presents them and how the built-in scanner did.

The package is a config schema, a detect, a scan and a watchDirs. The store
claim, sync engine, __config surface, console registration and the
detect/scan/parity/uninstall CLI verbs all come from
@punktfunk/plugin-kit/library.

Claiming the `heroic` store keeps the entry ids the built-in scanner produced
(`heroic:<runner>:<appName>`), so GameStream app ids, Moonlight pins, cached art
and the operator's enabled/disabled state all survive the migration.

Ported behaviours worth naming, each covered by a test:

  * a title counts as installed only if Heroic says so AND its install directory
    still exists. The second check is the workaround for Heroic's GOG
    is_installed bug (#2691), without which uninstalled games linger.
  * only http(s) art is emitted. A sideloaded title can carry a local file://
    path, which — unlike a path this plugin resolved itself — is not one the host
    should proxy, and the client cannot fetch either. It degrades to the title
    card, as in-host.
  * both detect signals ride along: the install dir and the HEROIC_APP_NAME env
    marker. Heroic hands off to legendary/gogdl/nile, so the host never sees the
    game's own process any other way, and the env marker is what works under
    Proton (verified on-glass 2026-07-27). They are a union, so a Heroic version
    that stops setting it degrades rather than breaking.

The launch VALUE and the `heroic` launch kind are unchanged — the host still owns
turning `<runner>:<appName>` into a heroic://launch command, so this plugin never
constructs a command line.

Verified locally against the kit: tsc clean, biome clean, 5 tests, bundle builds,
CLI runs (detect -> absent, scan -> 0 games).

As with lutris: no lockfile and CI cannot be green until
@punktfunk/plugin-kit@0.3.0 is published. The parity gate has NOT been run — that
needs a box with Heroic installed.
2026-08-05 19:17:02 +02:00