DrinkMeAlice (drink_me_alice v0.1.0)
Copy MarkdownA bounded SurrealDB client for Elixir, qualified against SurrealDB 3.0.5 (see the README's Compatibility section for the version policy and the cleartext-transport deployment boundary).
Layers, bottom up:
DrinkMeAlice.Ws/FrameGuard/Json— Mint WebSocket transport with frame bounds and a bounded JSON decode profile.DrinkMeAlice.Conn— one supervised connection owner with credit-bounded admission, deadlines and honest transport facts.DrinkMeAlice.Session— a caller-owned, synchronous socket for short-lived work (scripts, provisioning, migrations).DrinkMeAlice.Outcome+DrinkMeAlice.Tx— transaction scripts and the reply classifier that never collapsesunknownintorejectedorcommitted.DrinkMeAlice.Admin+DrinkMeAlice.Migrations— root-only provisioning and a checksummed, locked migration runner.DrinkMeAlice.Ash.DataLayer— an Ash data layer (compiled only when the consumer brings Ash).
This module holds the read-side helper query/4 and the shared
identifier check.
Summary
Functions
SurrealDB 3.0.5 protects the parameter names $access, $auth, $session, $token:
binding one makes the server refuse the WHOLE request (JSON-RPC -32600,
measured). :ok, or {:error, {:protected_param, name}} before sending.
Only atom and binary key names are inspected; other key types are
rejected later by the outbound encoder with its own typed error, so
this check never raises on them.
Wire value for an EXACT string parameter — pair it with exact_string_sql/1.
The SurrealQL expression that recovers a list of exact_string/1 values in param name.
The SurrealQL expression that recovers a exact_string/1 param named name.
True for a SurrealQL identifier this connector will splice into SQL:
[A-Za-z_][A-Za-z0-9_]*, at most 64 bytes. Everything
else travels as a bound $param.
Run one read-side query through a Conn owner.
Normalize a query's parameter map: atom names become strings (the
outbound encoder (DrinkMeAlice.Json.encode/1) accepts only
string keys). Values must already be canonical-domain terms — binaries,
i64 integers, booleans, nil, lists and string-keyed maps; floats,
decimals and datetimes travel as strings with a SurrealQL cast.
Functions
SurrealDB 3.0.5 protects the parameter names $access, $auth, $session, $token:
binding one makes the server refuse the WHOLE request (JSON-RPC -32600,
measured). :ok, or {:error, {:protected_param, name}} before sending.
Only atom and binary key names are inspected; other key types are
rejected later by the outbound encoder with its own typed error, so
this check never raises on them.
Wire value for an EXACT string parameter — pair it with exact_string_sql/1.
SurrealDB 3.0.5's JSON-RPC parameter conversion coerces strings that merely look typed — at any depth, inside arrays and objects too:
| sent | arrives as | <string> of it |
|---|---|---|
"2026-10-01" | datetime | "2026-10-01T00:00:00Z" ✗ |
"task:abc" | record id | "task:abc" |
| UUID-shaped string | uuid | the same string |
A <string>$p cast repairs the UUID
and record-id cases but NOT date-shaped strings, which come back
rewritten. Prefixing one character that no coercion recognises and
slicing it off server-side is exact for every string (verified against
the pinned server, including the empty string and non-ASCII text).
The SurrealQL expression that recovers a list of exact_string/1 values in param name.
The SurrealQL expression that recovers a exact_string/1 param named name.
True for a SurrealQL identifier this connector will splice into SQL:
[A-Za-z_][A-Za-z0-9_]*, at most 64 bytes. Everything
else travels as a bound $param.
Run one read-side query through a Conn owner.
Returns {:ok, results} where results is the per-statement array
(%{"status" => "OK" | "ERR", "result" => _} each — callers check
every status), or {:error, reason}:
{:rpc_error, code}/:session_refused— the server refused;{:lost, reason}— sent, no reply (for a write this is an UNKNOWN outcome, never a failure — useDrinkMeAlice.Tx.run/4for writes);{:refused, reason}— certified never sent (:down,:expired,:exhausted,:too_large,:encode).
Options: deadline_ms (≤ 2_000), class (:general | :internal).
Normalize a query's parameter map: atom names become strings (the
outbound encoder (DrinkMeAlice.Json.encode/1) accepts only
string keys). Values must already be canonical-domain terms — binaries,
i64 integers, booleans, nil, lists and string-keyed maps; floats,
decimals and datetimes travel as strings with a SurrealQL cast.