@lunora/auth 1.0.0-alpha.32 → 1.0.0-alpha.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/schema.d.mts CHANGED
@@ -1,44 +1,44 @@
1
1
  import { TableDefinition } from '@lunora/server';
2
- import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-Mwhb4gSc.mjs";
2
+ import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-COcIS_KU.mjs";
3
3
  import 'better-auth';
4
4
  /**
5
- * Derive Lunora table definitions from a better-auth config — the bridge that
6
- * makes the **full** better-auth plugin ecosystem first-class Lunora data.
7
- *
8
- * better-auth's own `getAuthTables(options)` already merges every configured
9
- * plugin's `schema` into one table map (core `user`/`session`/`account`/
10
- * `verification`, plus whatever the plugins on `options.plugins` add —
11
- * `organization`/`member`/`invitation`/`team`/`teamMember` from the
12
- * organization plugin, `role`/`banned`/… columns from admin, `passkey`,
13
- * `twoFactor`, `jwks`, …). This walks that map and emits an equivalent
14
- * `defineTable` for each, so adding a plugin to `options.plugins` automatically
15
- * surfaces its tables in the Lunora schema — no hand-written table definitions
16
- * to keep in sync.
17
- *
18
- * Spread the result into `defineSchema` alongside your app tables (the keys are
19
- * better-auth's real table names — `user`, `session`, … — left **unprefixed**
20
- * because better-auth's adapter addresses them by exactly those names). Because
21
- * the names are unprefixed, do **not** declare an app table that reuses one of
22
- * better-auth's reserved names in the same `defineSchema` — JS spread order
23
- * would let the later key win silently (unlike the plugin-extension path, which
24
- * throws on collision):
25
- *
26
- * ```ts
27
- * import { authTables } from "@lunora/auth";
28
- * const authOptions = { emailAndPassword: { enabled: true }, plugins: [organization(), admin()] };
29
- * export const schema = defineSchema({
30
- * ...authTables(authOptions),
31
- * todos: defineTable({ title: v.string() }),
32
- * });
33
- * ```
34
- *
35
- * Scope: this emits the table **shapes** (columns + types + nullability +
36
- * uniqueness + FK ids). It deliberately does not carry better-auth's
37
- * `defaultValue`/`onUpdate` (filled by better-auth's own write layer), `index`
38
- * hints, or `bigint` precision (`bigint` fields map to `v.number()`). Those only
39
- * matter once better-auth's writes are routed through Lunora's ORM — a separate
40
- * adapter follow-up; today the auth rows are still written by better-auth's D1
41
- * adapter and these tables make them typed + queryable via `ctx.db`.
42
- */
5
+ * Derive Lunora table definitions from a better-auth config — the bridge that
6
+ * makes the **full** better-auth plugin ecosystem first-class Lunora data.
7
+ *
8
+ * better-auth's own `getAuthTables(options)` already merges every configured
9
+ * plugin's `schema` into one table map (core `user`/`session`/`account`/
10
+ * `verification`, plus whatever the plugins on `options.plugins` add —
11
+ * `organization`/`member`/`invitation`/`team`/`teamMember` from the
12
+ * organization plugin, `role`/`banned`/… columns from admin, `passkey`,
13
+ * `twoFactor`, `jwks`, …). This walks that map and emits an equivalent
14
+ * `defineTable` for each, so adding a plugin to `options.plugins` automatically
15
+ * surfaces its tables in the Lunora schema — no hand-written table definitions
16
+ * to keep in sync.
17
+ *
18
+ * Spread the result into `defineSchema` alongside your app tables (the keys are
19
+ * better-auth's real table names — `user`, `session`, … — left **unprefixed**
20
+ * because better-auth's adapter addresses them by exactly those names). Because
21
+ * the names are unprefixed, do **not** declare an app table that reuses one of
22
+ * better-auth's reserved names in the same `defineSchema` — JS spread order
23
+ * would let the later key win silently (unlike the plugin-extension path, which
24
+ * throws on collision):
25
+ *
26
+ * ```ts
27
+ * import { authTables } from "@lunora/auth";
28
+ * const authOptions = { emailAndPassword: { enabled: true }, plugins: [organization(), admin()] };
29
+ * export const schema = defineSchema({
30
+ * ...authTables(authOptions),
31
+ * todos: defineTable({ title: v.string() }),
32
+ * });
33
+ * ```
34
+ *
35
+ * Scope: this emits the table **shapes** (columns + types + nullability +
36
+ * uniqueness + FK ids). It deliberately does not carry better-auth's
37
+ * `defaultValue`/`onUpdate` (filled by better-auth's own write layer), `index`
38
+ * hints, or `bigint` precision (`bigint` fields map to `v.number()`). Those only
39
+ * matter once better-auth's writes are routed through Lunora's ORM — a separate
40
+ * adapter follow-up; today the auth rows are still written by better-auth's D1
41
+ * adapter and these tables make them typed + queryable via `ctx.db`.
42
+ */
43
43
  declare const authTables: (options: LunoraAuthOptions) => Record<string, TableDefinition>;
44
44
  export { authTables as default };
package/dist/schema.d.ts CHANGED
@@ -1,44 +1,44 @@
1
1
  import { TableDefinition } from '@lunora/server';
2
- import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-Mwhb4gSc.js";
2
+ import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-COcIS_KU.js";
3
3
  import 'better-auth';
4
4
  /**
5
- * Derive Lunora table definitions from a better-auth config — the bridge that
6
- * makes the **full** better-auth plugin ecosystem first-class Lunora data.
7
- *
8
- * better-auth's own `getAuthTables(options)` already merges every configured
9
- * plugin's `schema` into one table map (core `user`/`session`/`account`/
10
- * `verification`, plus whatever the plugins on `options.plugins` add —
11
- * `organization`/`member`/`invitation`/`team`/`teamMember` from the
12
- * organization plugin, `role`/`banned`/… columns from admin, `passkey`,
13
- * `twoFactor`, `jwks`, …). This walks that map and emits an equivalent
14
- * `defineTable` for each, so adding a plugin to `options.plugins` automatically
15
- * surfaces its tables in the Lunora schema — no hand-written table definitions
16
- * to keep in sync.
17
- *
18
- * Spread the result into `defineSchema` alongside your app tables (the keys are
19
- * better-auth's real table names — `user`, `session`, … — left **unprefixed**
20
- * because better-auth's adapter addresses them by exactly those names). Because
21
- * the names are unprefixed, do **not** declare an app table that reuses one of
22
- * better-auth's reserved names in the same `defineSchema` — JS spread order
23
- * would let the later key win silently (unlike the plugin-extension path, which
24
- * throws on collision):
25
- *
26
- * ```ts
27
- * import { authTables } from "@lunora/auth";
28
- * const authOptions = { emailAndPassword: { enabled: true }, plugins: [organization(), admin()] };
29
- * export const schema = defineSchema({
30
- * ...authTables(authOptions),
31
- * todos: defineTable({ title: v.string() }),
32
- * });
33
- * ```
34
- *
35
- * Scope: this emits the table **shapes** (columns + types + nullability +
36
- * uniqueness + FK ids). It deliberately does not carry better-auth's
37
- * `defaultValue`/`onUpdate` (filled by better-auth's own write layer), `index`
38
- * hints, or `bigint` precision (`bigint` fields map to `v.number()`). Those only
39
- * matter once better-auth's writes are routed through Lunora's ORM — a separate
40
- * adapter follow-up; today the auth rows are still written by better-auth's D1
41
- * adapter and these tables make them typed + queryable via `ctx.db`.
42
- */
5
+ * Derive Lunora table definitions from a better-auth config — the bridge that
6
+ * makes the **full** better-auth plugin ecosystem first-class Lunora data.
7
+ *
8
+ * better-auth's own `getAuthTables(options)` already merges every configured
9
+ * plugin's `schema` into one table map (core `user`/`session`/`account`/
10
+ * `verification`, plus whatever the plugins on `options.plugins` add —
11
+ * `organization`/`member`/`invitation`/`team`/`teamMember` from the
12
+ * organization plugin, `role`/`banned`/… columns from admin, `passkey`,
13
+ * `twoFactor`, `jwks`, …). This walks that map and emits an equivalent
14
+ * `defineTable` for each, so adding a plugin to `options.plugins` automatically
15
+ * surfaces its tables in the Lunora schema — no hand-written table definitions
16
+ * to keep in sync.
17
+ *
18
+ * Spread the result into `defineSchema` alongside your app tables (the keys are
19
+ * better-auth's real table names — `user`, `session`, … — left **unprefixed**
20
+ * because better-auth's adapter addresses them by exactly those names). Because
21
+ * the names are unprefixed, do **not** declare an app table that reuses one of
22
+ * better-auth's reserved names in the same `defineSchema` — JS spread order
23
+ * would let the later key win silently (unlike the plugin-extension path, which
24
+ * throws on collision):
25
+ *
26
+ * ```ts
27
+ * import { authTables } from "@lunora/auth";
28
+ * const authOptions = { emailAndPassword: { enabled: true }, plugins: [organization(), admin()] };
29
+ * export const schema = defineSchema({
30
+ * ...authTables(authOptions),
31
+ * todos: defineTable({ title: v.string() }),
32
+ * });
33
+ * ```
34
+ *
35
+ * Scope: this emits the table **shapes** (columns + types + nullability +
36
+ * uniqueness + FK ids). It deliberately does not carry better-auth's
37
+ * `defaultValue`/`onUpdate` (filled by better-auth's own write layer), `index`
38
+ * hints, or `bigint` precision (`bigint` fields map to `v.number()`). Those only
39
+ * matter once better-auth's writes are routed through Lunora's ORM — a separate
40
+ * adapter follow-up; today the auth rows are still written by better-auth's D1
41
+ * adapter and these tables make them typed + queryable via `ctx.db`.
42
+ */
43
43
  declare const authTables: (options: LunoraAuthOptions) => Record<string, TableDefinition>;
44
44
  export { authTables as default };
@@ -12,40 +12,40 @@ interface D1Like {
12
12
  };
13
13
  }
14
14
  /**
15
- * The minimal SQL seam a {@link createSqlAuthStore} runs on — structurally the
16
- * same `{ all, run }` contract as `@lunora/d1`'s `D1Exec`, so a Lunora D1 binding
17
- * satisfies it directly (see {@link d1Executor}) and a `node:sqlite` handle does
18
- * too in tests. `all` runs reads and returns rows; `run` runs writes.
19
- */
15
+ * The minimal SQL seam a {@link createSqlAuthStore} runs on — structurally the
16
+ * same `{ all, run }` contract as `@lunora/d1`'s `D1Exec`, so a Lunora D1 binding
17
+ * satisfies it directly (see {@link d1Executor}) and a `node:sqlite` handle does
18
+ * too in tests. `all` runs reads and returns rows; `run` runs writes.
19
+ */
20
20
  interface SqlExecutor {
21
21
  all: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
22
22
  run: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<void>;
23
23
  }
24
24
  /**
25
- * An {@link AuthStore} backed by a SQL database through the {@link SqlExecutor}
26
- * seam — the production counterpart to `createMemoryAuthStore`. Point it at the
27
- * same database that hosts Lunora's global (D1) tables (the ones `authTables(...)`
28
- * generates) and better-auth's reads/writes land there as ordinary rows Lunora
29
- * can also query. Assumes the auth tables already exist (Lunora owns the schema /
30
- * migrations); it never issues DDL.
31
- *
32
- * ```ts
33
- * const store = createSqlAuthStore(d1Executor(env.DB));
34
- * const auth = createAuth({ secret: env.AUTH_SECRET, database: lunoraAuthAdapter(store) });
35
- * ```
36
- *
37
- * Clause semantics match `createMemoryAuthStore` (operator parity is
38
- * covered by a cross-store agreement test) with one unavoidable caveat:
39
- * case-**insensitive** matching uses SQLite's ASCII-only `LOWER()`, whereas the
40
- * in-memory store uses JS full-Unicode `toLowerCase()`. They agree on ASCII
41
- * (emails, ids, tokens — the credential path); they can differ only for
42
- * case-insensitive comparison of non-ASCII text.
43
- */
25
+ * An {@link AuthStore} backed by a SQL database through the {@link SqlExecutor}
26
+ * seam — the production counterpart to `createMemoryAuthStore`. Point it at the
27
+ * same database that hosts Lunora's global (D1) tables (the ones `authTables(...)`
28
+ * generates) and better-auth's reads/writes land there as ordinary rows Lunora
29
+ * can also query. Assumes the auth tables already exist (Lunora owns the schema /
30
+ * migrations); it never issues DDL.
31
+ *
32
+ * ```ts
33
+ * const store = createSqlAuthStore(d1Executor(env.DB));
34
+ * const auth = createAuth({ secret: env.AUTH_SECRET, database: lunoraAuthAdapter(store) });
35
+ * ```
36
+ *
37
+ * Clause semantics match `createMemoryAuthStore` (operator parity is
38
+ * covered by a cross-store agreement test) with one unavoidable caveat:
39
+ * case-**insensitive** matching uses SQLite's ASCII-only `LOWER()`, whereas the
40
+ * in-memory store uses JS full-Unicode `toLowerCase()`. They agree on ASCII
41
+ * (emails, ids, tokens — the credential path); they can differ only for
42
+ * case-insensitive comparison of non-ASCII text.
43
+ */
44
44
  declare const createSqlAuthStore: (executor: SqlExecutor) => AuthStore;
45
45
  /**
46
- * Wrap a Cloudflare D1 binding (`env.DB`) as a {@link SqlExecutor}, so
47
- * `createSqlAuthStore(d1Executor(env.DB))` routes better-auth onto D1 — the same
48
- * binding Lunora's `.global()` tables use.
49
- */
46
+ * Wrap a Cloudflare D1 binding (`env.DB`) as a {@link SqlExecutor}, so
47
+ * `createSqlAuthStore(d1Executor(env.DB))` routes better-auth onto D1 — the same
48
+ * binding Lunora's `.global()` tables use.
49
+ */
50
50
  declare const d1Executor: (database: D1Like) => SqlExecutor;
51
51
  export { SqlExecutor, createSqlAuthStore, d1Executor };
@@ -12,40 +12,40 @@ interface D1Like {
12
12
  };
13
13
  }
14
14
  /**
15
- * The minimal SQL seam a {@link createSqlAuthStore} runs on — structurally the
16
- * same `{ all, run }` contract as `@lunora/d1`'s `D1Exec`, so a Lunora D1 binding
17
- * satisfies it directly (see {@link d1Executor}) and a `node:sqlite` handle does
18
- * too in tests. `all` runs reads and returns rows; `run` runs writes.
19
- */
15
+ * The minimal SQL seam a {@link createSqlAuthStore} runs on — structurally the
16
+ * same `{ all, run }` contract as `@lunora/d1`'s `D1Exec`, so a Lunora D1 binding
17
+ * satisfies it directly (see {@link d1Executor}) and a `node:sqlite` handle does
18
+ * too in tests. `all` runs reads and returns rows; `run` runs writes.
19
+ */
20
20
  interface SqlExecutor {
21
21
  all: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
22
22
  run: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<void>;
23
23
  }
24
24
  /**
25
- * An {@link AuthStore} backed by a SQL database through the {@link SqlExecutor}
26
- * seam — the production counterpart to `createMemoryAuthStore`. Point it at the
27
- * same database that hosts Lunora's global (D1) tables (the ones `authTables(...)`
28
- * generates) and better-auth's reads/writes land there as ordinary rows Lunora
29
- * can also query. Assumes the auth tables already exist (Lunora owns the schema /
30
- * migrations); it never issues DDL.
31
- *
32
- * ```ts
33
- * const store = createSqlAuthStore(d1Executor(env.DB));
34
- * const auth = createAuth({ secret: env.AUTH_SECRET, database: lunoraAuthAdapter(store) });
35
- * ```
36
- *
37
- * Clause semantics match `createMemoryAuthStore` (operator parity is
38
- * covered by a cross-store agreement test) with one unavoidable caveat:
39
- * case-**insensitive** matching uses SQLite's ASCII-only `LOWER()`, whereas the
40
- * in-memory store uses JS full-Unicode `toLowerCase()`. They agree on ASCII
41
- * (emails, ids, tokens — the credential path); they can differ only for
42
- * case-insensitive comparison of non-ASCII text.
43
- */
25
+ * An {@link AuthStore} backed by a SQL database through the {@link SqlExecutor}
26
+ * seam — the production counterpart to `createMemoryAuthStore`. Point it at the
27
+ * same database that hosts Lunora's global (D1) tables (the ones `authTables(...)`
28
+ * generates) and better-auth's reads/writes land there as ordinary rows Lunora
29
+ * can also query. Assumes the auth tables already exist (Lunora owns the schema /
30
+ * migrations); it never issues DDL.
31
+ *
32
+ * ```ts
33
+ * const store = createSqlAuthStore(d1Executor(env.DB));
34
+ * const auth = createAuth({ secret: env.AUTH_SECRET, database: lunoraAuthAdapter(store) });
35
+ * ```
36
+ *
37
+ * Clause semantics match `createMemoryAuthStore` (operator parity is
38
+ * covered by a cross-store agreement test) with one unavoidable caveat:
39
+ * case-**insensitive** matching uses SQLite's ASCII-only `LOWER()`, whereas the
40
+ * in-memory store uses JS full-Unicode `toLowerCase()`. They agree on ASCII
41
+ * (emails, ids, tokens — the credential path); they can differ only for
42
+ * case-insensitive comparison of non-ASCII text.
43
+ */
44
44
  declare const createSqlAuthStore: (executor: SqlExecutor) => AuthStore;
