lift
lift is a Rust workspace for the Lift migration language.
This repository contains the language parser, a migration CLI, a small language server, and a tree-sitter grammar. It is for tools that need to read, validate, edit, scaffold, or run Lift migration files.
What Lift looks like
Lift is a small migration DSL with tables, enums, inline SQL, and optional rollback blocks.
create users {
id
email text unique
tenant_id uuid
remember_token
timestamps
soft_deletes
unique (tenant_id, email)
}
alter users {
add column timezone text default "UTC"
}
backfill {
update users
set timezone = 'UTC'
where timezone is null;
}
down {
drop users
}
The language also supports enum migrations:
create enum post_status { draft, published, archived }
alter enum post_status {
add value deleted
}
Relationships
Lift handles relationships at the schema level with foreign keys.
Use ref on a column to point at another table:
create posts {
id
author_id ref users on delete cascade
title text
}
author_id ref users means author_id references users(id).
You can combine ref with a few common modifiers:
nullablefor optional relationshipson delete cascade,on delete restrict,on delete set null, oron delete no actionon update cascade,on update restrict,on update set null, oron update no actionno indexif you do not want Lift to add the default index for the relation column
Example:
create comments {
id
post_id bigint ref posts on delete cascade
reviewer_id uuid ref users nullable on delete set null
body text
}
If you need a specific index name or a composite index, declare it yourself:
create comments {
id
post_id bigint ref posts no index
reviewer_id uuid ref users nullable no index
body text
index comments_post_id_idx (post_id)
index comments_post_reviewer_idx (post_id, reviewer_id)
}
Migration files
The parser reads migrations from a directory. It recognizes:
- Lift files named
<id>_<name>.lift - SQL files named
<id>_<name>.sql - optional SQL rollback files named
<id>_<name>.down.sql
Examples:
202604210001_create_users.lift202604220001_enable_pgcrypto.sql202604220001_enable_pgcrypto.down.sql
Lift migrations may contain one optional down { ... } block. SQL migrations
use a separate .down.sql file when a rollback is needed.
When loading a directory, the parser sorts migrations by numeric id and returns them as a single ordered list.
Workspace
This workspace has four crates.
lift
crates/lift parses Lift source and SQL migration files into Rust data
structures such as MigrationFile, Statement, TableItem, and Column. It
also ships the lift CLI for migration scaffolding and execution.
Use it when you need to:
- read a migration directory
- validate file names and migration contents
- inspect schema statements programmatically
- accept either Lift or SQL migrations
- scaffold and run migrations from the terminal
Install the CLI with an explicit backend feature:
Example commands:
Small example:
use ;
lift-migration
crates/lift-migration is the vendored migration runtime used by the lift
CLI. It applies parsed Lift and SQL migrations to supported databases and keeps
the execution logic local to this workspace.
The crate also exposes parse_migration_file and parse_source when you want
to parse one migration at a time.
lift-lsp
crates/lift-lsp is a language server for .lift files. It runs over stdio.
Today it focuses on a small set of editor features:
- diagnostics for invalid Lift syntax
- diagnostics for invalid migration file names
- keyword completion for Lift syntax
tree-sitter-lift
crates/tree-sitter-lift provides a tree-sitter grammar for Lift, along with
queries for highlighting, indentation, and injections.
Rust example:
let mut parser = new;
parser.set_language?;
Development
Build the workspace:
Run tests:
If you change crates/tree-sitter-lift/grammar.js, regenerate the parser:
License
Licensed under either of:
- MIT, see
LICENSE-MIT - Apache-2.0, see
LICENSE-APACHE