@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/adapter.d.mts +35 -35
- package/dist/adapter.d.ts +35 -35
- package/dist/index.d.mts +170 -169
- package/dist/index.d.ts +170 -169
- package/dist/middleware.d.mts +154 -154
- package/dist/middleware.d.ts +154 -154
- package/dist/packem_shared/create-auth.d-COcIS_KU.d.mts +128 -0
- package/dist/packem_shared/create-auth.d-COcIS_KU.d.ts +128 -0
- package/dist/schema.d.mts +39 -39
- package/dist/schema.d.ts +39 -39
- package/dist/sql-store.d.mts +28 -28
- package/dist/sql-store.d.ts +28 -28
- package/dist/store.d.mts +47 -47
- package/dist/store.d.ts +47 -47
- package/dist/turnstile-middleware.d.mts +55 -55
- package/dist/turnstile-middleware.d.ts +55 -55
- package/dist/turnstile.d.mts +42 -49
- package/dist/turnstile.d.ts +42 -49
- package/package.json +4 -4
- package/dist/packem_shared/create-auth.d-Mwhb4gSc.d.mts +0 -128
- package/dist/packem_shared/create-auth.d-Mwhb4gSc.d.ts +0 -128
package/dist/adapter.d.mts
CHANGED
|
@@ -2,42 +2,42 @@ import { createAdapterFactory } from 'better-auth/adapters';
|
|
|
2
2
|
import { d1Executor } from "./sql-store.mjs";
|
|
3
3
|
import { AuthStore } from "./store.mjs";
|
|
4
4
|
/**
|
|
5
|
-
* A better-auth database adapter backed by an {@link AuthStore} — the bridge
|
|
6
|
-
* that routes better-auth's reads and writes through Lunora's data layer
|
|
7
|
-
* instead of better-auth's built-in D1/Kysely adapter. Pass the result as
|
|
8
|
-
* `createAuth({ database: lunoraAuthAdapter(store) })`; better-auth's
|
|
9
|
-
* `createAdapterFactory` handles id generation, default values, field-name
|
|
10
|
-
* mapping and output shaping, so this only translates the cleaned CRUD calls
|
|
11
|
-
* onto the store.
|
|
12
|
-
*
|
|
13
|
-
* ```ts
|
|
14
|
-
* const auth = createAuth({
|
|
15
|
-
* secret: env.AUTH_SECRET,
|
|
16
|
-
* emailAndPassword: { enabled: true },
|
|
17
|
-
* database: lunoraAuthAdapter(lunoraStore), // lunoraStore writes via ctx.db
|
|
18
|
-
* });
|
|
19
|
-
* ```
|
|
20
|
-
*
|
|
21
|
-
* Scope: the {@link AuthStore} interface is single-table CRUD. better-auth's
|
|
22
|
-
* relational `join` reads (an advanced opt-in) are not handled — pair the
|
|
23
|
-
* adapter with `disableJoins` or let better-auth fall back to per-table reads.
|
|
24
|
-
*/
|
|
5
|
+
* A better-auth database adapter backed by an {@link AuthStore} — the bridge
|
|
6
|
+
* that routes better-auth's reads and writes through Lunora's data layer
|
|
7
|
+
* instead of better-auth's built-in D1/Kysely adapter. Pass the result as
|
|
8
|
+
* `createAuth({ database: lunoraAuthAdapter(store) })`; better-auth's
|
|
9
|
+
* `createAdapterFactory` handles id generation, default values, field-name
|
|
10
|
+
* mapping and output shaping, so this only translates the cleaned CRUD calls
|
|
11
|
+
* onto the store.
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* const auth = createAuth({
|
|
15
|
+
* secret: env.AUTH_SECRET,
|
|
16
|
+
* emailAndPassword: { enabled: true },
|
|
17
|
+
* database: lunoraAuthAdapter(lunoraStore), // lunoraStore writes via ctx.db
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Scope: the {@link AuthStore} interface is single-table CRUD. better-auth's
|
|
22
|
+
* relational `join` reads (an advanced opt-in) are not handled — pair the
|
|
23
|
+
* adapter with `disableJoins` or let better-auth fall back to per-table reads.
|
|
24
|
+
*/
|
|
25
25
|
declare const lunoraAuthAdapter: (store: AuthStore) => ReturnType<typeof createAdapterFactory>;
|
|
26
26
|
/**
|
|
27
|
-
* One-liner for the common case: a better-auth `database` backed by a Cloudflare
|
|
28
|
-
* D1 binding, via Lunora's SQL store — equivalent to
|
|
29
|
-
* `lunoraAuthAdapter(createSqlAuthStore(d1Executor(d1)))`.
|
|
30
|
-
*
|
|
31
|
-
* Prefer this over passing the raw `env.DB` as `database`. With raw D1,
|
|
32
|
-
* better-auth resolves its Kysely adapter through a runtime `await import(...)`
|
|
33
|
-
* inside `auth.$context`, and that dynamic import never settles under
|
|
34
|
-
* `@cloudflare/vite-plugin`'s worker runner — so it hangs *every* auth request
|
|
35
|
-
* in `pnpm dev` (a standalone `wrangler dev` or a deployed worker bundle it
|
|
36
|
-
* up-front, so they're unaffected — which makes the hang baffling to debug).
|
|
37
|
-
* This explicit adapter skips that import entirely, so dev and prod behave the
|
|
38
|
-
* same. The migration instance is the one exception — it wants raw `env.DB` so
|
|
39
|
-
* `ensureMigrated`'s Kysely migrator can create the tables (its `$context` is
|
|
40
|
-
* never resolved, so the hang doesn't apply there).
|
|
41
|
-
*/
|
|
27
|
+
* One-liner for the common case: a better-auth `database` backed by a Cloudflare
|
|
28
|
+
* D1 binding, via Lunora's SQL store — equivalent to
|
|
29
|
+
* `lunoraAuthAdapter(createSqlAuthStore(d1Executor(d1)))`.
|
|
30
|
+
*
|
|
31
|
+
* Prefer this over passing the raw `env.DB` as `database`. With raw D1,
|
|
32
|
+
* better-auth resolves its Kysely adapter through a runtime `await import(...)`
|
|
33
|
+
* inside `auth.$context`, and that dynamic import never settles under
|
|
34
|
+
* `@cloudflare/vite-plugin`'s worker runner — so it hangs *every* auth request
|
|
35
|
+
* in `pnpm dev` (a standalone `wrangler dev` or a deployed worker bundle it
|
|
36
|
+
* up-front, so they're unaffected — which makes the hang baffling to debug).
|
|
37
|
+
* This explicit adapter skips that import entirely, so dev and prod behave the
|
|
38
|
+
* same. The migration instance is the one exception — it wants raw `env.DB` so
|
|
39
|
+
* `ensureMigrated`'s Kysely migrator can create the tables (its `$context` is
|
|
40
|
+
* never resolved, so the hang doesn't apply there).
|
|
41
|
+
*/
|
|
42
42
|
declare const lunoraD1Adapter: (d1: Parameters<typeof d1Executor>[0]) => ReturnType<typeof lunoraAuthAdapter>;
|
|
43
43
|
export { lunoraAuthAdapter, lunoraD1Adapter };
|
package/dist/adapter.d.ts
CHANGED
|
@@ -2,42 +2,42 @@ import { createAdapterFactory } from 'better-auth/adapters';
|
|
|
2
2
|
import { d1Executor } from "./sql-store.js";
|
|
3
3
|
import { AuthStore } from "./store.js";
|
|
4
4
|
/**
|
|
5
|
-
* A better-auth database adapter backed by an {@link AuthStore} — the bridge
|
|
6
|
-
* that routes better-auth's reads and writes through Lunora's data layer
|
|
7
|
-
* instead of better-auth's built-in D1/Kysely adapter. Pass the result as
|
|
8
|
-
* `createAuth({ database: lunoraAuthAdapter(store) })`; better-auth's
|
|
9
|
-
* `createAdapterFactory` handles id generation, default values, field-name
|
|
10
|
-
* mapping and output shaping, so this only translates the cleaned CRUD calls
|
|
11
|
-
* onto the store.
|
|
12
|
-
*
|
|
13
|
-
* ```ts
|
|
14
|
-
* const auth = createAuth({
|
|
15
|
-
* secret: env.AUTH_SECRET,
|
|
16
|
-
* emailAndPassword: { enabled: true },
|
|
17
|
-
* database: lunoraAuthAdapter(lunoraStore), // lunoraStore writes via ctx.db
|
|
18
|
-
* });
|
|
19
|
-
* ```
|
|
20
|
-
*
|
|
21
|
-
* Scope: the {@link AuthStore} interface is single-table CRUD. better-auth's
|
|
22
|
-
* relational `join` reads (an advanced opt-in) are not handled — pair the
|
|
23
|
-
* adapter with `disableJoins` or let better-auth fall back to per-table reads.
|
|
24
|
-
*/
|
|
5
|
+
* A better-auth database adapter backed by an {@link AuthStore} — the bridge
|
|
6
|
+
* that routes better-auth's reads and writes through Lunora's data layer
|
|
7
|
+
* instead of better-auth's built-in D1/Kysely adapter. Pass the result as
|
|
8
|
+
* `createAuth({ database: lunoraAuthAdapter(store) })`; better-auth's
|
|
9
|
+
* `createAdapterFactory` handles id generation, default values, field-name
|
|
10
|
+
* mapping and output shaping, so this only translates the cleaned CRUD calls
|
|
11
|
+
* onto the store.
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* const auth = createAuth({
|
|
15
|
+
* secret: env.AUTH_SECRET,
|
|
16
|
+
* emailAndPassword: { enabled: true },
|
|
17
|
+
* database: lunoraAuthAdapter(lunoraStore), // lunoraStore writes via ctx.db
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Scope: the {@link AuthStore} interface is single-table CRUD. better-auth's
|
|
22
|
+
* relational `join` reads (an advanced opt-in) are not handled — pair the
|
|
23
|
+
* adapter with `disableJoins` or let better-auth fall back to per-table reads.
|
|
24
|
+
*/
|
|
25
25
|
declare const lunoraAuthAdapter: (store: AuthStore) => ReturnType<typeof createAdapterFactory>;
|
|
26
26
|
/**
|
|
27
|
-
* One-liner for the common case: a better-auth `database` backed by a Cloudflare
|
|
28
|
-
* D1 binding, via Lunora's SQL store — equivalent to
|
|
29
|
-
* `lunoraAuthAdapter(createSqlAuthStore(d1Executor(d1)))`.
|
|
30
|
-
*
|
|
31
|
-
* Prefer this over passing the raw `env.DB` as `database`. With raw D1,
|
|
32
|
-
* better-auth resolves its Kysely adapter through a runtime `await import(...)`
|
|
33
|
-
* inside `auth.$context`, and that dynamic import never settles under
|
|
34
|
-
* `@cloudflare/vite-plugin`'s worker runner — so it hangs *every* auth request
|
|
35
|
-
* in `pnpm dev` (a standalone `wrangler dev` or a deployed worker bundle it
|
|
36
|
-
* up-front, so they're unaffected — which makes the hang baffling to debug).
|
|
37
|
-
* This explicit adapter skips that import entirely, so dev and prod behave the
|
|
38
|
-
* same. The migration instance is the one exception — it wants raw `env.DB` so
|
|
39
|
-
* `ensureMigrated`'s Kysely migrator can create the tables (its `$context` is
|
|
40
|
-
* never resolved, so the hang doesn't apply there).
|
|
41
|
-
*/
|
|
27
|
+
* One-liner for the common case: a better-auth `database` backed by a Cloudflare
|
|
28
|
+
* D1 binding, via Lunora's SQL store — equivalent to
|
|
29
|
+
* `lunoraAuthAdapter(createSqlAuthStore(d1Executor(d1)))`.
|
|
30
|
+
*
|
|
31
|
+
* Prefer this over passing the raw `env.DB` as `database`. With raw D1,
|
|
32
|
+
* better-auth resolves its Kysely adapter through a runtime `await import(...)`
|
|
33
|
+
* inside `auth.$context`, and that dynamic import never settles under
|
|
34
|
+
* `@cloudflare/vite-plugin`'s worker runner — so it hangs *every* auth request
|
|
35
|
+
* in `pnpm dev` (a standalone `wrangler dev` or a deployed worker bundle it
|
|
36
|
+
* up-front, so they're unaffected — which makes the hang baffling to debug).
|
|
37
|
+
* This explicit adapter skips that import entirely, so dev and prod behave the
|
|
38
|
+
* same. The migration instance is the one exception — it wants raw `env.DB` so
|
|
39
|
+
* `ensureMigrated`'s Kysely migrator can create the tables (its `$context` is
|
|
40
|
+
* never resolved, so the hang doesn't apply there).
|
|
41
|
+
*/
|
|
42
42
|
declare const lunoraD1Adapter: (d1: Parameters<typeof d1Executor>[0]) => ReturnType<typeof lunoraAuthAdapter>;
|
|
43
43
|
export { lunoraAuthAdapter, lunoraD1Adapter };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { lunoraAuthAdapter, lunoraD1Adapter } from "./adapter.mjs";
|
|
2
2
|
import { LunoraError } from '@lunora/errors';
|
|
3
|
-
import { L as LunoraAuth, a as LunoraAuthOptions } from "./packem_shared/create-auth.d-
|
|
4
|
-
export { c as createAuth, r as resolveAuthOptions } from "./packem_shared/create-auth.d-
|
|
3
|
+
import { L as LunoraAuth, a as LunoraAuthOptions } from "./packem_shared/create-auth.d-COcIS_KU.mjs";
|
|
4
|
+
export { c as createAuth, r as resolveAuthOptions } from "./packem_shared/create-auth.d-COcIS_KU.mjs";
|
|
5
5
|
export { type LunoraAuthApiContext, LunoraAuthHeadersError, type WithAuthPluginsMiddleware, type WithAuthPluginsOptions, withAuthPlugins } from "./middleware.mjs";
|
|
6
6
|
export { default as authTables } from "./schema.mjs";
|
|
7
7
|
import { BetterAuthOptions } from 'better-auth';
|
|
@@ -12,17 +12,17 @@ export { type VerifyTurnstileMiddlewareOptions, verifyTurnstileMiddleware } from
|
|
|
12
12
|
import 'better-auth/adapters';
|
|
13
13
|
import '@lunora/server';
|
|
14
14
|
/**
|
|
15
|
-
* A timestamp as it leaves the admin API: epoch-ms (better-auth stores `Date`s,
|
|
16
|
-
* which we normalize on output) or `null` when the column is unset.
|
|
17
|
-
*/
|
|
15
|
+
* A timestamp as it leaves the admin API: epoch-ms (better-auth stores `Date`s,
|
|
16
|
+
* which we normalize on output) or `null` when the column is unset.
|
|
17
|
+
*/
|
|
18
18
|
type AuthTimestamp = null | number;
|
|
19
19
|
/**
|
|
20
|
-
* One user row as the admin API surfaces it. The fixed keys mirror better-auth's
|
|
21
|
-
* core `user` table plus the `admin()` plugin columns (`role`/`banned`/…); the
|
|
22
|
-
* index signature carries any app-defined `user.additionalFields` so callers
|
|
23
|
-
* (the studio) can render them generically. Password material never lives on
|
|
24
|
-
* this row (it's in the `account` table) and is never returned.
|
|
25
|
-
*/
|
|
20
|
+
* One user row as the admin API surfaces it. The fixed keys mirror better-auth's
|
|
21
|
+
* core `user` table plus the `admin()` plugin columns (`role`/`banned`/…); the
|
|
22
|
+
* index signature carries any app-defined `user.additionalFields` so callers
|
|
23
|
+
* (the studio) can render them generically. Password material never lives on
|
|
24
|
+
* this row (it's in the `account` table) and is never returned.
|
|
25
|
+
*/
|
|
26
26
|
interface AuthAdminUser {
|
|
27
27
|
[key: string]: unknown;
|
|
28
28
|
banExpires?: AuthTimestamp;
|
|
@@ -38,12 +38,12 @@ interface AuthAdminUser {
|
|
|
38
38
|
updatedAt?: AuthTimestamp;
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
* One session row as the admin API surfaces it. Mirrors better-auth's `session`
|
|
42
|
-
* table; `impersonatedBy` is set when the session was minted by
|
|
43
|
-
* {@link AuthAdmin.impersonateUser}. The signing `token` is stripped — it's a
|
|
44
|
-
* bearer credential, and the only place we hand one back is the explicit
|
|
45
|
-
* impersonation flow.
|
|
46
|
-
*/
|
|
41
|
+
* One session row as the admin API surfaces it. Mirrors better-auth's `session`
|
|
42
|
+
* table; `impersonatedBy` is set when the session was minted by
|
|
43
|
+
* {@link AuthAdmin.impersonateUser}. The signing `token` is stripped — it's a
|
|
44
|
+
* bearer credential, and the only place we hand one back is the explicit
|
|
45
|
+
* impersonation flow.
|
|
46
|
+
*/
|
|
47
47
|
interface AuthAdminSession {
|
|
48
48
|
[key: string]: unknown;
|
|
49
49
|
createdAt?: AuthTimestamp;
|
|
@@ -108,10 +108,10 @@ interface AuthTeamMember {
|
|
|
108
108
|
userId: string;
|
|
109
109
|
}
|
|
110
110
|
/**
|
|
111
|
-
* One custom organization role (from the organization plugin's dynamic
|
|
112
|
-
* access-control). `permission` is a JSON string of a `resource → actions[]` map
|
|
113
|
-
* as stored; the studio parses it for display/editing.
|
|
114
|
-
*/
|
|
111
|
+
* One custom organization role (from the organization plugin's dynamic
|
|
112
|
+
* access-control). `permission` is a JSON string of a `resource → actions[]` map
|
|
113
|
+
* as stored; the studio parses it for display/editing.
|
|
114
|
+
*/
|
|
115
115
|
interface AuthOrgRole {
|
|
116
116
|
[key: string]: unknown;
|
|
117
117
|
createdAt?: AuthTimestamp;
|
|
@@ -135,12 +135,12 @@ interface AuthPage<T> {
|
|
|
135
135
|
total: number;
|
|
136
136
|
}
|
|
137
137
|
/**
|
|
138
|
-
* Which admin surfaces a given auth instance supports, derived from the enabled
|
|
139
|
-
* better-auth plugins (and any {@link CreateAuthAdminOptions.features} overrides).
|
|
140
|
-
* The studio calls {@link AuthAdmin.capabilities} once and renders only the
|
|
141
|
-
* panels whose capability is `true` — so a deployment that doesn't enable, say,
|
|
142
|
-
* the `organization` plugin never shows an Organizations section.
|
|
143
|
-
*/
|
|
138
|
+
* Which admin surfaces a given auth instance supports, derived from the enabled
|
|
139
|
+
* better-auth plugins (and any {@link CreateAuthAdminOptions.features} overrides).
|
|
140
|
+
* The studio calls {@link AuthAdmin.capabilities} once and renders only the
|
|
141
|
+
* panels whose capability is `true` — so a deployment that doesn't enable, say,
|
|
142
|
+
* the `organization` plugin never shows an Organizations section.
|
|
143
|
+
*/
|
|
144
144
|
interface AuthCapabilities {
|
|
145
145
|
/** Linked-account browsing/unlinking — core (the `account` table always exists). */
|
|
146
146
|
accounts: boolean;
|
|
@@ -154,12 +154,12 @@ interface AuthCapabilities {
|
|
|
154
154
|
twoFactor: boolean;
|
|
155
155
|
}
|
|
156
156
|
/**
|
|
157
|
-
* One app/plugin-defined field the create-user form should render, derived from
|
|
158
|
-
* the merged better-auth `user` table (core + plugin + `additionalFields`). Only
|
|
159
|
-
* user-settable columns are surfaced — server-managed flags (`input: false`),
|
|
160
|
-
* foreign keys (`references`), and the core columns the form already handles
|
|
161
|
-
* (`email`/`name`/`role`/ban state/…) are filtered out upstream.
|
|
162
|
-
*/
|
|
157
|
+
* One app/plugin-defined field the create-user form should render, derived from
|
|
158
|
+
* the merged better-auth `user` table (core + plugin + `additionalFields`). Only
|
|
159
|
+
* user-settable columns are surfaced — server-managed flags (`input: false`),
|
|
160
|
+
* foreign keys (`references`), and the core columns the form already handles
|
|
161
|
+
* (`email`/`name`/`role`/ban state/…) are filtered out upstream.
|
|
162
|
+
*/
|
|
163
163
|
interface AuthUserFieldSpec {
|
|
164
164
|
/** Logical field name (the key passed back in `createUser`'s `data`). */
|
|
165
165
|
name: string;
|
|
@@ -171,13 +171,13 @@ interface AuthUserFieldSpec {
|
|
|
171
171
|
unique: boolean;
|
|
172
172
|
}
|
|
173
173
|
/**
|
|
174
|
-
* A rich, read-only description of the deployment's auth configuration for the
|
|
175
|
-
* studio's config panel and dynamic create-user form. Unlike
|
|
176
|
-
* {@link AuthCapabilities} (five booleans that gate panels), this exposes *what*
|
|
177
|
-
* is configured — enabled plugins, email/password + social sign-in, the
|
|
178
|
-
* user-settable fields, organization sub-features (teams / custom roles), and
|
|
179
|
-
* the session + rate-limit policy — without ever leaking a secret.
|
|
180
|
-
*/
|
|
174
|
+
* A rich, read-only description of the deployment's auth configuration for the
|
|
175
|
+
* studio's config panel and dynamic create-user form. Unlike
|
|
176
|
+
* {@link AuthCapabilities} (five booleans that gate panels), this exposes *what*
|
|
177
|
+
* is configured — enabled plugins, email/password + social sign-in, the
|
|
178
|
+
* user-settable fields, organization sub-features (teams / custom roles), and
|
|
179
|
+
* the session + rate-limit policy — without ever leaking a secret.
|
|
180
|
+
*/
|
|
181
181
|
interface AuthConfigInfo {
|
|
182
182
|
/** The same capability booleans {@link AuthAdmin.capabilities} returns, embedded so a single call drives the whole panel. */
|
|
183
183
|
capabilities: AuthCapabilities;
|
|
@@ -185,7 +185,8 @@ interface AuthConfigInfo {
|
|
|
185
185
|
emailAndPassword: boolean;
|
|
186
186
|
/** Organization plugin sub-features. */
|
|
187
187
|
organization: {
|
|
188
|
-
enabled: boolean;
|
|
188
|
+
enabled: boolean;
|
|
189
|
+
/** Custom roles / dynamic access control (`organizationRole` table present). */
|
|
189
190
|
roles: boolean;
|
|
190
191
|
/** Teams (`team` table present). */
|
|
191
192
|
teams: boolean;
|
|
@@ -236,14 +237,14 @@ interface ImpersonationResult {
|
|
|
236
237
|
user: AuthAdminUser;
|
|
237
238
|
}
|
|
238
239
|
/**
|
|
239
|
-
* The full read + write surface the studio's auth dashboard drives, backed by
|
|
240
|
-
* better-auth's tables. Returned by {@link createAuthAdmin}. The runtime accepts
|
|
241
|
-
* a structurally-compatible object as its `authAdmin` option and exposes each
|
|
242
|
-
* method behind an admin-token-gated endpoint. Methods whose backing plugin is
|
|
243
|
-
* absent still exist (they're not conditionally omitted) but the studio gates
|
|
244
|
-
* them on {@link AuthAdmin.capabilities}; calling one for an unconfigured plugin
|
|
245
|
-
* surfaces the underlying adapter error.
|
|
246
|
-
*/
|
|
240
|
+
* The full read + write surface the studio's auth dashboard drives, backed by
|
|
241
|
+
* better-auth's tables. Returned by {@link createAuthAdmin}. The runtime accepts
|
|
242
|
+
* a structurally-compatible object as its `authAdmin` option and exposes each
|
|
243
|
+
* method behind an admin-token-gated endpoint. Methods whose backing plugin is
|
|
244
|
+
* absent still exist (they're not conditionally omitted) but the studio gates
|
|
245
|
+
* them on {@link AuthAdmin.capabilities}; calling one for an unconfigured plugin
|
|
246
|
+
* surfaces the underlying adapter error.
|
|
247
|
+
*/
|
|
247
248
|
interface AuthAdmin {
|
|
248
249
|
/** Directly add an existing user as an org member (server-side, no invitation/acceptance). */
|
|
249
250
|
addMember: (input: {
|
|
@@ -427,152 +428,152 @@ interface AuthAdmin {
|
|
|
427
428
|
/** Options for {@link createAuthAdmin}. */
|
|
428
429
|
interface CreateAuthAdminOptions {
|
|
429
430
|
/**
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
431
|
+
* Force individual {@link AuthCapabilities} on or off regardless of which
|
|
432
|
+
* plugins are detected — e.g. `{ impersonate: false }`-style opt-outs by
|
|
433
|
+
* setting `admin: false`, or hiding linked accounts with `accounts: false`.
|
|
434
|
+
* A capability is reported only when both its plugin is enabled *and* its
|
|
435
|
+
* override isn't `false`.
|
|
436
|
+
*/
|
|
436
437
|
features?: Partial<AuthCapabilities>;
|
|
437
438
|
/**
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
439
|
+
* User id recorded as the impersonator on sessions minted by
|
|
440
|
+
* {@link AuthAdmin.impersonateUser}. Defaults to the impersonated user's own
|
|
441
|
+
* id (a self-reference) since the trusted admin plane has no acting user.
|
|
442
|
+
*/
|
|
442
443
|
impersonatedBy?: string;
|
|
443
444
|
/**
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
445
|
+
* How long (in seconds) an impersonation session lives. Must be a positive
|
|
446
|
+
* finite integer. Capped at 24 × {@link DEFAULT_IMPERSONATION_SECONDS}
|
|
447
|
+
* (86 400 s / 24 h). Defaults to {@link DEFAULT_IMPERSONATION_SECONDS}
|
|
448
|
+
* (3 600 s / 1 h).
|
|
449
|
+
*/
|
|
449
450
|
impersonationSeconds?: number;
|
|
450
451
|
}
|
|
451
452
|
/**
|
|
452
|
-
* A normalized failure from an admin operation. better-auth throws `APIError`s
|
|
453
|
-
* carrying a `body.code` (e.g. `USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL`); we
|
|
454
|
-
* surface that `code` so the runtime can map it onto an HTTP status and the
|
|
455
|
-
* studio can show a meaningful message instead of a generic 500.
|
|
456
|
-
*/
|
|
453
|
+
* A normalized failure from an admin operation. better-auth throws `APIError`s
|
|
454
|
+
* carrying a `body.code` (e.g. `USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL`); we
|
|
455
|
+
* surface that `code` so the runtime can map it onto an HTTP status and the
|
|
456
|
+
* studio can show a meaningful message instead of a generic 500.
|
|
457
|
+
*/
|
|
457
458
|
declare class LunoraAuthAdminError extends LunoraError {
|
|
458
459
|
constructor(message: string, code: string);
|
|
459
460
|
}
|
|
460
461
|
/**
|
|
461
|
-
* Build the studio's auth user-management plane on top of better-auth.
|
|
462
|
-
*
|
|
463
|
-
* Pass the result as the runtime's `authAdmin` option; the runtime exposes each
|
|
464
|
-
* method behind an admin-token-gated `/_lunora/admin/auth/*` endpoint. The set
|
|
465
|
-
* of usable surfaces is reported by {@link AuthAdmin.capabilities} — derived
|
|
466
|
-
* from the enabled better-auth plugins, so enabling `admin()`, `organization()`,
|
|
467
|
-
* `twoFactor()`, or the passkey plugin in the auth config is what lights up the
|
|
468
|
-
* matching dashboard panels.
|
|
469
|
-
*
|
|
470
|
-
* **Trust model — important.** These operations talk to better-auth's
|
|
471
|
-
* `internalAdapter` (and `adapter`/password hasher) **directly**, deliberately
|
|
472
|
-
* bypassing the plugins' own endpoints, which require the caller to hold an
|
|
473
|
-
* admin-role session. That session check is the wrong gate here: the runtime
|
|
474
|
-
* already authorizes every call with `LUNORA_ADMIN_TOKEN`, so this helper acts
|
|
475
|
-
* as a trusted server-side operator. It is therefore not an end-user-callable
|
|
476
|
-
* API — never expose it on a path that isn't admin-token gated.
|
|
477
|
-
*
|
|
478
|
-
* `auth.$context` is a promise (better-auth resolves the adapter, password
|
|
479
|
-
* config, etc. lazily); we memoize it so the first call pays the cost once.
|
|
480
|
-
*/
|
|
462
|
+
* Build the studio's auth user-management plane on top of better-auth.
|
|
463
|
+
*
|
|
464
|
+
* Pass the result as the runtime's `authAdmin` option; the runtime exposes each
|
|
465
|
+
* method behind an admin-token-gated `/_lunora/admin/auth/*` endpoint. The set
|
|
466
|
+
* of usable surfaces is reported by {@link AuthAdmin.capabilities} — derived
|
|
467
|
+
* from the enabled better-auth plugins, so enabling `admin()`, `organization()`,
|
|
468
|
+
* `twoFactor()`, or the passkey plugin in the auth config is what lights up the
|
|
469
|
+
* matching dashboard panels.
|
|
470
|
+
*
|
|
471
|
+
* **Trust model — important.** These operations talk to better-auth's
|
|
472
|
+
* `internalAdapter` (and `adapter`/password hasher) **directly**, deliberately
|
|
473
|
+
* bypassing the plugins' own endpoints, which require the caller to hold an
|
|
474
|
+
* admin-role session. That session check is the wrong gate here: the runtime
|
|
475
|
+
* already authorizes every call with `LUNORA_ADMIN_TOKEN`, so this helper acts
|
|
476
|
+
* as a trusted server-side operator. It is therefore not an end-user-callable
|
|
477
|
+
* API — never expose it on a path that isn't admin-token gated.
|
|
478
|
+
*
|
|
479
|
+
* `auth.$context` is a promise (better-auth resolves the adapter, password
|
|
480
|
+
* config, etc. lazily); we memoize it so the first call pays the cost once.
|
|
481
|
+
*/
|
|
481
482
|
declare const createAuthAdmin: (auth: LunoraAuth, options?: CreateAuthAdminOptions) => AuthAdmin;
|
|
482
483
|
/**
|
|
483
|
-
* Default basePath used by better-auth's client + handler. Override via the
|
|
484
|
-
* second argument if you mount the auth routes somewhere else.
|
|
485
|
-
*/
|
|
484
|
+
* Default basePath used by better-auth's client + handler. Override via the
|
|
485
|
+
* second argument if you mount the auth routes somewhere else.
|
|
486
|
+
*/
|
|
486
487
|
declare const DEFAULT_AUTH_BASE_PATH: string;
|
|
487
488
|
/**
|
|
488
|
-
* Route an inbound `Request` to better-auth if the path falls under
|
|
489
|
-
* `basePath`; otherwise return `null` so the caller can continue dispatching.
|
|
490
|
-
*
|
|
491
|
-
* Better-auth handles arbitrarily nested paths (`/api/auth/sign-in/email`,
|
|
492
|
-
* `/api/auth/callback/github`, …), so we use prefix matching instead of the
|
|
493
|
-
* exact-path map `createWorker` consumes for top-level routes.
|
|
494
|
-
*/
|
|
489
|
+
* Route an inbound `Request` to better-auth if the path falls under
|
|
490
|
+
* `basePath`; otherwise return `null` so the caller can continue dispatching.
|
|
491
|
+
*
|
|
492
|
+
* Better-auth handles arbitrarily nested paths (`/api/auth/sign-in/email`,
|
|
493
|
+
* `/api/auth/callback/github`, …), so we use prefix matching instead of the
|
|
494
|
+
* exact-path map `createWorker` consumes for top-level routes.
|
|
495
|
+
*/
|
|
495
496
|
declare const handleAuthRequest: (auth: LunoraAuth, request: Request, basePath?: string) => Promise<Response | undefined>;
|
|
496
497
|
/**
|
|
497
|
-
* Apply better-auth's required schema (`user`, `session`, `account`,
|
|
498
|
-
* `verification`) to the configured database. Idempotent — better-auth
|
|
499
|
-
* diffs the existing schema and only runs the missing DDL.
|
|
500
|
-
*
|
|
501
|
-
* Cached per `options` reference so the diff cost (one PRAGMA-style sweep
|
|
502
|
-
* per table) doesn't fire on every request. In Cloudflare Workers the same
|
|
503
|
-
* `env.DB` binding is reused across invocations within a single isolate, so
|
|
504
|
-
* caching against the options object — which captures the binding — is
|
|
505
|
-
* sufficient.
|
|
506
|
-
*
|
|
507
|
-
* For production you should prefer pre-applying the schema at deploy time
|
|
508
|
-
* via `compileMigrationsSql` + `wrangler d1 execute`; this helper exists for
|
|
509
|
-
* dev/playground and small deployments.
|
|
510
|
-
*/
|
|
498
|
+
* Apply better-auth's required schema (`user`, `session`, `account`,
|
|
499
|
+
* `verification`) to the configured database. Idempotent — better-auth
|
|
500
|
+
* diffs the existing schema and only runs the missing DDL.
|
|
501
|
+
*
|
|
502
|
+
* Cached per `options` reference so the diff cost (one PRAGMA-style sweep
|
|
503
|
+
* per table) doesn't fire on every request. In Cloudflare Workers the same
|
|
504
|
+
* `env.DB` binding is reused across invocations within a single isolate, so
|
|
505
|
+
* caching against the options object — which captures the binding — is
|
|
506
|
+
* sufficient.
|
|
507
|
+
*
|
|
508
|
+
* For production you should prefer pre-applying the schema at deploy time
|
|
509
|
+
* via `compileMigrationsSql` + `wrangler d1 execute`; this helper exists for
|
|
510
|
+
* dev/playground and small deployments.
|
|
511
|
+
*/
|
|
511
512
|
declare const ensureMigrated: (auth: LunoraAuth | {
|
|
512
513
|
options: LunoraAuthOptions;
|
|
513
514
|
}) => Promise<void>;
|
|
514
515
|
/**
|
|
515
|
-
* Compile better-auth's migrations to a single SQL string. Useful for
|
|
516
|
-
* `wrangler d1 execute --file -` in CI so the deploy step applies the schema
|
|
517
|
-
* before the first user request.
|
|
518
|
-
*
|
|
519
|
-
* Compiles from the SAME resolved options `createAuth` runs with (via
|
|
520
|
-
* `resolveAuthOptions`), not the raw caller options — so the schema includes the
|
|
521
|
-
* `rateLimit` table the worker's default-on durable limiter writes to. Compiling
|
|
522
|
-
* from the raw options would omit it, and the running worker would then write to
|
|
523
|
-
* a table the migration never created.
|
|
524
|
-
*/
|
|
516
|
+
* Compile better-auth's migrations to a single SQL string. Useful for
|
|
517
|
+
* `wrangler d1 execute --file -` in CI so the deploy step applies the schema
|
|
518
|
+
* before the first user request.
|
|
519
|
+
*
|
|
520
|
+
* Compiles from the SAME resolved options `createAuth` runs with (via
|
|
521
|
+
* `resolveAuthOptions`), not the raw caller options — so the schema includes the
|
|
522
|
+
* `rateLimit` table the worker's default-on durable limiter writes to. Compiling
|
|
523
|
+
* from the raw options would omit it, and the running worker would then write to
|
|
524
|
+
* a table the migration never created.
|
|
525
|
+
*/
|
|
525
526
|
declare const compileMigrationsSql: (options: LunoraAuthOptions) => Promise<string>;
|
|
526
527
|
/**
|
|
527
|
-
* Lunora-friendly view over better-auth's `session` option.
|
|
528
|
-
*
|
|
529
|
-
* This is a typed alias for better-auth's own `session` shape — Lunora stays a
|
|
530
|
-
* thin wrapper, so we don't reimplement the fields, we just give them a named,
|
|
531
|
-
* documented home so callers get autocomplete without reaching into
|
|
532
|
-
* `BetterAuthOptions`. The most relevant fields for session rotation / richer
|
|
533
|
-
* policies are `expiresIn` (absolute session lifetime, in seconds),
|
|
534
|
-
* `updateAge` (rolling-rotation interval, in seconds — how often an active
|
|
535
|
-
* session's expiry is pushed forward; `0` rotates on every use),
|
|
536
|
-
* `disableSessionRefresh` (turn rolling rotation off entirely so sessions
|
|
537
|
-
* expire at the absolute `expiresIn` regardless of activity), `freshAge`
|
|
538
|
-
* (freshness window, in seconds, for sensitive operations like account
|
|
539
|
-
* deletion; `0` treats every session as fresh — not recommended), and
|
|
540
|
-
* `cookieCache` (opt-in signed-cookie session cache to skip DB reads).
|
|
541
|
-
*
|
|
542
|
-
* See better-auth's `session` option for the full field list.
|
|
543
|
-
*/
|
|
528
|
+
* Lunora-friendly view over better-auth's `session` option.
|
|
529
|
+
*
|
|
530
|
+
* This is a typed alias for better-auth's own `session` shape — Lunora stays a
|
|
531
|
+
* thin wrapper, so we don't reimplement the fields, we just give them a named,
|
|
532
|
+
* documented home so callers get autocomplete without reaching into
|
|
533
|
+
* `BetterAuthOptions`. The most relevant fields for session rotation / richer
|
|
534
|
+
* policies are `expiresIn` (absolute session lifetime, in seconds),
|
|
535
|
+
* `updateAge` (rolling-rotation interval, in seconds — how often an active
|
|
536
|
+
* session's expiry is pushed forward; `0` rotates on every use),
|
|
537
|
+
* `disableSessionRefresh` (turn rolling rotation off entirely so sessions
|
|
538
|
+
* expire at the absolute `expiresIn` regardless of activity), `freshAge`
|
|
539
|
+
* (freshness window, in seconds, for sensitive operations like account
|
|
540
|
+
* deletion; `0` treats every session as fresh — not recommended), and
|
|
541
|
+
* `cookieCache` (opt-in signed-cookie session cache to skip DB reads).
|
|
542
|
+
*
|
|
543
|
+
* See better-auth's `session` option for the full field list.
|
|
544
|
+
*/
|
|
544
545
|
type SessionPolicy = NonNullable<BetterAuthOptions["session"]>;
|
|
545
546
|
/**
|
|
546
|
-
* Validate a {@link SessionPolicy} and return it unchanged (pass-through).
|
|
547
|
-
*
|
|
548
|
-
* better-auth happily accepts the `session` block verbatim, so the only job
|
|
549
|
-
* here is to catch obviously-broken numeric inputs at construction time —
|
|
550
|
-
* negative or non-finite durations — rather than letting them produce
|
|
551
|
-
* surprising cookie expiries at runtime. Field names mirror better-auth's
|
|
552
|
-
* `session` option exactly so the validated object forwards 1:1.
|
|
553
|
-
*/
|
|
547
|
+
* Validate a {@link SessionPolicy} and return it unchanged (pass-through).
|
|
548
|
+
*
|
|
549
|
+
* better-auth happily accepts the `session` block verbatim, so the only job
|
|
550
|
+
* here is to catch obviously-broken numeric inputs at construction time —
|
|
551
|
+
* negative or non-finite durations — rather than letting them produce
|
|
552
|
+
* surprising cookie expiries at runtime. Field names mirror better-auth's
|
|
553
|
+
* `session` option exactly so the validated object forwards 1:1.
|
|
554
|
+
*/
|
|
554
555
|
declare const validateSessionPolicy: (policy: SessionPolicy) => SessionPolicy;
|
|
555
556
|
/**
|
|
556
|
-
* Ready-made {@link SessionPolicy} presets covering the common rotation /
|
|
557
|
-
* expiry trade-offs. Spread or override fields as needed:
|
|
558
|
-
*
|
|
559
|
-
* ```ts
|
|
560
|
-
* import { createAuth, sessionPresets } from "@lunora/auth";
|
|
561
|
-
*
|
|
562
|
-
* export const auth = createAuth({
|
|
563
|
-
* secret: env.AUTH_SECRET,
|
|
564
|
-
* database: env.DB,
|
|
565
|
-
* session: { ...sessionPresets.rolling, freshAge: 60 * 5 },
|
|
566
|
-
* });
|
|
567
|
-
* ```
|
|
568
|
-
*
|
|
569
|
-
* - `rolling` — balanced default: 7-day absolute expiry, rotated once per day,
|
|
570
|
-
* with a 60s signed-cookie session cache so bursts of authenticated calls
|
|
571
|
-
* skip the per-request DB session read.
|
|
572
|
-
* - `strict` — short, security-sensitive: 1-hour expiry, 15-minute rotation,
|
|
573
|
-
* cookie cache **off** (fast revocation / short freshness is the whole point).
|
|
574
|
-
* - `longLived` — low-friction consumer apps: 30-day expiry, daily rotation,
|
|
575
|
-
* with the same 60s cookie cache as `rolling`.
|
|
576
|
-
*/
|
|
557
|
+
* Ready-made {@link SessionPolicy} presets covering the common rotation /
|
|
558
|
+
* expiry trade-offs. Spread or override fields as needed:
|
|
559
|
+
*
|
|
560
|
+
* ```ts
|
|
561
|
+
* import { createAuth, sessionPresets } from "@lunora/auth";
|
|
562
|
+
*
|
|
563
|
+
* export const auth = createAuth({
|
|
564
|
+
* secret: env.AUTH_SECRET,
|
|
565
|
+
* database: env.DB,
|
|
566
|
+
* session: { ...sessionPresets.rolling, freshAge: 60 * 5 },
|
|
567
|
+
* });
|
|
568
|
+
* ```
|
|
569
|
+
*
|
|
570
|
+
* - `rolling` — balanced default: 7-day absolute expiry, rotated once per day,
|
|
571
|
+
* with a 60s signed-cookie session cache so bursts of authenticated calls
|
|
572
|
+
* skip the per-request DB session read.
|
|
573
|
+
* - `strict` — short, security-sensitive: 1-hour expiry, 15-minute rotation,
|
|
574
|
+
* cookie cache **off** (fast revocation / short freshness is the whole point).
|
|
575
|
+
* - `longLived` — low-friction consumer apps: 30-day expiry, daily rotation,
|
|
576
|
+
* with the same 60s cookie cache as `rolling`.
|
|
577
|
+
*/
|
|
577
578
|
declare const sessionPresets: Record<"longLived" | "rolling" | "strict", SessionPolicy>;
|
|
578
579
|
export { type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthCapabilities, type AuthConfigInfo, type AuthInvitation, type AuthMember, type AuthOrgRole, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthTeam, type AuthTeamMember, type AuthTimestamp, type AuthUserFieldSpec, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, type LunoraAuthOptions, type SessionPolicy, compileMigrationsSql, createAuthAdmin, ensureMigrated, handleAuthRequest, sessionPresets, validateSessionPolicy };
|