Async-first ORM and libSQL client for Nim
モデル定義、クエリビルダ、マイグレーション、Turso/libSQL 接続を 1 パッケージにまとめた Nim 向け ORM 基盤です。
Why · Install · Quick Start · Migrations · CLI · Development
nimtra は、Nim で Turso/libSQL を扱うときに必要になりやすい層をまとめて提供します。HTTP ドライバだけでも、ORM だけでもなく、その間の移行コストまで含めて扱えるのが狙いです。
- Async-first な libSQL HTTP ドライバ
where(it.age >= 18)のような compile-time 指向のクエリ記述- モデルからの schema SQL 生成と migration 実行
- SQL ファイル管理にも対応した drizzle-like CLI
- TLS が不安定な環境でも使いやすい
curlフォールバック - ローカルレプリカ向けの native
libsqlsync hook
| Layer | Highlights |
|---|---|
| Driver | openLibSQL, openLibSQLEnv, execute, query, executeBatch, close |
| Connection helpers | withLibSQL, withLibSQLEnv, retry config, curl transport fallback |
| Query builder | select, fromRaw, columnsRaw, join, leftJoin, where, orderBy, limit, offset, paginate, count, exists |
| CRUD | insert, upsert, upsertReturningId, updateById, deleteById, findById, findAll, existsById |
| Mapper | rowToModel, rowsToModels, allModels, firstModel, findByIdModel |
| Schema | modelMeta, createTableSql, createSchemaSql |
| Migration | newMigration, migrationFromModel, migrate, migrateTo, pendingMigrations, verifyMigrationHistory |
| Schema diff | tableSnapshot, planModelDiff, ensureModelSchemaDiff |
| Embedded sync | openLibSQLWithEmbeddedSync, sync() |
nimble install nimtranimtra は hybrid package として公開されています。1 回のインストールで次が入ります。
- ライブラリ本体:
import nimtra - CLI バイナリ:
nimtra,nimtra_cli
環境変数で接続する場合は以下がデフォルトです。
export TURSO_DATABASE_URL="libsql://your-db.turso.io"
export TURSO_AUTH_TOKEN="YOUR_TOKEN"TURSO_URL / TURSO_TOKEN も fallback alias として扱えます。
import std/asyncdispatch
import nimtra
type
User = ref object
id {.primary, autoincrement.}: int
name {.maxLength: 50.}: string
email {.unique.}: string
age: int
proc main() {.async.} =
let db = await openLibSQLEnv()
discard await db.insert(User(
name: "Alice",
email: "alice@example.com",
age: 22
))
let users = await db
.select(User)
.where(it.age >= 18)
.orderBy("age", descending = true)
.paginate(page = 1, perPage = 20)
.allModels()
echo users.len
await db.close()
waitFor main()モデル定義からそのまま migration を作る構成です。小さく始めるならこの流れが最短です。
import std/asyncdispatch
import nimtra
type
User {.table: "users".} = ref object
id {.primary, autoincrement.}: int
email {.unique.}: string
age {.index.}: int
proc main() {.async.} =
let db = await openLibSQL(
url = "libsql://your-db.turso.io",
authToken = "YOUR_TOKEN"
)
let migration = migrationFromModel(User, 2026030701, migrationName = "create_users")
await db.migrate([migration])
await db.close()
waitFor main()Migration の適用状況や checksum 検証も API から扱えます。
let applied = await db.listAppliedMigrations()
let pending = await db.pendingMigrations([m1, m2, m3])
await db.verifyMigrationHistory([m1, m2, m3], allowUnknownApplied = false)
await db.migrateTo([m1, m2, m3], targetVersion = 2)SQL ファイルをディレクトリで管理する drizzle-like な運用にも対応しています。
利用できる subcommand は new, status, up, to, verify, list です。
db/
migrations/
20260307120000_create_users.sql
20260307121000_add_user_index.sql
# 0) インストール
nimble install nimtra
# 1) マイグレーション雛形を作成
nimtra migrate new "create users"
# 2) 適用状況を確認
nimtra migrate status --strict
# 3) 未適用を実行
nimtra migrate up
# 4) 特定バージョンまで適用
nimtra migrate to 20260307121000主なオプションは次のとおりです。
| Option | Meaning |
|---|---|
--dir, -d |
Migration SQL directory. デフォルトは db/migrations |
--table, -t |
Migration table 名. デフォルトは _nimtra_migrations |
--url, --token |
接続先を環境変数より優先して上書き |
--prefer-curl |
curl transport を優先して使用 |
--strict |
厳密な verification を有効化 |
--version, -v |
migrate new 作成時の version を明示 |
互換コマンドとして nimtra_cli も利用できます。
既存 DB とモデル定義の差分を見て、追加 SQL や rebuild が必要かを確認できます。
import std/asyncdispatch
import nimtra
type
User = ref object
id {.primary, autoincrement.}: int
email {.unique.}: string
age {.index.}: int
proc main() {.async.} =
let db = await openLibSQL(
url = "libsql://your-db.turso.io",
authToken = "YOUR_TOKEN"
)
let plan = await db.planModelDiff(User, autoRebuild = true)
for warning in plan.warnings:
echo "warning: ", warning
discard await db.ensureModelSchemaDiff(User, autoRebuild = true)
await db.close()
waitFor main()ローカルレプリカや embedded 運用では、libsql C API の sync hook を使えます。
import std/asyncdispatch
import nimtra
proc main() {.async.} =
let db = await openLibSQLWithEmbeddedSync(
url = "libsql://your-db.turso.io",
replicaPath = "local.db",
authToken = "YOUR_TOKEN",
# libraryPath = "/opt/homebrew/lib/libsql.dylib"
)
await db.sync()
await db.close()
waitFor main()nimble testOperational notes
sync()はsyncHookを優先し、未指定ならsyncUrl、さらに未指定なら軽量なSELECT 1checkpoint を実行します。- HTTP retry は transport error と
408/429/5xxresponse に適用されます。 useCurlFallback = trueは Nim 側 HTTP/TLS transport が失敗したときにcurlを使って再試行します。preferCurlTransport = trueは全リクエストでcurltransport を使います。openLibSQLEnvはTURSO_DATABASE_URL/TURSO_AUTH_TOKENを優先し、TURSO_URL/TURSO_TOKENも fallback として受け付けます。autoRebuild = falseは安全寄りの差分適用に留め、autoRebuild = trueは SQLite の table rebuild flow を生成します。- 適用済み migration には deterministic な
checksumが保存され、pendingMigrationsとverifyMigrationHistoryで drift を検出できます。 - Embedded sync には
libsql.dylib/libsql.so/libsql.dllのいずれかが必要です。自動検出できない場合はlibraryPathを指定してください。
Release flow
git tag v0.1.0
git push origin v0.1.0
nimble publish公開前のローカル確認:
nimble --nimbleDir:.nimble-publish-test install -y
nimble --nimbleDir:.nimble-publish-test build -y