Skip to content

feat(db): Phase 4a — Revit parameter mapping schema + migrations#86

Merged
thewrz merged 1 commit into
mainfrom
feat/issue-46
May 19, 2026
Merged

feat(db): Phase 4a — Revit parameter mapping schema + migrations#86
thewrz merged 1 commit into
mainfrom
feat/issue-46

Conversation

@thewrz
Copy link
Copy Markdown
Contributor

@thewrz thewrz commented May 19, 2026

Summary

Establishes the DB foundation for Phase 4 Revit integration. Adds migration 012_revit_parameter_mappings.ts plus the src/db/queries/revit.ts query module.

The schema reflects the design-doc reframe of the original issue (see docs/superpowers/specs/2026-05-18-issue-46-design.md):

  • Composite Revit identity(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_role is nullable; NULL = family-instance-level parameter.
  • Cross-spec fan-out — no spec_id denormalization; derive via paragraphs.spec_id FK chain. One Revit instance naturally appears on paragraphs across many specs (Div 26 + Div 27 for the data-outlet example).
  • Direction enumto_spec (default + only implemented), plus to_revit, bidirectional, spec_only reserved for feat(db): multi-Revit-model support — revit_model_id column on mappings #85. CHECK constraint blocks invalid values now.
  • Transform-type enumreplace | placeholder | append | prepend with CHECK.
  • Natural keyUNIQUE NULLS NOT DISTINCT (paragraph_id, revit_instance_id, revit_component_role, revit_param). Requires PG 15+; project runs PG 16 per docker-compose.yml. NULLS NOT DISTINCT is what makes upserts on family-instance-level rows (where component_role IS NULL) collide and update rather than duplicate.
  • 5 query functionsupsertMapping, deleteMapping, getMappingsBySpec, getMappingsByInstance, getMappingsByParagraph. All re-exported from src/db/index.ts.

ARCHITECTURE.md documents 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)

