appos 0.4.1-0 → 0.4.3-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 (47) hide show
  1. package/dist/exports/api/index.d.mts +5 -4
  2. package/dist/exports/api/index.mjs +88 -11
  3. package/dist/exports/api/orm.d.mts +1 -1
  4. package/dist/exports/api/orm.mjs +1 -1
  5. package/dist/exports/api/workflows/index.d.mts +4 -3
  6. package/dist/exports/api/workflows/index.mjs +2 -2
  7. package/dist/exports/app-context-B1VJ9qnH.mjs +3 -0
  8. package/dist/exports/auth-By0xx0MI.d.mts +759 -0
  9. package/dist/exports/cli/index.d.mts +4 -3
  10. package/dist/exports/cli/index.mjs +82 -103
  11. package/dist/exports/{index-B3m3Uvsl.d.mts → index-Bpo5QE7k.d.mts} +469 -875
  12. package/dist/exports/{instrumentation-CTl5Q8ky.mjs → instrumentation-DkoLNAtz.mjs} +14 -8
  13. package/dist/exports/instrumentation.d.mts +1 -1
  14. package/dist/exports/instrumentation.mjs +1 -1
  15. package/dist/exports/{mock-CURQkGUm.mjs → mock-2jMk5l3y.mjs} +1 -1
  16. package/dist/exports/{openapi-C7QT3gNU.mjs → openapi-crG3j4xx.mjs} +113 -11
  17. package/dist/exports/{orm-CQk1S10H.d.mts → orm-CJrd147z.d.mts} +1 -1
  18. package/dist/exports/{orm-BYSfGzG0.mjs → orm-COJ9l6sS.mjs} +1 -1
  19. package/dist/exports/{send-email-Do8SjZL7.mjs → send-email-Bgcdjy-e.mjs} +13 -1
  20. package/dist/exports/{server-6XZo256O.mjs → server-BlNxgHUc.mjs} +11 -9
  21. package/dist/exports/ssr-BsfNjYlJ.mjs +16 -0
  22. package/dist/exports/tests/api.d.mts +4 -3
  23. package/dist/exports/tests/api.mjs +7 -7
  24. package/dist/exports/tests/mock.mjs +1 -1
  25. package/dist/exports/vite/index.mjs +1 -1
  26. package/dist/exports/web/index.d.ts +919 -461
  27. package/dist/exports/web/index.js +809 -299
  28. package/dist/exports/web/routes.d.mts +137 -0
  29. package/dist/exports/web/routes.mjs +137 -0
  30. package/dist/exports/web/ssr.d.mts +7 -200
  31. package/dist/exports/web/ssr.mjs +2 -2
  32. package/package.json +9 -2
  33. package/src/web/routes/auth/_layout.tsx +19 -7
  34. package/src/web/routes/auth/forgot-password.tsx +3 -1
  35. package/src/web/routes/auth/phone-otp.tsx +1 -2
  36. package/src/web/routes/auth/utils.ts +30 -170
  37. package/src/web/ui/locales/en/ui.json +37 -3
  38. package/src/web/ui/locales/zh-CN/ui.json +37 -3
  39. package/src/web/ui/locales/zh-TW/ui.json +37 -3
  40. package/dist/exports/app-context-deZa7oJC.mjs +0 -3
  41. package/dist/exports/ssr-CVebWWYi.mjs +0 -163
  42. /package/dist/exports/{app-context-DoFRTUi5.mjs → app-context-LF4QmPUC.mjs} +0 -0
  43. /package/dist/exports/{chunk-Db_DmN2K.mjs → chunk-CHSICr2d.mjs} +0 -0
  44. /package/dist/exports/{constants-DbBfpyC3.mjs → constants-BePPc_yF.mjs} +0 -0
  45. /package/dist/exports/{instrumentation-B0Ev9PvT.d.mts → instrumentation-CFIspF8-.d.mts} +0 -0
  46. /package/dist/exports/{vite-compat-CeAU9UrA.mjs → vite-compat-CICObU9F.mjs} +0 -0
  47. /package/dist/exports/{youch-handler-BEWxHUsu.mjs → youch-handler-CHwX0Fou.mjs} +0 -0
