2.6 KiB
adapter/model-to-table
Purpose
Memoising mapper from Better-Auth model name to SurrealDB table name. The
mapper function is invoked once per distinct model and the resolved name
is validated against the SurrealQL identifier rule
(/^[a-zA-Z_][a-zA-Z0-9_]*$/). Caching avoids re-running operator-supplied
prefix logic on every call site while validation prevents accidental
injection through a hand-rolled modelToTable that returns SurrealQL
syntax.
Features
- Identity-default —
new ModelToTableCache()maps model→model verbatim. - Caches resolved name in a
Map<string,string>. - Identifier-rule validation: invalid names raise
INVALID_MODELon first use of the offending model. - Decoupled from the adapter shell so unit tests can exercise mapping semantics in isolation.
Usage: Basic
import { ModelToTableCache } from "@suaveplan/better-auth-surrealdb/adapter";
const cache = new ModelToTableCache();
cache.resolve("user"); // "user"
cache.resolve("session"); // "session"
Usage: Advanced
import { ModelToTableCache } from "@suaveplan/better-auth-surrealdb/adapter";
let calls = 0;
const cache = new ModelToTableCache((m) => {
calls++;
return `bauth_${m}`;
});
cache.resolve("user"); // "bauth_user" — calls === 1
cache.resolve("user"); // "bauth_user" — calls still 1 (cached)
cache.resolve("session"); // "bauth_session" — calls === 2
API Reference
class ModelToTableCacheconstructor(resolver?: ModelToTableResolver)— defaults to identity.resolve(model: string): string— cached + validated.
type ModelToTableResolver = (model: string) => string.
Implementation Notes
The cache is a plain Map because invalidation is unnecessary: model
names are stable Better-Auth contracts and the adapter is constructed per
process. Throwing on first use of an invalid name (rather than at adapter
construction) preserves the "lazy" semantics so callers wiring a
multi-tenant prefix function can return different names per request
without paying the validation cost upfront. The identifier check uses
the same regex as every other validator in this package
(/^[a-zA-Z_][a-zA-Z0-9_]*$/) so operators get consistent feedback when
a name shape is wrong — whether the offending input is a model alias, a
SurrealDB table name, a link-field target, or a select projection
entry.
The class field is protected rather than private so subclasses can
introspect the cache during debugging without paying the indirection cost
of an additional accessor method — useful when wiring per-tenant audit
trails that need to log every resolved table name on first use.