Concern Tracked by
PATCH /specs/:id/paragraphs/:nodeId endpoint that consumes mappings #47
Revit add-in (C#/.NET) scaffold that writes mappings via the REST API #48
Family-category → required MasterFormat sections registry + project preflight #82
Family-type-level mappings (revit_family_type_id) #83
Multi-Revit-model support (revit_model_id) #84
Bidirectional sync write path (to_revit / bidirectional / spec_only) #85

Table is created empty — no seed data in this PR.

Test plan

  • DATABASE_URL=... pnpm migrate — applies cleanly through 012
  • DATABASE_URL=... pnpm migrate:down — drops revit_parameter_mappings cleanly; re-pnpm migrate reapplies
  • DATABASE_URL=... pnpm lint — ESLint + tsc --noEmit + prettier check all green
  • DATABASE_URL=... pnpm test — 462 unit tests pass
  • DATABASE_URL=... pnpm test:integration — 121 integration tests pass (16 new in revit.integration.test.ts):
    • upsert defaults direction='to_spec'
    • upsert idempotent on the natural key (incl. NULL revit_component_role)
    • family-instance-level (NULL) and component-level rows remain distinct
    • getMappingsByInstance returns rows across multiple specs for one Revit instance
    • getMappingsBySpec joins through paragraphs.spec_id
    • getMappingsByParagraph returns only that paragraph's mappings
    • FK cascade: delete paragraph → mappings gone; delete spec → mappings gone (via paragraph chain)
    • CHECK constraints reject invalid direction (e.g. 'sideways') and transform_type (e.g. 'merge')
    • All four reserved direction values are accepted
  • DATABASE_URL=... pnpm build — tsc succeeds

Migration 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 main and keeps 012_*.ts unchanged.

Summary by CodeRabbit

  • New Features

    • Introduced Revit parameter mapping system enabling configuration of family instance parameters to specification paragraphs, supporting multiple synchronization directions and transformation strategies.
  • Documentation

    • Updated architecture documentation with mapping schema details and deferred implementation items.
  • Tests

    • Added integration tests covering parameter mapping operations, including CRUD functionality, upsert idempotency, cascade deletion, and constraint validation.

Review Change Stack

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
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ccbb8aab-765a-4eef-90bd-b4f3f955e85c

📥 Commits

Reviewing files that changed from the base of the PR and between 150fbbd and 9fbeb70.

📒 Files selected for processing (5)
  • ARCHITECTURE.md
  • src/db/index.ts
  • src/db/migrations/012_revit_parameter_mappings.ts
  • src/db/queries/revit.integration.test.ts
  • src/db/queries/revit.ts

📝 Walkthrough

Walkthrough

This 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 NULLS NOT DISTINCT, TypeScript type definitions and database query helpers, module re-exports, and comprehensive integration test coverage validating schema constraints, CRUD operations, and cascade behavior.

Changes

Revit Parameter Mapping Feature

Layer / File(s) Summary
Schema design and type contracts
ARCHITECTURE.md, src/db/migrations/012_revit_parameter_mappings.ts, src/db/queries/revit.ts
revit_parameter_mappings table with UUID PK, composite unique key (paragraph_id, revit_instance_id, revit_component_role, revit_param) using NULLS NOT DISTINCT for idempotent family-level upserts; direction and transform_type enums; created_at default; optional transform_config JSONB; FK to paragraphs with CASCADE delete. TypeScript exports RevitDirection, RevitTransformType, RevitMapping, and RevitMappingInput interfaces.
Query operations and module exports
src/db/queries/revit.ts, src/db/index.ts
upsertMapping performs INSERT ... ON CONFLICT DO UPDATE keyed by natural key, serializes transformConfig to JSON, defaults direction to 'to_spec', and wraps errors in DatabaseError. deleteMapping, getMappingsBySpec, getMappingsByInstance, and getMappingsByParagraph provide CRUD/read operations returning ordered RevitMapping[] results. All queries and types re-exported from src/db/index.ts.
Integration test coverage
src/db/queries/revit.integration.test.ts
Seeds specs and paragraphs, truncates mappings between tests. upsertMapping tests cover defaults, JSONB round-tripping, natural-key idempotency (including NULL component role equality and distinctness of family-level vs. component-level rows). Retrieval tests assert filtering by spec/instance/paragraph and empty-array behavior. Deletion tests verify by-id removal and no-op for unknown IDs. FK cascade tests confirm deletions propagate. Constraint tests validate enum rejection and reserved direction values.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • #83: Extends the same revit_parameter_mappings table with additional identity dimensions (revit_family_type_id) and alters the unique key constraint and query behavior.
  • #82: Depends on the mapping CRUD operations and queries (upsert/get/delete) to implement bidirectional sync orchestration and endpoint layer.
  • #85: Proposes schema extensions (e.g., revit_model_id) that directly affect the table structure, unique constraint, and query signatures introduced here.

Poem

🐇 A mapping is born in the PostgreSQL night,
Parameters dance with paragraphs so tight,
Unique keys whisper NULLS NOT DISTINCT,
Upserts and cascades forever linked,
Phase 4a—where Revit dreams take flight! 🏗️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely identifies the main change: introducing Phase 4a Revit parameter mapping schema and migrations. It accurately reflects the core deliverable.
Linked Issues check ✅ Passed All coding requirements from #46 are met: revit_parameter_mappings table created with proper schema via migrations [#46], query functions (upsertMapping, deleteMapping, getMappings variants) implemented [#46], re-exported from src/db/index.ts [#46], and ARCHITECTURE.md updated [#46].
Out of Scope Changes check ✅ Passed All changes are in-scope: migrations, query module, re-exports, tests, and ARCHITECTURE.md documentation directly support Phase 4a Revit mapping foundation. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-46

Comment @coderabbitai help to get the list of available commands and usage tips.

@thewrz thewrz merged commit 5213cd4 into main May 19, 2026
5 checks passed
@thewrz thewrz deleted the feat/issue-46 branch May 19, 2026 15:57
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.

feat(db): Phase 4a — Revit parameter mapping schema + migrations

1 participant