@lunora/auth 1.0.0-alpha.2 → 1.0.0-alpha.21
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/LICENSE.md +6 -0
- package/__assets__/package-og.svg +1 -1
- package/dist/adapter.mjs +1 -0
- package/dist/index.d.mts +199 -7
- package/dist/index.d.ts +199 -7
- package/dist/index.mjs +4 -4
- package/dist/middleware.d.mts +3 -2
- package/dist/middleware.d.ts +3 -2
- package/dist/middleware.mjs +6 -3
- package/dist/packem_shared/LunoraAuthAdminError-D4L7n6gN.mjs +510 -0
- package/dist/packem_shared/{compileMigrationsSql-wZH3oXDu.mjs → compileMigrationsSql-B9bj-mJv.mjs} +2 -1
- package/dist/packem_shared/create-auth.d-Mwhb4gSc.d.mts +128 -0
- package/dist/packem_shared/create-auth.d-Mwhb4gSc.d.ts +128 -0
- package/dist/packem_shared/{createAuth-B-tvsvQU.mjs → createAuth-BVMMllTm.mjs} +39 -8
- package/dist/packem_shared/{sessionPresets-B95rXrd8.mjs → sessionPresets-Dwwd74_J.mjs} +3 -0
- package/dist/schema.d.mts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/sql-store.mjs +22 -0
- package/dist/store.d.mts +18 -0
- package/dist/store.d.ts +18 -0
- package/dist/store.mjs +13 -0
- package/package.json +7 -6
- package/dist/packem_shared/LunoraAuthAdminError-BxrfEeA_.mjs +0 -249
- package/dist/packem_shared/create-auth.d-M36jwG_Y.d.mts +0 -58
- package/dist/packem_shared/create-auth.d-M36jwG_Y.d.ts +0 -58
package/dist/adapter.mjs
CHANGED
|
@@ -19,6 +19,7 @@ const lunoraAuthAdapter = (store) => createAdapterFactory({
|
|
|
19
19
|
const [row] = await store.read(model, { limit: 1, where });
|
|
20
20
|
return asRowOrNull(row);
|
|
21
21
|
},
|
|
22
|
+
incrementOne: async ({ increment, model, set, where }) => asRowOrNull(await store.incrementOne(model, where, increment, set)),
|
|
22
23
|
update: async ({ model, update, where }) => {
|
|
23
24
|
const [row] = await store.update(model, where, update);
|
|
24
25
|
return asRowOrNull(row);
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { lunoraAuthAdapter, lunoraD1Adapter } from "./adapter.mjs";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { LunoraError } from '@lunora/errors';
|
|
3
|
+
import { L as LunoraAuth, a as LunoraAuthOptions } from "./packem_shared/create-auth.d-Mwhb4gSc.mjs";
|
|
4
|
+
export { c as createAuth, r as resolveAuthOptions } from "./packem_shared/create-auth.d-Mwhb4gSc.mjs";
|
|
4
5
|
export { type LunoraAuthApiContext, LunoraAuthHeadersError, type WithAuthPluginsMiddleware, type WithAuthPluginsOptions, withAuthPlugins } from "./middleware.mjs";
|
|
5
6
|
export { default as authTables } from "./schema.mjs";
|
|
6
7
|
import { BetterAuthOptions } from 'better-auth';
|
|
@@ -90,6 +91,35 @@ interface AuthInvitation {
|
|
|
90
91
|
role?: null | string;
|
|
91
92
|
status?: null | string;
|
|
92
93
|
}
|
|
94
|
+
/** One team row (from the `organization` plugin with `teams.enabled`). */
|
|
95
|
+
interface AuthTeam {
|
|
96
|
+
[key: string]: unknown;
|
|
97
|
+
createdAt?: AuthTimestamp;
|
|
98
|
+
id: string;
|
|
99
|
+
name?: null | string;
|
|
100
|
+
organizationId: string;
|
|
101
|
+
}
|
|
102
|
+
/** One team-membership row (teams). */
|
|
103
|
+
interface AuthTeamMember {
|
|
104
|
+
[key: string]: unknown;
|
|
105
|
+
createdAt?: AuthTimestamp;
|
|
106
|
+
id: string;
|
|
107
|
+
teamId: string;
|
|
108
|
+
userId: string;
|
|
109
|
+
}
|
|
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
|
+
*/
|
|
115
|
+
interface AuthOrgRole {
|
|
116
|
+
[key: string]: unknown;
|
|
117
|
+
createdAt?: AuthTimestamp;
|
|
118
|
+
id: string;
|
|
119
|
+
organizationId: string;
|
|
120
|
+
permission?: null | string;
|
|
121
|
+
role?: null | string;
|
|
122
|
+
}
|
|
93
123
|
/** One registered passkey. Credential secrets (`publicKey`) are stripped. */
|
|
94
124
|
interface AuthPasskey {
|
|
95
125
|
[key: string]: unknown;
|
|
@@ -123,6 +153,63 @@ interface AuthCapabilities {
|
|
|
123
153
|
/** The `two-factor` plugin: per-user 2FA status / disable. */
|
|
124
154
|
twoFactor: boolean;
|
|
125
155
|
}
|
|
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
|
+
*/
|
|
163
|
+
interface AuthUserFieldSpec {
|
|
164
|
+
/** Logical field name (the key passed back in `createUser`'s `data`). */
|
|
165
|
+
name: string;
|
|
166
|
+
/** Best-effort plugin id the field originates from (`username`, `phone-number`, …); `undefined` for app `additionalFields`. */
|
|
167
|
+
plugin?: string;
|
|
168
|
+
required: boolean;
|
|
169
|
+
/** Coarse input kind the studio maps to a control (checkbox / number / date / text). */
|
|
170
|
+
type: "boolean" | "date" | "number" | "string";
|
|
171
|
+
unique: boolean;
|
|
172
|
+
}
|
|
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
|
+
*/
|
|
181
|
+
interface AuthConfigInfo {
|
|
182
|
+
/** The same capability booleans {@link AuthAdmin.capabilities} returns, embedded so a single call drives the whole panel. */
|
|
183
|
+
capabilities: AuthCapabilities;
|
|
184
|
+
/** Whether email + password sign-in is enabled. */
|
|
185
|
+
emailAndPassword: boolean;
|
|
186
|
+
/** Organization plugin sub-features. */
|
|
187
|
+
organization: {
|
|
188
|
+
enabled: boolean; /** Custom roles / dynamic access control (`organizationRole` table present). */
|
|
189
|
+
roles: boolean;
|
|
190
|
+
/** Teams (`team` table present). */
|
|
191
|
+
teams: boolean;
|
|
192
|
+
};
|
|
193
|
+
/** Enabled better-auth plugin ids, sorted. */
|
|
194
|
+
plugins: string[];
|
|
195
|
+
/** Rate-limit policy (window is in seconds). */
|
|
196
|
+
rateLimit: {
|
|
197
|
+
enabled: boolean;
|
|
198
|
+
max?: number;
|
|
199
|
+
window?: number;
|
|
200
|
+
};
|
|
201
|
+
/** Session policy (all durations in seconds). */
|
|
202
|
+
session: {
|
|
203
|
+
cookieCache?: boolean;
|
|
204
|
+
expiresIn?: number;
|
|
205
|
+
freshAge?: number;
|
|
206
|
+
updateAge?: number;
|
|
207
|
+
};
|
|
208
|
+
/** Configured social/OAuth provider ids, sorted. */
|
|
209
|
+
socialProviders: string[];
|
|
210
|
+
/** User-settable extra fields for the create-user form (plugin + app `additionalFields`). */
|
|
211
|
+
userFields: AuthUserFieldSpec[];
|
|
212
|
+
}
|
|
126
213
|
/** A scalar value usable in an adapter `where` clause / filter. */
|
|
127
214
|
type WhereValue = boolean | number | string;
|
|
128
215
|
/** Filtering / paging options for {@link AuthAdmin.listUsers}. */
|
|
@@ -158,6 +245,17 @@ interface ImpersonationResult {
|
|
|
158
245
|
* surfaces the underlying adapter error.
|
|
159
246
|
*/
|
|
160
247
|
interface AuthAdmin {
|
|
248
|
+
/** Directly add an existing user as an org member (server-side, no invitation/acceptance). */
|
|
249
|
+
addMember: (input: {
|
|
250
|
+
organizationId: string;
|
|
251
|
+
role?: string;
|
|
252
|
+
userId: string;
|
|
253
|
+
}) => Promise<AuthMember>;
|
|
254
|
+
/** Add a user to a team. */
|
|
255
|
+
addTeamMember: (input: {
|
|
256
|
+
teamId: string;
|
|
257
|
+
userId: string;
|
|
258
|
+
}) => Promise<AuthTeamMember>;
|
|
161
259
|
banUser: (input: {
|
|
162
260
|
expiresInSeconds?: number;
|
|
163
261
|
reason?: string;
|
|
@@ -167,6 +265,27 @@ interface AuthAdmin {
|
|
|
167
265
|
invitationId: string;
|
|
168
266
|
}) => Promise<void>;
|
|
169
267
|
capabilities: () => Promise<AuthCapabilities>;
|
|
268
|
+
/** Rich, read-only description of the auth configuration (plugins, fields, session policy, …). */
|
|
269
|
+
config: () => Promise<AuthConfigInfo>;
|
|
270
|
+
/** Create an organization; optionally seed an `owner` member for `ownerId`. */
|
|
271
|
+
createOrganization: (input: {
|
|
272
|
+
logo?: string;
|
|
273
|
+
metadata?: Record<string, unknown>;
|
|
274
|
+
name: string;
|
|
275
|
+
ownerId?: string;
|
|
276
|
+
slug?: string;
|
|
277
|
+
}) => Promise<AuthOrganization>;
|
|
278
|
+
/** Create a custom org role with a permission grant (a `resource → actions[]` map). */
|
|
279
|
+
createOrgRole: (input: {
|
|
280
|
+
organizationId: string;
|
|
281
|
+
permission: Record<string, string[]>;
|
|
282
|
+
role: string;
|
|
283
|
+
}) => Promise<AuthOrgRole>;
|
|
284
|
+
/** Create a team under an organization. */
|
|
285
|
+
createTeam: (input: {
|
|
286
|
+
name: string;
|
|
287
|
+
organizationId: string;
|
|
288
|
+
}) => Promise<AuthTeam>;
|
|
170
289
|
createUser: (input: {
|
|
171
290
|
data?: Record<string, unknown>;
|
|
172
291
|
email: string;
|
|
@@ -174,6 +293,14 @@ interface AuthAdmin {
|
|
|
174
293
|
password?: string;
|
|
175
294
|
role?: string | string[];
|
|
176
295
|
}) => Promise<AuthAdminUser>;
|
|
296
|
+
/** Delete an organization and cascade-delete its members, invitations, teams, and custom roles. */
|
|
297
|
+
deleteOrganization: (input: {
|
|
298
|
+
organizationId: string;
|
|
299
|
+
}) => Promise<void>;
|
|
300
|
+
/** Delete a custom org role. */
|
|
301
|
+
deleteOrgRole: (input: {
|
|
302
|
+
roleId: string;
|
|
303
|
+
}) => Promise<void>;
|
|
177
304
|
deletePasskey: (input: {
|
|
178
305
|
passkeyId: string;
|
|
179
306
|
}) => Promise<void>;
|
|
@@ -183,6 +310,13 @@ interface AuthAdmin {
|
|
|
183
310
|
impersonateUser: (input: {
|
|
184
311
|
userId: string;
|
|
185
312
|
}) => Promise<ImpersonationResult>;
|
|
313
|
+
/** Create a pending email invitation to an org (no acceptance side effects). */
|
|
314
|
+
inviteMember: (input: {
|
|
315
|
+
email: string;
|
|
316
|
+
inviterId?: string;
|
|
317
|
+
organizationId: string;
|
|
318
|
+
role?: string;
|
|
319
|
+
}) => Promise<AuthInvitation>;
|
|
186
320
|
listAccounts: (input: {
|
|
187
321
|
userId: string;
|
|
188
322
|
}) => Promise<AuthAccount[]>;
|
|
@@ -200,6 +334,12 @@ interface AuthAdmin {
|
|
|
200
334
|
limit?: number;
|
|
201
335
|
offset?: number;
|
|
202
336
|
}) => Promise<AuthPage<AuthOrganization>>;
|
|
337
|
+
/** List an org's custom roles. */
|
|
338
|
+
listOrgRoles: (options: {
|
|
339
|
+
limit?: number;
|
|
340
|
+
offset?: number;
|
|
341
|
+
organizationId: string;
|
|
342
|
+
}) => Promise<AuthPage<AuthOrgRole>>;
|
|
203
343
|
listPasskeys: (input: {
|
|
204
344
|
userId: string;
|
|
205
345
|
}) => Promise<AuthPasskey[]>;
|
|
@@ -208,10 +348,30 @@ interface AuthAdmin {
|
|
|
208
348
|
offset?: number;
|
|
209
349
|
userId?: string;
|
|
210
350
|
}) => Promise<AuthPage<AuthAdminSession>>;
|
|
351
|
+
/** List a team's members. */
|
|
352
|
+
listTeamMembers: (options: {
|
|
353
|
+
limit?: number;
|
|
354
|
+
offset?: number;
|
|
355
|
+
teamId: string;
|
|
356
|
+
}) => Promise<AuthPage<AuthTeamMember>>;
|
|
357
|
+
/** List an org's teams. */
|
|
358
|
+
listTeams: (options: {
|
|
359
|
+
limit?: number;
|
|
360
|
+
offset?: number;
|
|
361
|
+
organizationId: string;
|
|
362
|
+
}) => Promise<AuthPage<AuthTeam>>;
|
|
211
363
|
listUsers: (options: ListUsersOptions) => Promise<AuthPage<AuthAdminUser>>;
|
|
212
364
|
removeMember: (input: {
|
|
213
365
|
memberId: string;
|
|
214
366
|
}) => Promise<void>;
|
|
367
|
+
/** Delete a team and its memberships. */
|
|
368
|
+
removeTeam: (input: {
|
|
369
|
+
teamId: string;
|
|
370
|
+
}) => Promise<void>;
|
|
371
|
+
/** Remove a member from a team. */
|
|
372
|
+
removeTeamMember: (input: {
|
|
373
|
+
teamMemberId: string;
|
|
374
|
+
}) => Promise<void>;
|
|
215
375
|
removeUser: (input: {
|
|
216
376
|
userId: string;
|
|
217
377
|
}) => Promise<void>;
|
|
@@ -236,6 +396,29 @@ interface AuthAdmin {
|
|
|
236
396
|
accountId: string;
|
|
237
397
|
userId: string;
|
|
238
398
|
}) => Promise<void>;
|
|
399
|
+
/** Change a member's role. */
|
|
400
|
+
updateMemberRole: (input: {
|
|
401
|
+
memberId: string;
|
|
402
|
+
role: string | string[];
|
|
403
|
+
}) => Promise<AuthMember>;
|
|
404
|
+
/** Update an organization's name/slug/logo/metadata. */
|
|
405
|
+
updateOrganization: (input: {
|
|
406
|
+
logo?: string;
|
|
407
|
+
metadata?: Record<string, unknown>;
|
|
408
|
+
name?: string;
|
|
409
|
+
organizationId: string;
|
|
410
|
+
slug?: string;
|
|
411
|
+
}) => Promise<AuthOrganization>;
|
|
412
|
+
/** Replace a custom org role's permission grant. */
|
|
413
|
+
updateOrgRole: (input: {
|
|
414
|
+
permission: Record<string, string[]>;
|
|
415
|
+
roleId: string;
|
|
416
|
+
}) => Promise<AuthOrgRole>;
|
|
417
|
+
/** Rename a team. */
|
|
418
|
+
updateTeam: (input: {
|
|
419
|
+
name: string;
|
|
420
|
+
teamId: string;
|
|
421
|
+
}) => Promise<AuthTeam>;
|
|
239
422
|
updateUser: (input: {
|
|
240
423
|
data: Record<string, unknown>;
|
|
241
424
|
userId: string;
|
|
@@ -271,8 +454,7 @@ interface CreateAuthAdminOptions {
|
|
|
271
454
|
* surface that `code` so the runtime can map it onto an HTTP status and the
|
|
272
455
|
* studio can show a meaningful message instead of a generic 500.
|
|
273
456
|
*/
|
|
274
|
-
declare class LunoraAuthAdminError extends
|
|
275
|
-
readonly code: string;
|
|
457
|
+
declare class LunoraAuthAdminError extends LunoraError {
|
|
276
458
|
constructor(message: string, code: string);
|
|
277
459
|
}
|
|
278
460
|
/**
|
|
@@ -333,6 +515,12 @@ declare const ensureMigrated: (auth: LunoraAuth | {
|
|
|
333
515
|
* Compile better-auth's migrations to a single SQL string. Useful for
|
|
334
516
|
* `wrangler d1 execute --file -` in CI so the deploy step applies the schema
|
|
335
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.
|
|
336
524
|
*/
|
|
337
525
|
declare const compileMigrationsSql: (options: LunoraAuthOptions) => Promise<string>;
|
|
338
526
|
/**
|
|
@@ -378,9 +566,13 @@ declare const validateSessionPolicy: (policy: SessionPolicy) => SessionPolicy;
|
|
|
378
566
|
* });
|
|
379
567
|
* ```
|
|
380
568
|
*
|
|
381
|
-
* - `rolling` — balanced default: 7-day absolute expiry, rotated once per day
|
|
382
|
-
* -
|
|
383
|
-
*
|
|
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`.
|
|
384
576
|
*/
|
|
385
577
|
declare const sessionPresets: Record<"longLived" | "rolling" | "strict", SessionPolicy>;
|
|
386
578
|
export { type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthCapabilities, type AuthInvitation, type AuthMember, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthTimestamp, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, type LunoraAuthOptions, type SessionPolicy, compileMigrationsSql, createAuthAdmin, ensureMigrated, handleAuthRequest, sessionPresets, validateSessionPolicy };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { lunoraAuthAdapter, lunoraD1Adapter } from "./adapter.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { LunoraError } from '@lunora/errors';
|
|
3
|
+
import { L as LunoraAuth, a as LunoraAuthOptions } from "./packem_shared/create-auth.d-Mwhb4gSc.js";
|
|
4
|
+
export { c as createAuth, r as resolveAuthOptions } from "./packem_shared/create-auth.d-Mwhb4gSc.js";
|
|
4
5
|
export { type LunoraAuthApiContext, LunoraAuthHeadersError, type WithAuthPluginsMiddleware, type WithAuthPluginsOptions, withAuthPlugins } from "./middleware.js";
|
|
5
6
|
export { default as authTables } from "./schema.js";
|
|
6
7
|
import { BetterAuthOptions } from 'better-auth';
|
|
@@ -90,6 +91,35 @@ interface AuthInvitation {
|
|
|
90
91
|
role?: null | string;
|
|
91
92
|
status?: null | string;
|
|
92
93
|
}
|
|
94
|
+
/** One team row (from the `organization` plugin with `teams.enabled`). */
|
|
95
|
+
interface AuthTeam {
|
|
96
|
+
[key: string]: unknown;
|
|
97
|
+
createdAt?: AuthTimestamp;
|
|
98
|
+
id: string;
|
|
99
|
+
name?: null | string;
|
|
100
|
+
organizationId: string;
|
|
101
|
+
}
|
|
102
|
+
/** One team-membership row (teams). */
|
|
103
|
+
interface AuthTeamMember {
|
|
104
|
+
[key: string]: unknown;
|
|
105
|
+
createdAt?: AuthTimestamp;
|
|
106
|
+
id: string;
|
|
107
|
+
teamId: string;
|
|
108
|
+
userId: string;
|
|
109
|
+
}
|
|
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
|
+
*/
|
|
115
|
+
interface AuthOrgRole {
|
|
116
|
+
[key: string]: unknown;
|
|
117
|
+
createdAt?: AuthTimestamp;
|
|
118
|
+
id: string;
|
|
119
|
+
organizationId: string;
|
|
120
|
+
permission?: null | string;
|
|
121
|
+
role?: null | string;
|
|
122
|
+
}
|
|
93
123
|
/** One registered passkey. Credential secrets (`publicKey`) are stripped. */
|
|
94
124
|
interface AuthPasskey {
|
|
95
125
|
[key: string]: unknown;
|
|
@@ -123,6 +153,63 @@ interface AuthCapabilities {
|
|
|
123
153
|
/** The `two-factor` plugin: per-user 2FA status / disable. */
|
|
124
154
|
twoFactor: boolean;
|
|
125
155
|
}
|
|
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
|
+
*/
|
|
163
|
+
interface AuthUserFieldSpec {
|
|
164
|
+
/** Logical field name (the key passed back in `createUser`'s `data`). */
|
|
165
|
+
name: string;
|
|
166
|
+
/** Best-effort plugin id the field originates from (`username`, `phone-number`, …); `undefined` for app `additionalFields`. */
|
|
167
|
+
plugin?: string;
|
|
168
|
+
required: boolean;
|
|
169
|
+
/** Coarse input kind the studio maps to a control (checkbox / number / date / text). */
|
|
170
|
+
type: "boolean" | "date" | "number" | "string";
|
|
171
|
+
unique: boolean;
|
|
172
|
+
}
|
|
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
|
+
*/
|
|
181
|
+
interface AuthConfigInfo {
|
|
182
|
+
/** The same capability booleans {@link AuthAdmin.capabilities} returns, embedded so a single call drives the whole panel. */
|
|
183
|
+
capabilities: AuthCapabilities;
|
|
184
|
+
/** Whether email + password sign-in is enabled. */
|
|
185
|
+
emailAndPassword: boolean;
|
|
186
|
+
/** Organization plugin sub-features. */
|
|
187
|
+
organization: {
|
|
188
|
+
enabled: boolean; /** Custom roles / dynamic access control (`organizationRole` table present). */
|
|
189
|
+
roles: boolean;
|
|
190
|
+
/** Teams (`team` table present). */
|
|
191
|
+
teams: boolean;
|
|
192
|
+
};
|
|
193
|
+
/** Enabled better-auth plugin ids, sorted. */
|
|
194
|
+
plugins: string[];
|
|
195
|
+
/** Rate-limit policy (window is in seconds). */
|
|
196
|
+
rateLimit: {
|
|
197
|
+
enabled: boolean;
|
|
198
|
+
max?: number;
|
|
199
|
+
window?: number;
|
|
200
|
+
};
|
|
201
|
+
/** Session policy (all durations in seconds). */
|
|
202
|
+
session: {
|
|
203
|
+
cookieCache?: boolean;
|
|
204
|
+
expiresIn?: number;
|
|
205
|
+
freshAge?: number;
|
|
206
|
+
updateAge?: number;
|
|
207
|
+
};
|
|
208
|
+
/** Configured social/OAuth provider ids, sorted. */
|
|
209
|
+
socialProviders: string[];
|
|
210
|
+
/** User-settable extra fields for the create-user form (plugin + app `additionalFields`). */
|
|
211
|
+
userFields: AuthUserFieldSpec[];
|
|
212
|
+
}
|
|
126
213
|
/** A scalar value usable in an adapter `where` clause / filter. */
|
|
127
214
|
type WhereValue = boolean | number | string;
|
|
128
215
|
/** Filtering / paging options for {@link AuthAdmin.listUsers}. */
|
|
@@ -158,6 +245,17 @@ interface ImpersonationResult {
|
|
|
158
245
|
* surfaces the underlying adapter error.
|
|
159
246
|
*/
|
|
160
247
|
interface AuthAdmin {
|
|
248
|
+
/** Directly add an existing user as an org member (server-side, no invitation/acceptance). */
|
|
249
|
+
addMember: (input: {
|
|
250
|
+
organizationId: string;
|
|
251
|
+
role?: string;
|
|
252
|
+
userId: string;
|
|
253
|
+
}) => Promise<AuthMember>;
|
|
254
|
+
/** Add a user to a team. */
|
|
255
|
+
addTeamMember: (input: {
|
|
256
|
+
teamId: string;
|
|
257
|
+
userId: string;
|
|
258
|
+
}) => Promise<AuthTeamMember>;
|
|
161
259
|
banUser: (input: {
|
|
162
260
|
expiresInSeconds?: number;
|
|
163
261
|
reason?: string;
|
|
@@ -167,6 +265,27 @@ interface AuthAdmin {
|
|
|
167
265
|
invitationId: string;
|
|
168
266
|
}) => Promise<void>;
|
|
169
267
|
capabilities: () => Promise<AuthCapabilities>;
|
|
268
|
+
/** Rich, read-only description of the auth configuration (plugins, fields, session policy, …). */
|
|
269
|
+
config: () => Promise<AuthConfigInfo>;
|
|
270
|
+
/** Create an organization; optionally seed an `owner` member for `ownerId`. */
|
|
271
|
+
createOrganization: (input: {
|
|
272
|
+
logo?: string;
|
|
273
|
+
metadata?: Record<string, unknown>;
|
|
274
|
+
name: string;
|
|
275
|
+
ownerId?: string;
|
|
276
|
+
slug?: string;
|
|
277
|
+
}) => Promise<AuthOrganization>;
|
|
278
|
+
/** Create a custom org role with a permission grant (a `resource → actions[]` map). */
|
|
279
|
+
createOrgRole: (input: {
|
|
280
|
+
organizationId: string;
|
|
281
|
+
permission: Record<string, string[]>;
|
|
282
|
+
role: string;
|
|
283
|
+
}) => Promise<AuthOrgRole>;
|
|
284
|
+
/** Create a team under an organization. */
|
|
285
|
+
createTeam: (input: {
|
|
286
|
+
name: string;
|
|
287
|
+
organizationId: string;
|
|
288
|
+
}) => Promise<AuthTeam>;
|
|
170
289
|
createUser: (input: {
|
|
171
290
|
data?: Record<string, unknown>;
|
|
172
291
|
email: string;
|
|
@@ -174,6 +293,14 @@ interface AuthAdmin {
|
|
|
174
293
|
password?: string;
|
|
175
294
|
role?: string | string[];
|
|
176
295
|
}) => Promise<AuthAdminUser>;
|
|
296
|
+
/** Delete an organization and cascade-delete its members, invitations, teams, and custom roles. */
|
|
297
|
+
deleteOrganization: (input: {
|
|
298
|
+
organizationId: string;
|
|
299
|
+
}) => Promise<void>;
|
|
300
|
+
/** Delete a custom org role. */
|
|
301
|
+
deleteOrgRole: (input: {
|
|
302
|
+
roleId: string;
|
|
303
|
+
}) => Promise<void>;
|
|
177
304
|
deletePasskey: (input: {
|
|
178
305
|
passkeyId: string;
|
|
179
306
|
}) => Promise<void>;
|
|
@@ -183,6 +310,13 @@ interface AuthAdmin {
|
|
|
183
310
|
impersonateUser: (input: {
|
|
184
311
|
userId: string;
|
|
185
312
|
}) => Promise<ImpersonationResult>;
|
|
313
|
+
/** Create a pending email invitation to an org (no acceptance side effects). */
|
|
314
|
+
inviteMember: (input: {
|
|
315
|
+
email: string;
|
|
316
|
+
inviterId?: string;
|
|
317
|
+
organizationId: string;
|
|
318
|
+
role?: string;
|
|
319
|
+
}) => Promise<AuthInvitation>;
|
|
186
320
|
listAccounts: (input: {
|
|
187
321
|
userId: string;
|
|
188
322
|
}) => Promise<AuthAccount[]>;
|
|
@@ -200,6 +334,12 @@ interface AuthAdmin {
|
|
|
200
334
|
limit?: number;
|
|
201
335
|
offset?: number;
|
|
202
336
|
}) => Promise<AuthPage<AuthOrganization>>;
|
|
337
|
+
/** List an org's custom roles. */
|
|
338
|
+
listOrgRoles: (options: {
|
|
339
|
+
limit?: number;
|
|
340
|
+
offset?: number;
|
|
341
|
+
organizationId: string;
|
|
342
|
+
}) => Promise<AuthPage<AuthOrgRole>>;
|
|
203
343
|
listPasskeys: (input: {
|
|
204
344
|
userId: string;
|
|
205
345
|
}) => Promise<AuthPasskey[]>;
|
|
@@ -208,10 +348,30 @@ interface AuthAdmin {
|
|
|
208
348
|
offset?: number;
|
|
209
349
|
userId?: string;
|
|
210
350
|
}) => Promise<AuthPage<AuthAdminSession>>;
|
|
351
|
+
/** List a team's members. */
|
|
352
|
+
listTeamMembers: (options: {
|
|
353
|
+
limit?: number;
|
|
354
|
+
offset?: number;
|
|
355
|
+
teamId: string;
|
|
356
|
+
}) => Promise<AuthPage<AuthTeamMember>>;
|
|
357
|
+
/** List an org's teams. */
|
|
358
|
+
listTeams: (options: {
|
|
359
|
+
limit?: number;
|
|
360
|
+
offset?: number;
|
|
361
|
+
organizationId: string;
|
|
362
|
+
}) => Promise<AuthPage<AuthTeam>>;
|
|
211
363
|
listUsers: (options: ListUsersOptions) => Promise<AuthPage<AuthAdminUser>>;
|
|
212
364
|
removeMember: (input: {
|
|
213
365
|
memberId: string;
|
|
214
366
|
}) => Promise<void>;
|
|
367
|
+
/** Delete a team and its memberships. */
|
|
368
|
+
removeTeam: (input: {
|
|
369
|
+
teamId: string;
|
|
370
|
+
}) => Promise<void>;
|
|
371
|
+
/** Remove a member from a team. */
|
|
372
|
+
removeTeamMember: (input: {
|
|
373
|
+
teamMemberId: string;
|
|
374
|
+
}) => Promise<void>;
|
|
215
375
|
removeUser: (input: {
|
|
216
376
|
userId: string;
|
|
217
377
|
}) => Promise<void>;
|
|
@@ -236,6 +396,29 @@ interface AuthAdmin {
|
|
|
236
396
|
accountId: string;
|
|
237
397
|
userId: string;
|
|
238
398
|
}) => Promise<void>;
|
|
399
|
+
/** Change a member's role. */
|
|
400
|
+
updateMemberRole: (input: {
|
|
401
|
+
memberId: string;
|
|
402
|
+
role: string | string[];
|
|
403
|
+
}) => Promise<AuthMember>;
|
|
404
|
+
/** Update an organization's name/slug/logo/metadata. */
|
|
405
|
+
updateOrganization: (input: {
|
|
406
|
+
logo?: string;
|
|
407
|
+
metadata?: Record<string, unknown>;
|
|
408
|
+
name?: string;
|
|
409
|
+
organizationId: string;
|
|
410
|
+
slug?: string;
|
|
411
|
+
}) => Promise<AuthOrganization>;
|
|
412
|
+
/** Replace a custom org role's permission grant. */
|
|
413
|
+
updateOrgRole: (input: {
|
|
414
|
+
permission: Record<string, string[]>;
|
|
415
|
+
roleId: string;
|
|
416
|
+
}) => Promise<AuthOrgRole>;
|
|
417
|
+
/** Rename a team. */
|
|
418
|
+
updateTeam: (input: {
|
|
419
|
+
name: string;
|
|
420
|
+
teamId: string;
|
|
421
|
+
}) => Promise<AuthTeam>;
|
|
239
422
|
updateUser: (input: {
|
|
240
423
|
data: Record<string, unknown>;
|
|
241
424
|
userId: string;
|
|
@@ -271,8 +454,7 @@ interface CreateAuthAdminOptions {
|
|
|
271
454
|
* surface that `code` so the runtime can map it onto an HTTP status and the
|
|
272
455
|
* studio can show a meaningful message instead of a generic 500.
|
|
273
456
|
*/
|
|
274
|
-
declare class LunoraAuthAdminError extends
|
|
275
|
-
readonly code: string;
|
|
457
|
+
declare class LunoraAuthAdminError extends LunoraError {
|
|
276
458
|
constructor(message: string, code: string);
|
|
277
459
|
}
|
|
278
460
|
/**
|
|
@@ -333,6 +515,12 @@ declare const ensureMigrated: (auth: LunoraAuth | {
|
|
|
333
515
|
* Compile better-auth's migrations to a single SQL string. Useful for
|
|
334
516
|
* `wrangler d1 execute --file -` in CI so the deploy step applies the schema
|
|
335
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.
|
|
336
524
|
*/
|
|
337
525
|
declare const compileMigrationsSql: (options: LunoraAuthOptions) => Promise<string>;
|
|
338
526
|
/**
|
|
@@ -378,9 +566,13 @@ declare const validateSessionPolicy: (policy: SessionPolicy) => SessionPolicy;
|
|
|
378
566
|
* });
|
|
379
567
|
* ```
|
|
380
568
|
*
|
|
381
|
-
* - `rolling` — balanced default: 7-day absolute expiry, rotated once per day
|
|
382
|
-
* -
|
|
383
|
-
*
|
|
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`.
|
|
384
576
|
*/
|
|
385
577
|
declare const sessionPresets: Record<"longLived" | "rolling" | "strict", SessionPolicy>;
|
|
386
578
|
export { type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthCapabilities, type AuthInvitation, type AuthMember, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthTimestamp, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, type LunoraAuthOptions, type SessionPolicy, compileMigrationsSql, createAuthAdmin, ensureMigrated, handleAuthRequest, sessionPresets, validateSessionPolicy };
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { lunoraAuthAdapter, lunoraD1Adapter } from './adapter.mjs';
|
|
2
|
-
export { LunoraAuthAdminError, createAuthAdmin } from './packem_shared/LunoraAuthAdminError-
|
|
3
|
-
export { createAuth } from './packem_shared/createAuth-
|
|
2
|
+
export { LunoraAuthAdminError, createAuthAdmin } from './packem_shared/LunoraAuthAdminError-D4L7n6gN.mjs';
|
|
3
|
+
export { createAuth, resolveAuthOptions } from './packem_shared/createAuth-BVMMllTm.mjs';
|
|
4
4
|
export { DEFAULT_AUTH_BASE_PATH, handleAuthRequest } from './packem_shared/DEFAULT_AUTH_BASE_PATH-DjcUWEQl.mjs';
|
|
5
5
|
export { LunoraAuthHeadersError, withAuthPlugins } from './middleware.mjs';
|
|
6
|
-
export { compileMigrationsSql, ensureMigrated } from './packem_shared/compileMigrationsSql-
|
|
6
|
+
export { compileMigrationsSql, ensureMigrated } from './packem_shared/compileMigrationsSql-B9bj-mJv.mjs';
|
|
7
7
|
export { default as authTables } from './schema.mjs';
|
|
8
|
-
export { sessionPresets, validateSessionPolicy } from './packem_shared/sessionPresets-
|
|
8
|
+
export { sessionPresets, validateSessionPolicy } from './packem_shared/sessionPresets-Dwwd74_J.mjs';
|
|
9
9
|
export { createSqlAuthStore, d1Executor } from './sql-store.mjs';
|
|
10
10
|
export { createMemoryAuthStore, matchesWhere } from './store.mjs';
|
|
11
11
|
export { TURNSTILE_VERIFY_ENDPOINT, verifyTurnstile } from './turnstile.mjs';
|
package/dist/middleware.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
import { L as LunoraAuth } from "./packem_shared/create-auth.d-Mwhb4gSc.mjs";
|
|
2
3
|
import 'better-auth';
|
|
3
4
|
/**
|
|
4
5
|
* Structural mirror of `@lunora/server`'s `MiddlewareNext` — the continuation
|
|
@@ -22,7 +23,7 @@ interface MiddlewareNext<ContextIn> {
|
|
|
22
23
|
* advisor lint — both treat a header-less `ctx.authApi.*` call as an
|
|
23
24
|
* authorization bypass, so a call that trips the lint also trips this guard.
|
|
24
25
|
*/
|
|
25
|
-
declare class LunoraAuthHeadersError extends
|
|
26
|
+
declare class LunoraAuthHeadersError extends LunoraError {
|
|
26
27
|
/** The `ctx.authApi.<method>` that was called without `headers`. */
|
|
27
28
|
readonly method: string;
|
|
28
29
|
constructor(method: string);
|
package/dist/middleware.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
import { L as LunoraAuth } from "./packem_shared/create-auth.d-Mwhb4gSc.js";
|
|
2
3
|
import 'better-auth';
|
|
3
4
|
/**
|
|
4
5
|
* Structural mirror of `@lunora/server`'s `MiddlewareNext` — the continuation
|
|
@@ -22,7 +23,7 @@ interface MiddlewareNext<ContextIn> {
|
|
|
22
23
|
* advisor lint — both treat a header-less `ctx.authApi.*` call as an
|
|
23
24
|
* authorization bypass, so a call that trips the lint also trips this guard.
|
|
24
25
|
*/
|
|
25
|
-
declare class LunoraAuthHeadersError extends
|
|
26
|
+
declare class LunoraAuthHeadersError extends LunoraError {
|
|
26
27
|
/** The `ctx.authApi.<method>` that was called without `headers`. */
|
|
27
28
|
readonly method: string;
|
|
28
29
|
constructor(method: string);
|
package/dist/middleware.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
|
|
1
3
|
const callHasHeaders = (argument) => {
|
|
2
4
|
if (argument === void 0) {
|
|
3
5
|
return false;
|
|
@@ -30,14 +32,15 @@ const guardAuthApi = (api) => {
|
|
|
30
32
|
}
|
|
31
33
|
});
|
|
32
34
|
};
|
|
33
|
-
class LunoraAuthHeadersError extends
|
|
35
|
+
class LunoraAuthHeadersError extends LunoraError {
|
|
34
36
|
/** The `ctx.authApi.<method>` that was called without `headers`. */
|
|
35
37
|
method;
|
|
36
38
|
constructor(method) {
|
|
37
39
|
super(
|
|
38
|
-
|
|
40
|
+
"AUTH_HEADERS_MISSING",
|
|
41
|
+
`@lunora/auth: ctx.authApi.${method}(…) was called without \`headers\`. better-auth treats a header-less call as a trusted server-to-server invocation and skips session authorization entirely — an authorization bypass. Pass the inbound request headers: ctx.authApi.${method}({ body, headers: request.headers }). If you genuinely intend an unauthenticated server-to-server call, opt out explicitly via ctx.authApi.withoutHeaders().<method>(…), or disable the guard for the whole middleware with withAuthPlugins(auth, { enforceHeaders: false }).`,
|
|
42
|
+
{ name: "LunoraAuthHeadersError" }
|
|
39
43
|
);
|
|
40
|
-
this.name = "LunoraAuthHeadersError";
|
|
41
44
|
this.method = method;
|
|
42
45
|
}
|
|
43
46
|
}
|