- Include order_by / order_dir / group_by_meta_id in the char-index cache
key. The computed AlphaStrip positions depend on ordering and grouping,
so keying only by user reused a stale index when those changed.
- Gate the relevance-ranking test assertions to MySQL/MariaDB. Relevance
ordering uses MATCH ... AGAINST; PostgreSQL (also in the CI matrix) falls
back to name ordering, where those assertions don't hold.
- Clarify the order_by API docstring: relevance ordering applies on
MySQL/MariaDB; other databases fall back to name.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Centralize the *_no_tags / *_no_ext / *_extension columns (derived from a
file name) behind @validates hooks instead of computing them by hand at
every write site:
- Add pure helpers (compute_file_name_parts and friends) to models.base;
the filesystem base handler now delegates to them.
- Add @validates on Rom (fs_name), BaseAsset (file_name, inherited by all
asset subclasses), and Firmware (file_name).
- update_rom keeps the fs_name-derived columns in sync on bulk update(),
which also fixes the rename path never updating fs_extension.
- Drop the now-redundant computations at the scan/rename call sites.
Also fix the migration backfill loop and a pre-existing list[str | None]
type mismatch surfaced in scan_handler. Add tests for the helpers, the
validators, and the update_rom bulk-sync path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the before_insert/before_update event listener with a
@validates("name") method on Rom. The sort key is now recomputed exactly
when name is assigned (ORM construction or mutation) rather than on every
flush of any field. Bulk update() still sets it explicitly in update_rom.
Also linearize the merged 0084 migration onto 0083_rom_category_soundtrack
so there is a single alembic head.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Combine 0083_add_roms_search_indexes, 0084_add_roms_name_index, and
0085_add_roms_name_sort_key into one migration (revision 0084) off
0082_save_origin_device.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The pytest CI was failing on every vcr-marked test with:
AttributeError: module 'aiohttp.streams' has no attribute
'AsyncStreamReaderMixin'
aiohttp 3.14 (bumped in #3530) removed AsyncStreamReaderMixin, which
vcrpy's aiohttp stub referenced until 8.2.0. The lockfile still pinned
vcrpy 7.0.0 because the aiohttp bump only re-resolved aiohttp, and the
fixed vcrpy 8.2.x releases fall inside the global `exclude-newer = "7 days"`
window. Add a per-package exclude-newer override (mirroring starlette) so
the fixed release is allowed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a few new indexes to handle full-text searches instead of doing
`ILIKE` matching, improving performance substantially.
Alongside that, a few other things were done in order to improve search
performance, such as caching filter values so they're not computed on
each request to /api/roms. Overall, this should have a very noticeable
impact on large collections when using the search feature.
- Added "esbuild" version "^0.28.1" to frontend package overrides.
- Updated "exclude-newer-package" in pyproject.toml to include "vcrpy" with a date of "2026-06-17".
- Modified uv.lock to reflect the new "vcrpy" version "8.2.1" and removed platform-specific markers for dependencies.
- Added new dependencies including @one-ini/wasm and @oxc-parser bindings for various platforms in package-lock.json.
- Updated vitest to version 4.1.8 with its dependencies.
- Removed exclusion of vue-i18n from Vite's optimizeDeps configuration to improve dependency optimization.
- Updated `useGameActions` to improve navigation handling during game play.
- Modified `RMenu` to allow modifier-clicks on links to open in new tabs without closing the menu.
- Added new stories and tests for `RMenuItem` to ensure correct behavior for new-tab gestures.
- Introduced `colorCoverArt` for procedural cover-art generation, ensuring consistent styling across missing and unmatched cover images.
- Implemented SVG generation for cover art in `covers.ts`, providing unique visuals for identified and unidentified ROMs.
- Enhanced `EmulatorJS` and `Ruffle` views to support dynamic cover art based on selected styles, improving user experience during gameplay.
- Refactored cover image handling to support animations and maintain aspect ratios.
- Deleted the V2_PLAN.md file which contained the full UI overhaul plan for the RomM frontend.
- Updated vite.config.js to exclude vue-i18n from pre-bundling to fix issues with Vite 8's Rolldown dependency optimizer.
Adopt master's ROM schema design (sibling_roms + files, batched
get_files_for_roms / get_siblings_for_roms) while preserving the v2-branch
features master lacks: per-user is_main_sibling on siblings and audio_meta
on rom files.
Conflict resolution:
- responses/rom.py: keep master's sibling_roms/files fields; re-graft
is_main_sibling via SiblingRomSchema.from_rom(rom, is_main_sibling=...);
restore the eager-relationship fallback in
SimpleRomSchema.from_orm_with_request (None sentinel) so the v2
/{id}/simple endpoint still returns siblings/files.
- roms_handler.py: get_siblings_for_roms now left-joins RomUser and returns
(Rom, is_main_sibling) tuples; keep both branch and master file helpers.
- drop the redundant branch-only sibling_ids field and
get_sibling_data_for_roms.
- generated types resolved to match (sibling_roms + files; RomFileSchema
keeps audio_meta and gains archive_members).
- update v2 components and the RelatedGameCard mock to read sibling_roms.
- fix stale exclude={"siblings"} -> "sibling_roms" in scan emit payloads.
- re-chain the audio_meta migration as 0083 (after master's 0082) to keep a
single Alembic head.
- package.json: union of branch tooling + master dependency bumps; lock
regenerated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>