# 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`. - Identifier-rule validation: invalid names raise `INVALID_MODEL` on first use of the offending model. - Decoupled from the adapter shell so unit tests can exercise mapping semantics in isolation. ## Usage: Basic ```ts import { ModelToTableCache } from "@suaveplan/better-auth-surrealdb/adapter"; const cache = new ModelToTableCache(); cache.resolve("user"); // "user" cache.resolve("session"); // "session" ``` ## Usage: Advanced ```ts 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 ModelToTableCache` - `constructor(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.