appos 0.4.3-0 → 0.5.1-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 (206) hide show
  1. package/dist/exports/api/index.d.mts +3 -3
  2. package/dist/exports/api/index.mjs +34 -9
  3. package/dist/exports/api/workflows/index.d.mts +2 -2
  4. package/dist/exports/api/workflows/index.mjs +2 -2
  5. package/dist/exports/{auth-By0xx0MI.d.mts → auth-BCOIpGDO.d.mts} +325 -214
  6. package/dist/exports/cli/index.d.mts +105 -106
  7. package/dist/exports/cli/index.mjs +87 -13
  8. package/dist/exports/{constants-BePPc_yF.mjs → constants-BicCnEiJ.mjs} +7 -1
  9. package/dist/exports/{index-Bpo5QE7k.d.mts → index-CiuTp085.d.mts} +580 -614
  10. package/dist/exports/{openapi-crG3j4xx.mjs → openapi-uisUTLq7.mjs} +45 -102
  11. package/dist/exports/{send-email-Bgcdjy-e.mjs → send-email-CXxlkfFL.mjs} +1 -1
  12. package/dist/exports/{server-BlNxgHUc.mjs → server-CA4aI0U6.mjs} +6 -2
  13. package/dist/exports/storybook/index.d.ts +40 -0
  14. package/dist/exports/storybook/index.js +43 -0
  15. package/dist/exports/tests/api.d.mts +2 -2
  16. package/dist/exports/tests/api.mjs +3 -3
  17. package/dist/exports/vite/index.d.mts +19 -3
  18. package/dist/exports/vite/index.mjs +82 -6
  19. package/dist/exports/web/index.d.ts +2247 -700
  20. package/dist/exports/web/index.js +2445 -754
  21. package/dist/exports/web/routes.d.mts +41 -43
  22. package/dist/exports/web/ssr.d.mts +2 -2
  23. package/package.json +48 -31
  24. package/src/storybook/.storybook/main.ts +119 -0
  25. package/src/storybook/.storybook/manager.ts +75 -0
  26. package/src/storybook/.storybook/preview.tsx +76 -0
  27. package/src/storybook/components/ColorGrid.tsx +324 -0
  28. package/src/storybook/components/IconGallery.tsx +268 -0
  29. package/src/storybook/components/SpacingScale.tsx +236 -0
  30. package/src/storybook/components/TypographyScale.tsx +277 -0
  31. package/src/storybook/components/index.ts +3 -0
  32. package/src/storybook/docs/Introduction.mdx +29 -0
  33. package/src/storybook/docs/foundations/Colors.mdx +27 -0
  34. package/src/storybook/docs/foundations/Icons.mdx +26 -0
  35. package/src/storybook/docs/foundations/Spacing.mdx +23 -0
  36. package/src/storybook/docs/foundations/Typography.mdx +39 -0
  37. package/src/storybook/index.ts +147 -0
  38. package/src/storybook/shims/void-elements.js +18 -0
  39. package/src/web/client/auth-paths.ts +148 -0
  40. package/src/web/client/auth.ts +218 -0
  41. package/src/web/client/i18n.d.ts +9 -0
  42. package/src/web/client/i18n.ts +127 -0
  43. package/src/web/client/react-router.ts +84 -0
  44. package/src/web/hooks/index.ts +1 -0
  45. package/src/web/hooks/use-mobile.ts +19 -0
  46. package/src/web/index.ts +42 -0
  47. package/src/web/lib/colors.ts +220 -0
  48. package/src/web/lib/utils.ts +52 -0
  49. package/src/web/routes/auth/_layout.tsx +5 -11
  50. package/src/web/routes.ts +101 -0
  51. package/src/web/server/context.ts +14 -0
  52. package/src/web/server/render.ts +11 -0
  53. package/src/web/ssr.ts +17 -0
  54. package/src/web/ui/accordion.stories.tsx +183 -0
  55. package/src/web/ui/accordion.tsx +134 -0
  56. package/src/web/ui/alert-dialog.stories.tsx +215 -0
  57. package/src/web/ui/alert-dialog.tsx +328 -0
  58. package/src/web/ui/alert.stories.tsx +224 -0
  59. package/src/web/ui/alert.tsx +136 -0
  60. package/src/web/ui/animated-check.stories.tsx +200 -0
  61. package/src/web/ui/animated-check.tsx +98 -0
  62. package/src/web/ui/aspect-ratio.stories.tsx +204 -0
  63. package/src/web/ui/aspect-ratio.tsx +36 -0
  64. package/src/web/ui/auth/__mocks__/auth-context.tsx +273 -0
  65. package/src/web/ui/auth/auth-card.stories.tsx +295 -0
  66. package/src/web/ui/auth/auth-card.tsx +124 -0
  67. package/src/web/ui/auth/auth-layout.stories.tsx +330 -0
  68. package/src/web/ui/auth/auth-layout.tsx +269 -0
  69. package/src/web/ui/auth/captcha-widget.stories.tsx +200 -0
  70. package/src/web/ui/auth/captcha-widget.tsx +197 -0
  71. package/src/web/ui/auth/context.tsx +87 -0
  72. package/src/web/ui/auth/email-input.stories.tsx +167 -0
  73. package/src/web/ui/auth/email-input.tsx +84 -0
  74. package/src/web/ui/auth/forms/email-otp-form.tsx +377 -0
  75. package/src/web/ui/auth/forms/forgot-password-form.tsx +240 -0
  76. package/src/web/ui/auth/forms/index.ts +40 -0
  77. package/src/web/ui/auth/forms/login-form.tsx +486 -0
  78. package/src/web/ui/auth/forms/phone-otp-form.tsx +388 -0
  79. package/src/web/ui/auth/forms/reset-password-form.tsx +331 -0
  80. package/src/web/ui/auth/forms/signup-form.tsx +499 -0
  81. package/src/web/ui/auth/forms/two-factor-form.tsx +410 -0
  82. package/src/web/ui/auth/forms/verify-email-form.tsx +373 -0
  83. package/src/web/ui/auth/hooks.ts +266 -0
  84. package/src/web/ui/auth/index.ts +31 -0
  85. package/src/web/ui/auth/magic-link-form.tsx +191 -0
  86. package/src/web/ui/auth/otp-input.stories.tsx +199 -0
  87. package/src/web/ui/auth/otp-input.tsx +157 -0
  88. package/src/web/ui/auth/passkey-button.stories.tsx +115 -0
  89. package/src/web/ui/auth/passkey-button.tsx +113 -0
  90. package/src/web/ui/auth/passkey-register-button.stories.tsx +109 -0
  91. package/src/web/ui/auth/passkey-register-button.tsx +106 -0
  92. package/src/web/ui/auth/password-input.stories.tsx +287 -0
  93. package/src/web/ui/auth/password-input.tsx +306 -0
  94. package/src/web/ui/auth/phone-input.stories.tsx +160 -0
  95. package/src/web/ui/auth/phone-input.tsx +89 -0
  96. package/src/web/ui/auth/social-buttons.stories.tsx +217 -0
  97. package/src/web/ui/auth/social-buttons.tsx +196 -0
  98. package/src/web/ui/auth/sso-button.stories.tsx +160 -0
  99. package/src/web/ui/auth/sso-button.tsx +108 -0
  100. package/src/web/ui/auth/trust-signals.stories.tsx +208 -0
  101. package/src/web/ui/auth/trust-signals.tsx +260 -0
  102. package/src/web/ui/avatar.stories.tsx +302 -0
  103. package/src/web/ui/avatar.tsx +189 -0
  104. package/src/web/ui/badge.stories.tsx +225 -0
  105. package/src/web/ui/badge.tsx +66 -0
  106. package/src/web/ui/brand.stories.tsx +266 -0
  107. package/src/web/ui/brand.tsx +162 -0
  108. package/src/web/ui/breadcrumb.stories.tsx +271 -0
  109. package/src/web/ui/breadcrumb.tsx +214 -0
  110. package/src/web/ui/button-group.stories.tsx +251 -0
  111. package/src/web/ui/button-group.tsx +87 -0
  112. package/src/web/ui/button.stories.tsx +264 -0
  113. package/src/web/ui/button.tsx +120 -0
  114. package/src/web/ui/calendar.stories.tsx +235 -0
  115. package/src/web/ui/calendar.tsx +221 -0
  116. package/src/web/ui/card.stories.tsx +262 -0
  117. package/src/web/ui/card.tsx +199 -0
  118. package/src/web/ui/carousel.stories.tsx +244 -0
  119. package/src/web/ui/carousel.tsx +241 -0
  120. package/src/web/ui/chart.stories.tsx +833 -0
  121. package/src/web/ui/chart.tsx +390 -0
  122. package/src/web/ui/checkbox.stories.tsx +208 -0
  123. package/src/web/ui/checkbox.tsx +39 -0
  124. package/src/web/ui/collapsible.stories.tsx +239 -0
  125. package/src/web/ui/collapsible.tsx +21 -0
  126. package/src/web/ui/command.stories.tsx +291 -0
  127. package/src/web/ui/command.tsx +189 -0
  128. package/src/web/ui/context-menu.stories.tsx +255 -0
  129. package/src/web/ui/context-menu.tsx +263 -0
  130. package/src/web/ui/dialog.stories.tsx +263 -0
  131. package/src/web/ui/dialog.tsx +273 -0
  132. package/src/web/ui/drawer.stories.tsx +299 -0
  133. package/src/web/ui/drawer.tsx +130 -0
  134. package/src/web/ui/dropdown-menu.stories.tsx +320 -0
  135. package/src/web/ui/dropdown-menu.tsx +263 -0
  136. package/src/web/ui/empty.stories.tsx +204 -0
  137. package/src/web/ui/empty.tsx +101 -0
  138. package/src/web/ui/error-page.stories.tsx +181 -0
  139. package/src/web/ui/error-page.tsx +136 -0
  140. package/src/web/ui/field.stories.tsx +364 -0
  141. package/src/web/ui/field.tsx +252 -0
  142. package/src/web/ui/globals.css +3 -0
  143. package/src/web/ui/hover-card.stories.tsx +261 -0
  144. package/src/web/ui/hover-card.tsx +50 -0
  145. package/src/web/ui/index.ts +55 -0
  146. package/src/web/ui/input-group.stories.tsx +290 -0
  147. package/src/web/ui/input-group.tsx +157 -0
  148. package/src/web/ui/input-otp.stories.tsx +235 -0
  149. package/src/web/ui/input-otp.tsx +86 -0
  150. package/src/web/ui/input.stories.tsx +205 -0
  151. package/src/web/ui/input.tsx +30 -0
  152. package/src/web/ui/item.stories.tsx +348 -0
  153. package/src/web/ui/item.tsx +200 -0
  154. package/src/web/ui/kbd.stories.tsx +236 -0
  155. package/src/web/ui/kbd.tsx +27 -0
  156. package/src/web/ui/label.stories.tsx +180 -0
  157. package/src/web/ui/label.tsx +32 -0
  158. package/src/web/ui/locales/en/ui.json +13 -30
  159. package/src/web/ui/locales/zh-CN/ui.json +17 -34
  160. package/src/web/ui/locales/zh-TW/ui.json +17 -34
  161. package/src/web/ui/menubar.stories.tsx +385 -0
  162. package/src/web/ui/menubar.tsx +273 -0
  163. package/src/web/ui/navigation-menu.stories.tsx +361 -0
  164. package/src/web/ui/navigation-menu.tsx +168 -0
  165. package/src/web/ui/pagination.stories.tsx +312 -0
  166. package/src/web/ui/pagination.tsx +221 -0
  167. package/src/web/ui/popover.stories.tsx +315 -0
  168. package/src/web/ui/popover.tsx +89 -0
  169. package/src/web/ui/progress.stories.tsx +239 -0
  170. package/src/web/ui/progress.tsx +128 -0
  171. package/src/web/ui/radio-group.stories.tsx +315 -0
  172. package/src/web/ui/radio-group.tsx +38 -0
  173. package/src/web/ui/resizable.stories.tsx +304 -0
  174. package/src/web/ui/resizable.tsx +53 -0
  175. package/src/web/ui/scroll-area.stories.tsx +276 -0
  176. package/src/web/ui/scroll-area.tsx +53 -0
  177. package/src/web/ui/select.stories.tsx +314 -0
  178. package/src/web/ui/select.tsx +312 -0
  179. package/src/web/ui/separator.stories.tsx +246 -0
  180. package/src/web/ui/separator.tsx +36 -0
  181. package/src/web/ui/sheet.stories.tsx +417 -0
  182. package/src/web/ui/sheet.tsx +133 -0
  183. package/src/web/ui/sidebar.stories.tsx +402 -0
  184. package/src/web/ui/sidebar.tsx +723 -0
  185. package/src/web/ui/skeleton.stories.tsx +235 -0
  186. package/src/web/ui/skeleton.tsx +26 -0
  187. package/src/web/ui/slider.stories.tsx +294 -0
  188. package/src/web/ui/slider.tsx +75 -0
  189. package/src/web/ui/sonner.stories.tsx +279 -0
  190. package/src/web/ui/sonner.tsx +46 -0
  191. package/src/web/ui/spinner.stories.tsx +204 -0
  192. package/src/web/ui/spinner.tsx +28 -0
  193. package/src/web/ui/switch.stories.tsx +285 -0
  194. package/src/web/ui/switch.tsx +43 -0
  195. package/src/web/ui/table.stories.tsx +362 -0
  196. package/src/web/ui/table.tsx +115 -0
  197. package/src/web/ui/tabs.stories.tsx +401 -0
  198. package/src/web/ui/tabs.tsx +136 -0
  199. package/src/web/ui/textarea.stories.tsx +272 -0
  200. package/src/web/ui/textarea.tsx +28 -0
  201. package/src/web/ui/toggle-group.stories.tsx +334 -0
  202. package/src/web/ui/toggle-group.tsx +88 -0
  203. package/src/web/ui/toggle.stories.tsx +264 -0
  204. package/src/web/ui/toggle.tsx +57 -0
  205. package/src/web/ui/tooltip.stories.tsx +342 -0
  206. package/src/web/ui/tooltip.tsx +116 -0
