Vault

The shared database abstraction layer underneath Karango (ArangoDB) and Monko (MongoDB).

Vault is not a database driver. It defines the common types and interfaces that Karango and Monko implement. If you use either of those libraries, you are already using Vault.

Why it matters

Switch between ArangoDB and MongoDB without rewriting your domain model. Your entities, queries, and repository patterns stay the same. Vault gives you a single set of abstractions so that choosing or changing a database backend is a wiring decision, not a rewrite.

What Vault provides

Every persistence layer needs the same building blocks: entity wrappers with metadata, lazy references, cursor-based result iteration, a repository interface with hooks, and an entity cache for deduplication. Rather than duplicating these across Karango and Monko, Vault defines them once.

Your data classes stay clean. Database metadata (_id, _key, _rev) lives in the wrapper, not in your domain model:

// Your data — no database concerns
@Vault
data class Person(val name: String, val age: Int)

// After inserting into either ArangoDB or MongoDB:
val stored: Stored<Person> = repo.insert(Person("Alice", 30))

stored()      // Person(name="Alice", age=30) — your data
stored._id    // "persons/abc123" — database ID
stored._key   // "abc123" — document key

The Storable hierarchy

Three wrapper types represent different entity lifecycle stages:

  • New<T> — an entity before it has been persisted
  • Stored<T> — an entity loaded from or saved to the database, carrying full metadata
  • Ref<T> — a lazy reference to another entity, resolved on demand via suspend resolve()

All three share a common base (Storable<T>) with uniform access via suspend resolve() and suspend invoke(). For Stored and New, resolution is instant. For Ref, it may suspend to load from the database.

What You Get

Entity Wrappers

Storable, Stored, New, and Ref — your data stays clean while database metadata lives in the wrapper.

Flow Cursors

Cursor<T> wraps Kotlin Flow with 29 suspend convenience extensions that mirror stdlib collections.

Lazy References

Ref<T> resolves on first access, with thread-safe caching. Eager and lazy construction supported.

Suspend-First

All repository and cursor operations are suspend functions. No blocking calls, no callbacks.

Dual-Backend

Same types and interfaces for ArangoDB (Karango) and MongoDB (Monko). Switch backends without rewriting domain code.

Type-Safe

Generic wrappers preserve your domain types end-to-end. Safe downcasting via castTyped and castUntyped.