Skip to content

Load the plugin store list from store/stores.json - #195

Open
FlazeIGuess wants to merge 3 commits into
Inrixia:masterfrom
FlazeIGuess:store/registry-json
Open

Load the plugin store list from store/stores.json#195
FlazeIGuess wants to merge 3 commits into
Inrixia:masterfrom
FlazeIGuess:store/registry-json

Conversation

@FlazeIGuess

@FlazeIGuess FlazeIGuess commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Moves the default store list out of PluginStoreTab/index.tsx and into store/stores.json, which the client fetches at runtime.

Problem

The defaults are 22 hardcoded addToStores(...) calls in plugins/ui/src/SettingsPage/PluginStoreTab/index.tsx, under a comment that already says what should happen:

// Devs! Add your stores here <3
// TODO: Abstract this to a git repo

Because the list lives in client source, adding a store needs a release before anyone sees it. That is what #179, #190 and #194 all are. Removing one has the same problem in reverse: #184 took a dead repo out of the list, but every client built before that merge still tries to fetch it and still shows a red error card. And there is no way to pull a store that turns hostile without shipping a new build.

Change

store/stores.json is the list. The client reads it from raw.githubusercontent.com/Inrixia/TidaLuna/master/store, pinned to master deliberately, so a merged store reaches users in minutes instead of at the next release.

  • store/stores.schema.json and store/validate.sh check every entry in CI on any PR touching store/: url shape, no duplicates, and that each store.json actually resolves and parses.
  • Removing a store sets "status": "removed" with a reason rather than deleting the line. Deleting it only stops new clients picking it up; the tombstone is what removes it from clients that already have it.
  • store/blocklist.json is a kill switch. Glob patterns, matching stores disappear everywhere on the next fetch.
  • Removals the user makes now persist, so a store you removed does not come back on restart.
  • The pre-registry storeUrls key is migrated once and then deleted. Note that SettingsPage/Storage.tsx held a second storeUrls on a different idb store, so anything added from the Themes tab was never shown in the store tab. That key is removed rather than migrated.

Three fixes ride along because the wiring touched them: the tidaluna://settings/store deeplink lowercased the whole url including the store link in its query, plugin names used replace where they needed replaceAll, and LunaStore called .filter on an unvalidated third party plugins array.

The store tab looks exactly as it does today. Only the source of the list moves.

Also bumps the version to 1.17.0-beta, since the [master] Release workflow only runs on pushes to master that touch package.json.

Validation

All 22 active stores return HTTP 200 with a parseable store.json, and store/validate.sh passes on all 29 entries.

Tested in the client rather than only built. Because stores.json does not exist on master yet, a plain run only exercises the offline fallback to the old storeUrls key, so I served stores.json locally, pointed a test build at it and cleared every key the client could fall back on. From that empty state the tab populated all stores with no error rows, and adding a glob to the served blocklist.json made the matching store disappear on the next fetch.

The plugin store list lives in plugins/ui/src/SettingsPage/PluginStoreTab/index.tsx
today, so adding a store needs a code change plus a client release, and removing
one never reaches users who already have it persisted.

store/stores.json is the list instead. Seeded with the 22 stores currently
hardcoded and 7 tombstones recovered from the git history of index.tsx, three of
which are hard 404s that have been showing up as error cards for months.

store/validate.sh checks schema, unknown keys, url and repo consistency,
duplicates and that every active store.json actually resolves with a non empty
plugins array. Needs only jq and curl, runs in about 9 seconds.
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

Flake Review Results for #195

Available systems: aarch64-darwin, aarch64-linux, armv6l-linux, armv7l-linux, i686-linux, powerpc64le-linux, riscv64-linux, x86_64-darwin, x86_64-freebsd, x86_64-linux
Requested systems: aarch64-darwin, x86_64-linux

