Skip to content

Add active_profile_nexus_files query; fix query-type generator#23646

Open
halgari wants to merge 2 commits into
masterfrom
misc/active-profile-nexus-files-query
Open

Add active_profile_nexus_files query; fix query-type generator#23646
halgari wants to merge 2 commits into
masterfrom
misc/active-profile-nexus-files-query

Conversation

@halgari

@halgari halgari commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What

Adds a registered query, active_profile_nexus_files, that lists the gameId/modId/fileId for every installed Nexus mod file of the currently active profile's game — expressed entirely through the level_pivot pivot-table system rather than raw kv key parsing.

Query definitions (src/queries/)

  • setup/tables.sql — three new pivot tables alongside the existing ones:
    • profile_settings_pivotsettings###{section}###{attr} → exposes activeProfileId
    • mod_attributes_pivotpersistent###mods###{game_id}###{vortex_mod_id}###attributes###{attr}source, modId, fileId, downloadGame (uses a mid-pattern literal attributes### segment; JSON BIGINT/JSON VARCHAR column types let the extension unwrap the JSON-encoded values natively)
    • mod_state_pivotpersistent###mods###{game_id}###{vortex_mod_id}###{attr}state (a top-level mod field, not an attribute)
  • select/nexus_files.sql — the select itself: joins active profile → profile's game → mod attributes + state, filtered to source = 'nexus' and state = 'installed'.

No runtime code changes were needed for the query itself: initQuerySystem auto-discovers .sql files, and the nx copy-assets target already tracks src/queries/ as an input.

TypeScript changes

All in scripts/generate-query-types.ts. This is the first parameterless select fed through the generator, which exercised previously-dead code paths and exposed three latent bugs (the generator was unrunnable at HEAD):

  1. Stale extension URL — the generator installed level_pivot from halgari.github.io, whose current release is built for DuckDB v1.4.4; the workspace's @duckdb/node-api is v1.5.1, so INSTALL hard-failed on the version check. Now uses nexus-mods.github.io (same source download-duckdb-extensions.ts uses), which serves a v1.5.1 build.
  2. Missing View import — parameterless selects get a View<Row> accessor in the generated Models, but the generated file never imported the View type, so the output didn't compile. The import is now emitted whenever a parameterless select exists.
  3. interface rows vs View<T> — select result rows were emitted as interface, which doesn't satisfy View<T>'s T extends Record<string, unknown> constraint (interfaces have no implicit index signature; type aliases do). Rows are now emitted as type aliases, which also made the as Models cast in createModels unnecessary — it's removed (eslint flags it as an unnecessary assertion once the types line up).

src/main/src/store/generated/queryTypes.ts is regenerated with the new row types (ProfileSettingsPivotRow, ModAttributesPivotRow, ModStatePivotRow, ActiveProfileNexusFilesRow) and query maps.

Known limitation (pre-existing generator design, not introduced here): the generated createModels() maps parameterless selects to db.createView(name), which assumes a DuckDB VIEW of that name exists — but selects are registered as named queries, not CREATE VIEWs, so that accessor would fail if called. The typed QueryParamsMap/QueryResultMap route via QueryRegistry.executeQuery is the working path.

Example usage

Executed through the query system (parsed by queryParser, setup + select run in QueryRegistry.initialize order) against a real Stardew Valley profile — 100 rows, first 10 shown:

game_id mod_id file_id vortex_mod_id
stardewvalley 239 165575 NPC Map Locations 3.5.2-239-3-5-2-1777140225
stardewvalley 518 160464 Chests Anywhere 1.30.1-518-1-30-1-1773542861
stardewvalley 541 160470 Lookup Anything 1.55.0-541-1-55-0-1773543281
stardewvalley 923 161305 Part of the Community-923-1-3-2-1774019661
stardewvalley 1063 160585 Automate 2.6.1-1063-2-6-1-1773591401
stardewvalley 1348 145986 SpaceCore 1.28.4-1348-1-28-4-1760884041
stardewvalley 1536 128517 MailFrameworkMod-v1.20.0-1536-1-20-0-1743142619
stardewvalley 1915 160463 Content Patcher 2.9.1-1915-2-9-1-1773542770
stardewvalley 2306 92532 Tidy Pam 3.0-2306-3-0-1713192783
stardewvalley 2400 160380 SMAPI 4.5.2-2400-4-5-2-1773515243

Note: an installed collection also matches (source: "nexus", state: "installed") but identifies via collectionId rather than modId/fileId, so it returns null ids. Filter with modId IS NOT NULL if collections should be excluded, or pivot collectionId/revisionId in as columns if they should be identified.

Verification

  • pnpm run generate:query-types — succeeds (was broken at HEAD)
  • @vortex/main: build, typecheck, lint, test (233 passed / 4 skipped), format — all clean
  • Query validated end-to-end against a live profile database via the source queryParser + the QueryRegistry execution semantics

Notes for reviewers

  • The pre-existing mods_pivot in tables.sql appears mis-shaped for the real key layout (persistent###mods###{mod_id}###{attr} — the {mod_id} capture lands on the game segment, so its name/version/state columns can never match). Nothing references it; mod_state_pivot here demonstrates the correct shape. Left untouched to keep this change narrow — could be fixed or dropped in a follow-up.

Adds pivot tables (profile_settings_pivot, mod_attributes_pivot,
mod_state_pivot) and a registered select that lists gameId/modId/fileId
for every installed Nexus mod file of the active profile's game.

Fixes three latent bugs in scripts/generate-query-types.ts exposed by
the first parameterless select: stale halgari.github.io extension URL
(v1.4.4 build, workspace is on v1.5.1), missing View type import, and
select rows emitted as interfaces which don't satisfy View<T>'s
Record<string, unknown> constraint. Regenerates queryTypes.ts.
@halgari halgari self-assigned this Jul 7, 2026
@halgari halgari marked this pull request as ready for review July 8, 2026 02:58
@halgari halgari requested a review from a team as a code owner July 8, 2026 02:58
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.

2 participants