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 = "2.2.0", features = ["orm", "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 — Admin positioningRUNIQUE_USER_TABLE in .envGuaranteed order 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
  • nullablenot null (requires a default or a backfill)
  • 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

makemigrations detects the engine (via DB_URL/DATABASE_URL/DB_ENGINE) and adapts FK generation:

  • PostgreSQL / MySQL / MariaDB: all FK constraints are grouped into a …_create_relations migration applied after the tables are created (ALTER TABLE … ADD CONSTRAINT).
  • SQLite: does not support adding FKs to an existing table. FKs are therefore declared inline in the CREATE TABLE, and no create_relations migration is generated.

As a result, migration files are specific to the engine they were generated for. To switch engines, regenerate the migrations (from scratch) with the target DB_ENGINE.


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.


Using a Custom User Table

If you prefer to manage your own user table, declare it in .env:

RUNIQUE_USER_TABLE=my_users_table

makemigrations will then position AdminTableMigration right after the migration for my_users_table. The FK in eihwaz_users_groupes will automatically target my_users_table.

Default (no RUNIQUE_USER_TABLE): eihwaz_users is used.


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 Wrapper — Atomic Rollback (advanced)

runique migration down --migrations migration/src --files <file> [<file2> ...]
runique migration down --migrations migration/src --batch <timestamp>
runique migration status --migrations migration/src

Without --files or --batch, the command just lists available migrations without rolling anything back.

These commands use the Runique batch system with transactional rollback. Prefer sea-orm-cli for the normal workflow.


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.