|
| 1 | +# VESPERTIDE KNOWLEDGE BASE |
| 2 | + |
| 3 | +**Generated:** 2026-01-07T01:39:00+09:00 |
| 4 | +**Commit:** d6c2411 |
| 5 | +**Branch:** export-with-python |
| 6 | + |
| 7 | +## OVERVIEW |
| 8 | + |
| 9 | +Rust workspace for declarative database schema management. Define schemas in JSON, diff against migration history, generate typed actions and SQL. |
| 10 | + |
| 11 | +## STRUCTURE |
| 12 | + |
| 13 | +``` |
| 14 | +vespertide/ |
| 15 | +├── crates/ |
| 16 | +│ ├── vespertide-core/ # Data structures: TableDef, ColumnDef, MigrationAction |
| 17 | +│ ├── vespertide-planner/ # Schema diffing, baseline reconstruction, validation |
| 18 | +│ ├── vespertide-query/ # SQL generation (Postgres/MySQL/SQLite) |
| 19 | +│ ├── vespertide-cli/ # CLI commands: init, diff, sql, revision, export |
| 20 | +│ ├── vespertide-exporter/ # ORM codegen: SeaORM, SQLAlchemy, SQLModel |
| 21 | +│ ├── vespertide-loader/ # Filesystem loading of models/migrations |
| 22 | +│ ├── vespertide-config/ # vespertide.json configuration |
| 23 | +│ ├── vespertide-macro/ # Compile-time migration macro |
| 24 | +│ ├── vespertide-naming/ # Naming convention utilities |
| 25 | +│ ├── vespertide-schema-gen/# JSON Schema generation |
| 26 | +│ └── vespertide/ # Re-export crate (user-facing API) |
| 27 | +├── examples/app/ # Example project with models/migrations |
| 28 | +├── schemas/ # Generated JSON Schemas for IDE support |
| 29 | +└── CLAUDE.md # Detailed implementation guidance |
| 30 | +``` |
| 31 | + |
| 32 | +## WHERE TO LOOK |
| 33 | + |
| 34 | +| Task | Location | Notes | |
| 35 | +|------|----------|-------| |
| 36 | +| Core types (TableDef, ColumnDef) | `vespertide-core/src/schema/` | Start with `table.rs`, `column.rs` | |
| 37 | +| Column type system | `vespertide-core/src/schema/column.rs` | `ColumnType::Simple/Complex` variants | |
| 38 | +| Migration actions | `vespertide-core/src/action.rs` | 12 action variants, `MigrationPlan` struct | |
| 39 | +| Schema diffing | `vespertide-planner/src/diff.rs` | **3215 lines** - topological sort for FK deps | |
| 40 | +| SQL generation | `vespertide-query/src/sql/` | One file per action type | |
| 41 | +| CLI commands | `vespertide-cli/src/commands/` | `cmd_*` functions | |
| 42 | +| ORM export | `vespertide-exporter/src/{seaorm,sqlalchemy,sqlmodel}/` | Backend-specific generators | |
| 43 | +| Compile-time macro | `vespertide-macro/src/lib.rs` | `vespertide_migration!` proc macro | |
| 44 | + |
| 45 | +## DATA FLOW |
| 46 | + |
| 47 | +``` |
| 48 | +JSON Models → load_models() → Vec<TableDef> |
| 49 | + ↓ |
| 50 | +Applied Migrations → schema_from_plans() → Baseline Schema |
| 51 | + ↓ |
| 52 | + diff_schemas() → Vec<MigrationAction> |
| 53 | + ↓ |
| 54 | + plan_next_migration() → MigrationPlan |
| 55 | + ↓ |
| 56 | + build_action_queries() → Vec<BuiltQuery> |
| 57 | + ↓ |
| 58 | + BuiltQuery.build(backend) → SQL String |
| 59 | +``` |
| 60 | + |
| 61 | +## CONVENTIONS |
| 62 | + |
| 63 | +### ColumnType Usage (CRITICAL) |
| 64 | +```rust |
| 65 | +// CORRECT - Always use wrapped variant |
| 66 | +ColumnType::Simple(SimpleColumnType::Integer) |
| 67 | +SimpleColumnType::Integer.into() |
| 68 | + |
| 69 | +// WRONG - Old flat syntax |
| 70 | +ColumnType::Integer // Does not exist |
| 71 | +``` |
| 72 | + |
| 73 | +### ColumnDef Initialization |
| 74 | +ALL fields required including inline constraint fields: |
| 75 | +```rust |
| 76 | +ColumnDef { |
| 77 | + name, r#type, nullable, default, comment, |
| 78 | + primary_key: None, // Must include |
| 79 | + unique: None, // Must include |
| 80 | + index: None, // Must include |
| 81 | + foreign_key: None, // Must include |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +### Naming |
| 86 | +- Indexes: `ix_{table}__{columns}` or `ix_{table}__{name}` |
| 87 | +- Unique: `uq_{table}__{columns}` |
| 88 | +- Foreign keys: `fk_{table}__{columns}` |
| 89 | + |
| 90 | +## ANTI-PATTERNS |
| 91 | + |
| 92 | +| Pattern | Why Bad | |
| 93 | +|---------|---------| |
| 94 | +| `ColumnType::Integer` | Use `ColumnType::Simple(SimpleColumnType::Integer)` | |
| 95 | +| Forgetting inline fields in ColumnDef | Will cause compile errors - 4 Option fields required | |
| 96 | +| Raw SQL in migrations | Use typed `MigrationAction` enums | |
| 97 | +| Skipping `normalize()` on TableDef | Inline constraints won't convert to table-level | |
| 98 | +| Assuming YAML works | YAML loading NOT implemented (templates only) | |
| 99 | + |
| 100 | +## COMMANDS |
| 101 | + |
| 102 | +```bash |
| 103 | +# Build/Test |
| 104 | +cargo build |
| 105 | +cargo test |
| 106 | +cargo clippy --all-targets --all-features |
| 107 | +cargo fmt |
| 108 | + |
| 109 | +# CLI (always use -p vespertide-cli) |
| 110 | +cargo run -p vespertide-cli -- init |
| 111 | +cargo run -p vespertide-cli -- new <model> |
| 112 | +cargo run -p vespertide-cli -- diff |
| 113 | +cargo run -p vespertide-cli -- sql |
| 114 | +cargo run -p vespertide-cli -- revision -m "message" |
| 115 | +cargo run -p vespertide-cli -- export --orm seaorm |
| 116 | + |
| 117 | +# Regenerate JSON schemas |
| 118 | +cargo run -p vespertide-schema-gen -- --out schemas |
| 119 | + |
| 120 | +# Snapshot testing |
| 121 | +cargo insta test -p vespertide-exporter |
| 122 | +cargo insta accept |
| 123 | +``` |
| 124 | + |
| 125 | +## COMPLEXITY HOTSPOTS |
| 126 | + |
| 127 | +| File | Lines | What | |
| 128 | +|------|-------|------| |
| 129 | +| `planner/src/diff.rs` | 3215 | Schema diffing with topological FK sort | |
| 130 | +| `exporter/src/seaorm/mod.rs` | 2961 | SeaORM codegen with relation inference | |
| 131 | +| `planner/src/validate.rs` | 1821 | Schema/migration validation | |
| 132 | +| `core/src/schema/table.rs` | 1582 | Table normalization logic | |
| 133 | +| `query/src/sql/remove_constraint.rs` | 1581 | SQLite temp table workarounds | |
| 134 | + |
| 135 | +## TESTING |
| 136 | + |
| 137 | +- `rstest` for parameterized tests |
| 138 | +- `serial_test::serial` for filesystem tests |
| 139 | +- `insta` for snapshot testing (exporter crate) |
| 140 | +- Helper functions: `col()`, `table()` reduce boilerplate |
| 141 | +- ~1289 tests across 53 files |
| 142 | + |
| 143 | +## DATABASE BACKENDS |
| 144 | + |
| 145 | +| Backend | Identifier Quoting | Notes | |
| 146 | +|---------|-------------------|-------| |
| 147 | +| PostgreSQL | `"identifier"` | Full feature support | |
| 148 | +| MySQL | `` `identifier` `` | Full feature support | |
| 149 | +| SQLite | `"identifier"` | Temp table workarounds for ALTER | |
| 150 | + |
| 151 | +## NOTES |
| 152 | + |
| 153 | +- Edition 2024 (bleeding edge) |
| 154 | +- No LSP available - use grep/AST tools |
| 155 | +- YAML loading not implemented |
| 156 | +- Migration replay pattern: baseline always reconstructed from history |
0 commit comments