@@ -0,0 +1,759 @@
1
+ import { betterAuth } from "better-auth";
2
+ import { Role, createAccessControl } from "better-auth/plugins/access";
3
+ import { z } from "zod";
4
+ import * as drizzle_orm0 from "drizzle-orm";
5
+ import { AnyRelations, EmptyRelations } from "drizzle-orm";
6
+ import { PgTable } from "drizzle-orm/pg-core";
7
+ import * as drizzle_orm_node_postgres0 from "drizzle-orm/node-postgres";
8
+ import * as pg0 from "pg";
9
+ import pg from "pg";
10
+ import pino, { LoggerOptions } from "pino";
11
+ import { MigrationConfig } from "drizzle-orm/migrator";
12
+
13
+ //#region src/api/logger.d.ts
14
+ /**
15
+ * Extended logger options with OpenTelemetry support.
16
+ */
17
+ interface DefineLoggerOptions extends LoggerOptions {}
18
+ /**
19
+ * The logger instance type.
20
+ */
21
+ type Logger = Awaited<ReturnType<typeof defineLogger>>;
22
+ /**
23
+ * Define the logger instance.
24
+ *
25
+ * @param opts - The options.
26
+ * @returns The logger.
27
+ */
28
+ declare function defineLogger(opts: DefineLoggerOptions): Promise<pino.Logger<never, boolean>>;
29
+ //#endregion
30
+ //#region src/api/database.d.ts
31
+ type PoolConfig = pg.PoolConfig;
32
+ /**
33
+ * Extract qualified table names from db object.
34
+ */
35
+ type QualifiedTableNames<TDb> = { [K in keyof TDb]: TDb[K] extends {
36
+ _: {
37
+ fullSchema: infer S;
38
+ };
39
+ } ? `${K & string}.${keyof S & string}` : never }[keyof TDb];
40
+ /**
41
+ * The schema used for migrations.
42
+ */
43
+ declare const migrationsSchema = "public";
44
+ /**
45
+ * The type of migration (schema or data).
46
+ */
47
+ type MigrationType = "schema" | "data";
48
+ /**
49
+ * Get the migration options for a specific database.
50
+ *
51
+ * @param name Name of the database to get migration options for
52
+ * @param type Type of migration (schema or data), defaults to "schema"
53
+ * @returns Migration configuration for drizzle-orm
54
+ */
55
+ declare function defineMigrationOpts(name: string, type?: MigrationType): MigrationConfig;
56
+ /**
57
+ * Options for defining the database.
58
+ */
59
+ interface DefineDatabaseOptions<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> {
60
+ logger: Logger;
61
+ poolConfig: PoolConfig;
62
+ relations?: TRelations;
63
+ schema?: TSchema;
64
+ }
65
+ /**
66
+ * The database type.
67
+ */
68
+ type Database = Awaited<ReturnType<typeof defineDatabase>>;
69
+ /**
70
+ * Generate old and new row JSONB representations for delete/insert/update queries.
71
+ * Uses PostgreSQL 18's OLD/NEW support in RETURNING clause.
72
+ *
73
+ * @param table The table to generate changes for.
74
+ * @returns Object containing `_table`, `old` and `new` JSONB columns.
75
+ */
76
+ declare function dbChanges<T extends PgTable>(table: T): {
77
+ _table: drizzle_orm0.SQL.Aliased<string>;
78
+ old: drizzle_orm0.SQL.Aliased<({ [Key in keyof T["_"]["columns"] & string]: T["_"]["columns"][Key]["_"]["notNull"] extends true ? T["_"]["columns"][Key]["_"]["data"] : T["_"]["columns"][Key]["_"]["data"] | null } extends infer T_1 ? { [K in keyof T_1]: T_1[K] } : never) | null>;
79
+ new: drizzle_orm0.SQL.Aliased<({ [Key in keyof T["_"]["columns"] & string]: T["_"]["columns"][Key]["_"]["notNull"] extends true ? T["_"]["columns"][Key]["_"]["data"] : T["_"]["columns"][Key]["_"]["data"] | null } extends infer T_2 ? { [K in keyof T_2]: T_2[K] } : never) | null>;
80
+ };
81
+ /**
82
+ * Define the database with the provided options.
83
+ *
84
+ * Algorithm:
85
+ * 1. Create a connection pool with sensible defaults
86
+ * 2. Initialize drizzle ORM with schema and relations
87
+ *
88
+ * @param opts The options for defining the database, including pool configuration, relations, and schema.
89
+ * @template TSchema The schema type for the database.
90
+ * @template TRelations The relations type for the database.
91
+ * @returns The defined database instance.
92
+ */
93
+ declare function defineDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(opts: DefineDatabaseOptions<TSchema, TRelations>): Promise<drizzle_orm_node_postgres0.NodePgDatabase<TSchema, TRelations> & {
94
+ $client: pg0.Pool;
95
+ }>;
96
+ /**
97
+ * Options for defining a test database.
98
+ */
99
+ interface DefineTestDatabaseOptions<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations> {
100
+ connectionString: string;
101
+ logger: Logger;
102
+ name: string;
103
+ schema: TSchema;
104
+ relations: TRelations;
105
+ }
106
+ /**
107
+ * Create a single test database with isolated schema.
108
+ *
109
+ * @param connectionString - Database connection string
110
+ * @param name - Name of the test database
111
+ * @returns Test database instance and cleanup function
112
+ */
113
+ declare function defineTestDatabase<TSchema extends Record<string, unknown> = Record<string, never>, TRelations extends AnyRelations = EmptyRelations>(opts: DefineTestDatabaseOptions<TSchema, TRelations>): Promise<{
114
+ cleanUp: () => Promise<void>;
115
+ db: drizzle_orm_node_postgres0.NodePgDatabase<TSchema, TRelations> & {
116
+ $client: pg0.Pool;
117
+ };
118
+ dbName: string;
119
+ }>;
120
+ //#endregion
121
+ //#region src/web/client/auth-paths.d.ts
122
+ /**
123
+ * Configuration for authentication route paths.
124
+ *
125
+ * All paths should be absolute (starting with "/").
126
+ * These paths are used for both route generation and navigation.
127
+ */
128
+ interface AuthPaths {
129
+ /**
130
+ * Path to the login page.
131
+ *
132
+ * @default "/login"
133
+ */
134
+ login: string;
135
+ /**
136
+ * Path to the signup/registration page.
137
+ *
138
+ * @default "/signup"
139
+ */
140
+ signup: string;
141
+ /**
142
+ * Path to the email verification page.
143
+ * Only used when email verification is enabled.
144
+ *
145
+ * @default "/verify-email"
146
+ */
147
+ verifyEmail: string;
148
+ /**
149
+ * Path to the forgot password page.
150
+ *
151
+ * @default "/forgot-password"
152
+ */
153
+ forgotPassword: string;
154
+ /**
155
+ * Path to the password reset page.
156
+ *
157
+ * @default "/reset-password"
158
+ */
159
+ resetPassword: string;
160
+ /**
161
+ * Path to the phone OTP login page.
162
+ * Only generated when phone OTP is enabled in auth config.
163
+ *
164
+ * @default "/phone-login"
165
+ */
166
+ phoneOtp: string;
167
+ /**
168
+ * Path to the email OTP login page.
169
+ * Only generated when email OTP is enabled in auth config.
170
+ *
171
+ * @default "/email-login"
172
+ */
173
+ emailOtp: string;
174
+ }
175
+ //#endregion
176
+ //#region src/api/auth.d.ts
177
+ /**
178
+ * Type for access controller created via createAccessControl().
179
+ * Used for RBAC on both server and client.
180
+ */
181
+ type AccessController = ReturnType<typeof createAccessControl>;
182
+ /**
183
+ * Type for roles created via ac.newRole().
184
+ */
185
+ type AccessControlRoles = Record<string, Role>;
186
+ /**
187
+ * Standard audit log actions following OCSF/CADF standards. Zod enum provides
188
+ * both runtime validation and TypeScript type.
189
+ *
190
+ * Actions:
191
+ * - Data ops: INSERT, UPDATE, DELETE, TRUNCATE, SELECT
192
+ * - Auth ops: LOGIN, LOGOUT, LOGIN_FAILED, PASSWORD_CHANGE
193
+ * - Custom: CUSTOM (use customAction field for app-specific events)
194
+ */
195
+ declare const auditActionSchema: z.ZodEnum<{
196
+ DELETE: "DELETE";
197
+ LOGIN: "LOGIN";
198
+ LOGOUT: "LOGOUT";
199
+ INSERT: "INSERT";
200
+ PASSWORD_CHANGE: "PASSWORD_CHANGE";
201
+ TRUNCATE: "TRUNCATE";
202
+ UPDATE: "UPDATE";
203
+ }>;
204
+ /**
205
+ * TypeScript type extracted from Zod enum.
206
+ */
207
+ type AuditAction = z.infer<typeof auditActionSchema>;
208
+ /**
209
+ * Type-safe audit log options for defineAuth().
210
+ *
211
+ * @template TDb - Database record type for table name inference
212
+ */
213
+ type AuditLogOptions<TDb> = {
214
+ /**
215
+ * Tables to exclude from audit logging.
216
+ */
217
+ excludeTables?: QualifiedTableNames<TDb>[];
218
+ /**
219
+ * Cron expression for purge schedule.
220
+ *
221
+ * @default "0 0 * * *"
222
+ */
223
+ purgeCron?: string;
224
+ /**
225
+ * Retention period in days. Audit logs older than this are auto-deleted.
226
+ * @default 90
227
+ */
228
+ retentionDays?: number;
229
+ };
230
+ /**
231
+ * Neutral auth configuration - shared between server and client.
232
+ * Contains ONLY fields that affect both sides (UI + server features).
233
+ *
234
+ * PRESENCE-BASED CONFIG: If a key exists, it's enabled. No redundant `enabled` fields.
235
+ * Server-only fields (appName, session) are passed via DefineAuthOptions.
236
+ */
237
+ interface AuthConfig {
238
+ /**
239
+ * Base URL where auth server is hosted.
240
+ *
241
+ * @default "" (same origin - client uses relative URLs)
242
+ * @example "http://localhost:8000" for cross-origin
243
+ */
244
+ baseURL?: string;
245
+ /**
246
+ * Base path for auth routes.
247
+ *
248
+ * @default "/auth"
249
+ */
250
+ basePath?: string;
251
+ /**
252
+ * Custom paths for authentication pages.
253
+ *
254
+ * @example
255
+ * ```typescript
256
+ * paths: {
257
+ * login: "/signin",
258
+ * signup: "/register",
259
+ * }
260
+ * ```
261
+ */
262
+ paths?: Partial<AuthPaths>;
263
+ /**
264
+ * Authentication methods - if defined, it's enabled.
265
+ **/
266
+ methods?: {
267
+ /**
268
+ * Email/password auth. If defined, enabled.
269
+ **/
270
+ emailPassword?: {
271
+ requireEmailVerification?: boolean;
272
+ minPasswordLength?: number;
273
+ maxPasswordLength?: number;
274
+ };
275
+ /**
276
+ * Magic link auth. If defined, enabled.
277
+ **/
278
+ magicLink?: {
279
+ expiresIn?: number;
280
+ };
281
+ /**
282
+ * Passkey auth. If defined (even as empty object), enabled.
283
+ **/
284
+ passkey?: Record<string, never>;
285
+ /**
286
+ * Phone OTP auth. If defined, enabled.
287
+ **/
288
+ phoneOtp?: {
289
+ otpLength?: number;
290
+ expiresIn?: number;
291
+ };
292
+ /**
293
+ * Email OTP auth. If defined, enabled.
294
+ **/
295
+ emailOtp?: {
296
+ otpLength?: number;
297
+ expiresIn?: number;
298
+ };
299
+ };
300
+ /**
301
+ * OAuth providers - true = enabled, undefined/false = disabled.
302
+ **/
303
+ oauth?: {
304
+ google?: boolean;
305
+ github?: boolean;
306
+ apple?: boolean;
307
+ facebook?: boolean;
308
+ };
309
+ /**
310
+ * Plugins - if defined, it's enabled.
311
+ **/
312
+ plugins?: {
313
+ /**
314
+ * Admin plugin. If defined, enabled. Includes RBAC for both server and client.
315
+ **/
316
+ admin?: {
317
+ defaultRole?: string;
318
+ adminRoles?: string[];
319
+ /**
320
+ * Access controller created via createAccessControl().
321
+ **/
322
+ ac: AccessController;
323
+ /**
324
+ * Role definitions created via ac.newRole().
325
+ **/
326
+ roles: AccessControlRoles;
327
+ };
328
+ /**
329
+ * API key plugin. If defined, enabled.
330
+ **/
331
+ apiKey?: {
332
+ defaultPrefix?: string;
333
+ defaultKeyLength?: number;
334
+ rateLimit?: {
335
+ maxRequests?: number;
336
+ timeWindow?: number;
337
+ };
338
+ };
339
+ /**
340
+ * Two-factor plugin. If defined, enabled. Sub-features also presence-based.
341
+ **/
342
+ twoFactor?: {
343
+ issuer?: string;
344
+ totp?: {
345
+ digits?: 6 | 8;
346
+ period?: number;
347
+ };
348
+ otp?: boolean;
349
+ backupCodes?: {
350
+ amount?: number;
351
+ length?: number;
352
+ };
353
+ };
354
+ /**
355
+ * Multi-session plugin. If defined, enabled.
356
+ **/
357
+ multiSession?: {
358
+ /**
359
+ * Maximum number of active sessions per user.
360
+ */
361
+ maximumSessions?: number;
362
+ };
363
+ /**
364
+ * Username plugin. If defined, enabled.
365
+ **/
366
+ username?: {
367
+ minUsernameLength?: number;
368
+ maxUsernameLength?: number;
369
+ };
370
+ /**
371
+ * Anonymous auth plugin. If defined, enabled.
372
+ **/
373
+ anonymous?: {
374
+ emailDomainName?: string;
375
+ };
376
+ /**
377
+ * SSO plugin. If defined, enabled.
378
+ **/
379
+ sso?: {
380
+ providersLimit?: number;
381
+ trustEmailVerified?: boolean;
382
+ domainVerification?: boolean;
383
+ };
384
+ };
385
+ /**
386
+ * Brand configuration for auth pages.
387
+ * Controls the logo and app name displayed on authentication screens.
388
+ */
389
+ brand?: {
390
+ /**
391
+ * Logo URL or path relative to the public folder.
392
+ *
393
+ * @default "/logo.png"
394
+ */
395
+ logo?: string;
396
+ /**
397
+ * Alt text for the logo image.
398
+ *
399
+ * @default App name or "Logo"
400
+ */
401
+ logoAlt?: string;
402
+ /**
403
+ * App or brand name displayed next to the logo.
404
+ *
405
+ * @default "AppOS"
406
+ */
407
+ name?: string;
408
+ };
409
+ /**
410
+ * Rate limiting configuration for auth endpoints.
411
+ * Uses database storage for horizontal scaling support.
412
+ * Set to false to disable.
413
+ *
414
+ * @default { enabled: true, window: 60, max: 100 }
415
+ *
416
+ * @example
417
+ * ```typescript
418
+ * // Default - enabled with sensible defaults
419
+ * rateLimit: undefined
420
+ *
421
+ * // Custom limits
422
+ * rateLimit: { window: 30, max: 50 }
423
+ *
424
+ * // Override specific endpoint limits
425
+ * rateLimit: {
426
+ * customRules: {
427
+ * "/send-verification-email": { window: 60, max: 10 },
428
+ * },
429
+ * }
430
+ *
431
+ * // Disable completely
432
+ * rateLimit: false
433
+ * ```
434
+ */
435
+ rateLimit?: {
436
+ /** Enable rate limiting. @default true */
437
+ enabled?: boolean;
438
+ /** Time window in seconds. @default 60 */
439
+ window?: number;
440
+ /** Max requests per window. @default 100 */
441
+ max?: number;
442
+ /** Custom rate limits per endpoint. Merged with defaults. */
443
+ customRules?: Record<string, {
444
+ window: number;
445
+ max: number;
446
+ }>;
447
+ } | false;
448
+ }
449
+ /** Base hook types for reference */
450
+ type EmailHook = (params: {
451
+ email: string;
452
+ url: string;
453
+ token: string;
454
+ }) => Promise<void>;
455
+ type OtpHook = (params: {
456
+ email: string;
457
+ otp: string;
458
+ }) => Promise<void>;
459
+ type PhoneOtpHook = (params: {
460
+ phoneNumber: string;
461
+ otp: string;
462
+ }) => Promise<void>;
463
+ /**
464
+ * Conditionally required hooks based on config.
465
+ */
466
+ type RequiredHooks<T extends AuthConfig> = (T["methods"] extends {
467
+ emailPassword: {
468
+ requireEmailVerification: true;
469
+ };
470
+ } ? {
471
+ sendVerificationEmail: EmailHook;
472
+ } : {
473
+ sendVerificationEmail?: EmailHook;
474
+ }) & (T["methods"] extends {
475
+ emailPassword: object;
476
+ } ? {
477
+ sendResetPasswordEmail: EmailHook;
478
+ } : {
479
+ sendResetPasswordEmail?: EmailHook;
480
+ }) & (T["methods"] extends {
481
+ magicLink: object;
482
+ } ? {
483
+ sendMagicLink: EmailHook;
484
+ } : {
485
+ sendMagicLink?: EmailHook;
486
+ }) & (T["methods"] extends {
487
+ emailOtp: object;
488
+ } ? {
489
+ sendEmailOTP: OtpHook;
490
+ } : {
491
+ sendEmailOTP?: OtpHook;
492
+ }) & (T["methods"] extends {
493
+ phoneOtp: object;
494
+ } ? {
495
+ sendPhoneOTP: PhoneOtpHook;
496
+ } : {
497
+ sendPhoneOTP?: PhoneOtpHook;
498
+ }) & (T["plugins"] extends {
499
+ twoFactor: {
500
+ otp: true;
501
+ };
502
+ } ? {
503
+ send2FAOTP: OtpHook;
504
+ } : {
505
+ send2FAOTP?: OtpHook;
506
+ });
507
+ /**
508
+ * Conditionally required OAuth credentials based on config.
509
+ * If an OAuth provider is enabled in config, its credentials are REQUIRED.
510
+ */
511
+ type RequiredOAuth<T extends AuthConfig> = (T["oauth"] extends {
512
+ google: true;
513
+ } ? {
514
+ google: {
515
+ clientId: string;
516
+ clientSecret: string;
517
+ };
518
+ } : {
519
+ google?: {
520
+ clientId: string;
521
+ clientSecret: string;
522
+ };
523
+ }) & (T["oauth"] extends {
524
+ github: true;
525
+ } ? {
526
+ github: {
527
+ clientId: string;
528
+ clientSecret: string;
529
+ };
530
+ } : {
531
+ github?: {
532
+ clientId: string;
533
+ clientSecret: string;
534
+ };
535
+ }) & (T["oauth"] extends {
536
+ apple: true;
537
+ } ? {
538
+ apple: {
539
+ clientId: string;
540
+ clientSecret: string;
541
+ };
542
+ } : {
543
+ apple?: {
544
+ clientId: string;
545
+ clientSecret: string;
546
+ };
547
+ }) & (T["oauth"] extends {
548
+ facebook: true;
549
+ } ? {
550
+ facebook: {
551
+ clientId: string;
552
+ clientSecret: string;
553
+ };
554
+ } : {
555
+ facebook?: {
556
+ clientId: string;
557
+ clientSecret: string;
558
+ };
559
+ });
560
+ /**
561
+ * Check if any OAuth provider is enabled.
562
+ **/
563
+ type HasOAuthEnabled<T extends AuthConfig> = T["oauth"] extends {
564
+ google: true;
565
+ } | {
566
+ github: true;
567
+ } | {
568
+ apple: true;
569
+ } | {
570
+ facebook: true;
571
+ } ? true : false;
572
+ /**
573
+ * Check if passkey is enabled
574
+ **/
575
+ type HasPasskeyEnabled<T extends AuthConfig> = T["methods"] extends {
576
+ passkey: object;
577
+ } ? true : false;
578
+ /**
579
+ * Server-only session configuration.
580
+ */
581
+ interface AuthSessionConfig {
582
+ /**
583
+ * Session duration in seconds.
584
+ *
585
+ * @default 604800 (7 days)
586
+ */
587
+ expiresIn?: number;
588
+ /**
589
+ * How often to update session in seconds.
590
+ *
591
+ * @default 86400 (1 day)
592
+ */
593
+ updateAge?: number;
594
+ /**
595
+ * Session freshness in seconds for sensitive ops.
596
+ *
597
+ * @default 86400 (1 day)
598
+ */
599
+ freshAge?: number;
600
+ }
601
+ /**
602
+ * Server-only passkey configuration (required if passkey is enabled).
603
+ */
604
+ interface AuthPasskeyConfig {
605
+ /**
606
+ * Relying Party ID - domain for passkey (e.g., "example.com" or "localhost").
607
+ */
608
+ rpID: string;
609
+ /**
610
+ * Origin URL for passkey verification (e.g., "http://localhost:8000").
611
+ */
612
+ origin: string;
613
+ }
614
+ /**
615
+ * Fully type-safe options for defineAuth().
616
+ *
617
+ * Server-only fields:
618
+ * - `appName` - Application name for passkey rpName, TOTP issuer, emails
619
+ * - `auditLog` - Audit logging configuration
620
+ * - `session` - Session duration and freshness settings
621
+ *
622
+ * Conditional requirements:
623
+ * - If config has `oauth.google: true`, then `oauth.google` credentials are REQUIRED
624
+ * - If config has `methods.magicLink` defined, then `hooks.sendMagicLink` is REQUIRED
625
+ *
626
+ * @template T - Auth config type
627
+ * @template TDb - Database record type for type-safe excludeTables
628
+ */
629
+ type DefineAuthOptions<T extends AuthConfig, TDb = unknown> = {
630
+ /**
631
+ * The application name.
632
+ */
633
+ appName: string;
634
+ /**
635
+ * Audit logging configuration (server-only). Use qualified table names: "dbName.tableName".
636
+ */
637
+ auditLog?: AuditLogOptions<TDb>;
638
+ /**
639
+ * The neutral auth configuration.
640
+ */
641
+ config: T;
642
+ /**
643
+ * Full db object (container.db) for type inference.
644
+ */
645
+ db: TDb;
646
+ /**
647
+ * Primary database for Better Auth storage.
648
+ */
649
+ database: Database;
650
+ /**
651
+ * Hooks for email sending and OTP delivery.
652
+ */
653
+ hooks: RequiredHooks<T>;
654
+ /**
655
+ * Secret key for signing tokens and cookies.
656
+ */
657
+ secret: string;
658
+ /**
659
+ * Session configuration.
660
+ */
661
+ session?: AuthSessionConfig;
662
+ /**
663
+ * URL to redirect users when auth errors occur (e.g., OAuth failures).
664
+ *
665
+ * Better Auth automatically appends `?error=...&error_description=...`
666
+ * query params to this URL when redirecting.
667
+ *
668
+ * @default "/login"
669
+ */
670
+ errorURL?: string;
671
+ } & (HasOAuthEnabled<T> extends true ? {
672
+ oauth: RequiredOAuth<T>;
673
+ } : {
674
+ oauth?: RequiredOAuth<T>;
675
+ }) & (HasPasskeyEnabled<T> extends true ? {
676
+ passkey: AuthPasskeyConfig;
677
+ } : {
678
+ passkey?: AuthPasskeyConfig;
679
+ });
680
+ /**
681
+ * Rate limit rule for a single endpoint.
682
+ */
683
+ type RateLimitRule = {
684
+ window: number;
685
+ max: number;
686
+ };
687
+ /**
688
+ * Default rate limits for endpoints that trigger costly 3rd party services.
689
+ * 3 requests per 60 seconds to prevent excessive email/SMS costs.
690
+ */
691
+ declare const DEFAULT_COSTLY_RATE_LIMITS: {
692
+ readonly "/send-verification-email": {
693
+ readonly window: 60;
694
+ readonly max: 3;
695
+ };
696
+ readonly "/request-password-reset": {
697
+ readonly window: 60;
698
+ readonly max: 3;
699
+ };
700
+ readonly "/sign-in/magic-link": {
701
+ readonly window: 60;
702
+ readonly max: 3;
703
+ };
704
+ readonly "/email-otp/send-verification-otp": {
705
+ readonly window: 60;
706
+ readonly max: 3;
707
+ };
708
+ readonly "/two-factor/send-otp": {
709
+ readonly window: 60;
710
+ readonly max: 3;
711
+ };
712
+ readonly "/phone-number/send-otp": {
713
+ readonly window: 60;
714
+ readonly max: 3;
715
+ };
716
+ };
717
+ /**
718
+ * Default endpoint paths that have rate limiting applied.
719
+ */
720
+ type DefaultRateLimitEndpoint = keyof typeof DEFAULT_COSTLY_RATE_LIMITS;
721
+ /**
722
+ * Creates endpoint-specific rate limit rules by merging user overrides with defaults.
723
+ * User overrides take precedence over defaults.
724
+ *
725
+ * @param overrides - Custom rate limits to override defaults (type-safe for default endpoints).
726
+ * @returns Merged rate limit rules.
727
+ *
728
+ * @see https://www.better-auth.com/docs/concepts/rate-limit
729
+ *
730
+ * @example
731
+ * ```typescript
732
+ * // Use defaults
733
+ * defineEndpointRateLimits()
734
+ *
735
+ * // Override specific endpoint (type-safe)
736
+ * defineEndpointRateLimits({
737
+ * "/send-verification-email": { window: 120, max: 5 },
738
+ * })
739
+ *
740
+ * // Add custom endpoint
741
+ * defineEndpointRateLimits({
742
+ * "/custom-endpoint": { window: 30, max: 10 },
743
+ * })
744
+ * ```
745
+ */
746
+ declare function defineEndpointRateLimits(overrides?: Partial<Record<DefaultRateLimitEndpoint, RateLimitRule>> & Record<string, RateLimitRule>): Record<string, RateLimitRule>;
747
+ /**
748
+ * Defines Better Auth instance from neutral config + server dependencies.
749
+ */
750
+ declare function defineAuth<T extends AuthConfig, TDb extends Record<"primary", Database> & Record<string, Database> = Record<"primary", Database> & Record<string, Database>>(opts: DefineAuthOptions<T, TDb>): ReturnType<typeof betterAuth> & {
751
+ auditLog?: AuditLogOptions<TDb>;
752
+ shouldAudit(tableName: QualifiedTableNames<TDb>): boolean;
753
+ };
754
+ /**
755
+ * The auth instance type.
756
+ */
757
+ type Auth$1<TDb extends Record<"primary", Database> & Record<string, Database> = Record<"primary", Database> & Record<string, Database>> = ReturnType<typeof defineAuth<AuthConfig, TDb>>;
758
+ //#endregion
759
+ export { defineTestDatabase as C, defineLogger as D, Logger as E, defineMigrationOpts as S, DefineLoggerOptions as T, DefineTestDatabaseOptions as _, AuthConfig as a, dbChanges as b, DefineAuthOptions as c, createAccessControl as d, defineAuth as f, DefineDatabaseOptions as g, Database as h, Auth$1 as i, Role as l, AuthPaths as m, AccessController as n, AuthPasskeyConfig as o, defineEndpointRateLimits as p, AuditAction as r, AuthSessionConfig as s, AccessControlRoles as t, auditActionSchema as u, MigrationType as v, migrationsSchema as w, defineDatabase as x, QualifiedTableNames as y };