MigLib.Codegen
12.1.0
dotnet add package MigLib.Codegen --version 12.1.0
NuGet\Install-Package MigLib.Codegen -Version 12.1.0
<PackageReference Include="MigLib.Codegen" Version="12.1.0" />
<PackageVersion Include="MigLib.Codegen" Version="12.1.0" />
<PackageReference Include="MigLib.Codegen" />
paket add MigLib.Codegen --version 12.1.0
#r "nuget: MigLib.Codegen, 12.1.0"
#:package MigLib.Codegen@12.1.0
#addin nuget:?package=MigLib.Codegen&version=12.1.0
#tool nuget:?package=MigLib.Codegen&version=12.1.0
Migrate is a SQLite-first toolkit: a schema directory is the desired catalog, _migration.sql is the hop from the previous catalog, and mig codegen emits typed F# query modules plus Migration.migrate.
What it does
- You author snapshot
*.sqlfiles underschema/(nested dirs allowed) and optionalschema/_migration.sql. - You annotate tables/views with
-- mig:comments for the ops you want. mig codegenapplies the snapshot to a temp DB, introspects, and emits one.fsmodule per annotated relation plusMigration.fs(let migrate dbPath).- At runtime you call
Migration.migrate dbPathand usedbTxnwith generated helpers.
SQL travels inside the binary as compiled string data. Empty databases get the snapshot; existing databases get the hop and must then match the snapshot catalog.
See specs/schema_dir_and_migration.md.
Annotation example
-- mig:rel User
-- mig:ops insert, select_by(email), select_by_id, count
-- mig:ops upsert
-- mig:bool active
-- mig:datetime created_at
CREATE TABLE app_user (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL,
active INTEGER NOT NULL,
created_at TEXT NOT NULL
) STRICT;
-- mig:ops select_all, select_one_by(email), count
CREATE VIEW active_user AS
SELECT id, email, created_at FROM app_user WHERE active = 1;
-- Optional AND filters (filter catalog):
-- mig:ops filter_search(created_at desc, id), filter_count
-- mig:filter status eq status
-- mig:filter label_prefix like_prefix label
-- mig:filter text_any eq_any label, notes
CREATE TABLE item (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
status TEXT NOT NULL,
label TEXT NOT NULL,
notes TEXT NOT NULL,
created_at TEXT NOT NULL
) STRICT;
Rules:
- Unannotated relations generate no F#.
- Ops are explicit; no ops means no type.
- Multiple
-- mig:opslines on one relation are merged in order (handy for long lists). - Views allow read ops (
select_*,count,filter_search,filter_count) plus optionaldelete_matching(table, key); other write ops fail at codegen. countemits unfilteredSELECT COUNT(*) FROM [relation]aslet count : TxnStep<int64>(tables and views).- Filter catalog (
-- mig:filter name kind column[, column…]plusfilter_search/filter_count):- Emits
{Rel}Filter(each fieldT option),emptyFilter, publicapplyFilter(WHERE + params for hand SQL),search filter skip take, and/orcountByFilter filter. - Kinds:
eq,neq,gt,gte,lt,lte,like_prefix(bindsv + "%"),eq_any(OR across 2+ columns, one bind),in(T list; empty list is1=0). - Present
Somevalues become AND clauses; all-NoneusesWHERE 1=1. - Requires at least one
-- mig:filterwithfilter_searchand/orfilter_count(and vice versa). At most one of each filter op per relation.
- Emits
-- mig:rel Nameis optional; otherwise the F# name is derived from the SQL identifier.
See specs/schema_dir_and_migration.md and specs/sql_first_rewrite.md.
Installation
dotnet tool install --global migtool
Library:
dotnet add package MigLib
Codegen
mig codegen \
--migrations ./schema \
--output ./Stores \
--namespace MyApp.Db
This writes Stores/User.fs, Stores/ActiveUser.fs, etc., plus Stores/Migration.fs (module MyApp.Db.Migration with let migrate). Hand-written companions can live alongside generated files; only files marked // <auto-generated /> are deleted when a relation disappears (Migration.fs is always kept).
From build.fsx / F#:
open MigLib.Codegen
match generate "./schema" "./Stores" "MyApp.Db" with
| Ok r ->
Console.WriteLine(
"generated "
+ string r.relationCount
+ " relations in "
+ r.outputDir)
r.generatedFiles |> List.iter (fun p -> Console.WriteLine(" " + p))
| Error e -> failwith e
Runtime
open System
open MigLib
open MyApp.Db
// apply compiled snapshot / hop (module MyApp.Db.Migration)
let! db = Migration.migrate dbPath
// use transactions + generated queries (module MyApp.Db.User)
let! user =
db {
match! User.selectOneByEmail email with
| Some u -> return u
| None ->
let! id =
User.insert
{ Email = email
Active = true
CreatedAt = DateTimeOffset.UtcNow }
return! User.selectById id |> TxnStep.map Option.get
}
Packages
| Package | Role |
|---|---|
| migtool | CLI (mig codegen, mig version) |
| MigLib | Runtime: dbTxn / TxnStep, Query, migrate (AOT-friendly; no reflection) |
| MigLib.Codegen | Dev-time generate API (used by CLI and build.fsx) |
Local build
dotnet fsi build.fsx -- --target build
dotnet fsi build.fsx -- --target install
cd src && dotnet test
Version
Major version 10 is a greenfield rewrite (SQL-first). Older MigSchema / attribute-based workflows are not supported.
Further reading
See documentation/interesting-links.md for SQLite concurrency, migrations, and related theory links.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- FSharp.Core (>= 10.1.301)
- Lamg.Env (>= 0.6.0)
- Microsoft.Data.Sqlite (>= 9.0.0)
- MigLib (>= 12.1.0)
- SQLitePCLRaw.bundle_e_sqlite3 (>= 2.1.12)
- SQLitePCLRaw.core (>= 2.1.12)
- SQLitePCLRaw.lib.e_sqlite3 (>= 2.1.12)
- SQLitePCLRaw.provider.e_sqlite3 (>= 2.1.12)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.