🔄 Modified (2)

  • packages.aarch64-darwin.default

    • Output: /nix/store/6p58sf8kq8lpm1pbzdwlmv4kk6kpg7hv-tidal-2.41.3
    Derivation diff
    - /nix/store/w8r83gqv80qc441h1y8pzp9n4yjkrkqx-tidal-2.41.3.drv:{out}
    + /nix/store/7n5kmbk984ybxdq4n24ryynf8l8lr7db-tidal-2.41.3.drv:{out}
    • The set of input derivation names do not match:
        - TidaLuna-1.16.6-beta
        + TidaLuna-1.17.0-beta
    • The environments do not match:
        __json=''
        {"NIX_MAIN_PROGRAM":"tidal","__darwinAllowLocalNetworking":false,"__impureHostDeps":["/bin/sh","/usr/lib/libSystem.B.dylib","/usr/lib/system/libunc.dylib","/dev/zero","/dev/random","/dev/urandom","/bin/sh"],"__propagatedImpureHostDeps":[],"__propagatedSandboxProfile":[""],"__sandboxProfile":"","buildInputs":[],"builder":"/nix/store/f700nj7wlwg441h39gkq29qbviy99sgq-bash-5.3p9/bin/bash","cmakeFlags":[],"configureFlags":[],"depsBuildBuild":[],"depsBuildBuildPropagated":[],"depsBuildTarget":[],"depsBuildTargetPropagated":[],"depsHostHost":[],"depsHostHostPropagated":[],"depsTargetTarget":[],"depsTargetTargetPropagated":[],"doCheck":false,"doInstallCheck":false,"dontStrip":true,"env":{"NIX_MAIN_PROGRAM":"tidal"},"installPhase":"runHook preInstall\n\nmkdir -p $out/Applications\ncp -r *.app $out/Applications\n\nrunHook postInstall\n","mesonFlags":[],"name":"tidal-2.41.3","nativeBuildInputs":["/nix/store/q61ydp78wcs21i3aji0pc3xwa78xvd8d-undmg-1.1.0-unstable-2024-08-02"],"outputChecks":{"out":{}},"outputs":["out"],"patches":[],"pname":"tidal","postInstall":"if [ -f \"$out/Applications/TIDAL.app/Contents/Resources/app.asar\" ]; then\n  mv \"$out/Applications/TIDAL.app/Contents/Resources/app.asar\" \\\n     \"$out/Applications/TIDAL.app/Contents/Resources/original.asar\"\nfi\n\nmkdir -p \"$out/Applications/TIDAL.app/Contents/Resources/app/\"\ncp -R /nix/store/bpzav915wd94lspzwc1hrgh8xm9xd8yw-TidaLuna-1.16.6-beta/* \"$out/Applications/TIDAL.app/Contents/Resources/app/\"\n","propagatedBuildInputs":[],"propagatedNativeBuildInputs":[],"sourceRoot":".","src":"/nix/store/sckhn4ryh7jqkdzqi3hz02sgglkl7jwd-TIDAL.arm64.dmg","stdenv":"/nix/store/5qpb391n5rpgdi95j6sczjsplkkgw2v1-stdenv-darwin","strictDeps":true,"system":"aarch64-darwin","version":"2.41.3"}{"NIX_MAIN_PROGRAM":"tidal","__darwinAllowLocalNetworking":false,"__impureHostDeps":["/bin/sh","/usr/lib/libSystem.B.dylib","/usr/lib/system/libunc.dylib","/dev/zero","/dev/random","/dev/urandom","/bin/sh"],"__propagatedImpureHostDeps":[],"__propagatedSandboxProfile":[""],"__sandboxProfile":"","buildInputs":[],"builder":"/nix/store/f700nj7wlwg441h39gkq29qbviy99sgq-bash-5.3p9/bin/bash","cmakeFlags":[],"configureFlags":[],"depsBuildBuild":[],"depsBuildBuildPropagated":[],"depsBuildTarget":[],"depsBuildTargetPropagated":[],"depsHostHost":[],"depsHostHostPropagated":[],"depsTargetTarget":[],"depsTargetTargetPropagated":[],"doCheck":false,"doInstallCheck":false,"dontStrip":true,"env":{"NIX_MAIN_PROGRAM":"tidal"},"installPhase":"runHook preInstall\n\nmkdir -p $out/Applications\ncp -r *.app $out/Applications\n\nrunHook postInstall\n","mesonFlags":[],"name":"tidal-2.41.3","nativeBuildInputs":["/nix/store/q61ydp78wcs21i3aji0pc3xwa78xvd8d-undmg-1.1.0-unstable-2024-08-02"],"outputChecks":{"out":{}},"outputs":["out"],"patches":[],"pname":"tidal","postInstall":"if [ -f \"$out/Applications/TIDAL.app/Contents/Resources/app.asar\" ]; then\n  mv \"$out/Applications/TIDAL.app/Contents/Resources/app.asar\" \\\n     \"$out/Applications/TIDAL.app/Contents/Resources/original.asar\"\nfi\n\nmkdir -p \"$out/Applications/TIDAL.app/Contents/Resources/app/\"\ncp -R /nix/store/0vvlzvnsnhas9d77njzz9ja4k024w888-TidaLuna-1.17.0-beta/* \"$out/Applications/TIDAL.app/Contents/Resources/app/\"\n","propagatedBuildInputs":[],"propagatedNativeBuildInputs":[],"sourceRoot":".","src":"/nix/store/sckhn4ryh7jqkdzqi3hz02sgglkl7jwd-TIDAL.arm64.dmg","stdenv":"/nix/store/5qpb391n5rpgdi95j6sczjsplkkgw2v1-stdenv-darwin","strictDeps":true,"system":"aarch64-darwin","version":"2.41.3"}
    ''
  • packages.x86_64-linux.default

    • Output: /nix/store/y1psdkm62xrxapyz38b4xj7igs4w6754-tidal-hifi-6.3.1-Mavy
    Derivation diff
    - /nix/store/js64gd6v64y4rpzhz00q7729n6h7rnyq-tidal-hifi-6.3.1-Mavy.drv:{out}
    + /nix/store/1ll2jb02sql5hwqjjbmh99a0ignl76m1-tidal-hifi-6.3.1-Mavy.drv:{out}
    • The set of input derivation names do not match:
        - TidaLuna-1.16.6-beta
        + TidaLuna-1.17.0-beta
    • The environments do not match:
        postInstall=''
        mv $out/share/tidal-hifi/resources/app.asar $out/share/tidal-hifi/resources/original.asar
        
        mkdir -p "$out/share/tidal-hifi/resources/app/"
        cp -R /nix/store/zbin7zfshnznw7y1sajwl51x1mgxdysq-TidaLuna-1.16.6-beta/* $out/share/tidal-hifi/resources/app/
        cp -R /nix/store/d0n0gziw2xfjcqjv6j2sgjaxhg9r3kj0-TidaLuna-1.17.0-beta/* $out/share/tidal-hifi/resources/app/
    ''

Generated by flake-review

…ng it

Replaces the 22 addToStores calls with a fetch of store/stores.json from raw
githubusercontent, pinned to master so a merged store reaches clients without a
release.

The old storeUrls key mixed defaults and user additions in one list, so removing
a default brought it back on the next start and removing one from the code never
reached anyone who already had it. Split into three: userStoreUrls for what the
user added, hiddenStoreUrls for defaults they dismissed, and the fetched list,
which is persisted and doubles as the offline cache. Tombstoned entries drop dead
stores from clients that already carry them.

The decision logic lives in registry.logic.ts, separate from the reactive state
and the fetching in registry.ts.

Three things found on the way are fixed here because the wiring touched them:
- the deeplink handler lowercased the whole url and pushed it without stripping
  /store.json, persisting a url that always 404s
- Storage.tsx had a second addToStores writing to a different idb store, so
  adding a store from the themes tab silently went nowhere
- LunaStore mapped only the first space in a plugin name and called .filter on
  unvalidated third party json, which takes down the whole settings page
The [master] Release workflow only runs on pushes to master that touch
package.json, so without this the merge would not produce a release build.
FlazeIGuess added a commit to FlazeIGuess/TidaLuna that referenced this pull request Sep 7, 2026
This stacks on Inrixia#195, which bumps to 1.17.0-beta. Each merge to master needs its
own package.json touch to trigger the [master] Release build, so this PR carries
the next patch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant