@holeauth/core 0.0.1-alpha.0

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.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/cjs-error.cjs +8 -0
  4. package/dist/adapters/index.d.ts +1 -0
  5. package/dist/adapters/index.js +3 -0
  6. package/dist/adapters/index.js.map +1 -0
  7. package/dist/cookies/index.d.ts +3 -0
  8. package/dist/cookies/index.js +74 -0
  9. package/dist/cookies/index.js.map +1 -0
  10. package/dist/errors/index.d.ts +40 -0
  11. package/dist/errors/index.js +70 -0
  12. package/dist/errors/index.js.map +1 -0
  13. package/dist/events/index.d.ts +3 -0
  14. package/dist/events/index.js +52 -0
  15. package/dist/events/index.js.map +1 -0
  16. package/dist/flows/index.d.ts +4 -0
  17. package/dist/flows/index.js +835 -0
  18. package/dist/flows/index.js.map +1 -0
  19. package/dist/index-BIXESLma.d.ts +58 -0
  20. package/dist/index-BYtkmk9_.d.ts +18 -0
  21. package/dist/index-BbEXbI_k.d.ts +116 -0
  22. package/dist/index-BmYQquGs.d.ts +563 -0
  23. package/dist/index-BwEvEa8-.d.ts +20 -0
  24. package/dist/index-CHS-socJ.d.ts +97 -0
  25. package/dist/index-CNtnPdzk.d.ts +136 -0
  26. package/dist/index-CjEXpqaW.d.ts +22 -0
  27. package/dist/index-CotvcK_b.d.ts +42 -0
  28. package/dist/index-D57PvFMN.d.ts +105 -0
  29. package/dist/index-DRN-5E_H.d.ts +26 -0
  30. package/dist/index.d.ts +39 -0
  31. package/dist/index.js +1757 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/jwt/index.d.ts +2 -0
  34. package/dist/jwt/index.js +53 -0
  35. package/dist/jwt/index.js.map +1 -0
  36. package/dist/otp/index.d.ts +1 -0
  37. package/dist/otp/index.js +16 -0
  38. package/dist/otp/index.js.map +1 -0
  39. package/dist/password/index.d.ts +1 -0
  40. package/dist/password/index.js +75 -0
  41. package/dist/password/index.js.map +1 -0
  42. package/dist/plugins/index.d.ts +4 -0
  43. package/dist/plugins/index.js +480 -0
  44. package/dist/plugins/index.js.map +1 -0
  45. package/dist/registry-CZhM1tEB.d.ts +101 -0
  46. package/dist/session/index.d.ts +3 -0
  47. package/dist/session/index.js +346 -0
  48. package/dist/session/index.js.map +1 -0
  49. package/dist/sso/index.d.ts +3 -0
  50. package/dist/sso/index.js +475 -0
  51. package/dist/sso/index.js.map +1 -0
  52. package/package.json +121 -0
@@ -0,0 +1,563 @@
1
+ import { a as AdapterAuditEvent, A as AdapterUser, U as UserAdapter, S as SessionAdapter, b as AuditLogAdapter, c as AccountAdapter, V as VerificationTokenAdapter, T as TransactionAdapter } from './index-CNtnPdzk.js';
2
+
3
+ /**
4
+ * Event type is intentionally an open string. Core emits well-known
5
+ * `user.*`, `session.*`, `account.*`, `sso.*` events; plugins emit under
6
+ * their own `<pluginId>.<name>` namespace (e.g. `twofa.verified`).
7
+ *
8
+ * Well-known core event names (non-exhaustive):
9
+ * - user.registered, user.signed_in, user.signed_out
10
+ * - session.created, session.rotated, session.revoked, session.reuse_detected
11
+ * - account.linked, account.unlinked
12
+ * - sso.authorize, sso.callback_ok, sso.callback_failed
13
+ * - plugin.error
14
+ */
15
+ type HoleauthEventType = string;
16
+ interface HoleauthEvent extends AdapterAuditEvent {
17
+ type: HoleauthEventType;
18
+ }
19
+
20
+ /**
21
+ * Plugin types.
22
+ *
23
+ * A holeauth plugin is a first-class extension that can:
24
+ * - contribute its own adapter (opaque to core, typed to the plugin)
25
+ * - hook into core flows (register / signIn / refresh / signOut /
26
+ * passwordChange / passwordReset / userUpdate / userDelete / session.*)
27
+ * - contribute HTTP routes that the framework binding (@holeauth/nextjs)
28
+ * mounts automatically under the same prefix as core routes
29
+ * - expose a typed API surface that is merged into the returned
30
+ * HoleauthInstance at `auth[plugin.id]`
31
+ *
32
+ * Plugins are registered via `defineHoleauth({ plugins: [...] as const })`.
33
+ * The returned instance type is inferred from the tuple so consumers get
34
+ * full IntelliSense without any `declare module` augmentation.
35
+ */
36
+
37
+ /** Minimal logger surface. Plugins MUST NOT depend on console directly. */
38
+ interface PluginLogger {
39
+ debug(msg: string, data?: unknown): void;
40
+ info(msg: string, data?: unknown): void;
41
+ warn(msg: string, data?: unknown): void;
42
+ error(msg: string, err?: unknown): void;
43
+ }
44
+ /**
45
+ * Event emitter handle exposed to plugins. Intentionally narrower than the
46
+ * internal emitter — plugins may subscribe, unsubscribe, and emit events
47
+ * scoped to their id namespace.
48
+ */
49
+ interface PluginEvents {
50
+ on(type: string, handler: (e: HoleauthEvent) => void | Promise<void>): () => void;
51
+ off(type: string, handler: (e: HoleauthEvent) => void | Promise<void>): void;
52
+ /** Emit a (persisted + observed) event. Plugins should namespace as `<id>.<name>`. */
53
+ emit(e: HoleauthEvent): Promise<void>;
54
+ }
55
+ /**
56
+ * Request context passed to plugin-owned routes. Framework bindings
57
+ * (e.g. @holeauth/nextjs) adapt their native primitives into this shape.
58
+ */
59
+ interface PluginRouteContext {
60
+ req: Request;
61
+ /** Parsed body (best-effort JSON) — may be empty object. */
62
+ body: Record<string, unknown>;
63
+ /** Response headers the handler can append Set-Cookie / other headers to. */
64
+ responseHeaders: Headers;
65
+ /** Read raw cookies. */
66
+ cookies: {
67
+ get(name: string): string | undefined;
68
+ };
69
+ /** Set a cookie on the response (framework-serialized). */
70
+ setCookie(spec: {
71
+ name: string;
72
+ value: string;
73
+ maxAge?: number;
74
+ httpOnly?: boolean;
75
+ path?: string;
76
+ sameSite?: 'lax' | 'strict' | 'none';
77
+ }): void;
78
+ /** Current authenticated session, if any (cheap — cached per request). */
79
+ getSession(): Promise<{
80
+ userId: string;
81
+ sessionId: string;
82
+ expiresAt: number;
83
+ } | null>;
84
+ /** Client metadata (ip + user-agent). */
85
+ meta: {
86
+ ip?: string;
87
+ userAgent?: string;
88
+ };
89
+ /** Plugin context (config + adapters + core helpers + other plugin APIs). */
90
+ plugin: PluginContext;
91
+ }
92
+ interface PluginRoute {
93
+ method: 'GET' | 'POST';
94
+ /** Path relative to the auth basePath (e.g. '/2fa/verify'). Must start with '/'. */
95
+ path: string;
96
+ /** If true, the dispatcher enforces a valid session before calling the handler. */
97
+ requireAuth?: boolean;
98
+ /** If true, the dispatcher enforces CSRF (double-submit). */
99
+ requireCsrf?: boolean;
100
+ /** Your handler. Return a Response; the dispatcher merges response headers. */
101
+ handler(ctx: PluginRouteContext): Promise<Response> | Response;
102
+ }
103
+ /**
104
+ * Result produced by a plugin's signIn challenge hook. Plugins may return
105
+ * `null` to opt out (user not enrolled in this factor) or a pending state
106
+ * to halt sign-in pending a follow-up verification step.
107
+ */
108
+ interface ChallengeResult {
109
+ /** Plugin id (must match the returning plugin's id). */
110
+ pluginId: string;
111
+ /** Opaque token issued by the plugin (typically a short-lived JWT). */
112
+ pendingToken: string;
113
+ /** Unix-ms expiry. */
114
+ expiresAt: number;
115
+ /** Arbitrary extra payload echoed back to the caller. */
116
+ data?: Record<string, unknown> | null;
117
+ }
118
+ interface RegisterHookInput {
119
+ email: string;
120
+ password: string;
121
+ name?: string | null;
122
+ }
123
+ interface PasswordChangeHookInput {
124
+ userId: string;
125
+ currentPassword: string;
126
+ newPassword: string;
127
+ }
128
+ interface PasswordResetHookInput {
129
+ email: string;
130
+ token?: string;
131
+ newPassword?: string;
132
+ }
133
+ interface SessionIssueHookData {
134
+ userId: string;
135
+ sessionId: string;
136
+ familyId: string;
137
+ }
138
+ interface SessionRotateHookData {
139
+ userId: string;
140
+ sessionId: string;
141
+ familyId: string;
142
+ }
143
+ interface SessionRevokeHookData {
144
+ userId: string | null;
145
+ sessionId: string | null;
146
+ /** Set when the revoke is a global signout for the user. */
147
+ scope?: 'all';
148
+ }
149
+ /**
150
+ * Hooks are co-operative, never destructive. `before` hooks may throw to
151
+ * abort a flow; `after` hooks run post-success and must not throw —
152
+ * exceptions are caught, logged, and emitted as `plugin.error` events.
153
+ */
154
+ interface HoleauthHooks {
155
+ register?: {
156
+ before?(input: RegisterHookInput, ctx: PluginContext): Promise<void> | void;
157
+ after?(user: AdapterUser, ctx: PluginContext): Promise<void> | void;
158
+ };
159
+ signIn?: {
160
+ before?(input: {
161
+ email: string;
162
+ ip?: string;
163
+ userAgent?: string;
164
+ }, ctx: PluginContext): Promise<void> | void;
165
+ /**
166
+ * Return a ChallengeResult to halt signIn and require a follow-up step.
167
+ * Return `null` to opt out. Only the first non-null wins; subsequent
168
+ * non-null results trigger a warning.
169
+ */
170
+ challenge?(user: AdapterUser, input: {
171
+ ip?: string;
172
+ userAgent?: string;
173
+ }, ctx: PluginContext): Promise<ChallengeResult | null> | ChallengeResult | null;
174
+ after?(result: {
175
+ user: AdapterUser;
176
+ tokens: IssuedTokens;
177
+ method: 'password' | 'passkey' | 'sso' | string;
178
+ }, ctx: PluginContext): Promise<void> | void;
179
+ };
180
+ signOut?: {
181
+ after?(data: {
182
+ userId: string | null;
183
+ sessionId: string | null;
184
+ }, ctx: PluginContext): Promise<void> | void;
185
+ };
186
+ refresh?: {
187
+ before?(input: {
188
+ ip?: string;
189
+ userAgent?: string;
190
+ }, ctx: PluginContext): Promise<void> | void;
191
+ after?(data: {
192
+ userId: string;
193
+ sessionId: string;
194
+ tokens: IssuedTokens;
195
+ }, ctx: PluginContext): Promise<void> | void;
196
+ };
197
+ passwordChange?: {
198
+ before?(input: PasswordChangeHookInput, ctx: PluginContext): Promise<void> | void;
199
+ after?(data: {
200
+ userId: string;
201
+ }, ctx: PluginContext): Promise<void> | void;
202
+ };
203
+ passwordReset?: {
204
+ before?(input: PasswordResetHookInput, ctx: PluginContext): Promise<void> | void;
205
+ after?(data: {
206
+ userId: string;
207
+ stage: 'request' | 'consume';
208
+ }, ctx: PluginContext): Promise<void> | void;
209
+ };
210
+ userUpdate?: {
211
+ after?(data: {
212
+ user: AdapterUser;
213
+ patch: Partial<AdapterUser>;
214
+ }, ctx: PluginContext): Promise<void> | void;
215
+ };
216
+ userDelete?: {
217
+ after?(data: {
218
+ userId: string;
219
+ }, ctx: PluginContext): Promise<void> | void;
220
+ };
221
+ session?: {
222
+ onIssue?(data: SessionIssueHookData, ctx: PluginContext): Promise<void> | void;
223
+ onRotate?(data: SessionRotateHookData, ctx: PluginContext): Promise<void> | void;
224
+ onRevoke?(data: SessionRevokeHookData, ctx: PluginContext): Promise<void> | void;
225
+ };
226
+ }
227
+ /**
228
+ * Curated core surface exposed to plugins. Deliberately narrower than
229
+ * HoleauthInstance to prevent plugins from ping-ponging through the
230
+ * public API and to keep plugin code decoupled from framework bindings.
231
+ */
232
+ interface PluginCoreSurface {
233
+ getUserById(id: string): Promise<AdapterUser | null>;
234
+ getUserByEmail(email: string): Promise<AdapterUser | null>;
235
+ issueSession(input: {
236
+ userId: string;
237
+ ip?: string | null;
238
+ userAgent?: string | null;
239
+ }): Promise<IssuedTokens>;
240
+ /**
241
+ * Run `signIn.after` hooks for a given user + method, then issue tokens.
242
+ * Used by passkey / SSO to funnel through the same post-sign-in hook
243
+ * chain as password sign-in.
244
+ */
245
+ completeSignIn(userId: string, input: {
246
+ method: string;
247
+ ip?: string;
248
+ userAgent?: string;
249
+ }): Promise<{
250
+ user: AdapterUser;
251
+ tokens: IssuedTokens;
252
+ }>;
253
+ revokeSession(sessionId: string, userId?: string): Promise<void>;
254
+ /** Shortcut for read-only code paths: pre-computes the SignInResult for a user (no challenge). */
255
+ issueSignInResult(user: AdapterUser, input: {
256
+ ip?: string;
257
+ userAgent?: string;
258
+ }): Promise<SignInResult>;
259
+ }
260
+ /**
261
+ * Full context handed to plugins. `getPlugin` is typed via dependsOn-aware
262
+ * overloads at the registry level.
263
+ */
264
+ interface PluginContext {
265
+ config: HoleauthConfig;
266
+ events: PluginEvents;
267
+ logger: PluginLogger;
268
+ core: PluginCoreSurface;
269
+ /** Retrieve another plugin's API by id. Throws if not found. */
270
+ getPlugin<T = unknown>(id: string): T;
271
+ /**
272
+ * Retrieve this plugin's adapter from `config.pluginAdapters[id]`.
273
+ * Returns `undefined` if none was supplied. Plugins decide whether
274
+ * that is an error (most will throw a friendly message).
275
+ */
276
+ getPluginAdapter<T = unknown>(id: string): T | undefined;
277
+ }
278
+ /**
279
+ * A holeauth plugin. Users construct plugins via `definePlugin(...)`.
280
+ *
281
+ * Type parameters:
282
+ * - Id: literal id (so `auth[plugin.id]` can be inferred)
283
+ * - Api: the typed public API produced by `api(ctx)`
284
+ */
285
+ interface HoleauthPlugin<Id extends string = string, Api = unknown> {
286
+ readonly id: Id;
287
+ readonly version?: string;
288
+ /** Plugin ids that must be loaded before this plugin. */
289
+ readonly dependsOn?: readonly string[];
290
+ /** Plugin-owned adapter instance. Opaque to core; typed inside the plugin. */
291
+ readonly adapter?: unknown;
292
+ /** Hook implementations. Every key optional. */
293
+ readonly hooks?: HoleauthHooks;
294
+ /** HTTP routes auto-mounted by the framework binding. */
295
+ readonly routes?: readonly PluginRoute[];
296
+ /** Construct the public API surface. Called once per defineHoleauth(). */
297
+ readonly api: (ctx: PluginContext) => Api;
298
+ /** Called after all plugins have been wired. */
299
+ readonly onInit?: (ctx: PluginContext) => Promise<void> | void;
300
+ /** Called on shutdown (best-effort; consumer-controlled). */
301
+ readonly onShutdown?: () => Promise<void> | void;
302
+ }
303
+ /** Helper type: derive `auth[id]` mapping from a plugins tuple. */
304
+ type PluginsApi<Plugins extends readonly HoleauthPlugin<string, unknown>[]> = {
305
+ [P in Plugins[number] as P['id']]: ReturnType<P['api']>;
306
+ };
307
+
308
+ interface TokenPolicy {
309
+ /** Access token lifetime in seconds. Default: 900 (15m). */
310
+ accessTtl?: number;
311
+ /** Refresh token lifetime in seconds. Default: 2592000 (30d). */
312
+ refreshTtl?: number;
313
+ /** Pending challenge cookie lifetime. Default: 300 (5m). */
314
+ pendingTtl?: number;
315
+ /** Cookie name prefix. Default: 'holeauth'. */
316
+ cookiePrefix?: string;
317
+ /** Optional cookie Domain attribute (e.g. '.example.com'). */
318
+ cookieDomain?: string;
319
+ /** Override Secure flag for cookies (auto-true in production). */
320
+ cookieSecure?: boolean;
321
+ /** SameSite. Default: 'lax'. SSO callbacks always bypass to avoid drops. */
322
+ sameSite?: 'lax' | 'strict' | 'none';
323
+ }
324
+ interface HoleauthSecrets {
325
+ /** JWT signing secret (or asymmetric key material). */
326
+ jwtSecret: string | Uint8Array;
327
+ }
328
+ interface BaseProviderConfig {
329
+ id: string;
330
+ name: string;
331
+ clientId: string;
332
+ clientSecret: string;
333
+ redirectUri: string;
334
+ scopes?: string[];
335
+ }
336
+ interface OIDCProviderConfig extends BaseProviderConfig {
337
+ kind: 'oidc';
338
+ issuer: string;
339
+ authorizationUrl: string;
340
+ tokenUrl: string;
341
+ userinfoUrl: string;
342
+ }
343
+ interface OAuth2ProviderConfig extends BaseProviderConfig {
344
+ kind: 'oauth2';
345
+ authorizationUrl: string;
346
+ tokenUrl: string;
347
+ userinfoUrl: string;
348
+ /** Map provider-specific profile to a normalised shape. */
349
+ profile: (raw: unknown) => {
350
+ providerAccountId: string;
351
+ email: string;
352
+ name?: string | null;
353
+ image?: string | null;
354
+ };
355
+ }
356
+ type ProviderConfig = OIDCProviderConfig | OAuth2ProviderConfig;
357
+ interface HoleauthAdapters {
358
+ user: UserAdapter;
359
+ session: SessionAdapter;
360
+ /** MANDATORY — persisted audit log (awaited). */
361
+ auditLog: AuditLogAdapter;
362
+ account?: AccountAdapter;
363
+ verificationToken?: VerificationTokenAdapter;
364
+ /** Optional — wraps multi-step writes in a DB transaction when provided. */
365
+ transaction?: TransactionAdapter;
366
+ }
367
+ interface LoggerOptions {
368
+ silent?: boolean;
369
+ }
370
+ interface RegistrationConfig {
371
+ /**
372
+ * If `false`, the public `register` flow throws `REGISTRATION_DISABLED` (403).
373
+ * Invites continue to work regardless. Default: `true`.
374
+ */
375
+ selfServe?: boolean;
376
+ /** Default TTL (seconds) for invite tokens when callers do not pass one. */
377
+ inviteTtlSeconds?: number;
378
+ /**
379
+ * Builder for the user-visible invite acceptance URL. Called by
380
+ * `createInvite`; returning `undefined` omits the `url` field from the
381
+ * result and leaves URL construction to the caller.
382
+ */
383
+ inviteUrl?: (args: {
384
+ token: string;
385
+ email: string;
386
+ }) => string | undefined;
387
+ }
388
+ interface HoleauthConfig {
389
+ secrets: HoleauthSecrets;
390
+ adapters: HoleauthAdapters;
391
+ tokens?: TokenPolicy;
392
+ providers?: ProviderConfig[];
393
+ /** Plugins to register. See `@holeauth/core/plugins`. */
394
+ plugins?: readonly HoleauthPlugin<string, unknown>[];
395
+ /**
396
+ * Per-plugin adapter map, keyed by plugin id. Preferred over embedding
397
+ * adapters inside each plugin's options closure — keeps adapters in one
398
+ * place and out of serialisable plugin configuration.
399
+ *
400
+ * Access inside a plugin via `ctx.getPluginAdapter<T>(id)`.
401
+ */
402
+ pluginAdapters?: Record<string, unknown>;
403
+ /** Allow auto-linking on matching verified email (UNSAFE when provider does not verify email). */
404
+ allowDangerousEmailAccountLinking?: boolean;
405
+ /** Registration / invite configuration. */
406
+ registration?: RegistrationConfig;
407
+ /** Legacy single-listener event hook. Still supported; new code should use `events.on(...)`. */
408
+ onEvent?: (e: HoleauthEvent) => void | Promise<void>;
409
+ logger?: LoggerOptions;
410
+ }
411
+ interface SessionData {
412
+ userId: string;
413
+ sessionId: string;
414
+ expiresAt: number;
415
+ [key: string]: unknown;
416
+ }
417
+ interface IssuedTokens {
418
+ accessToken: string;
419
+ refreshToken: string;
420
+ csrfToken: string;
421
+ sessionId: string;
422
+ familyId: string;
423
+ accessExpiresAt: number;
424
+ refreshExpiresAt: number;
425
+ }
426
+ /**
427
+ * A signIn outcome.
428
+ * - `ok`: fully authenticated; tokens ready to be set as cookies.
429
+ * - `pending`: a plugin's challenge hook halted the flow. The caller
430
+ * must drive the plugin's follow-up verification step. `pluginId`
431
+ * identifies which plugin issued the challenge.
432
+ */
433
+ type SignInResult = {
434
+ kind: 'ok';
435
+ user: AdapterUser;
436
+ tokens: IssuedTokens;
437
+ } | {
438
+ kind: 'pending';
439
+ pluginId: string;
440
+ userId: string;
441
+ pendingToken: string;
442
+ pendingExpiresAt: number;
443
+ data?: Record<string, unknown> | null;
444
+ };
445
+ interface InviteInput {
446
+ email: string;
447
+ name?: string | null;
448
+ /** RBAC group ids to assign on consume. Consumer/plugin hooks handle assignment. */
449
+ groupIds?: string[];
450
+ /** User id of the admin creating the invite (for audit). */
451
+ invitedBy?: string | null;
452
+ /** Opaque metadata stored in the JWT claim `meta`. */
453
+ metadata?: Record<string, unknown> | null;
454
+ /** Override default TTL (seconds). Falls back to `registration.inviteTtlSeconds`. */
455
+ ttlSeconds?: number;
456
+ }
457
+ interface InviteClaims {
458
+ /** Target email (JWT subject). */
459
+ email: string;
460
+ name?: string | null;
461
+ groupIds?: string[];
462
+ invitedBy?: string | null;
463
+ metadata?: Record<string, unknown> | null;
464
+ expiresAt: number;
465
+ /** JWT id; also the verification token identifier. */
466
+ identifier: string;
467
+ }
468
+ interface CreateInviteResult {
469
+ token: string;
470
+ url?: string;
471
+ identifier: string;
472
+ expiresAt: number;
473
+ }
474
+ interface ConsumeInviteInput {
475
+ token: string;
476
+ password: string;
477
+ name?: string;
478
+ autoSignIn?: boolean;
479
+ ip?: string;
480
+ userAgent?: string;
481
+ }
482
+ interface ConsumeInviteResult {
483
+ user: AdapterUser;
484
+ tokens?: IssuedTokens;
485
+ groupIds?: string[];
486
+ }
487
+ interface InviteListEntry {
488
+ identifier: string;
489
+ email: string;
490
+ expiresAt: number;
491
+ }
492
+ interface HoleauthInstance {
493
+ config: HoleauthConfig;
494
+ register(input: {
495
+ email: string;
496
+ password: string;
497
+ name?: string;
498
+ }): Promise<AdapterUser>;
499
+ signIn(input: {
500
+ email: string;
501
+ password: string;
502
+ ip?: string;
503
+ userAgent?: string;
504
+ }): Promise<SignInResult>;
505
+ signOut(input: {
506
+ accessToken?: string;
507
+ refreshToken?: string;
508
+ }): Promise<void>;
509
+ refresh(input: {
510
+ refreshToken: string;
511
+ ip?: string;
512
+ userAgent?: string;
513
+ }): Promise<IssuedTokens>;
514
+ getSession(accessToken?: string): Promise<SessionData | null>;
515
+ changePassword(input: {
516
+ userId: string;
517
+ currentPassword: string;
518
+ newPassword: string;
519
+ revokeOtherSessions?: boolean;
520
+ }): Promise<void>;
521
+ requestPasswordReset(input: {
522
+ email: string;
523
+ }): Promise<{
524
+ token?: string;
525
+ userId?: string;
526
+ }>;
527
+ consumePasswordReset(input: {
528
+ email: string;
529
+ token: string;
530
+ newPassword: string;
531
+ }): Promise<void>;
532
+ updateUser(userId: string, patch: Partial<AdapterUser>): Promise<AdapterUser>;
533
+ deleteUser(userId: string): Promise<void>;
534
+ createInvite(input: InviteInput): Promise<CreateInviteResult>;
535
+ getInviteInfo(input: {
536
+ token: string;
537
+ }): Promise<InviteClaims>;
538
+ consumeInvite(input: ConsumeInviteInput): Promise<ConsumeInviteResult>;
539
+ revokeInvite(input: {
540
+ identifier: string;
541
+ }): Promise<void>;
542
+ listInvites(): Promise<InviteListEntry[]>;
543
+ sso: {
544
+ authorize(providerId: string): Promise<{
545
+ url: string;
546
+ state: string;
547
+ codeVerifier: string;
548
+ nonce?: string;
549
+ }>;
550
+ callback(providerId: string, input: {
551
+ code: string;
552
+ state: string;
553
+ codeVerifier: string;
554
+ ip?: string;
555
+ userAgent?: string;
556
+ }): Promise<{
557
+ user: AdapterUser;
558
+ tokens: IssuedTokens;
559
+ }>;
560
+ };
561
+ }
562
+
563
+ export type { SessionRevokeHookData as A, BaseProviderConfig as B, ChallengeResult as C, SessionRotateHookData as D, HoleauthPlugin as H, InviteClaims as I, LoggerOptions as L, OAuth2ProviderConfig as O, PluginsApi as P, RegistrationConfig as R, SessionData as S, TokenPolicy as T, HoleauthConfig as a, HoleauthInstance as b, ConsumeInviteInput as c, ConsumeInviteResult as d, CreateInviteResult as e, HoleauthAdapters as f, HoleauthHooks as g, HoleauthSecrets as h, InviteInput as i, InviteListEntry as j, IssuedTokens as k, OIDCProviderConfig as l, PluginContext as m, PluginCoreSurface as n, PluginEvents as o, PluginLogger as p, PluginRoute as q, PluginRouteContext as r, ProviderConfig as s, SignInResult as t, HoleauthEvent as u, HoleauthEventType as v, PasswordChangeHookInput as w, PasswordResetHookInput as x, RegisterHookInput as y, SessionIssueHookData as z };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Email / numeric OTP helpers. The mailer itself is adapter-injected.
3
+ */
4
+ declare function generateNumericOtp(length?: number): string;
5
+ interface OtpChallenge {
6
+ code: string;
7
+ expiresAt: number;
8
+ }
9
+ declare function createChallenge(ttlSeconds?: number, length?: number): OtpChallenge;
10
+ declare function isExpired(challenge: OtpChallenge): boolean;
11
+
12
+ type index_OtpChallenge = OtpChallenge;
13
+ declare const index_createChallenge: typeof createChallenge;
14
+ declare const index_generateNumericOtp: typeof generateNumericOtp;
15
+ declare const index_isExpired: typeof isExpired;
16
+ declare namespace index {
17
+ export { type index_OtpChallenge as OtpChallenge, index_createChallenge as createChallenge, index_generateNumericOtp as generateNumericOtp, index_isExpired as isExpired };
18
+ }
19
+
20
+ export { type OtpChallenge as O, isExpired as a, createChallenge as c, generateNumericOtp as g, index as i };
@@ -0,0 +1,97 @@
1
+ import { a as HoleauthConfig, s as ProviderConfig, k as IssuedTokens, l as OIDCProviderConfig, O as OAuth2ProviderConfig } from './index-BmYQquGs.js';
2
+ import { A as AdapterUser } from './index-CNtnPdzk.js';
3
+
4
+ interface AuthorizeParams {
5
+ issuerAuthUrl: string;
6
+ clientId: string;
7
+ redirectUri: string;
8
+ scopes?: string[];
9
+ state: string;
10
+ codeChallenge: string;
11
+ nonce?: string;
12
+ /** Extra params merged into the query string. */
13
+ extra?: Record<string, string>;
14
+ }
15
+ declare function buildAuthorizeUrl(p: AuthorizeParams): string;
16
+ declare function generatePkcePair(): Promise<{
17
+ verifier: string;
18
+ challenge: string;
19
+ }>;
20
+ declare function generateState(): string;
21
+ declare function generateNonce(): string;
22
+ interface TokenExchangeInput {
23
+ tokenUrl: string;
24
+ clientId: string;
25
+ clientSecret: string;
26
+ redirectUri: string;
27
+ code: string;
28
+ codeVerifier: string;
29
+ }
30
+ declare function exchangeCode(i: TokenExchangeInput): Promise<Record<string, unknown>>;
31
+ declare function fetchUserInfo(userinfoUrl: string, accessToken: string): Promise<Record<string, unknown>>;
32
+ declare function base64url(bytes: Uint8Array): string;
33
+
34
+ declare function findProvider(cfg: HoleauthConfig, id: string): ProviderConfig;
35
+ /**
36
+ * Begin the SSO hop. Returns a URL to redirect the user to, plus state +
37
+ * PKCE verifier the caller must persist (typically in httpOnly cookies)
38
+ * to validate the callback.
39
+ */
40
+ declare function authorize(cfg: HoleauthConfig, providerId: string): Promise<{
41
+ url: string;
42
+ state: string;
43
+ codeVerifier: string;
44
+ nonce?: string;
45
+ }>;
46
+
47
+ interface CallbackInput {
48
+ code: string;
49
+ state: string;
50
+ codeVerifier: string;
51
+ ip?: string;
52
+ userAgent?: string;
53
+ }
54
+ declare function callback(cfg: HoleauthConfig, providerId: string, input: CallbackInput): Promise<{
55
+ user: AdapterUser;
56
+ tokens: IssuedTokens;
57
+ }>;
58
+
59
+ interface GoogleOptions {
60
+ clientId: string;
61
+ clientSecret: string;
62
+ redirectUri: string;
63
+ id?: string;
64
+ scopes?: string[];
65
+ }
66
+ /** Google OpenID Connect provider. */
67
+ declare function GoogleProvider(opts: GoogleOptions): OIDCProviderConfig;
68
+
69
+ interface GithubOptions {
70
+ clientId: string;
71
+ clientSecret: string;
72
+ redirectUri: string;
73
+ id?: string;
74
+ scopes?: string[];
75
+ }
76
+ /** GitHub OAuth2 provider. Uses REST userinfo (no OIDC). */
77
+ declare function GithubProvider(opts: GithubOptions): OAuth2ProviderConfig;
78
+
79
+ type index_AuthorizeParams = AuthorizeParams;
80
+ declare const index_GithubProvider: typeof GithubProvider;
81
+ declare const index_GoogleProvider: typeof GoogleProvider;
82
+ type index_TokenExchangeInput = TokenExchangeInput;
83
+ declare const index_authorize: typeof authorize;
84
+ declare const index_base64url: typeof base64url;
85
+ declare const index_buildAuthorizeUrl: typeof buildAuthorizeUrl;
86
+ declare const index_callback: typeof callback;
87
+ declare const index_exchangeCode: typeof exchangeCode;
88
+ declare const index_fetchUserInfo: typeof fetchUserInfo;
89
+ declare const index_findProvider: typeof findProvider;
90
+ declare const index_generateNonce: typeof generateNonce;
91
+ declare const index_generatePkcePair: typeof generatePkcePair;
92
+ declare const index_generateState: typeof generateState;
93
+ declare namespace index {
94
+ export { type index_AuthorizeParams as AuthorizeParams, index_GithubProvider as GithubProvider, index_GoogleProvider as GoogleProvider, type index_TokenExchangeInput as TokenExchangeInput, index_authorize as authorize, index_base64url as base64url, index_buildAuthorizeUrl as buildAuthorizeUrl, index_callback as callback, index_exchangeCode as exchangeCode, index_fetchUserInfo as fetchUserInfo, index_findProvider as findProvider, index_generateNonce as generateNonce, index_generatePkcePair as generatePkcePair, index_generateState as generateState };
95
+ }
96
+
97
+ export { type AuthorizeParams as A, GithubProvider as G, type TokenExchangeInput as T, GoogleProvider as a, authorize as b, base64url as c, buildAuthorizeUrl as d, callback as e, exchangeCode as f, fetchUserInfo as g, findProvider as h, index as i, generateNonce as j, generatePkcePair as k, generateState as l };