feat(db): Phase 4a — Revit parameter mapping schema + migrations#86
Conversation
Add migration 012 + src/db/queries/revit.ts establishing the DB foundation for Revit add-in writes (#48) and the upcoming paragraph PATCH endpoint (#47). Schema reflects the design-doc reframe of #46: composite Revit identity (instance_id + nullable component_role + param) so one family instance can fan out to many paragraphs across many specs, a direction enum reserving four edge semantics (only to_spec implemented today), a transform_type enum with CHECK, and UNIQUE NULLS NOT DISTINCT (PG 15+) so family-instance- level rows collide correctly on idempotent upsert. spec_id intentionally not denormalized — derived via paragraphs.spec_id. Query module exposes upsert/delete + getBySpec/ByInstance/ByParagraph with DatabaseError context chains. ARCHITECTURE.md documents the table, the composite identity rationale, the direction enum, and points to #82–#85 as the deferred Phase 4 work that builds on this schema. Closes #46
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis pull request implements the Phase 4a database foundation for Revit parameter-to-paragraph mapping. It adds a new PostgreSQL table with idempotent upsert semantics via composite unique keys with ChangesRevit Parameter Mapping Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Summary
Establishes the DB foundation for Phase 4 Revit integration. Adds migration
012_revit_parameter_mappings.tsplus thesrc/db/queries/revit.tsquery module.The schema reflects the design-doc reframe of the original issue (see
docs/superpowers/specs/2026-05-18-issue-46-design.md):(revit_instance_id, revit_component_role, revit_param)so one family instance (e.g. "Data Outlet A") can fan out to many paragraphs.revit_component_roleis nullable;NULL= family-instance-level parameter.spec_iddenormalization; derive viaparagraphs.spec_idFK chain. One Revit instance naturally appears on paragraphs across many specs (Div 26 + Div 27 for the data-outlet example).to_spec(default + only implemented), plusto_revit,bidirectional,spec_onlyreserved for feat(db): multi-Revit-model support — revit_model_id column on mappings #85.CHECKconstraint blocks invalid values now.replace | placeholder | append | prependwithCHECK.UNIQUE NULLS NOT DISTINCT (paragraph_id, revit_instance_id, revit_component_role, revit_param). Requires PG 15+; project runs PG 16 perdocker-compose.yml.NULLS NOT DISTINCTis what makes upserts on family-instance-level rows (wherecomponent_role IS NULL) collide and update rather than duplicate.upsertMapping,deleteMapping,getMappingsBySpec,getMappingsByInstance,getMappingsByParagraph. All re-exported fromsrc/db/index.ts.ARCHITECTURE.mddocuments the table, the composite identity rationale, the direction enum, and points to follow-up issues.Closes #46.
Out of scope (deferred to follow-up issues)
PATCH /specs/:id/paragraphs/:nodeIdendpoint that consumes mappingsrevit_family_type_id)revit_model_id)to_revit/bidirectional/spec_only)Table is created empty — no seed data in this PR.
Test plan
DATABASE_URL=... pnpm migrate— applies cleanly through 012DATABASE_URL=... pnpm migrate:down— dropsrevit_parameter_mappingscleanly; re-pnpm migratereappliesDATABASE_URL=... pnpm lint— ESLint + tsc --noEmit + prettier check all greenDATABASE_URL=... pnpm test— 462 unit tests passDATABASE_URL=... pnpm test:integration— 121 integration tests pass (16 new inrevit.integration.test.ts):direction='to_spec'NULLrevit_component_role)NULL) and component-level rows remain distinctgetMappingsByInstancereturns rows across multiple specs for one Revit instancegetMappingsBySpecjoins throughparagraphs.spec_idgetMappingsByParagraphreturns only that paragraph's mappingsdirection(e.g.'sideways') andtransform_type(e.g.'merge')directionvalues are acceptedDATABASE_URL=... pnpm build— tsc succeedsMigration coordination note
Migration number 012 was reserved for this PR while #30 is taking 010 + 011 in parallel. If #30 merges first, this PR rebases on
mainand keeps012_*.tsunchanged.Summary by CodeRabbit
New Features
Documentation
Tests