Thanks for your interest in contributing! This guide covers the project structure, how to build native libraries, run tests, and add new drivers.
- Dart SDK ≥ 3.10
- Rust ≥ 1.83 (for compiling native connectors)
- Docker (for running database integration tests)
anakiORM/
├── rust/ # Single Rust crate — all drivers via feature flags
│ ├── Cargo.toml # [features] sqlite, postgres, mysql, mssql, oracle
│ └── src/
│ ├── lib.rs # FFI exports + generic connector dispatch
│ ├── connector.rs # DatabaseConnector trait (shared)
│ ├── error.rs # AnakiError (shared)
│ ├── types.rs # FfiResponse, QueryResult, etc. (shared)
│ ├── sqlite.rs # SQLite impl (cfg feature = "sqlite")
│ ├── postgres.rs # PostgreSQL impl (cfg feature = "postgres")
│ ├── mysql.rs # MySQL impl (cfg feature = "mysql")
│ └── mssql.rs # SQL Server impl (cfg feature = "mssql")
├── packages/
│ ├── anaki_orm/ # Core Dart package (AnakiDb, QueryBuilder, Migrator)
│ ├── anaki_sqlite/ # SQLite driver (FFI bindings + native_libs/)
│ ├── anaki_postgres/ # PostgreSQL driver
│ ├── anaki_mysql/ # MySQL driver
│ ├── anaki_mssql/ # SQL Server driver
│ └── anaki_oracle/ # Oracle driver (deferred — requires OCI)
├── example/
│ └── shelf_sqlite_example/ # Example REST API with Shelf + SQLite
├── scripts/
│ └── build_native.sh # Cross-compilation script
└── docs/
└── docker-aot.md # Docker AOT deployment guide
┌──────────────┐ ┌─────────────────┐ ┌──────────────┐
│ Dart App │────▶│ anaki_orm │────▶│ AnakiDriver │
│ (Shelf/Vaden)│ │ (AnakiDb API) │ │ (interface) │
└──────────────┘ └─────────────────┘ └──────┬───────┘
│ implements
┌─────┴─────┐
│ │
┌──────────┴──┐ ┌──────┴────────┐
│ SqliteDriver │ │ PostgresDriver │ ...
│ (FFI→Rust) │ │ (FFI→Rust) │
└──────────────┘ └────────────────┘
│ │
┌──────┴──────────────────┴──────┐
│ Single Rust crate (rust/) │
│ compiled with --features flag │
│ sqlite │ postgres │ mysql │ … │
└─────────────────────────────────┘
Key design decisions:
- One Rust crate with feature flags, not one crate per driver
- FFI protocol: Rust returns JSON string → Dart decodes to
Map<String, dynamic> - One Dart package per driver — each contains FFI bindings and pre-built native libraries
anaki_ormis pure Dart — no native dependencies, no FFI
All drivers share the Rust crate in rust/. The build script compiles with the correct feature flag and copies the output to the right package.
# Build a single driver (local platform only)
./scripts/build_native.sh sqlite --local
# Build a single driver (all platforms)
./scripts/build_native.sh sqlite
# Build all drivers
./scripts/build_native.sh allUnder the hood:
cargo build --release --features sqlite # → libanaki_sqlite-darwin-arm64.dylib
cargo build --release --features postgres # → libanaki_postgres-linux-x64.soThe output goes to packages/anaki_<driver>/native_libs/.
cd packages/anaki_orm
dart test# Build the native lib first
./scripts/build_native.sh sqlite --local
# Then run tests
cd packages/anaki_sqlite
dart testFor PostgreSQL, MySQL, and MSSQL, start the containers first:
docker compose up -d
# Then run tests
cd packages/anaki_postgres
dart test
cd packages/anaki_mssql
dart test-
Rust side — Add a new module in
rust/src/(e.g.,newdb.rs):- Implement the
DatabaseConnectortrait - Add a feature flag in
Cargo.toml - Register it in
lib.rsundercreate_connector()with#[cfg(feature = "newdb")]
- Implement the
-
Dart side — Create
packages/anaki_newdb/:lib/src/newdb_driver.dart— implementsAnakiDriverlib/src/bindings.dart— FFI bindings using@Nativelib/anaki_newdb.dart— library exportspubspec.yaml— depends onanaki_ormnative_libs/— will hold compiled binaries
-
Build script — Add the driver name to
scripts/build_native.sh -
Tests — Add integration tests in
test/
- Implements all
AnakiDrivermethods - Sets correct
SqlDialect(.genericor.mssql) - Named parameters use
@namesyntax - FFI bindings load correct platform-specific library
- Integration tests cover: connect, CRUD, scalar, batch, pagination, transactions
- Native libraries built for: linux-x64, darwin-arm64, darwin-x64, windows-x64
Drivers that need dialect-specific SQL generation override the dialect getter:
@override
SqlDialect get dialect => SqlDialect.mssql;Currently affects:
- Pagination:
LIMIT/OFFSET(generic) vsOFFSET/FETCH(MSSQL) - Migrator DDL:
AUTOINCREMENT(generic) vsIDENTITY(MSSQL) - COUNT subqueries: ORDER BY stripping for MSSQL
See docs/docker-aot.md for production deployment with dart compile exe.
- Follow Dart conventions (
dart format,dart analyze) - Keep
AnakiDbSQL-first — no ORM-like abstractions in the core class - The
AnakiQueryBuilderis opt-in and standalone — it doesn't modifyAnakiDb - Tests: unit tests in
anaki_orm/test/, integration tests in each driver package
MIT