45
45
  /**
46
- * Wrap a Cloudflare D1 binding (`env.DB`) as a {@link SqlExecutor}, so
47
- * `createSqlAuthStore(d1Executor(env.DB))` routes better-auth onto D1 — the same
48
- * binding Lunora's `.global()` tables use.
49
- */
46
+ * Wrap a Cloudflare D1 binding (`env.DB`) as a {@link SqlExecutor}, so
47
+ * `createSqlAuthStore(d1Executor(env.DB))` routes better-auth onto D1 — the same
48
+ * binding Lunora's `.global()` tables use.
49
+ */
50
50
  declare const d1Executor: (database: D1Like) => SqlExecutor;
51
51
  export { SqlExecutor, createSqlAuthStore, d1Executor };
package/dist/store.d.mts CHANGED
@@ -2,10 +2,10 @@ import { CustomAdapter } from 'better-auth/adapters';
2
2
  /** A stored auth row — an opaque bag of columns keyed by better-auth field name. */
3
3
  type AuthRow = Record<string, unknown>;
4
4
  /**
5
- * One normalized better-auth where clause. Derived from {@link CustomAdapter}'s
6
- * own method signature (rather than re-declared) so a better-auth change to the
7
- * clause shape surfaces as a compile error here, not a silent mis-match.
8
- */
5
+ * One normalized better-auth where clause. Derived from {@link CustomAdapter}'s
6
+ * own method signature (rather than re-declared) so a better-auth change to the
7
+ * clause shape surfaces as a compile error here, not a silent mis-match.
8
+ */
9
9
  type AuthWhereClause = NonNullable<Parameters<CustomAdapter["findOne"]>[0]["where"]>[number];
