artemix.org

raft - simple sqlite3 migration tool and janet library

the migration format

all migrations are written inside a directory of your choice (by default ./migrations is used), each migration a janet file.

a migration file is named following ID.name+.janet where ID is a decimal number and name+ "anything that's a valid file name". it must end with .janet.

that file must contain two defns: up and down, both expecting a single param, the DB connection.

(import sqlite3 :as sql)

(defn up [db]
  (sql/eval "create table woof (name text not null)"))

(defn down [db]
  (sql/eval "drop table woof"))

the passed DB is inside a started transaction which will be committed once your fn finishes; each migration has its own transaction context.

setup and deps

  • requires the janet libs spork, sqlite3, and for testing testament
  • can be installed with jpm
  • with jpm, it produces a bin to ~/.jpm/bin (or wherever you've pointed your JANET_TREE at)
$ jpm install https://git.sr.ht/~artemis/raft

usage - cli

Important: the cli always expects to be working on an existing sqlite3 file, it doesn't create any.

the database file and migrations directory can be configured through the env so they don't have to be manually passed through the CLI args.

  • $DB_PATH, or -d or --db-path - path to the sqlite3 file
  • $MIGRATION_DIR, or -m or --migration-dir (defaults to ./migrations) - path to the migration dir
usage: raft.janet [option] <command...>

raft - basic SQLite3 migration tool

 Required:
 -d, --db-path VALUE                         the sqlite3 db file to work on ($DB_PATH)

 Optional:
 -h, --help                                  Show this help message.
 -m, --migration-dir VALUE                   the dir containing the migration files (default ./migrations/, $MIGRATION_DIR)
     --noconfirm                             considers all questions to be yes
     --noinit                                don't run the migration init call on this query

Note that --db-path is only marked as required when the env var is unset.

here's the available commands.

raft    available commands
        ls              list all migrations and see if they're applied
        migrate         run all unapplied migrations
        rollback        rollback the most recent migration
        rollback ID     rollback all migrations down to and including the one with this ID

        help            show this message

by default, every run of raft against a DB file will execute the migration-state-init fn to ensure it's ready for use. if the db was already initialised, this is a NOP and can be ignored. for those who would like to explicitly disable this, --noinit is provided.

usage - lib

the lib exposes a few methods, some higher-level than others, to let you manipulate your DB. they're mostly all documented, so i'd recommend doing (doc ...) on them for their full documentation.

  • (init-db db) - creates the migration table if it doesn't exist
  • (migration-exists? db mig) - checks in DB if the migration exists
  • (run-migration db mig mode) #mode = 'up or 'down - applies the migration or rollback against the DB, registering the changes in the migration table
  • (maybe-run-migration db mig mode) - checks if the migration was already applied, and only apply migrations that aren't applied and rollbacks of migrations that were applied
  • (list-migrations mig-dir) - lists all migration files found in the target directory
  • (migrate-all db migs) - of all provided migrations, apply all those that have an ID higher than the highest applied one, ordered
  • (rollback db &opt id) - rollback the highest ID migration or, if given an ID, rollback everything up to and including that ID