@@ -1,4 +1,5 @@
1
- import { betterAuth } from "better-auth";
1
+ import { PasskeyOptions } from "@better-auth/passkey";
2
+ import { BetterAuthOptions, betterAuth } from "better-auth";
2
3
  import { Role, createAccessControl } from "better-auth/plugins/access";
3
4
  import { z } from "zod";
4
5
  import * as drizzle_orm0 from "drizzle-orm";
@@ -127,49 +128,49 @@ declare function defineTestDatabase<TSchema extends Record<string, unknown> = Re
127
128
  */
128
129
  interface AuthPaths {
129
130
  /**
130
- * Path to the login page.
131
- *
132
- * @default "/login"
133
- */
131
+ * Path to the login page.
132
+ *
133
+ * @default "/login"
134
+ */
134
135
  login: string;
135
136
  /**
136
- * Path to the signup/registration page.
137
- *
138
- * @default "/signup"
139
- */
137
+ * Path to the signup/registration page.
138
+ *
139
+ * @default "/signup"
140
+ */
140
141
  signup: string;
141
142
  /**
142
- * Path to the email verification page.
143
- * Only used when email verification is enabled.
144
- *
145
- * @default "/verify-email"
146
- */
143
+ * Path to the email verification page.
144
+ * Only used when email verification is enabled.
145
+ *
146
+ * @default "/verify-email"
147
+ */
147
148
  verifyEmail: string;
148
149
  /**
149
- * Path to the forgot password page.
150
- *
151
- * @default "/forgot-password"
152
- */
150
+ * Path to the forgot password page.
151
+ *
152
+ * @default "/forgot-password"
153
+ */
153
154
  forgotPassword: string;
154
155
  /**
155
- * Path to the password reset page.
156
- *
157
- * @default "/reset-password"
158
- */
156
+ * Path to the password reset page.
157
+ *
158
+ * @default "/reset-password"
159
+ */
159
160
  resetPassword: string;
160
161
  /**
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
- */
162
+ * Path to the phone OTP login page.
163
+ * Only generated when phone OTP is enabled in auth config.
164
+ *
165
+ * @default "/phone-login"
166
+ */
166
167
  phoneOtp: string;
167
168
  /**
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
- */
169
+ * Path to the email OTP login page.
170
+ * Only generated when email OTP is enabled in auth config.
171
+ *
172
+ * @default "/email-login"
173
+ */
173
174
  emailOtp: string;
174
175
  }