10
10
  /** Read query handed to {@link AuthStore.read}: a where filter plus optional sort/window. */
11
11
  interface AuthQuery {
@@ -18,48 +18,48 @@ interface AuthQuery {
18
18
  where: ReadonlyArray<AuthWhereClause>;
19
19
  }
20
20
  /**
21
- * The minimal table-addressed store the `lunoraAuthAdapter` drives. This is the
22
- * seam a Lunora runtime binds to its ORM: back each method with `ctx.db` over
23
- * the global (D1) auth tables that `authTables(...)` generates, and better-auth's
24
- * reads/writes flow through Lunora's data layer (triggers, aggregates, OCC)
25
- * instead of better-auth's own adapter. Field names and table (`model`) names are
26
- * already the database names better-auth resolved from the schema, so a store
27
- * passes them straight through.
28
- *
29
- * {@link createMemoryAuthStore} is a reference in-memory implementation (also
30
- * what the tests run better-auth against); `createSqlAuthStore` is the SQL one.
31
- */
21
+ * The minimal table-addressed store the `lunoraAuthAdapter` drives. This is the
22
+ * seam a Lunora runtime binds to its ORM: back each method with `ctx.db` over
23
+ * the global (D1) auth tables that `authTables(...)` generates, and better-auth's
24
+ * reads/writes flow through Lunora's data layer (triggers, aggregates, OCC)
25
+ * instead of better-auth's own adapter. Field names and table (`model`) names are
26
+ * already the database names better-auth resolved from the schema, so a store
27
+ * passes them straight through.
28
+ *
29
+ * {@link createMemoryAuthStore} is a reference in-memory implementation (also
30
+ * what the tests run better-auth against); `createSqlAuthStore` is the SQL one.
31
+ */
32
32
  interface AuthStore {
33
33
  /**
34
- * Atomically delete **at most one** row in `model` matching `where` and
35
- * return it (or `undefined` if none matched). Backs better-auth's
36
- * single-use-token consume (OTP / magic-link / email-verification /
37
- * password-reset): implementing it natively — one round trip that finds and
38
- * deletes in a single statement — closes the read-then-delete race the
39
- * factory's `findMany` + `deleteMany` fallback would otherwise leave open.
40
- */
34
+ * Atomically delete **at most one** row in `model` matching `where` and
35
+ * return it (or `undefined` if none matched). Backs better-auth's
36
+ * single-use-token consume (OTP / magic-link / email-verification /
37
+ * password-reset): implementing it natively — one round trip that finds and
38
+ * deletes in a single statement — closes the read-then-delete race the
39
+ * factory's `findMany` + `deleteMany` fallback would otherwise leave open.
40
+ */
41
41
  consumeOne: (model: string, where: ReadonlyArray<AuthWhereClause>) => Promise<AuthRow | undefined>;
42
42
  /** Count rows in `model` matching `where` (empty `where` = all rows). */
43
43
  count: (model: string, where: ReadonlyArray<AuthWhereClause>) => Promise<number>;
44
44
  /** Insert `data` into `model`; return the stored row (the adapter pre-fills `id`). */
45
45
  create: (model: string, data: AuthRow) => Promise<AuthRow>;
46
46
  /**
47
- * Atomically apply signed numeric deltas to **at most one** row in `model`
48
- * matching `where`, then return the updated row (or `undefined` if the guard
49
- * matched none). For each `increment` entry it applies `field = field + delta`
50
- * (a negative delta decrements); the optional `set` map assigns absolute
51
- * values in the same step. The `where` clause is both selector **and** guard
52
- * — comparison operators are honoured, so a guard like
53
- * `{ field: "count", operator: "lt", value: max }` only mutates the row while
54
- * it still satisfies the predicate.
55
- *
56
- * Backs better-auth's durable (`storage: "database"`) rate limiter, whose
57
- * counter rides these tables. Implementing it natively — one statement that
58
- * guards, increments, and returns — gives the **one-winner-across-isolates**
59
- * guarantee the read-then-update fallback cannot: on Workers two concurrent
60
- * requests would otherwise both read `count=4` and both write `5`, letting a
61
- * `max` of 5 pass 6+. Same race-closing rationale as {@link AuthStore.consumeOne}.
62
- */
47
+ * Atomically apply signed numeric deltas to **at most one** row in `model`
48
+ * matching `where`, then return the updated row (or `undefined` if the guard
49
+ * matched none). For each `increment` entry it applies `field = field + delta`
50
+ * (a negative delta decrements); the optional `set` map assigns absolute
51
+ * values in the same step. The `where` clause is both selector **and** guard
52
+ * — comparison operators are honoured, so a guard like
53
+ * `{ field: "count", operator: "lt", value: max }` only mutates the row while
54
+ * it still satisfies the predicate.
55
+ *
56
+ * Backs better-auth's durable (`storage: "database"`) rate limiter, whose
57
+ * counter rides these tables. Implementing it natively — one statement that
58
+ * guards, increments, and returns — gives the **one-winner-across-isolates**
59
+ * guarantee the read-then-update fallback cannot: on Workers two concurrent
60
+ * requests would otherwise both read `count=4` and both write `5`, letting a
61
+ * `max` of 5 pass 6+. Same race-closing rationale as {@link AuthStore.consumeOne}.
62
+ */
63
63
  incrementOne: (model: string, where: ReadonlyArray<AuthWhereClause>, increment: Record<string, number>, set?: AuthRow) => Promise<AuthRow | undefined>;
64
64
  /** Read rows from `model` honouring the filter/sort/window in `query`. */
65
65
  read: (model: string, query: AuthQuery) => Promise<AuthRow[]>;
@@ -69,16 +69,16 @@ interface AuthStore {
69
69
  update: (model: string, where: ReadonlyArray<AuthWhereClause>, values: AuthRow) => Promise<AuthRow[]>;
70
70
  }
71
71
  /**
72
- * Evaluate a better-auth where clause list against a row. Clauses fold
73
- * left-to-right by their `connector` (`AND` by default, `OR` when set) — the
74
- * same precedence better-auth's own adapters use. An empty list matches every
75
- * row. Exported so any in-memory-style {@link AuthStore} can reuse it.
76
- */
72
+ * Evaluate a better-auth where clause list against a row. Clauses fold
73
+ * left-to-right by their `connector` (`AND` by default, `OR` when set) — the
74
+ * same precedence better-auth's own adapters use. An empty list matches every
75
+ * row. Exported so any in-memory-style {@link AuthStore} can reuse it.
76
+ */
77
77
  declare const matchesWhere: (row: AuthRow, where: ReadonlyArray<AuthWhereClause>) => boolean;
78
78
  /**
79
- * Reference in-memory {@link AuthStore} — used to run better-auth end to end in
80
- * tests, and a worked example of the contract a Lunora-`ctx.db`-backed store
81
- * fulfils. Not for production (state is per-instance and non-durable).
82
- */
79
+ * Reference in-memory {@link AuthStore} — used to run better-auth end to end in
80
+ * tests, and a worked example of the contract a Lunora-`ctx.db`-backed store
81
+ * fulfils. Not for production (state is per-instance and non-durable).
82
+ */
83
83
  declare const createMemoryAuthStore: () => AuthStore;
84
84
  export { AuthQuery, type AuthRow, AuthStore, type AuthWhereClause, createMemoryAuthStore, matchesWhere };
package/dist/store.d.ts CHANGED
@@ -2,10 +2,10 @@ import { CustomAdapter } from 'better-auth/adapters';
2
2
  /** A stored auth row — an opaque bag of columns keyed by better-auth field name. */
3
3
  type AuthRow = Record<string, unknown>;
4
4
  /**
5
- * One normalized better-auth where clause. Derived from {@link CustomAdapter}'s
6
- * own method signature (rather than re-declared) so a better-auth change to the
7
- * clause shape surfaces as a compile error here, not a silent mis-match.
8
- */
5
+ * One normalized better-auth where clause. Derived from {@link CustomAdapter}'s
6
+ * own method signature (rather than re-declared) so a better-auth change to the
7
+ * clause shape surfaces as a compile error here, not a silent mis-match.
8
+ */
9
9
  type AuthWhereClause = NonNullable<Parameters<CustomAdapter["findOne"]>[0]["where"]>[number];
10
10
  /** Read query handed to {@link AuthStore.read}: a where filter plus optional sort/window. */
11
11
  interface AuthQuery {
@@ -18,48 +18,48 @@ interface AuthQuery {
18
18
  where: ReadonlyArray<AuthWhereClause>;
19
19
  }
20
20
  /**
21
- * The minimal table-addressed store the `lunoraAuthAdapter` drives. This is the
22
- * seam a Lunora runtime binds to its ORM: back each method with `ctx.db` over
23
- * the global (D1) auth tables that `authTables(...)` generates, and better-auth's
24
- * reads/writes flow through Lunora's data layer (triggers, aggregates, OCC)
25
- * instead of better-auth's own adapter. Field names and table (`model`) names are
26
- * already the database names better-auth resolved from the schema, so a store
27
- * passes them straight through.
28
- *
29
- * {@link createMemoryAuthStore} is a reference in-memory implementation (also
30
- * what the tests run better-auth against); `createSqlAuthStore` is the SQL one.
31
- */
21
+ * The minimal table-addressed store the `lunoraAuthAdapter` drives. This is the
22
+ * seam a Lunora runtime binds to its ORM: back each method with `ctx.db` over
23
+ * the global (D1) auth tables that `authTables(...)` generates, and better-auth's
24
+ * reads/writes flow through Lunora's data layer (triggers, aggregates, OCC)
25
+ * instead of better-auth's own adapter. Field names and table (`model`) names are
26
+ * already the database names better-auth resolved from the schema, so a store
27
+ * passes them straight through.
28
+ *
29
+ * {@link createMemoryAuthStore} is a reference in-memory implementation (also
30
+ * what the tests run better-auth against); `createSqlAuthStore` is the SQL one.
31
+ */
32
32
  interface AuthStore {
33
33
  /**
34
- * Atomically delete **at most one** row in `model` matching `where` and
35
- * return it (or `undefined` if none matched). Backs better-auth's
36
- * single-use-token consume (OTP / magic-link / email-verification /
37
- * password-reset): implementing it natively — one round trip that finds and
38
- * deletes in a single statement — closes the read-then-delete race the
39
- * factory's `findMany` + `deleteMany` fallback would otherwise leave open.
40
- */
34
+ * Atomically delete **at most one** row in `model` matching `where` and
35
+ * return it (or `undefined` if none matched). Backs better-auth's
36
+ * single-use-token consume (OTP / magic-link / email-verification /
37
+ * password-reset): implementing it natively — one round trip that finds and
38
+ * deletes in a single statement — closes the read-then-delete race the
39
+ * factory's `findMany` + `deleteMany` fallback would otherwise leave open.
40
+ */
41
41
  consumeOne: (model: string, where: ReadonlyArray<AuthWhereClause>) => Promise<AuthRow | undefined>;
42
42
  /** Count rows in `model` matching `where` (empty `where` = all rows). */
43
43
  count: (model: string, where: ReadonlyArray<AuthWhereClause>) => Promise<number>;
44
44
  /** Insert `data` into `model`; return the stored row (the adapter pre-fills `id`). */
45
45
  create: (model: string, data: AuthRow) => Promise<AuthRow>;
46
46
  /**
47
- * Atomically apply signed numeric deltas to **at most one** row in `model`
48
- * matching `where`, then return the updated row (or `undefined` if the guard
49
- * matched none). For each `increment` entry it applies `field = field + delta`
50
- * (a negative delta decrements); the optional `set` map assigns absolute
51
- * values in the same step. The `where` clause is both selector **and** guard
52
- * — comparison operators are honoured, so a guard like
53
- * `{ field: "count", operator: "lt", value: max }` only mutates the row while
54
- * it still satisfies the predicate.
55
- *
56
- * Backs better-auth's durable (`storage: "database"`) rate limiter, whose
57
- * counter rides these tables. Implementing it natively — one statement that
58
- * guards, increments, and returns — gives the **one-winner-across-isolates**
59
- * guarantee the read-then-update fallback cannot: on Workers two concurrent
60
- * requests would otherwise both read `count=4` and both write `5`, letting a
61
- * `max` of 5 pass 6+. Same race-closing rationale as {@link AuthStore.consumeOne}.
62
- */
47
+ * Atomically apply signed numeric deltas to **at most one** row in `model`
48
+ * matching `where`, then return the updated row (or `undefined` if the guard
49
+ * matched none). For each `increment` entry it applies `field = field + delta`
50
+ * (a negative delta decrements); the optional `set` map assigns absolute
51
+ * values in the same step. The `where` clause is both selector **and** guard
52
+ * — comparison operators are honoured, so a guard like
53
+ * `{ field: "count", operator: "lt", value: max }` only mutates the row while
54
+ * it still satisfies the predicate.
55
+ *
56
+ * Backs better-auth's durable (`storage: "database"`) rate limiter, whose
57
+ * counter rides these tables. Implementing it natively — one statement that
58
+ * guards, increments, and returns — gives the **one-winner-across-isolates**
59
+ * guarantee the read-then-update fallback cannot: on Workers two concurrent
60
+ * requests would otherwise both read `count=4` and both write `5`, letting a
61
+ * `max` of 5 pass 6+. Same race-closing rationale as {@link AuthStore.consumeOne}.
62
+ */
63
63
  incrementOne: (model: string, where: ReadonlyArray<AuthWhereClause>, increment: Record<string, number>, set?: AuthRow) => Promise<AuthRow | undefined>;
64
64
  /** Read rows from `model` honouring the filter/sort/window in `query`. */
65
65
  read: (model: string, query: AuthQuery) => Promise<AuthRow[]>;
@@ -69,16 +69,16 @@ interface AuthStore {
69
69
  update: (model: string, where: ReadonlyArray<AuthWhereClause>, values: AuthRow) => Promise<AuthRow[]>;
70
70
  }
71
71
  /**
72
- * Evaluate a better-auth where clause list against a row. Clauses fold
73
- * left-to-right by their `connector` (`AND` by default, `OR` when set) — the
74
- * same precedence better-auth's own adapters use. An empty list matches every
75
- * row. Exported so any in-memory-style {@link AuthStore} can reuse it.
76
- */
72
+ * Evaluate a better-auth where clause list against a row. Clauses fold
73
+ * left-to-right by their `connector` (`AND` by default, `OR` when set) — the
74
+ * same precedence better-auth's own adapters use. An empty list matches every
75
+ * row. Exported so any in-memory-style {@link AuthStore} can reuse it.
76
+ */
77
77
  declare const matchesWhere: (row: AuthRow, where: ReadonlyArray<AuthWhereClause>) => boolean;
78
78
  /**
79
- * Reference in-memory {@link AuthStore} — used to run better-auth end to end in
80
- * tests, and a worked example of the contract a Lunora-`ctx.db`-backed store
81
- * fulfils. Not for production (state is per-instance and non-durable).
82
- */
79
+ * Reference in-memory {@link AuthStore} — used to run better-auth end to end in
80
+ * tests, and a worked example of the contract a Lunora-`ctx.db`-backed store
81
+ * fulfils. Not for production (state is per-instance and non-durable).
82
+ */
83
83
  declare const createMemoryAuthStore: () => AuthStore;
84
84
  export { AuthQuery, type AuthRow, AuthStore, type AuthWhereClause, createMemoryAuthStore, matchesWhere };