Split the database schema file into a folder of focused files - #1720
Conversation
…ionally unfixed)
Split the 1626-line src/shared/db/migrations/schema.ts into a schema/ folder
of focused files (each under 400 lines) so it passes the 1000-line ceiling:
schema/types.ts — Column, Index, Table, Trigger types
schema/version.ts — LATEST_UPDATE, SCHEMA_MIGRATIONS_TABLE
schema/tables-core.ts — settings, auth, listings, assets, rate limits
schema/tables-attendees.ts — attendees, bookings, payments, activity
schema/tables-catalog.ts — groups, modifiers, listing hierarchy
schema/tables-questions.ts — questions, answers, attributes, built sites
schema/tables-content.ts — ledger, comms, pages, contacts, cache
schema/listing-aggregates.ts — pure ticket-count predicates/expressions
schema/triggers.ts — aggregate trigger arrays + TRIGGERS
schema/index.ts — assembles ordered SCHEMA, computes SCHEMA_HASH
Table order is preserved byte-for-byte (contiguous chunks concatenated in FK
order), so SCHEMA_HASH stays "n2axyb" — the schema-change guard is untouched.
All 12 callers migrated to import each symbol from its new home; the biome
noExcessiveLinesPerFile override for schema.ts is removed.
NOT GREEN on cpd (committed --no-verify): `deno task cpd` reports 2 clones
(0.01%) that the split surfaced from the old monolith (jscpd could not fully
scan the 1626-line file). Per instructions these are left unfixed for review:
1. tables-content.ts:181 (site_pages cols) vs tables-catalog.ts:7 (groups cols)
— both start id/slug/slug_index/name/...
2. tables-content.ts:243 (site_page_items cols) vs tables-core.ts:209 (image_uses cols)
— both share item_type/item_id/sort_order link columns
deno check src/shared/db (+ test files) and biome lint:ci both pass.
…pers The schema split exposed two duplicated column sequences that jscpd could not see inside the 1626-line monolith. Both are now shared const arrays in schema/columns.ts, spread into each table's columns — one definition, no drift: - slugNamedEntityColumns (id/slug/slug_index/name) — shared by groups and site_pages, both slug-addressed named entities. - itemLinkColumns (item_type/item_id/sort_order) — shared by image_uses and site_page_items, both ordered link tables keyed by a polymorphic item ref. SCHEMA_HASH unchanged (n2axyb): spreading a const array produces the same runtime columns array, so JSON.stringify — and the hash — are identical. deno task cpd: 0 clones (src + test). deno check: pass. biome lint: pass.
|
Warning Review limit reached
Next review available in: 4 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThe database migration schema is split from one module into typed, domain-specific table, trigger, aggregate, version, and assembly modules. Runtime imports, migration exports, tests, and Biome configuration are updated to reference the new module paths. ChangesDatabase schema modularization
Estimated code review effort: 4 (Complex) | ~45 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
# Conflicts: # biome.json # test/lib/servicing/listing-aggregates.test.ts
# Conflicts: # biome.json
# Conflicts: # src/shared/db/attendees/delete.ts
What changed
The database schema lived in one file,
src/shared/db/migrations/schema.ts, that had grown to 1626 lines. Almost all of it was a single giant list of table definitions, with trigger definitions, types, and a hash function bolted on at the end. It was the only file in the project that had to be exempted from our own 1000-line-file limit.This PR splits that one big file into 11 small files in a
schema/folder, each under 400 lines, grouped by what they hold:Why
A 1626-line file is hard to navigate and hard to review. Splitting it into focused files means a future change to, say, the attendee tables only touches one small file, and you can tell from the filename which file to open. The project requires files to stay under 400 lines, and the 1000-line ceiling this file was breaking was only suppressible via an override in the linter config.
How it stays safe
The order of the tables in the schema list matters — it's used to compute a hash (
SCHEMA_HASH) that detects when the schema has changed and a migration needs to run. The split preserves that order byte-for-byte: the table definitions are sliced into contiguous chunks and concatenated back in the same order, so the hash is unchanged (n2axyb). All 12 places in the codebase that imported from the old file now import from the right small file instead.Fixing the duplication the split exposed
Our duplication checker (jscpd) runs at a strict 0% threshold. It could not fully scan the old 1626-line file, so two duplicated column sequences were quietly hiding inside it. Once the file was split, those duplicates became visible:
groupsandsite_pagestables both start with the same four columns (id,slug,slug_index,name).image_usesandsite_page_itemstables both share the same three columns (item_type,item_id,sort_order).Both are now shared reusable lists in
columns.ts, spread into each table's column list — one definition instead of two copies that can drift apart.Cleanup
schema.tsentry from thenoExcessiveLinesPerFileoverride inbiome.json(the file no longer exists, so the exemption is no longer needed).schema.tsby name were updated to point at the new file that holds the relevant declaration.Checks
All green:
deno check src/shared/db/migrations) — passesbiome check --error-on-warnings) — passesdeno task cpd) — 0 clones, in both source and testn2axyb), so no spurious migration is triggeredSummary by CodeRabbit