175
176
  //#endregion
@@ -183,6 +184,20 @@ type AccessController = ReturnType<typeof createAccessControl>;
183
184
  * Type for roles created via ac.newRole().
184
185
  */
185
186
  type AccessControlRoles = Record<string, Role>;
187
+ /**
188
+ * Array of all supported captcha providers.
189
+ * Use with z.enum() for config validation.
190
+ *
191
+ * @example
192
+ * ```ts
193
+ * CAPTCHA_PROVIDER: z.enum(captchaProviders).optional(),
194
+ * ```
195
+ */
196
+ declare const captchaProviders: readonly ["cloudflare-turnstile", "google-recaptcha", "hcaptcha", "captchafox"];
197
+ /**
198
+ * Captcha provider type.
199
+ */
200
+ type CaptchaProvider = (typeof captchaProviders)[number];
186
201
  /**
187
202
  * Standard audit log actions following OCSF/CADF standards. Zod enum provides
188
203
  * both runtime validation and TypeScript type.
@@ -212,19 +227,19 @@ type AuditAction = z.infer<typeof auditActionSchema>;
212
227
  */
213
228
  type AuditLogOptions<TDb> = {
214
229
  /**
215
- * Tables to exclude from audit logging.
216
- */
230
+ * Tables to exclude from audit logging.
231
+ */
217
232
  excludeTables?: QualifiedTableNames<TDb>[];
218
233
  /**
219
- * Cron expression for purge schedule.
220
- *
221
- * @default "0 0 * * *"
222
- */
234
+ * Cron expression for purge schedule.
235
+ *
236
+ * @default "0 0 * * *"
237
+ */
223
238
  purgeCron?: string;
224
239
  /**
225
- * Retention period in days. Audit logs older than this are auto-deleted.
226
- * @default 90
227
- */
240
+ * Retention period in days. Audit logs older than this are auto-deleted.
241
+ * @default 90
242
+ */
228
243
  retentionDays?: number;
229
244
  };
