Installation & Setup

Migrations (SeaORM)

Bootstrapping the `migration` crate (one time only)

runique makemigrations writes .rs files into migration/src/, but creates neither the Cargo.toml nor the CLI binary that compiles them โ€” migration/ must already exist as a compilable Rust crate before the first generation.

sea-orm-cli migrate init --migration-dir migration/src

Two manual adjustments in migration/Cargo.toml after init:

  • Enable at least one runtime + one DB driver in sea-orm-migration's features โ€” the list generated by migrate init is empty (only example comments).
  • Add runique as a dependency: generated migrations reference runique::prelude::migrations_table for the eihwaz_* tables (see below).
[dependencies]
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] }
runique = { version = "3.0.0", features = ["sqlite"] }

[dependencies.sea-orm-migration]
version = "2.0.0"
features = ["runtime-tokio-rustls", "sqlx-sqlite"]

Match sqlite/sqlx-sqlite to your target engine (postgres/sqlx-postgres, mysql/sqlx-mysql) โ€” see Database.

runique makemigrations then overwrites migration/src/lib.rs and removes the placeholder migration file that sea-orm-cli migrate init created โ€” nothing else to do on that front.


Two-Step Workflow

1. Generate Migration Files

runique makemigrations reads your entities declared in src/entities and generates the corresponding migration files:

runique makemigrations --entities src/entities --migrations migration/src

What makemigrations does in a single command:

PassSourceOutput
1 โ€” App tablesmodel!{} blocks in src/entitiesCREATE TABLE / ALTER TABLE
2 โ€” Framework extensionsextend!{} blocks in src/entitiesALTER TABLE ADD/DROP COLUMN
3 โ€” Framework tablesAutomaticeihwaz_* migrations placed first in lib.rs

2. Apply Migrations

sea-orm-cli migrate up --migration-dir migration/src

Destructive Changes โ€” `--force`

Before writing anything, makemigrations detects destructive changes and refuses to generate the migration unless you pass --force:

  • DROP COLUMN (data loss)
  • a column type change
  • nullable โ†’ not null (requires a default or a backfill)
  • column length shrink (smaller max_length): longer values would be cut or refused
  • dropping a foreign key (orphan records possible)
  • adding an ON DELETE CASCADE FK on existing data (cascading deletes possible)
runique makemigrations --force

The check covers both application tables (model!{}) and framework table extensions (extend!{}).


Atomic Generation

Generation is all-or-nothing. Model and extend!{} changes are first planned in memory, validated (destructive check above), then written as a single batch. On a write error, every generated file is rolled back and the existing snapshots and lib.rs are restored to their initial state.


Foreign keys and target engine

The generated files are shared by every engine: what only concerns one engine is chosen at run time, inside the file.

  • FKs are declared in the CREATE TABLE, on every engine; referenced tables are created before the tables referencing them.
  • Cycle (two new tables referencing each other): on SQLite, which only checks a FK when rows are written, the key stays in the CREATE TABLE; on PostgreSQL / MySQL / MariaDB, the key closing the cycle is added by an ALTER TABLE once its target table exists. The choice is made at run time: the same file works on every engine.
  • Every belongs_to column gets an index idx_<table>_<column>.

Likewise, enums become a CREATE TYPE โ€ฆ AS ENUM on PostgreSQL only (a VARCHAR elsewhere): switching engines doesn't require regenerating the migrations.


Framework Tables โ€” Provided Automatically

Runique automatically injects four migrations into your lib.rs without you having to define them:

MigrationCreatesOrder
EihwazUsersMigrationeihwaz_users (id, username, email, password, is_active, is_staff, is_superuser, created_at, updated_at)1st
EihwazSessionsMigrationeihwaz_sessions (authenticated session persistence)2nd
AdminTableMigrationeihwaz_groupes, eihwaz_groupes_droits, eihwaz_users_groupes, eihwaz_history3rd
EihwazResetTokensMigrationeihwaz_reset_tokens (hashed password-reset tokens)4th

You do not need to declare eihwaz_users in your entities.


Extending a Framework Table โ€” `extend!{}`

To add columns to a framework table, use extend!{} in an entity file:

use runique::prelude::*;

extend! {
    table: "eihwaz_users",
    fields: {
        avatar: image [upload_to: "avatars/"],
        bio: textarea,
        website: url [required],
    }
}

makemigrations detects these blocks and generates the corresponding ALTER TABLE ADD COLUMN statements. The extension snapshot is stored in migration/src/snapshots/runique/eihwaz_users.rs.

Extensible tables:

eihwaz_users ยท eihwaz_groupes ยท eihwaz_sessions
eihwaz_users_groupes ยท eihwaz_groupes_droits

Extending an unknown table triggers a compile-time error.


Other Migration Commands

sea-orm-cli migrate down --migration-dir migration/src   # Revert the last migration
sea-orm-cli migrate status --migration-dir migration/src # Check migration status

runique makemigrations is the only tool to use for generating migration files. Do not use sea-orm-cli migrate generate: Runique maintains its own snapshots and chronological order.