Dahlia is Grimvane’s structured storage library. Define a schema, insert records, query by field values with filter operators. Three pluggable backends: in-memory, SQLite, PostgreSQL. Same API regardless of backend. No concept of what your records represent.
Schema-Driven Design
Every collection has a schema defined up front. Dahlia validates on write, not at query time. Bad data is caught at the boundary, before it reaches application logic.
Schemas can be plain dicts or Python dataclasses. Both work the same way:
from dahlia import Store
store = Store()
store.define("cards", {"name": str, "faction": str, "ember_cost": int, "type": str})
store.insert("cards", {"name": "Forge Strike", "faction": "warden", "ember_cost": 2, "type": "strike"})
Supported field types: str, int, float, bool, datetime, Optional[T].
Query Filtering
Dahlia supports operator-based filtering without writing custom loops for every query pattern:
# Exact match
store.query("cards", where={"faction": "ashen"})
# Comparison operators
store.query("cards", where={"ember_cost": {"$lte": 2}})
# Multiple conditions
store.query("cards", where={"faction": "warden", "type": "strike"})
# Ordering and pagination
store.query("cards", order_by="ember_cost", limit=10)
Operators: $eq, $ne, $gt, $gte, $lt, $lte, $contains, $in, $not_in. Each one is a single conditional under the hood, no query language to parse.
Pluggable Backends
| Backend | Dependency | Use Case |
|---|---|---|
memory | None | Testing, ephemeral data, embedded runtimes |
sqlite | Python stdlib | Single-file persistence, desktop apps |
postgres | psycopg | Server deployments, large datasets |
Switching backends is a one-line change. The in-memory backend ports to other languages with zero dependencies, which is how Dahlia travels to GDScript inside Godot.
Consumers
| Project | Usage |
|---|---|
| Corvath | Structured data storage for session state and tool configuration |
| Kindlefall | Card definitions, enemy data, relic collections, run state, meta-progression (via GDScript port) |