230
245
  /**
@@ -236,98 +251,98 @@ type AuditLogOptions<TDb> = {
236
251
  */
237
252
  interface AuthConfig {
238
253
  /**
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
- */
254
+ * Base URL where auth server is hosted.
255
+ *
256
+ * @default "" (same origin - client uses relative URLs)
257
+ * @example "http://localhost:8000" for cross-origin
258
+ */
244
259
  baseURL?: string;
245
260
  /**
246
- * Base path for auth routes.
247
- *
248
- * @default "/auth"
249
- */
261
+ * Base path for auth routes.
262
+ *
263
+ * @default "/auth"
264
+ */
250
265
  basePath?: string;
251
266
  /**
252
- * Custom paths for authentication pages.
253
- *
254
- * @example
255
- * ```typescript
256
- * paths: {
257
- * login: "/signin",
258
- * signup: "/register",
259
- * }
260
- * ```
261
- */
267
+ * Custom paths for authentication pages.
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * paths: {
272
+ * login: "/signin",
273
+ * signup: "/register",
274
+ * }
275
+ * ```
276
+ */
262
277
  paths?: Partial<AuthPaths>;
263
278
  /**
264
- * Authentication methods - if defined, it's enabled.
265
- **/
279
+ * Authentication methods - if defined, it's enabled.
280
+ **/
266
281
  methods?: {
267
282
  /**
268
- * Email/password auth. If defined, enabled.
269
- **/
283
+ * Email/password auth. If defined, enabled.
284
+ **/
270
285
  emailPassword?: {
271
286
  requireEmailVerification?: boolean;
272
287
  minPasswordLength?: number;
273
288
  maxPasswordLength?: number;
274
289
  };
275
290
  /**
276
- * Magic link auth. If defined, enabled.
277
- **/
291
+ * Magic link auth. If defined, enabled.
292
+ **/
278
293
  magicLink?: {
279
294
  expiresIn?: number;
280
295
  };
281
296
  /**
282
- * Passkey auth. If defined (even as empty object), enabled.
283
- **/
297
+ * Passkey auth. If defined (even as empty object), enabled.
298
+ **/
284
299
  passkey?: Record<string, never>;
285
300
  /**
286
- * Phone OTP auth. If defined, enabled.
287
- **/
301
+ * Phone OTP auth. If defined, enabled.
302
+ **/
288
303
  phoneOtp?: {
289
304
  otpLength?: number;
290
305
  expiresIn?: number;
291
306
  };
292
307
  /**
293
- * Email OTP auth. If defined, enabled.
294
- **/
308
+ * Email OTP auth. If defined, enabled.
309
+ **/
295
310
  emailOtp?: {
296
311
  otpLength?: number;
297
312
  expiresIn?: number;
298
313
  };
314
+ /**
315
+ * OAuth providers - true = enabled, undefined/false = disabled.
316
+ **/
317
+ oauth?: {
318
+ google?: boolean;
319
+ github?: boolean;
320
+ apple?: boolean;
321
+ facebook?: boolean;
322
+ };
299
323
  };
300
324
  /**
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
- **/
325
+ * Plugins - if defined, it's enabled.
326
+ **/
312
327
  plugins?: {
313
328
  /**
314
- * Admin plugin. If defined, enabled. Includes RBAC for both server and client.
315
- **/
329
+ * Admin plugin. If defined, enabled. Includes RBAC for both server and client.
330
+ **/
316
331
  admin?: {
317
332
  defaultRole?: string;
318
333
  adminRoles?: string[];
319
334
  /**
320
- * Access controller created via createAccessControl().
321
- **/
335
+ * Access controller created via createAccessControl().
336
+ **/
322
337
  ac: AccessController;
323
338
  /**
324
- * Role definitions created via ac.newRole().
325
- **/
339
+ * Role definitions created via ac.newRole().
340
+ **/
326
341
  roles: AccessControlRoles;
327
342
  };
328
343
  /**
329
- * API key plugin. If defined, enabled.
330
- **/
344
+ * API key plugin. If defined, enabled.
345
+ **/
331
346
  apiKey?: {
332
347
  defaultPrefix?: string;
333
348
  defaultKeyLength?: number;
@@ -337,8 +352,8 @@ interface AuthConfig {
337
352
  };
338
353
  };
339
354
  /**
340
- * Two-factor plugin. If defined, enabled. Sub-features also presence-based.
341
- **/
355
+ * Two-factor plugin. If defined, enabled. Sub-features also presence-based.
356
+ **/
342
357
  twoFactor?: {
343
358
  issuer?: string;
344
359
  totp?: {
@@ -352,94 +367,159 @@ interface AuthConfig {
352
367
  };
353
368
  };
354
369
  /**
355
- * Multi-session plugin. If defined, enabled.
356
- **/
370
+ * Multi-session plugin. If defined, enabled.
371
+ **/
357
372
  multiSession?: {
358
373
  /**
359
- * Maximum number of active sessions per user.
360
- */
374
+ * Maximum number of active sessions per user.
375
+ */
361
376
  maximumSessions?: number;
362
377
  };
363
378
  /**
364
- * Username plugin. If defined, enabled.
365
- **/
379
+ * Username plugin. If defined, enabled.
380
+ **/
366
381
  username?: {
367
382
  minUsernameLength?: number;
368
383
  maxUsernameLength?: number;
369
384
  };
370
385
  /**
371
- * Anonymous auth plugin. If defined, enabled.
372
- **/
386
+ * Anonymous auth plugin. If defined, enabled.
387
+ **/
373
388
  anonymous?: {
374
389
  emailDomainName?: string;
375
390
  };
376
391
  /**
377
- * SSO plugin. If defined, enabled.
378
- **/
392
+ * SSO plugin. If defined, enabled.
393
+ **/
379
394
  sso?: {
380
395
  providersLimit?: number;
381
396
  trustEmailVerified?: boolean;
382
397
  domainVerification?: boolean;
383
398
  };
399
+ /**
400
+ * Last used login method plugin. If defined, enabled.
401
+ * Tracks the most recent authentication method used by each user.
402
+ **/
403
+ lastUsedMethod?: {
404
+ /**
405
+ * Persist last used method to database for cross-device access.
406
+ *
407
+ * @default false (cookie-only storage)
408
+ */
409
+ storeInDatabase?: boolean;
410
+ };
411
+ /**
412
+ * Captcha plugin. If defined, enabled.
413
+ * Protects auth endpoints from bots and abuse.
414
+ **/
415
+ captcha?: {
416
+ /**
417
+ * Captcha provider to use.
418
+ * For Google reCAPTCHA: v2 vs v3 is determined by server-side minScore config.
419
+ */
420
+ provider: "cloudflare-turnstile" | "google-recaptcha" | "hcaptcha" | "captchafox";
421
+ /**
422
+ * Public site key for the captcha widget (safe to expose in client).
423
+ */
424
+ siteKey: string;
425
+ /**
426
+ * Endpoints to protect with captcha validation.
427
+ * Uses substring matching via `request.url.includes(endpoint)`.
428
+ *
429
+ * @default ["/sign-up/email", "/sign-in/email", "/request-password-reset"]
430
+ *
431
+ * @example
432
+ * ```typescript
433
+ * // Protect high-risk endpoints (recommended)
434
+ * endpoints: [
435
+ * "/sign-up/email",
436
+ * "/sign-in/email",
437
+ * "/sign-in/magic-link",
438
+ * "/request-password-reset",
439
+ * "/email-otp/send-verification-otp",
440
+ * "/send-verification-email",
441
+ * "/phone-number/send-otp",
442
+ * ]
443
+ * ```
444
+ */
445
+ endpoints?: string[];
446
+ };
384
447
  };
385
448
  /**
386
- * Brand configuration for auth pages.
387
- * Controls the logo and app name displayed on authentication screens.
388
- */
449
+ * Brand configuration for auth pages.
450
+ * Controls the logo, app name, layout, and legal URLs displayed on authentication screens.
451
+ */
389
452
  brand?: {
390
453
  /**
391
- * Logo URL or path relative to the public folder.
392
- *
393
- * @default "/logo.png"
394
- */
454
+ * Logo URL or path relative to the public folder.
455
+ *
456
+ * @default "/logo.png"
457
+ */
395
458
  logo?: string;
396
459
  /**
397
- * Alt text for the logo image.
398
- *
399
- * @default App name or "Logo"
400
- */
460
+ * Alt text for the logo image.
461
+ *
462
+ * @default App name or "Logo"
463
+ */
401
464
  logoAlt?: string;
402
465
  /**
403
- * App or brand name displayed next to the logo.
404
- *
405
- * @default "AppOS"
406
- */
466
+ * App or brand name displayed next to the logo.
467
+ *
468
+ * @default "AppOS"
469
+ */
407
470
  name?: string;
471
+ /**
472
+ * URL to the privacy policy page.
473
+ *
474
+ * @default "/legal/privacy-policy"
475
+ */
476
+ privacyUrl?: string;
477
+ /**
478
+ * URL to the terms of service page.
479
+ *
480
+ * @default "/legal/terms"
481
+ */
482
+ termsUrl?: string;
483
+ /**
484
+ * Layout variant for auth pages.
485
+ * - "centered": Card centered on page (default)
486
+ * - "split": Two-column layout with branding on left
487
+ * - "minimal": Simple centered layout without trust signals
488
+ *
489
+ * @default "centered"
490
+ */
491
+ layoutVariant?: "centered" | "split" | "minimal";
408
492
  };
409
493
  /**
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
- */
494
+ * Rate limiting configuration for auth endpoints.
495
+ * Uses database storage for horizontal scaling support.
496
+ * Set to false to disable.
497
+ *
498
+ * @default { enabled: true, window: 60, max: 100 }
499
+ *
500
+ * @example
501
+ * ```typescript
502
+ * // Default - enabled with sensible defaults
503
+ * rateLimit: undefined
504
+ *
505
+ * // Custom limits
506
+ * rateLimit: { window: 30, max: 50 }
507
+ *
508
+ * // Override specific endpoint limits
509
+ * rateLimit: {
510
+ * customRules: {
511
+ * "/send-verification-email": { window: 60, max: 10 },
512
+ * },
513
+ * }
514
+ *
515
+ * // Disable completely
516
+ * rateLimit: false
517
+ * ```
518
+ */
435
519
  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. */
520
+ /** Enable rate limiting. @default true */enabled?: boolean; /** Time window in seconds. @default 60 */
521
+ window?: number; /** Max requests per window. @default 100 */
522
+ max?: number; /** Custom rate limits per endpoint. Merged with defaults. */
443
523
  customRules?: Record<string, {
444
524
  window: number;
445
525
  max: number;
@@ -508,8 +588,10 @@ type RequiredHooks<T extends AuthConfig> = (T["methods"] extends {
508
588
  * Conditionally required OAuth credentials based on config.
509
589
  * If an OAuth provider is enabled in config, its credentials are REQUIRED.
510
590
  */
511
- type RequiredOAuth<T extends AuthConfig> = (T["oauth"] extends {
512
- google: true;
591
+ type RequiredOAuth<T extends AuthConfig> = (T["methods"] extends {
592
+ oauth: {
593
+ google: true;
594
+ };
513
595
  } ? {
514
596
  google: {
515
597
  clientId: string;
@@ -520,8 +602,10 @@ type RequiredOAuth<T extends AuthConfig> = (T["oauth"] extends {
520
602
  clientId: string;
521
603
  clientSecret: string;
522
604
  };
523
- }) & (T["oauth"] extends {
524
- github: true;
605
+ }) & (T["methods"] extends {
606
+ oauth: {
607
+ github: true;
608
+ };
525
609
  } ? {
526
610
  github: {
527
611
  clientId: string;
@@ -532,8 +616,10 @@ type RequiredOAuth<T extends AuthConfig> = (T["oauth"] extends {
532
616
  clientId: string;
533
617
  clientSecret: string;
534
618
  };
535
- }) & (T["oauth"] extends {
536
- apple: true;
619
+ }) & (T["methods"] extends {
620
+ oauth: {
621
+ apple: true;
622
+ };
537
623
  } ? {
538
624
  apple: {
539
625
  clientId: string;
@@ -544,8 +630,10 @@ type RequiredOAuth<T extends AuthConfig> = (T["oauth"] extends {
544
630
  clientId: string;
545
631
  clientSecret: string;
546
632
  };
547
- }) & (T["oauth"] extends {
548
- facebook: true;
633
+ }) & (T["methods"] extends {
634
+ oauth: {
635
+ facebook: true;
636
+ };
549
637
  } ? {
550
638
  facebook: {
551
639
  clientId: string;
@@ -560,14 +648,22 @@ type RequiredOAuth<T extends AuthConfig> = (T["oauth"] extends {
560
648
  /**
561
649
  * Check if any OAuth provider is enabled.
562
650
  **/
563
- type HasOAuthEnabled<T extends AuthConfig> = T["oauth"] extends {
564
- google: true;
651
+ type HasOAuthEnabled<T extends AuthConfig> = T["methods"] extends {
652
+ oauth: {
653
+ google: true;
654
+ };
565
655
  } | {
566
- github: true;
656
+ oauth: {
657
+ github: true;
658
+ };
567
659
  } | {
568
- apple: true;
660
+ oauth: {
661
+ apple: true;
662
+ };
569
663
  } | {
570
- facebook: true;
664
+ oauth: {
665
+ facebook: true;
666
+ };
571
667
  } ? true : false;
572
668
  /**
573
669
  * Check if passkey is enabled
@@ -575,41 +671,52 @@ type HasOAuthEnabled<T extends AuthConfig> = T["oauth"] extends {
575
671
  type HasPasskeyEnabled<T extends AuthConfig> = T["methods"] extends {
576
672
  passkey: object;
577
673
  } ? true : false;
674
+ /**
675
+ * Check if captcha is enabled
676
+ **/
677
+ type HasCaptchaEnabled<T extends AuthConfig> = T["plugins"] extends {
678
+ captcha: object;
679
+ } ? true : false;
680
+ /**
681
+ * Helper type to extract Better Auth's session options.
682
+ */
683
+ type BetterAuthSessionOptions = NonNullable<BetterAuthOptions["session"]>;
578
684
  /**
579
685
  * Server-only session configuration.
686
+ * Derived from Better Auth's BetterAuthOptions['session'] for type safety.
580
687
  */
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
- }
688
+ type AuthSessionConfig = Pick<BetterAuthSessionOptions, "expiresIn" | "updateAge" | "freshAge">;
601
689
  /**
602
690
  * Server-only passkey configuration (required if passkey is enabled).
691
+ * Derived from Better Auth's PasskeyOptions with rpID made required
692
+ * and origin narrowed to string (appos doesn't support array origins).
603
693
  */
604
- interface AuthPasskeyConfig {
605
- /**
606
- * Relying Party ID - domain for passkey (e.g., "example.com" or "localhost").
607
- */
608
- rpID: string;
694
+ type AuthPasskeyConfig = Required<Pick<PasskeyOptions, "rpID">> & {
609
695
  /**
610
- * Origin URL for passkey verification (e.g., "http://localhost:8000").
611
- */
696
+ * Origin URL for passkey verification (e.g., "http://localhost:8000").
697
+ * Unlike Better Auth which supports string | string[] | null, appos
698
+ * requires a single origin string for simplicity.
699
+ */
612
700
  origin: string;
701
+ };
702
+ /**
703
+ * Server-only captcha configuration (required if captcha is enabled).
704
+ * These fields align with Better Auth's captcha plugin options.
705
+ */
706
+ interface AuthCaptchaConfig {
707
+ /**
708
+ * Secret key for server-side captcha validation.
709
+ * Keep this secret - never expose in client code.
710
+ */
711
+ secretKey: string;
712
+ /**
713
+ * Minimum score threshold for Google reCAPTCHA v3.
714
+ * Scores range from 0.0 (bot) to 1.0 (human).
715
+ * Only applicable when using Google reCAPTCHA.
716
+ *
717
+ * @default 0.5
718
+ */
719
+ minScore?: number;
613
720
  }
614
721
  /**
615
722
  * Fully type-safe options for defineAuth().
@@ -628,45 +735,45 @@ interface AuthPasskeyConfig {
628
735
  */
629
736
  type DefineAuthOptions<T extends AuthConfig, TDb = unknown> = {
630
737
  /**
631
- * The application name.
632
- */
738
+ * The application name.
739
+ */
633
740
  appName: string;
634
741
  /**
635
- * Audit logging configuration (server-only). Use qualified table names: "dbName.tableName".
636
- */
742
+ * Audit logging configuration (server-only). Use qualified table names: "dbName.tableName".
743
+ */
637
744
  auditLog?: AuditLogOptions<TDb>;
638
745
  /**
639
- * The neutral auth configuration.
640
- */
746
+ * The neutral auth configuration.
747
+ */
641
748
  config: T;
642
749
  /**
643
- * Full db object (container.db) for type inference.
644
- */
750
+ * Full db object (container.db) for type inference.
751
+ */
645
752
  db: TDb;
646
753
  /**
647
- * Primary database for Better Auth storage.
648
- */
754
+ * Primary database for Better Auth storage.
755
+ */
649
756
  database: Database;
650
757
  /**
651
- * Hooks for email sending and OTP delivery.
652
- */
758
+ * Hooks for email sending and OTP delivery.
759
+ */
653
760
  hooks: RequiredHooks<T>;
654
761
  /**
655
- * Secret key for signing tokens and cookies.
656
- */
762
+ * Secret key for signing tokens and cookies.
763
+ */
657
764
  secret: string;
658
765
  /**
659
- * Session configuration.
660
- */
766
+ * Session configuration.
767
+ */
661
768
  session?: AuthSessionConfig;
662
769
  /**
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
- */
770
+ * URL to redirect users when auth errors occur (e.g., OAuth failures).
771
+ *
772
+ * Better Auth automatically appends `?error=...&error_description=...`
773
+ * query params to this URL when redirecting.
774
+ *
775
+ * @default "/login"
776
+ */
670
777
  errorURL?: string;
671
778
  } & (HasOAuthEnabled<T> extends true ? {
672
779
  oauth: RequiredOAuth<T>;
@@ -676,6 +783,10 @@ type DefineAuthOptions<T extends AuthConfig, TDb = unknown> = {
676
783
  passkey: AuthPasskeyConfig;
677
784
  } : {
678
785
  passkey?: AuthPasskeyConfig;
786
+ }) & (HasCaptchaEnabled<T> extends true ? {
787
+ captcha: AuthCaptchaConfig;
788
+ } : {
789
+ captcha?: AuthCaptchaConfig;
679
790
  });
680
791
  /**
681
792
  * Rate limit rule for a single endpoint.
@@ -756,4 +867,4 @@ declare function defineAuth<T extends AuthConfig, TDb extends Record<"primary",
756
867
  */
757
868
  type Auth$1<TDb extends Record<"primary", Database> & Record<string, Database> = Record<"primary", Database> & Record<string, Database>> = ReturnType<typeof defineAuth<AuthConfig, TDb>>;
758
869
  //#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 };
870
+ export { defineLogger as A, dbChanges as C, migrationsSchema as D, defineTestDatabase as E, DefineLoggerOptions as O, QualifiedTableNames as S, defineMigrationOpts as T, AuthPaths as _, AuthCaptchaConfig as a, DefineTestDatabaseOptions as b, AuthSessionConfig as c, Role as d, auditActionSchema as f, defineEndpointRateLimits as g, defineAuth as h, Auth$1 as i, Logger as k, CaptchaProvider as l, createAccessControl as m, AccessController as n, AuthConfig as o, captchaProviders as p, AuditAction as r, AuthPasskeyConfig as s, AccessControlRoles as t, DefineAuthOptions as u, Database as v, defineDatabase as w, MigrationType as x, DefineDatabaseOptions as y };