view --main vespertide-skill-dlya-json-shem-i-migratsiy-bd.md
Vespertide: Скилл для JSON-схем и миграций БД
readonly
--- lines
---
name: vespertide
description: Define database schemas in JSON and generate migration plans. Use this skill when creating or modifying database models, defining tables with columns, constraints, and ENUM types for Vespertide-based projects.
---
# Vespertide Database Schema Definition
Declarative database schema management. Define tables in JSON, generate typed migrations and SQL.
## Schema Validation (MANDATORY)
Every model file MUST include `$schema`. Before saving: ensure no IDE validation errors, then run `vespertide diff`.
```json
{
"$schema": "https://raw.githubusercontent.com/dev-five-git/vespertide/refs/heads/main/schemas/model.schema.json",
"name": "table_name",
"columns": []
}
```
## Post-Edit Validation (MANDATORY)
After EVERY model edit, run:
```bash
vespertide diff # Check for parsing errors and expected changes
vespertide sql # Preview generated SQL for correctness
```
Only proceed to `vespertide revision` after both pass cleanly.
---
## Installation
```bash
cargo install vespertide-cli
```
## CLI Commands
| Command | Description |
|---------|-------------|
| `vespertide init` | Initialize `vespertide.json` with defaults |
| `vespertide new <name>` | Create model template with `$schema` |
| `vespertide new <name> -f yaml` | Create model in specific format (`json`/`yaml`/`yml`) |
| `vespertide diff` | Show pending changes between migrations and models |
| `vespertide sql` | Preview SQL for next migration (default: postgres) |
| `vespertide sql -b mysql` | SQL for specific backend (`postgres`/`mysql`/`sqlite`) |
| `vespertide log` | Show SQL per applied migration |
| `vespertide log -b mysql` | Migration log for specific backend |
| `vespertide status` | Show config and sync overview |
| `vespertide revision -m "msg"` | Create migration file |
| `vespertide revision -m "msg" --fill-with table.col=value` | Create migration with fill values (repeatable) |
| `vespertide export --orm seaorm` | Export to ORM code (`seaorm`/`sqlalchemy`/`sqlmodel`) |
| `vespertide export --orm seaorm -d out/` | Export to custom directory |
---
## Configuration (`vespertide.json`)
```json
{
"modelsDir": "models",
"migrationsDir": "migrations",
"tableNamingCase": "snake",
"columnNamingCase": "snake",
"modelFormat": "json",
"migrationFormat": "json",
"migrationFilenamePattern": "%04v_%m",
"modelExportDir": "src/models",
"prefix": "",
"seaorm": {
"extraEnumDerives": ["vespera::Schema"],
"extraModelDerives": [],
"enumNamingCase": "camel",
"vesperaSchemaType": true
}
}
```
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `modelsDir` | string | `"models"` | Model JSON files directory |
| `migrationsDir` | string | `"migrations"` | Migration files directory |
| `tableNamingCase` | string | `"snake"` | `snake` / `camel` / `pascal` |
| `columnNamingCase` | string | `"snake"` | `snake` / `camel` / `pascal` |
| `modelFormat` | string | `"json"` | `json` / `yaml` / `yml` |
| `migrationFormat` | string | `"json"` | `json` / `yaml` / `yml` |
| `migrationFilenamePattern` | string | `"%04v_%m"` | `%v`=version, `%m`=message |
| `modelExportDir` | string | `"src/models"` | ORM export output directory |
| `prefix` | string | `""` | Prefix for all table names |
**SeaORM Config** (`seaorm` nested object):
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `extraEnumDerives` | string[] | `["vespera::Schema"]` | Extra derives for generated enums |
| `extraModelDerives` | string[] | `[]` | Extra derives for entity models |
| `enumNamingCase` | string | `"camel"` | Serde `rename_all` for enums |
| `vesperaSchemaType` | bool | `true` | Generate `vespera::schema_type!` calls |
---
## Exported ORM Files (DO NOT EDIT)
> **CRITICAL**: Files in `src/models/` (e.g. `src/models/*.rs`, `src/models/*.py`) are AUTO-GENERATED by `vespertide export`. **NEVER manually create or edit these files.** Always edit source models in `models/*.json`, then regenerate:
```bash
# Edit models/*.json -> regenerate
vespertide export --orm seaorm
```
## Migration / Revision Files (DO NOT EDIT)
> **CRITICAL**: Migration files in the `migrations/` directory are AUTO-GENERATED by `vespertide revision`. **NEVER manually create, edit, or modify revision files.** Always edit source models in `models/*.json`, then create a new revision:
```bash
# Edit models/*.json -> create revision
vespertide revision -m "describe your change"
```
**Only exception**: Adding `fill_with` values when prompted (NOT NULL columns without defaults).
```json
{
"type": "add_column",
"table": "user",
"column": {
"name": "status",
"type": "text",
"nullable": false
},
"fill_with": "'active'"
}
```
---
## Model Structure
```json
{
"$schema": "https://raw.githubusercontent.com/dev-five-git/vespertide/refs/heads/main/schemas/model.schema.json",
"name": "table_name",
"description": "Optional table description",
"columns": [ /* ColumnDef[] */ ],
"constraints": [ /* Optional: CHECK constraints only */ ]
}
```
| Field | Required | Type | Description |
|-------|----------|------|-------------|
| `name` | yes | string | Table name (snake_case) |
| `columns` | yes | array | Column definitions |
| `description` | no | string | Table documentation |
| `constraints` | no | array | Table-level constraints (CHECK only) |
---
## Column Definition
### Required Fields
```json
{ "name": "column_name", "type": "ColumnType", "nullable": false }
```
### Optional Fields
| Field | Type | Description |
|-------|------|-------------|
| `default` | string | boolean | number | Default value |
| `comment` | string | Column documentation |
| `primary_key` | boolean | object | Inline primary key |
| `unique` | boolean | string | string[] | Inline unique constraint |
| `index` | boolean | string | string[] | Inline index |
| `foreign_key` | string | object | Inline foreign key |
---
## Column Types
### Simple Types (string values)
| Type | SQL | Type | SQL |
|------|-----|------|-----|
| `"small_int"` | SMALLINT | `"text"` | TEXT |
| `"integer"` | INTEGER | `"boolean"` | BOOLEAN |
| `"big_int"` | BIGINT | `"uuid"` | UUID |
| `"real"` | REAL | `"json"` | JSON |
| `"double_precision"` | DOUBLE PRECISION | `"bytea"` | BYTEA |
| `"date"` | DATE | `"inet"` | INET |
| `"time"` | TIME | `"cidr"` | CIDR |
| `"timestamp"` | TIMESTAMP | `"macaddr"` | MACADDR |
| `"timestamptz"` | TIMESTAMPTZ | `"xml"` | XML |
| `"interval"` | INTERVAL | | |
### Complex Types (object values)
```json
{ "kind": "varchar", "length": 255 }
{ "kind": "char", "length": 2 }
{ "kind": "numeric", "precision": 10, "scale": 2 }
{ "kind": "enum", "name": "...", "values": [...] }
{ "kind": "custom", "custom_type": "..." }
```
### Enum Types (RECOMMENDED for status/category fields)
**String Enum** (PostgreSQL native enum):
```json
{
"name": "status",
"type": {
"kind": "enum",
"name": "article_status",
"values": ["draft", "review", "published", "archived"]
},
"nullable": false,
"default": "'draft'"
}
```
**Integer Enum** (stored as INTEGER -- no DB migration needed for new values):
```json
{
"name": "role",
"type": {
"kind": "enum",
"name": "user_role",
"values": [
{ "name": "guest", "value": 0 },
{ "name": "user", "value": 10 },
{ "name": "moderator", "value": 50 },
{ "name": "admin", "value": 100 }
]
},
"nullable": false,
"default": 0
}
```
> **Tip**: Leave gaps in integer values (0, 10, 50, 100) to allow inserting new values without renumbering.
| Scenario | Recommended Type |
|----------|------------------|
| Status fields (order_status, user_status) | String or Integer enum |
| Categories with fixed values | String enum |
| Priority/severity levels | Integer enum |
| Roles with potential expansion | Integer enum |
---
## Inline Constraints (PREFERRED)
> Always define constraints on columns. Use table-level `constraints` ONLY for CHECK expressions.
### Primary Key
```json
{ "name": "id", "type": "integer", "nullable": false, "primary_key": true }
{ "name": "id", "type": "integer", "nullable": false, "primary_key": { "auto_increment": true } }
```
### Unique
```json
{ "name": "email", "type": "text", "nullable": false, "unique": true }
```
Named composite unique:
```json
{ "name": "tenant_id", "type": "integer", "nullable": false, "unique": ["uq_tenant_user"] },
{ "name": "username", "type": "text", "nullable": false, "unique": ["uq_tenant_user"] }
```
### Index
```json
{ "name": "email", "type": "text", "nullable": false, "index": true }
```
Composite index:
```json
{ "name": "user_id", "type": "integer", "nullable": false, "index": ["idx_user_created"] },
{ "name": "created_at", "type": "timestamptz", "nullable": false, "index": ["idx_user_created"] }
```
### Foreign Key
Object syntax (recommended):
```json
{
"name": "user_id",
"type": "integer",
"nullable": false,
"foreign_key": {
"ref_table": "user",
"ref_columns": ["id"],
"on_delete": "cascade",
"on_update": null
},
"index": true
}
```
Shorthand syntax:
```json
{ "name": "user_id", "type": "integer", "nullable": false, "foreign_key": "user.id", "index": true }
```
**Reference Actions** (snake_case): `"cascade"`, `"restrict"`, `"set_null"`, `"set_default"`, `"no_action"`
> Always add `"index": true` on foreign key columns for query performance.
### Composite Primary Key (Inline)
Both columns with `"primary_key": true` create a single composite primary key:
```json
{
"columns": [
{ "name": "user_id", "type": "integer", "nullable": false, "primary_key": true },
{ "name": "role_id", "type": "integer", "nullable": false, "primary_key": true }
]
}
```
---
## Table-Level Constraints (CHECK only)
> Use inline constraints for everything else (PK, unique, index, FK).
```json
"constraints": [
{ "type": "check", "name": "check_positive_amount", "expr": "amount > 0" },
{ "type": "check", "name": "check_dates", "expr": "end_date > start_date" }
]
```
---
## Default Values
| Type | Example | Notes |
|------|---------|-------|
| String literal | `"'pending'"` | Single quotes inside string |
| Boolean | `true` / `false` | Native JSON boolean |
| Integer | `0` | Native JSON number |
| Float | `0.0` | Native JSON number |
| SQL function | `"NOW()"` | No quotes around function |
| UUID generation | `"gen_random_uuid()"` | PostgreSQL |
---
## Runtime Migration Macro
Use `vespertide_migration!` to run migrations at application startup:
```toml
[dependencies]
vespertide = "0.1"
sea-orm = { version = "2.0.0-rc", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] }
```
```rust
use sea_orm::Database;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let db = Database::connect("postgres://user:pass@localhost/mydb").await?;
vespertide::vespertide_migration!(db).await?;
Ok(())
}
```
The macro generates database-specific SQL at compile time for zero-runtime overhead.
---
## Complete Examples
### User Table with Enum Status
```json
{
"$schema": "https://raw.githubusercontent.com/dev-five-git/vespertide/refs/heads/main/schemas/model.schema.json",
"name": "user",
"columns": [
{ "name": "id", "type": "integer", "nullable": false, "primary_key": { "auto_increment": true } },
{ "name": "email", "type": "text", "nullable": false, "unique": true, "index": true },
{ "name": "name", "type": { "kind": "varchar", "length": 100 }, "nullable": false },
{
"name": "status",
"type": { "kind": "enum", "name": "user_status", "values": ["pending", "active", "suspended", "deleted"] },
"nullable": false,
"default": "'pending'"
},
{ "name": "metadata", "type": "json", "nullable": true },
{ "name": "created_at", "type": "timestamptz", "nullable": false, "default": "NOW()" },
{ "name": "updated_at", "type": "timestamptz", "nullable": true }
]
}
```
### Order Table with Integer Enum and CHECK
```json
{
"$schema": "https://raw.githubusercontent.com/dev-five-git/vespertide/refs/heads/main/schemas/model.schema.json",
"name": "order",
"columns": [
{ "name": "id", "type": "uuid", "nullable": false, "primary_key": true, "default": "gen_random_uuid()" },
{
"name": "customer_id",
"type": "integer",
"nullable": false,
"foreign_key": { "ref_table": "customer", "ref_columns": ["id"], "on_delete": "restrict" },
"index": true
},
{ "name": "total", "type": { "kind": "numeric", "precision": 10, "scale": 2 }, "nullable": false },
{
"name": "priority",
"type": {
"kind": "enum",
"name": "order_priority",
"values": [
{ "name": "low", "value": 0 },
{ "name": "normal", "value": 10 },
{ "name": "high", "value": 20 },
{ "name": "urgent", "value": 30 }
]
},
"nullable": false,
"default": 10
},
{
"name": "status",
"type": { "kind": "enum", "name": "order_status", "values": ["pending", "confirmed", "shipped", "delivered", "cancelled"] },
"nullable": false,
"default": "'pending'"
},
{ "name": "notes", "type": "text", "nullable": true },
{ "name": "created_at", "type": "timestamptz", "nullable": false, "default": "NOW()" }
],
"constraints": [
{ "type": "check", "name": "check_total_positive", "expr": "total >= 0" }
]
}
```
### Many-to-Many Join Table
```json
{
"$schema": "https://raw.githubusercontent.com/dev-five-git/vespertide/refs/heads/main/schemas/model.schema.json",
"name": "user_role",
"columns": [
{
"name": "user_id",
"type": "integer",
"nullable": false,
"primary_key": true,
"foreign_key": { "ref_table": "user", "ref_columns": ["id"], "on_delete": "cascade" }
},
{
"name": "role_id",
"type": "integer",
"nullable": false,
"primary_key": true,
"foreign_key": { "ref_table": "role", "ref_columns": ["id"], "on_delete": "cascade" },
"index": true
},
{ "name": "granted_at", "type": "timestamptz", "nullable": false, "default": "NOW()" },
{ "name": "granted_by", "type": "integer", "nullable": true, "foreign_key": "user.id" }
]
}
```
---
## Workflow Summary
```bash
# 1. Create model
vespertide new user
# 2. Edit models/user.json
# 3. Validate
vespertide diff # Check changes
vespertide sql # Preview SQL
# 4. Create migration
vespertide revision -m "create user table"
# 5. Export ORM code (if needed)
vespertide export --orm seaorm
```
---
## Guidelines Summary
### MUST DO
1. Always include `$schema` in every model file
2. Always specify `nullable` on every column
3. Run `vespertide diff` + `vespertide sql` after every model edit
4. Index foreign key columns (`"index": true`)
5. Use inline constraints (`primary_key`, `unique`, `index`, `foreign_key` on columns)
### SHOULD DO
1. Use enums for status/category fields (prefer over text + CHECK)
2. Use integer enums for expandable value sets (no migration needed)
3. Use `timestamptz` over `timestamp` (timezone-aware)
4. Use `json` type for JSON data (cross-backend compatible)
### MUST NOT DO
1. **Manually create/edit/modify revision (migration) files** -- use `vespertide revision` only
2. **Manually create/edit `src/models/*.rs` (or `*.py`) files** -- use `vespertide export` to regenerate
3. Use PascalCase for reference actions -- use `"cascade"` not `"Cascade"`
4. Skip schema validation
5. Add NOT NULL columns without `default` or `fill_with`
6. Use table-level constraints for anything except CHECK
7. Use `jsonb` type -- use `json` instead (not supported cross-backend)
8. Use `custom` types -- breaks cross-database compatibility
9. Use array types -- use a join table instead
---
## Naming Conventions
| Item | Convention | Example |
|------|------------|---------|
| Tables | snake_case | `user_role` |
| Columns | snake_case | `created_at` |
| Indexes | `ix_{table}__{columns}` | `ix_user__email` |
| Unique | `uq_{table}__{columns}` | `uq_user__email` |
| Foreign Key | `fk_{table}__{columns}` | `fk_post__author_id` |
| Check | `check_{description}` | `check_positive_amount` |
| Enums | snake_case | `order_status` |
> **Note**: Auto-generated constraint names use double underscore `__` as separator.
---
## Quick Reference
```
SIMPLE TYPES COMPLEX TYPES
---------------------------------------- ----------------------------------------
integer, big_int, small_int Numbers { "kind": "varchar", "length": N }
real, double_precision Floats { "kind": "char", "length": N }
text Strings { "kind": "numeric", "precision": P, "scale": S }
boolean Flags { "kind": "enum", "name": "...", "values": [...] }
date, time, timestamp Time { "kind": "custom", "custom_type": "..." }
timestamptz, interval Time+
uuid UUIDs REFERENCE ACTIONS (snake_case!)
json JSON ----------------------------------------
bytea Binary cascade, restrict, set_null,
inet, cidr, macaddr Network set_default, no_action
xml XML
CONSTRAINT TYPES (inline preferred) DATABASE BACKENDS
---------------------------------------- ----------------------------------------
primary_key, unique, index, postgres (default), mysql, sqlite
foreign_key, check
```
---
## Troubleshooting
| Error | Cause | Fix |
|-------|-------|-----|
| Invalid enum in `on_delete` | PascalCase used | Use `"cascade"` not `"Cascade"` |
| Missing required property | `nullable` omitted | Add `"nullable": true/false` |
| Unknown column type | Typo in type name | Check column types table above |
| FK validation failed | Referenced table missing | Create referenced table first |
| NOT NULL without default | Adding column to existing table | Add `default` or use `fill_with` in revision |
Инициализация мануала...
//
$ ls -R related_skills/
2026-03-30
⭐ 3588
surreal-sync — Синхронизация и резервное копирование данных в SurrealDB
2026-04-09
⭐ 31
cloud-sql-postgres-data: Скилл для работы с данными
2026-04-11
⭐ 113
database-engineering: Скилл для проектирования и оптимизации БД
2026-04-09
⭐ 57
database-query-expert: Скилл для запросов к базе данных
package.json
$ install --global
skills.sh
npx skills add https://github.com/dev-five-git/vespertide/tree/main
$ download --local
man
[HINT] Скачивает всю директорию скилла с GitHub: SKILL.md и все связанные файлы