turso_orm_migration/lib.rs
1//! Migration: versioned schema migrations for turso-orm.
2//!
3//! A migration is a type implementing [`MigrationTrait`] (with `up` and
4//! `down`) and [`MigrationName`] (derived with [`DeriveMigrationName`] from
5//! the module name). A [`MigratorTrait`] lists the migrations in order and
6//! applies them through a [`SchemaManager`], which wraps the transaction a
7//! migration runs in and offers DDL helpers and catalog lookups.
8//!
9//! The crate owns the bookkeeping — which migrations have been applied, in
10//! which order — and the transactional envelope around each one. It does not
11//! own DDL rendering (that is `turso_sql`, re-exported through the prelude)
12//! nor the connection (that is `turso_orm`).
13//!
14//! # Design decisions
15//!
16//! - Each migration runs together with its bookkeeping insert inside one
17//! `BEGIN IMMEDIATE` transaction, so a failing migration leaves neither a
18//! partial schema nor a stale version row behind.
19//! - Versions are the migration names, taken from the module path, so that
20//! every migration struct can simply be called `Migration` and the file
21//! name is the single source of truth for ordering.
22//! - `down` defaults to failing with [`DbErr::Migration`], so a migration
23//! that cannot be reverted says so instead of silently doing nothing.
24//!
25//! # Example
26//!
27//! ```ignore
28//! use turso_orm_migration::prelude::*;
29//!
30//! mod m20240101_000001_create_user {
31//! use turso_orm_migration::prelude::*;
32//!
33//! #[derive(DeriveMigrationName)]
34//! pub struct Migration;
35//!
36//! #[async_trait]
37//! impl MigrationTrait for Migration {
38//! async fn up(&self, manager: &SchemaManager<'_>) -> Result<(), DbErr> {
39//! manager
40//! .create_table(
41//! Table::create()
42//! .table("user")
43//! .col(ColumnDef::integer("id").primary_key().auto_increment())
44//! .col(ColumnDef::text("email").not_null().unique_key()),
45//! )
46//! .await
47//! }
48//!
49//! async fn down(&self, manager: &SchemaManager<'_>) -> Result<(), DbErr> {
50//! manager.drop_table(Table::drop().table("user")).await
51//! }
52//! }
53//! }
54//!
55//! pub struct Migrator;
56//!
57//! #[async_trait]
58//! impl MigratorTrait for Migrator {
59//! fn migrations() -> Vec<Box<dyn MigrationTrait>> {
60//! vec![Box::new(m20240101_000001_create_user::Migration)]
61//! }
62//! }
63//! ```
64
65#![cfg_attr(docsrs, feature(doc_cfg))]
66
67mod manager;
68mod migrator;
69
70pub use manager::SchemaManager;
71pub use migrator::{MigrationIssue, MigrationStatus, MigratorTrait};
72
73pub use async_trait::async_trait;
74pub use turso_orm;
75pub use turso_orm::DbErr;
76pub use turso_orm_macros::DeriveMigrationName;
77
78/// The name of a migration, used as its version key in the bookkeeping table.
79pub trait MigrationName {
80 /// The name, which must be unique across the migrator.
81 fn name(&self) -> &str;
82}
83
84/// A migration: a reversible schema change.
85#[async_trait]
86pub trait MigrationTrait: MigrationName + Send + Sync {
87 /// Applies the migration inside the transaction `manager` wraps.
88 ///
89 /// # Errors
90 ///
91 /// Returns [`DbErr::Driver`] when a statement fails; implementations may
92 /// return any other variant to abort, and the transaction is rolled back.
93 async fn up(&self, manager: &SchemaManager<'_>) -> Result<(), DbErr>;
94
95 /// Reverts the migration inside the transaction `manager` wraps.
96 ///
97 /// # Errors
98 ///
99 /// The default returns [`DbErr::Migration`] unconditionally, marking the
100 /// migration as irreversible; overriding implementations return
101 /// [`DbErr::Driver`] when a statement fails.
102 async fn down(&self, _manager: &SchemaManager<'_>) -> Result<(), DbErr> {
103 Err(DbErr::Migration("this migration cannot be reverted".into()))
104 }
105}
106
107/// Everything a migration module needs, meant to be glob-imported.
108pub mod prelude {
109 pub use crate::{
110 DeriveMigrationName, MigrationIssue, MigrationName, MigrationStatus, MigrationTrait,
111 MigratorTrait, SchemaManager, async_trait,
112 };
113 pub use turso_orm::entity::EntityTrait;
114 pub use turso_orm::sql::{
115 AlterTable, ColumnDef, ColumnType, CreateIndex, CreateTable, DropIndex, DropTable, Expr,
116 ForeignKey, ForeignKeyAction, Order, Table,
117 };
118 pub use turso_orm::{
119 ConnectOptions, ConnectionTrait, Database, DbErr, Schema, Statement, Transaction,
120 TransactionMode, TransactionTrait,
121 };
122}