@depup/better-auth__core 1.6.23-depup.2

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 (310) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +32 -0
  3. package/changes.json +14 -0
  4. package/dist/api/index.d.mts +281 -0
  5. package/dist/api/index.mjs +92 -0
  6. package/dist/async_hooks/index.d.mts +6 -0
  7. package/dist/async_hooks/index.mjs +20 -0
  8. package/dist/async_hooks/pure.index.d.mts +6 -0
  9. package/dist/async_hooks/pure.index.mjs +33 -0
  10. package/dist/context/endpoint-context.d.mts +18 -0
  11. package/dist/context/endpoint-context.mjs +29 -0
  12. package/dist/context/global.d.mts +6 -0
  13. package/dist/context/global.mjs +36 -0
  14. package/dist/context/index.d.mts +5 -0
  15. package/dist/context/index.mjs +5 -0
  16. package/dist/context/request-state.d.mts +27 -0
  17. package/dist/context/request-state.mjs +47 -0
  18. package/dist/context/transaction.d.mts +27 -0
  19. package/dist/context/transaction.mjs +96 -0
  20. package/dist/db/adapter/factory.d.mts +17 -0
  21. package/dist/db/adapter/factory.mjs +905 -0
  22. package/dist/db/adapter/get-default-field-name.d.mts +18 -0
  23. package/dist/db/adapter/get-default-field-name.mjs +36 -0
  24. package/dist/db/adapter/get-default-model-name.d.mts +12 -0
  25. package/dist/db/adapter/get-default-model-name.mjs +30 -0
  26. package/dist/db/adapter/get-field-attributes.d.mts +26 -0
  27. package/dist/db/adapter/get-field-attributes.mjs +37 -0
  28. package/dist/db/adapter/get-field-name.d.mts +18 -0
  29. package/dist/db/adapter/get-field-name.mjs +31 -0
  30. package/dist/db/adapter/get-id-field.d.mts +36 -0
  31. package/dist/db/adapter/get-id-field.mjs +64 -0
  32. package/dist/db/adapter/get-model-name.d.mts +12 -0
  33. package/dist/db/adapter/get-model-name.mjs +21 -0
  34. package/dist/db/adapter/index.d.mts +615 -0
  35. package/dist/db/adapter/index.mjs +24 -0
  36. package/dist/db/adapter/types.d.mts +105 -0
  37. package/dist/db/adapter/utils.d.mts +7 -0
  38. package/dist/db/adapter/utils.mjs +37 -0
  39. package/dist/db/get-tables.d.mts +6 -0
  40. package/dist/db/get-tables.mjs +266 -0
  41. package/dist/db/index.d.mts +10 -0
  42. package/dist/db/index.mjs +8 -0
  43. package/dist/db/plugin.d.mts +12 -0
  44. package/dist/db/schema/account.d.mts +28 -0
  45. package/dist/db/schema/account.mjs +17 -0
  46. package/dist/db/schema/rate-limit.d.mts +18 -0
  47. package/dist/db/schema/rate-limit.mjs +9 -0
  48. package/dist/db/schema/session.d.mts +23 -0
  49. package/dist/db/schema/session.mjs +12 -0
  50. package/dist/db/schema/shared.d.mts +10 -0
  51. package/dist/db/schema/shared.mjs +9 -0
  52. package/dist/db/schema/user.d.mts +22 -0
  53. package/dist/db/schema/user.mjs +11 -0
  54. package/dist/db/schema/verification.d.mts +21 -0
  55. package/dist/db/schema/verification.mjs +10 -0
  56. package/dist/db/type.d.mts +194 -0
  57. package/dist/env/color-depth.d.mts +4 -0
  58. package/dist/env/color-depth.mjs +86 -0
  59. package/dist/env/env-impl.d.mts +32 -0
  60. package/dist/env/env-impl.mjs +81 -0
  61. package/dist/env/index.d.mts +4 -0
  62. package/dist/env/index.mjs +4 -0
  63. package/dist/env/logger.d.mts +48 -0
  64. package/dist/env/logger.mjs +79 -0
  65. package/dist/error/codes.d.mts +69 -0
  66. package/dist/error/codes.mjs +55 -0
  67. package/dist/error/index.d.mts +26 -0
  68. package/dist/error/index.mjs +27 -0
  69. package/dist/index.d.mts +9 -0
  70. package/dist/index.mjs +1 -0
  71. package/dist/instrumentation/api.mjs +12 -0
  72. package/dist/instrumentation/attributes.d.mts +11 -0
  73. package/dist/instrumentation/attributes.mjs +10 -0
  74. package/dist/instrumentation/index.d.mts +3 -0
  75. package/dist/instrumentation/index.mjs +3 -0
  76. package/dist/instrumentation/noop.mjs +42 -0
  77. package/dist/instrumentation/pure.index.d.mts +7 -0
  78. package/dist/instrumentation/pure.index.mjs +7 -0
  79. package/dist/instrumentation/tracer.d.mts +13 -0
  80. package/dist/instrumentation/tracer.mjs +53 -0
  81. package/dist/oauth2/client-credentials-token.d.mts +56 -0
  82. package/dist/oauth2/client-credentials-token.mjs +64 -0
  83. package/dist/oauth2/create-authorization-url.d.mts +44 -0
  84. package/dist/oauth2/create-authorization-url.mjs +41 -0
  85. package/dist/oauth2/index.d.mts +8 -0
  86. package/dist/oauth2/index.mjs +7 -0
  87. package/dist/oauth2/oauth-provider.d.mts +192 -0
  88. package/dist/oauth2/refresh-access-token.d.mts +54 -0
  89. package/dist/oauth2/refresh-access-token.mjs +73 -0
  90. package/dist/oauth2/reject-redirects.mjs +60 -0
  91. package/dist/oauth2/utils.d.mts +24 -0
  92. package/dist/oauth2/utils.mjs +48 -0
  93. package/dist/oauth2/validate-authorization-code.d.mts +85 -0
  94. package/dist/oauth2/validate-authorization-code.mjs +86 -0
  95. package/dist/oauth2/verify.d.mts +65 -0
  96. package/dist/oauth2/verify.mjs +202 -0
  97. package/dist/social-providers/apple.d.mts +133 -0
  98. package/dist/social-providers/apple.mjs +117 -0
  99. package/dist/social-providers/atlassian.d.mts +70 -0
  100. package/dist/social-providers/atlassian.mjs +80 -0
  101. package/dist/social-providers/cognito.d.mts +85 -0
  102. package/dist/social-providers/cognito.mjs +162 -0
  103. package/dist/social-providers/discord.d.mts +124 -0
  104. package/dist/social-providers/discord.mjs +62 -0
  105. package/dist/social-providers/dropbox.d.mts +69 -0
  106. package/dist/social-providers/dropbox.mjs +72 -0
  107. package/dist/social-providers/facebook.d.mts +79 -0
  108. package/dist/social-providers/facebook.mjs +157 -0
  109. package/dist/social-providers/figma.d.mts +61 -0
  110. package/dist/social-providers/figma.mjs +83 -0
  111. package/dist/social-providers/github.d.mts +102 -0
  112. package/dist/social-providers/github.mjs +92 -0
  113. package/dist/social-providers/gitlab.d.mts +123 -0
  114. package/dist/social-providers/gitlab.mjs +79 -0
  115. package/dist/social-providers/google.d.mts +123 -0
  116. package/dist/social-providers/google.mjs +137 -0
  117. package/dist/social-providers/huggingface.d.mts +83 -0
  118. package/dist/social-providers/huggingface.mjs +73 -0
  119. package/dist/social-providers/index.d.mts +1834 -0
  120. package/dist/social-providers/index.mjs +78 -0
  121. package/dist/social-providers/kakao.d.mts +161 -0
  122. package/dist/social-providers/kakao.mjs +70 -0
  123. package/dist/social-providers/kick.d.mts +73 -0
  124. package/dist/social-providers/kick.mjs +68 -0
  125. package/dist/social-providers/line.d.mts +105 -0
  126. package/dist/social-providers/line.mjs +110 -0
  127. package/dist/social-providers/linear.d.mts +68 -0
  128. package/dist/social-providers/linear.mjs +85 -0
  129. package/dist/social-providers/linkedin.d.mts +67 -0
  130. package/dist/social-providers/linkedin.mjs +73 -0
  131. package/dist/social-providers/microsoft-entra-id.d.mts +174 -0
  132. package/dist/social-providers/microsoft-entra-id.mjs +152 -0
  133. package/dist/social-providers/naver.d.mts +92 -0
  134. package/dist/social-providers/naver.mjs +65 -0
  135. package/dist/social-providers/notion.d.mts +64 -0
  136. package/dist/social-providers/notion.mjs +72 -0
  137. package/dist/social-providers/paybin.d.mts +71 -0
  138. package/dist/social-providers/paybin.mjs +81 -0
  139. package/dist/social-providers/paypal.d.mts +131 -0
  140. package/dist/social-providers/paypal.mjs +188 -0
  141. package/dist/social-providers/polar.d.mts +74 -0
  142. package/dist/social-providers/polar.mjs +71 -0
  143. package/dist/social-providers/railway.d.mts +65 -0
  144. package/dist/social-providers/railway.mjs +74 -0
  145. package/dist/social-providers/reddit.d.mts +62 -0
  146. package/dist/social-providers/reddit.mjs +81 -0
  147. package/dist/social-providers/roblox.d.mts +70 -0
  148. package/dist/social-providers/roblox.mjs +57 -0
  149. package/dist/social-providers/salesforce.d.mts +79 -0
  150. package/dist/social-providers/salesforce.mjs +87 -0
  151. package/dist/social-providers/slack.d.mts +83 -0
  152. package/dist/social-providers/slack.mjs +66 -0
  153. package/dist/social-providers/spotify.d.mts +63 -0
  154. package/dist/social-providers/spotify.mjs +69 -0
  155. package/dist/social-providers/tiktok.d.mts +168 -0
  156. package/dist/social-providers/tiktok.mjs +60 -0
  157. package/dist/social-providers/twitch.d.mts +79 -0
  158. package/dist/social-providers/twitch.mjs +75 -0
  159. package/dist/social-providers/twitter.d.mts +126 -0
  160. package/dist/social-providers/twitter.mjs +85 -0
  161. package/dist/social-providers/vercel.d.mts +62 -0
  162. package/dist/social-providers/vercel.mjs +58 -0
  163. package/dist/social-providers/vk.d.mts +70 -0
  164. package/dist/social-providers/vk.mjs +81 -0
  165. package/dist/social-providers/wechat.d.mts +113 -0
  166. package/dist/social-providers/wechat.mjs +81 -0
  167. package/dist/social-providers/zoom.d.mts +163 -0
  168. package/dist/social-providers/zoom.mjs +69 -0
  169. package/dist/types/context.d.mts +319 -0
  170. package/dist/types/cookie.d.mts +15 -0
  171. package/dist/types/helper.d.mts +10 -0
  172. package/dist/types/index.d.mts +9 -0
  173. package/dist/types/init-options.d.mts +1430 -0
  174. package/dist/types/plugin-client.d.mts +123 -0
  175. package/dist/types/plugin.d.mts +124 -0
  176. package/dist/types/secret.d.mts +11 -0
  177. package/dist/utils/async.d.mts +22 -0
  178. package/dist/utils/async.mjs +32 -0
  179. package/dist/utils/db.d.mts +9 -0
  180. package/dist/utils/db.mjs +15 -0
  181. package/dist/utils/deprecate.d.mts +9 -0
  182. package/dist/utils/deprecate.mjs +16 -0
  183. package/dist/utils/error-codes.d.mts +13 -0
  184. package/dist/utils/error-codes.mjs +10 -0
  185. package/dist/utils/fetch-metadata.d.mts +4 -0
  186. package/dist/utils/fetch-metadata.mjs +6 -0
  187. package/dist/utils/host.d.mts +147 -0
  188. package/dist/utils/host.mjs +295 -0
  189. package/dist/utils/id.d.mts +4 -0
  190. package/dist/utils/id.mjs +7 -0
  191. package/dist/utils/ip.d.mts +77 -0
  192. package/dist/utils/ip.mjs +230 -0
  193. package/dist/utils/is-api-error.d.mts +6 -0
  194. package/dist/utils/is-api-error.mjs +8 -0
  195. package/dist/utils/json.d.mts +4 -0
  196. package/dist/utils/json.mjs +41 -0
  197. package/dist/utils/redirect-uri.d.mts +20 -0
  198. package/dist/utils/redirect-uri.mjs +48 -0
  199. package/dist/utils/string.d.mts +8 -0
  200. package/dist/utils/string.mjs +25 -0
  201. package/dist/utils/url.d.mts +37 -0
  202. package/dist/utils/url.mjs +61 -0
  203. package/package.json +216 -0
  204. package/src/api/index.ts +185 -0
  205. package/src/async_hooks/index.ts +40 -0
  206. package/src/async_hooks/pure.index.ts +46 -0
  207. package/src/context/endpoint-context.ts +50 -0
  208. package/src/context/global.ts +57 -0
  209. package/src/context/index.ts +23 -0
  210. package/src/context/request-state.ts +91 -0
  211. package/src/context/transaction.ts +169 -0
  212. package/src/db/adapter/factory.ts +1740 -0
  213. package/src/db/adapter/get-default-field-name.ts +59 -0
  214. package/src/db/adapter/get-default-model-name.ts +51 -0
  215. package/src/db/adapter/get-field-attributes.ts +62 -0
  216. package/src/db/adapter/get-field-name.ts +43 -0
  217. package/src/db/adapter/get-id-field.ts +150 -0
  218. package/src/db/adapter/get-model-name.ts +36 -0
  219. package/src/db/adapter/index.ts +656 -0
  220. package/src/db/adapter/types.ts +134 -0
  221. package/src/db/adapter/utils.ts +61 -0
  222. package/src/db/get-tables.ts +304 -0
  223. package/src/db/index.ts +43 -0
  224. package/src/db/plugin.ts +11 -0
  225. package/src/db/schema/account.ts +47 -0
  226. package/src/db/schema/rate-limit.ts +36 -0
  227. package/src/db/schema/session.ts +29 -0
  228. package/src/db/schema/shared.ts +7 -0
  229. package/src/db/schema/user.ts +31 -0
  230. package/src/db/schema/verification.ts +28 -0
  231. package/src/db/type.ts +360 -0
  232. package/src/env/color-depth.ts +172 -0
  233. package/src/env/env-impl.ts +123 -0
  234. package/src/env/index.ts +23 -0
  235. package/src/env/logger.ts +145 -0
  236. package/src/error/codes.ts +72 -0
  237. package/src/error/index.ts +44 -0
  238. package/src/index.ts +1 -0
  239. package/src/instrumentation/api.ts +17 -0
  240. package/src/instrumentation/attributes.ts +22 -0
  241. package/src/instrumentation/index.ts +2 -0
  242. package/src/instrumentation/noop.ts +74 -0
  243. package/src/instrumentation/pure.index.ts +31 -0
  244. package/src/instrumentation/tracer.ts +95 -0
  245. package/src/oauth2/client-credentials-token.ts +126 -0
  246. package/src/oauth2/create-authorization-url.ts +89 -0
  247. package/src/oauth2/index.ts +34 -0
  248. package/src/oauth2/oauth-provider.ts +222 -0
  249. package/src/oauth2/refresh-access-token.ts +157 -0
  250. package/src/oauth2/reject-redirects.ts +70 -0
  251. package/src/oauth2/utils.ts +70 -0
  252. package/src/oauth2/validate-authorization-code.ts +190 -0
  253. package/src/oauth2/verify.ts +408 -0
  254. package/src/social-providers/apple.ts +249 -0
  255. package/src/social-providers/atlassian.ts +133 -0
  256. package/src/social-providers/cognito.ts +281 -0
  257. package/src/social-providers/discord.ts +170 -0
  258. package/src/social-providers/dropbox.ts +112 -0
  259. package/src/social-providers/facebook.ts +288 -0
  260. package/src/social-providers/figma.ts +118 -0
  261. package/src/social-providers/github.ts +184 -0
  262. package/src/social-providers/gitlab.ts +155 -0
  263. package/src/social-providers/google.ts +263 -0
  264. package/src/social-providers/huggingface.ts +119 -0
  265. package/src/social-providers/index.ts +132 -0
  266. package/src/social-providers/kakao.ts +179 -0
  267. package/src/social-providers/kick.ts +109 -0
  268. package/src/social-providers/line.ts +169 -0
  269. package/src/social-providers/linear.ts +121 -0
  270. package/src/social-providers/linkedin.ts +110 -0
  271. package/src/social-providers/microsoft-entra-id.ts +391 -0
  272. package/src/social-providers/naver.ts +113 -0
  273. package/src/social-providers/notion.ts +108 -0
  274. package/src/social-providers/paybin.ts +118 -0
  275. package/src/social-providers/paypal.ts +371 -0
  276. package/src/social-providers/polar.ts +111 -0
  277. package/src/social-providers/railway.ts +100 -0
  278. package/src/social-providers/reddit.ts +126 -0
  279. package/src/social-providers/roblox.ts +112 -0
  280. package/src/social-providers/salesforce.ts +159 -0
  281. package/src/social-providers/slack.ts +112 -0
  282. package/src/social-providers/spotify.ts +94 -0
  283. package/src/social-providers/tiktok.ts +211 -0
  284. package/src/social-providers/twitch.ts +112 -0
  285. package/src/social-providers/twitter.ts +199 -0
  286. package/src/social-providers/vercel.ts +87 -0
  287. package/src/social-providers/vk.ts +125 -0
  288. package/src/social-providers/wechat.ts +220 -0
  289. package/src/social-providers/zoom.ts +230 -0
  290. package/src/types/context.ts +460 -0
  291. package/src/types/cookie.ts +10 -0
  292. package/src/types/helper.ts +27 -0
  293. package/src/types/index.ts +40 -0
  294. package/src/types/init-options.ts +1679 -0
  295. package/src/types/plugin-client.ts +143 -0
  296. package/src/types/plugin.ts +163 -0
  297. package/src/types/secret.ts +8 -0
  298. package/src/utils/async.ts +53 -0
  299. package/src/utils/db.ts +20 -0
  300. package/src/utils/deprecate.ts +21 -0
  301. package/src/utils/error-codes.ts +68 -0
  302. package/src/utils/fetch-metadata.ts +3 -0
  303. package/src/utils/host.ts +416 -0
  304. package/src/utils/id.ts +5 -0
  305. package/src/utils/ip.ts +395 -0
  306. package/src/utils/is-api-error.ts +10 -0
  307. package/src/utils/json.ts +56 -0
  308. package/src/utils/redirect-uri.ts +54 -0
  309. package/src/utils/string.ts +40 -0
  310. package/src/utils/url.ts +77 -0
@@ -0,0 +1,1679 @@
1
+ import type { Database as BunDatabase } from "bun:sqlite";
2
+ import type { DatabaseSync } from "node:sqlite";
3
+ import type { D1Database } from "@cloudflare/workers-types";
4
+ import type { CookieOptions } from "better-call";
5
+ import type {
6
+ Dialect,
7
+ Kysely,
8
+ MysqlPool,
9
+ PostgresPool,
10
+ SqliteDatabase,
11
+ } from "kysely";
12
+ import type { AuthMiddleware } from "../api";
13
+ import type {
14
+ Account,
15
+ DBFieldAttribute,
16
+ ModelNames,
17
+ RateLimit,
18
+ SecondaryStorage,
19
+ Session,
20
+ User,
21
+ Verification,
22
+ } from "../db";
23
+ import type { DBAdapterDebugLogOption, DBAdapterInstance } from "../db/adapter";
24
+ import type { BaseAccount } from "../db/schema/account";
25
+ import type { BaseRateLimit } from "../db/schema/rate-limit";
26
+ import type { BaseSession } from "../db/schema/session";
27
+ import type { BaseUser } from "../db/schema/user";
28
+ import type { BaseVerification } from "../db/schema/verification";
29
+ import type { Logger } from "../env";
30
+ import type { SocialProviderList, SocialProviders } from "../social-providers";
31
+ import type { AuthContext, GenericEndpointContext } from "./context";
32
+ import type { Awaitable, LiteralString, LiteralUnion } from "./helper";
33
+ import type { BetterAuthPlugin } from "./plugin";
34
+
35
+ type KyselyDatabaseType = "postgres" | "mysql" | "sqlite" | "mssql";
36
+ type Optional<T> = {
37
+ [P in keyof T]?: T[P] | undefined;
38
+ };
39
+
40
+ export type StoreIdentifierOption =
41
+ | "plain"
42
+ | "hashed"
43
+ | { hash: (identifier: string) => Promise<string> };
44
+
45
+ export type GenerateIdFn = (options: {
46
+ model: ModelNames;
47
+ size?: number | undefined;
48
+ }) => string | false;
49
+
50
+ /**
51
+ * Configuration for dynamic base URL resolution.
52
+ * Allows Better Auth to work with multiple domains (e.g., Vercel preview deployments).
53
+ */
54
+ export type DynamicBaseURLConfig = {
55
+ /**
56
+ * List of allowed hostnames. Supports wildcard patterns.
57
+ *
58
+ * The derived host from the request will be validated against this list.
59
+ * Uses the same wildcard matching as `trustedOrigins`.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * allowedHosts: [
64
+ * "myapp.com", // Exact match
65
+ * "*.vercel.app", // Any Vercel preview
66
+ * "preview-*.myapp.com" // Pattern match
67
+ * ]
68
+ * ```
69
+ */
70
+ allowedHosts: string[];
71
+
72
+ /**
73
+ * Fallback URL to use if the derived host doesn't match any allowed host.
74
+ * If not set, Better Auth will throw an error when the host doesn't match.
75
+ *
76
+ * @example "https://myapp.com"
77
+ */
78
+ fallback?: string | undefined;
79
+
80
+ /**
81
+ * Protocol to use when constructing the URL.
82
+ * - `"https"`: Always use HTTPS (recommended for production)
83
+ * - `"http"`: Always use HTTP (for local development)
84
+ * - `"auto"`: Derive from `x-forwarded-proto` header or default to HTTPS
85
+ *
86
+ * @default "auto"
87
+ */
88
+ protocol?: "http" | "https" | "auto" | undefined;
89
+ };
90
+
91
+ /**
92
+ * Base URL configuration.
93
+ * Can be a static string or a dynamic config for multi-domain deployments.
94
+ */
95
+ export type BaseURLConfig = string | DynamicBaseURLConfig;
96
+
97
+ export interface BetterAuthRateLimitStorage {
98
+ get: (key: string) => Promise<RateLimit | null | undefined>;
99
+ set: (
100
+ key: string,
101
+ value: RateLimit,
102
+ update?: boolean | undefined,
103
+ ) => Promise<void>;
104
+ /**
105
+ * Atomically records one request against `key` within the `window`
106
+ * (in seconds) and reports whether it is allowed.
107
+ *
108
+ * When `allowed` is true the request was counted within the active window;
109
+ * when `allowed` is false the limit was already reached and `retryAfter` is
110
+ * the number of seconds until the window frees up. Whether the window slides
111
+ * or is fixed depends on the backing storage: the database backend resets
112
+ * once the window elapses, while secondary storage uses a fixed time-to-live
113
+ * set when the window first opens.
114
+ *
115
+ * Performing the check and the increment in a single step closes the
116
+ * concurrent-bypass gap of the separate `get`/`set` path: N simultaneous
117
+ * requests can no longer all pass a stale read before any increment lands.
118
+ *
119
+ * Optional for backwards compatibility. A storage without it falls back to
120
+ * the legacy non-atomic `get`/`set` path, which is best-effort under
121
+ * concurrency.
122
+ *
123
+ * TODO(rate-limit-consume-required): make this the sole required member on
124
+ * `next`, dropping `get`/`set` and the non-atomic fallback.
125
+ */
126
+ consume?: (
127
+ key: string,
128
+ rule: { window: number; max: number },
129
+ ) => Promise<{ allowed: boolean; retryAfter: number | null }>;
130
+ }
131
+
132
+ export type BetterAuthRateLimitRule = {
133
+ /**
134
+ * Default window to use for rate limiting. The value
135
+ * should be in seconds.
136
+ *
137
+ * @default 10 seconds
138
+ */
139
+ window: number;
140
+ /**
141
+ * The default maximum number of requests allowed within the window.
142
+ *
143
+ * @default 100 requests
144
+ */
145
+ max: number;
146
+ };
147
+
148
+ export type BetterAuthDBOptions<
149
+ ModelName extends string,
150
+ Keys extends string = string,
151
+ > = {
152
+ /**
153
+ * The name of the model. Defaults to the model name.
154
+ */
155
+ modelName?: ModelName | LiteralString;
156
+ /**
157
+ * Map fields to database columns
158
+ */
159
+ fields?: Partial<Record<Exclude<Keys, "id">, string>>;
160
+ /**
161
+ * Additional fields for the model
162
+ */
163
+ additionalFields?: {
164
+ [Key in Exclude<string, Keys | "id">]: DBFieldAttribute;
165
+ };
166
+ };
167
+
168
+ export type BetterAuthRateLimitOptions = Optional<BetterAuthRateLimitRule> &
169
+ Omit<
170
+ BetterAuthDBOptions<"rateLimit", keyof BaseRateLimit>,
171
+ "additionalFields"
172
+ > & {
173
+ /**
174
+ * By default, rate limiting is only
175
+ * enabled on production.
176
+ */
177
+ enabled?: boolean | undefined;
178
+ /**
179
+ * Custom rate limit rules to apply to
180
+ * specific paths.
181
+ */
182
+ customRules?:
183
+ | {
184
+ [key: string]:
185
+ | BetterAuthRateLimitRule
186
+ | false
187
+ | ((
188
+ request: Request,
189
+ currentRule: BetterAuthRateLimitRule,
190
+ ) => Awaitable<false | BetterAuthRateLimitRule>);
191
+ }
192
+ | undefined;
193
+ /**
194
+ * Storage configuration
195
+ *
196
+ * By default, rate limiting is stored in memory. If you passed a
197
+ * secondary storage, rate limiting will be stored in the secondary
198
+ * storage.
199
+ *
200
+ * @default "memory"
201
+ */
202
+ storage?: ("memory" | "database" | "secondary-storage") | undefined;
203
+ /**
204
+ * custom storage configuration.
205
+ *
206
+ * NOTE: If custom storage is used storage
207
+ * is ignored
208
+ */
209
+ customStorage?: BetterAuthRateLimitStorage;
210
+ };
211
+
212
+ export type BetterAuthAdvancedOptions = {
213
+ /**
214
+ * Ip address configuration
215
+ */
216
+ ipAddress?:
217
+ | {
218
+ /**
219
+ * List of headers to use for ip address
220
+ *
221
+ * Ip address is used for rate limiting and session tracking
222
+ *
223
+ * @example ["x-client-ip", "x-forwarded-for", "cf-connecting-ip"]
224
+ *
225
+ * @default
226
+ * @link https://github.com/better-auth/better-auth/blob/main/packages/core/src/utils/ip.ts
227
+ */
228
+ ipAddressHeaders?: string[];
229
+ /**
230
+ * Disable ip tracking
231
+ *
232
+ * ⚠︎ This is a security risk and it may expose your application to abuse
233
+ */
234
+ disableIpTracking?: boolean;
235
+ /**
236
+ * IPv6 prefix length used to collapse addresses before rate-limit keying.
237
+ * Any integer from 0 to 128 is accepted; common values are 32, 48, 56, 64, 128.
238
+ * Out-of-range values fall back to safe behavior (negative -> mask all, > 128 -> no mask).
239
+ *
240
+ * @default 64
241
+ */
242
+ ipv6Subnet?: number;
243
+ /**
244
+ * Trusted reverse-proxy IPs or CIDR ranges. When set, a forwarded IP
245
+ * chain is walked right to left, trusted hops are skipped, and the
246
+ * first untrusted address is the client IP. Unset trusts only
247
+ * single-value IP headers. Use the actual address or subnet of your
248
+ * proxies, not a broad private range that also covers clients.
249
+ *
250
+ * This only interprets the forwarded header chain and cannot verify
251
+ * the direct sender. It is safe only when your origin is reachable
252
+ * through these proxies and clients cannot set forwarded headers
253
+ * directly.
254
+ *
255
+ * @example ["192.0.2.10", "10.0.0.0/24"]
256
+ */
257
+ trustedProxies?: string[];
258
+ }
259
+ | undefined;
260
+ /**
261
+ * Force cookies to always use the `Secure` attribute. By default,
262
+ * cookies are secure in production environments. Set this to `true`
263
+ * to enforce secure cookies in all environments.
264
+ *
265
+ * @default false
266
+ */
267
+ useSecureCookies?: boolean | undefined;
268
+ /**
269
+ * Disable all CSRF protection.
270
+ *
271
+ * When enabled, this disables:
272
+ * - Origin header validation when cookies are present
273
+ * - Fetch Metadata checks (Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest)
274
+ * - Cross-site navigation blocking for first-login scenarios
275
+ *
276
+ * ⚠︎ This is a security risk and it may expose your application to
277
+ * CSRF attacks
278
+ *
279
+ * @default false
280
+ */
281
+ disableCSRFCheck?: boolean | undefined;
282
+ /**
283
+ * Disable URL validation against trustedOrigins.
284
+ *
285
+ * When enabled, this disables validation of:
286
+ * - callbackURL
287
+ * - redirectTo
288
+ * - errorCallbackURL
289
+ * - newUserCallbackURL
290
+ *
291
+ * ⚠︎ This may allow open redirects and could lead to security
292
+ * vulnerabilities.
293
+ *
294
+ * @default false
295
+ */
296
+ disableOriginCheck?: boolean | undefined;
297
+ /**
298
+ * Configure cookies to be cross subdomains
299
+ */
300
+ crossSubDomainCookies?:
301
+ | {
302
+ /**
303
+ * Enable cross subdomain cookies
304
+ */
305
+ enabled: boolean;
306
+ /**
307
+ * Additional cookies to be shared across subdomains
308
+ */
309
+ additionalCookies?: string[];
310
+ /**
311
+ * The domain to use for the cookies
312
+ *
313
+ * By default, the domain will be the root
314
+ * domain from the base URL.
315
+ */
316
+ domain?: string;
317
+ }
318
+ | undefined;
319
+ /*
320
+ * Allows you to change default cookie names and attributes
321
+ *
322
+ * default cookie names:
323
+ * - "session_token"
324
+ * - "session_data"
325
+ * - "dont_remember"
326
+ * - "account_data"
327
+ *
328
+ * plugins can also add additional cookies
329
+ */
330
+ cookies?:
331
+ | {
332
+ [key: string]: {
333
+ name?: string;
334
+ attributes?: CookieOptions;
335
+ };
336
+ }
337
+ | undefined;
338
+ defaultCookieAttributes?: CookieOptions | undefined;
339
+ /**
340
+ * Prefix for cookies. If a cookie name is provided
341
+ * in cookies config, this will be overridden.
342
+ *
343
+ * @default
344
+ * ```txt
345
+ * "appName" -> which defaults to "better-auth"
346
+ * ```
347
+ */
348
+ cookiePrefix?: string | undefined;
349
+ /**
350
+ * Database configuration.
351
+ */
352
+ database?:
353
+ | {
354
+ /**
355
+ * The default number of records to return from the database
356
+ * when using the `findMany` adapter method.
357
+ *
358
+ * @default 100
359
+ */
360
+ defaultFindManyLimit?: number;
361
+ /**
362
+ * Custom generateId function.
363
+ *
364
+ * If not provided, random ids will be generated.
365
+ * If set to false, the database's auto generated id
366
+ * will be used.
367
+ *
368
+ * If set to "serial", the database's auto generated
369
+ * id will be used.
370
+ *
371
+ * If set to "uuid", we generate a random UUID for
372
+ * the id. If postgres, we use the `gen_random_uuid()
373
+ * ` function. If mysql or mssql, we use the `uuid()`
374
+ * function.
375
+ */
376
+ generateId?: GenerateIdFn | false | "serial" | "uuid";
377
+ }
378
+ | undefined;
379
+ /**
380
+ * Trusted proxy headers
381
+ *
382
+
383
+ * - `x-forwarded-host`
384
+ * - `x-forwarded-proto`
385
+ *
386
+ * If set to `true` and no `baseURL` option is provided, we will use the headers to infer the
387
+ * base URL.
388
+ *
389
+ * ⚠︎ This may expose your application to security vulnerabilities if not
390
+ * used correctly. Please use this with caution.
391
+ */
392
+ trustedProxyHeaders?: boolean | undefined;
393
+ /**
394
+ * Configure background task handling for deferred operations.
395
+ *
396
+ * Background tasks allow non-critical operations (like cleanup, analytics,
397
+ * or timing-attack mitigation) to run after the response is sent.
398
+ *
399
+ * Use `waitUntil` from `@vercel/functions` on Vercel,
400
+ * or `ctx.waitUntil` on Cloudflare Workers.
401
+ *
402
+ * @example
403
+ * // Vercel
404
+ * import { waitUntil } from "@vercel/functions";
405
+ * advanced: { backgroundTasks: { handler: waitUntil } }
406
+ *
407
+ * @example
408
+ * // Cloudflare Workers (with AsyncLocalStorage)
409
+ * advanced: {
410
+ * backgroundTasks: {
411
+ * handler: (p) => execCtxStorage.getStore()?.waitUntil(p)
412
+ * }
413
+ * }
414
+ */
415
+ backgroundTasks?: {
416
+ handler: (promise: Promise<unknown>) => void;
417
+ };
418
+ /**
419
+ * Skip trailing slashes in API routes.
420
+ *
421
+ * When enabled, requests with trailing slashes (e.g., `/api/auth/session/`)
422
+ * will be handled the same as requests without (e.g., `/api/auth/session`).
423
+ *
424
+ * @default false
425
+ */
426
+ skipTrailingSlashes?: boolean;
427
+ };
428
+
429
+ export type BetterAuthOptions = {
430
+ /**
431
+ * The name of your application. Used as a display name in contexts
432
+ * where your app needs to be identified — for example, as the default
433
+ * issuer name in authenticator apps when users set up 2FA/TOTP.
434
+ *
435
+ * Can also be set via the `APP_NAME` environment variable.
436
+ *
437
+ * @default "Better Auth"
438
+ */
439
+ appName?: string | undefined;
440
+ /**
441
+ * Base URL for the Better Auth. This is typically the
442
+ * root URL where your application server is hosted.
443
+ *
444
+ * Can be configured as:
445
+ * - A static string: `"https://myapp.com"`
446
+ * - A dynamic config with allowed hosts for multi-domain deployments
447
+ *
448
+ * If not explicitly set, the system will check environment variables:
449
+ * `BETTER_AUTH_URL`, `NEXT_PUBLIC_BETTER_AUTH_URL`, etc.
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * // Static URL
454
+ * baseURL: "https://myapp.com"
455
+ *
456
+ * // Dynamic with allowed hosts (for Vercel, multi-domain, etc.)
457
+ * baseURL: {
458
+ * allowedHosts: ["myapp.com", "*.vercel.app", "preview-*.myapp.com"],
459
+ * fallback: "https://myapp.com"
460
+ * }
461
+ * ```
462
+ */
463
+ baseURL?: BaseURLConfig | undefined;
464
+ /**
465
+ * Base path for the Better Auth. This is typically
466
+ * the path where the
467
+ * Better Auth routes are mounted.
468
+ *
469
+ * @default "/api/auth"
470
+ */
471
+ basePath?: string | undefined;
472
+ /**
473
+ * The secret to use for encryption,
474
+ * signing and hashing.
475
+ *
476
+ * By default Better Auth will look for
477
+ * the following environment variables:
478
+ * process.env.BETTER_AUTH_SECRET,
479
+ * process.env.AUTH_SECRET
480
+ * If none of these environment
481
+ * variables are set,
482
+ * it will default to
483
+ * "better-auth-secret-123456789".
484
+ *
485
+ * on production if it's not set
486
+ * it will throw an error.
487
+ *
488
+ * you can generate a good secret
489
+ * using the following command:
490
+ * @example
491
+ * ```bash
492
+ * openssl rand -base64 32
493
+ * ```
494
+ */
495
+ secret?: string | undefined;
496
+ /**
497
+ * Versioned secrets for non-destructive secret rotation.
498
+ * When set, encryption uses an envelope format with key IDs.
499
+ * First entry is the current key used for new encryption.
500
+ * Remaining entries are decryption-only (previous rotations).
501
+ *
502
+ * Can also be set via BETTER_AUTH_SECRETS env var:
503
+ * `BETTER_AUTH_SECRETS=2:base64secret,1:base64secret`
504
+ *
505
+ * When set, `secret` is only used as legacy fallback
506
+ * for decrypting bare-hex payloads that predate the envelope format.
507
+ */
508
+ secrets?: Array<{ version: number; value: string }> | undefined;
509
+ /**
510
+ * Database configuration
511
+ */
512
+ database?:
513
+ | (
514
+ | PostgresPool
515
+ | MysqlPool
516
+ | SqliteDatabase
517
+ | Dialect
518
+ | DBAdapterInstance
519
+ | BunDatabase
520
+ | DatabaseSync
521
+ | D1Database
522
+ | {
523
+ dialect: Dialect;
524
+ type: KyselyDatabaseType;
525
+ /**
526
+ * casing for table names
527
+ *
528
+ * @default "camel"
529
+ */
530
+ casing?: "snake" | "camel";
531
+ /**
532
+ * Enable debug logs for the adapter
533
+ *
534
+ * @default false
535
+ */
536
+ debugLogs?: DBAdapterDebugLogOption;
537
+ /**
538
+ * Whether to execute multiple operations in a transaction.
539
+ * If the database doesn't support transactions,
540
+ * set this to `false` and operations will be executed sequentially.
541
+ *
542
+ * @default false
543
+ */
544
+ transaction?: boolean;
545
+ }
546
+ | {
547
+ /**
548
+ * Kysely instance
549
+ */
550
+ db: Kysely<any>;
551
+ /**
552
+ * Database type between postgres, mysql and sqlite
553
+ */
554
+ type: KyselyDatabaseType;
555
+ /**
556
+ * casing for table names
557
+ *
558
+ * @default "camel"
559
+ */
560
+ casing?: "snake" | "camel";
561
+ /**
562
+ * Enable debug logs for the adapter
563
+ *
564
+ * @default false
565
+ */
566
+ debugLogs?: DBAdapterDebugLogOption;
567
+ /**
568
+ * Whether to execute multiple operations in a transaction.
569
+ * If the database doesn't support transactions,
570
+ * set this to `false` and operations will be executed sequentially.
571
+ *
572
+ * @default false
573
+ */
574
+ transaction?: boolean;
575
+ }
576
+ )
577
+ | undefined;
578
+ /**
579
+ * Secondary storage configuration
580
+ *
581
+ * This is used to store session and rate limit data.
582
+ */
583
+ secondaryStorage?: SecondaryStorage | undefined;
584
+ /**
585
+ * Email verification configuration
586
+ */
587
+ emailVerification?:
588
+ | {
589
+ /**
590
+ * Send a verification email
591
+ * @param data the data object
592
+ * @param request the request object
593
+ */
594
+ sendVerificationEmail?: (
595
+ /**
596
+ * @param user the user to send the
597
+ * verification email to
598
+ * @param url the URL to send the verification email to
599
+ * it contains the token as well
600
+ * @param token the token to send the verification email to
601
+ */
602
+ data: {
603
+ user: User;
604
+ url: string;
605
+ token: string;
606
+ },
607
+ /**
608
+ * The request object
609
+ */
610
+ request?: Request,
611
+ ) => Promise<void>;
612
+ /**
613
+ * Send a verification email automatically after sign up.
614
+ *
615
+ * - `true`: Always send verification email on sign up
616
+ * - `false`: Never send verification email on sign up
617
+ * - `undefined`: Follows `requireEmailVerification` behavior
618
+ *
619
+ * @default undefined
620
+ */
621
+ sendOnSignUp?: boolean;
622
+ /**
623
+ * Send a verification email automatically
624
+ * on sign in when the user's email is not verified
625
+ *
626
+ * @default false
627
+ */
628
+ sendOnSignIn?: boolean;
629
+ /**
630
+ * Auto signin the user after they verify their email
631
+ */
632
+ autoSignInAfterVerification?: boolean;
633
+ /**
634
+ * Number of seconds the verification token is
635
+ * valid for.
636
+ * @default 3600 seconds (1 hour)
637
+ */
638
+ expiresIn?: number;
639
+ /**
640
+ * A function that is called before a user verifies their email
641
+ * @param user the user that verified their email
642
+ * @param request the request object
643
+ */
644
+ beforeEmailVerification?: (
645
+ user: User,
646
+ request?: Request,
647
+ ) => Promise<void>;
648
+ /**
649
+ * A function that is called when a user's email is updated to verified
650
+ * @param user the user that verified their email
651
+ * @param request the request object
652
+ */
653
+ afterEmailVerification?: (
654
+ user: User,
655
+ request?: Request,
656
+ ) => Promise<void>;
657
+ }
658
+ | undefined;
659
+ /**
660
+ * Email and password authentication
661
+ */
662
+ emailAndPassword?:
663
+ | {
664
+ /**
665
+ * Enable email and password authentication
666
+ *
667
+ * @default false
668
+ */
669
+ enabled: boolean;
670
+ /**
671
+ * Disable email and password sign up
672
+ *
673
+ * @default false
674
+ */
675
+ disableSignUp?: boolean;
676
+ /**
677
+ * Require email verification before a session
678
+ * can be created for the user.
679
+ *
680
+ * if the user is not verified, the user will not be able to sign in
681
+ * and on sign in attempts, the user will be prompted to verify their email.
682
+ */
683
+ requireEmailVerification?: boolean;
684
+ /**
685
+ * The maximum length of the password.
686
+ *
687
+ * @default 128
688
+ */
689
+ maxPasswordLength?: number;
690
+ /**
691
+ * The minimum length of the password.
692
+ *
693
+ * @default 8
694
+ */
695
+ minPasswordLength?: number;
696
+ /**
697
+ * send reset password
698
+ */
699
+ sendResetPassword?: (
700
+ /**
701
+ * @param user the user to send the
702
+ * reset password email to
703
+ * @param url the URL to send the reset password email to
704
+ * @param token the token to send to the user (could be used instead of sending the url
705
+ * if you need to redirect the user to custom route)
706
+ */
707
+ data: { user: User; url: string; token: string },
708
+ /**
709
+ * The request object
710
+ */
711
+ request?: Request,
712
+ ) => Promise<void>;
713
+ /**
714
+ * Number of seconds the reset password token is
715
+ * valid for.
716
+ * @default 1 hour (60 * 60)
717
+ */
718
+ resetPasswordTokenExpiresIn?: number;
719
+ /**
720
+ * A callback function that is triggered
721
+ * when a user's password is changed successfully.
722
+ */
723
+ onPasswordReset?: (
724
+ data: { user: User },
725
+ request?: Request,
726
+ ) => Promise<void>;
727
+ /**
728
+ * Password hashing and verification
729
+ *
730
+ * By default Scrypt is used for password hashing and
731
+ * verification. You can provide your own hashing and
732
+ * verification function. if you want to use a
733
+ * different algorithm.
734
+ */
735
+ password?: {
736
+ hash?: (password: string) => Promise<string>;
737
+ verify?: (data: {
738
+ hash: string;
739
+ password: string;
740
+ }) => Promise<boolean>;
741
+ };
742
+ /**
743
+ * Automatically sign in the user after sign up
744
+ *
745
+ * @default true
746
+ */
747
+ autoSignIn?: boolean;
748
+ /**
749
+ * Whether to revoke all other sessions when resetting password
750
+ * @default false
751
+ */
752
+ revokeSessionsOnPasswordReset?: boolean;
753
+ /**
754
+ * A callback function that is triggered when a user tries to sign up
755
+ * with an email that already exists. Useful for notifying the existing user
756
+ * that someone attempted to register with their email.
757
+ *
758
+ * This is only called when `requireEmailVerification: true` or `autoSignIn: false`.
759
+ */
760
+ onExistingUserSignUp?: (
761
+ /**
762
+ * @param user the existing user from the database
763
+ */
764
+ data: { user: User },
765
+ request?: Request,
766
+ ) => Promise<void>;
767
+ /**
768
+ * Build a custom synthetic user for email enumeration
769
+ * protection. When a sign-up attempt is made with an
770
+ * email that already exists, this function is called
771
+ * to build the fake user response.
772
+ *
773
+ * Use this when plugins add fields to the user table
774
+ * (e.g. admin plugin adds `role`, `banned`, etc.)
775
+ * to ensure the fake response is indistinguishable
776
+ * from a real sign-up.
777
+ *
778
+ * @example
779
+ * ```ts
780
+ * customSyntheticUser: ({ coreFields, additionalFields, id }) => ({
781
+ * ...coreFields,
782
+ * role: "user",
783
+ * banned: false,
784
+ * banReason: null,
785
+ * banExpires: null,
786
+ * ...additionalFields,
787
+ * id,
788
+ * })
789
+ * ```
790
+ */
791
+ customSyntheticUser?: (params: {
792
+ /** Core user fields: name, email, emailVerified, image, createdAt, updatedAt */
793
+ coreFields: {
794
+ name: string;
795
+ email: string;
796
+ emailVerified: boolean;
797
+ image: string | null;
798
+ createdAt: Date;
799
+ updatedAt: Date;
800
+ };
801
+ /** Processed additional fields from options.user.additionalFields (with defaults applied) */
802
+ additionalFields: Record<string, unknown>;
803
+ /** Generated user ID */
804
+ id: string;
805
+ }) => Record<string, unknown>;
806
+ }
807
+ | undefined;
808
+ /**
809
+ * list of social providers
810
+ */
811
+ socialProviders?: SocialProviders | undefined;
812
+ /**
813
+ * List of Better Auth plugins
814
+ */
815
+ plugins?: ([] | BetterAuthPlugin[]) | undefined;
816
+ /**
817
+ * User configuration
818
+ */
819
+ user?:
820
+ | (BetterAuthDBOptions<"user", keyof BaseUser> & {
821
+ /**
822
+ * Changing email configuration
823
+ */
824
+ changeEmail?: {
825
+ /**
826
+ * Enable changing email
827
+ * @default false
828
+ */
829
+ enabled: boolean;
830
+ /**
831
+ * Send a confirmation email to the old email address when the user changes their email.
832
+ * @param data the data object
833
+ * @param request the request object
834
+ */
835
+ sendChangeEmailConfirmation?: (
836
+ data: {
837
+ user: User;
838
+ newEmail: string;
839
+ url: string;
840
+ token: string;
841
+ },
842
+ request?: Request,
843
+ ) => Promise<void>;
844
+ /**
845
+ * Update the email without verification if the user is not verified.
846
+ * @default false
847
+ */
848
+ updateEmailWithoutVerification?: boolean;
849
+ };
850
+ /**
851
+ * User deletion configuration
852
+ */
853
+ deleteUser?: {
854
+ /**
855
+ * Enable user deletion
856
+ */
857
+ enabled?: boolean;
858
+ /**
859
+ * Send a verification email when the user deletes their account.
860
+ *
861
+ * if this is not set, the user will be deleted immediately.
862
+ * @param data the data object
863
+ * @param request the request object
864
+ */
865
+ sendDeleteAccountVerification?: (
866
+ data: {
867
+ user: User;
868
+ url: string;
869
+ token: string;
870
+ },
871
+ request?: Request,
872
+ ) => Promise<void>;
873
+ /**
874
+ * A function that is called before a user is deleted.
875
+ *
876
+ * to interrupt with error you can throw `APIError`
877
+ */
878
+ beforeDelete?: (user: User, request?: Request) => Promise<void>;
879
+ /**
880
+ * A function that is called after a user is deleted.
881
+ *
882
+ * This is useful for cleaning up user data
883
+ */
884
+ afterDelete?: (user: User, request?: Request) => Promise<void>;
885
+ /**
886
+ * The expiration time for the delete token.
887
+ *
888
+ * @default 1 day (60 * 60 * 24) in seconds
889
+ */
890
+ deleteTokenExpiresIn?: number;
891
+ };
892
+ })
893
+ | undefined;
894
+ session?:
895
+ | (BetterAuthDBOptions<"session", keyof BaseSession> & {
896
+ /**
897
+ * Expiration time for the session token. The value
898
+ * should be in seconds.
899
+ * @default 7 days (60 * 60 * 24 * 7)
900
+ */
901
+ expiresIn?: number;
902
+ /**
903
+ * How often the session should be refreshed. The value
904
+ * should be in seconds.
905
+ * If set 0 the session will be refreshed every time it is used.
906
+ * @default 1 day (60 * 60 * 24)
907
+ */
908
+ updateAge?: number;
909
+ /**
910
+ * Disable session refresh so that the session is not updated
911
+ * regardless of the `updateAge` option.
912
+ *
913
+ * @default false
914
+ */
915
+ disableSessionRefresh?: boolean;
916
+ /**
917
+ * Defer session refresh writes to POST requests.
918
+ * When enabled, GET is read-only and POST performs refresh.
919
+ * Useful for read-replica database setups.
920
+ *
921
+ * @default false
922
+ */
923
+ deferSessionRefresh?: boolean;
924
+ /**
925
+ * By default if secondary storage is provided
926
+ * the session is stored in the secondary storage.
927
+ *
928
+ * Set this to true to store the session in the database
929
+ * as well.
930
+ *
931
+ * Reads are always done from the secondary storage.
932
+ *
933
+ * @default false
934
+ */
935
+ storeSessionInDatabase?: boolean;
936
+ /**
937
+ * By default, sessions are deleted from the database when secondary storage
938
+ * is provided when session is revoked.
939
+ *
940
+ * Set this to true to preserve session records in the database,
941
+ * even if they are deleted from the secondary storage.
942
+ *
943
+ * @default false
944
+ */
945
+ preserveSessionInDatabase?: boolean;
946
+ /**
947
+ * Enable caching session in cookie
948
+ */
949
+ cookieCache?: {
950
+ /**
951
+ * max age of the cookie
952
+ * @default 5 minutes (5 * 60)
953
+ */
954
+ maxAge?: number;
955
+ /**
956
+ * Enable caching session in cookie
957
+ * @default false
958
+ */
959
+ enabled?: boolean;
960
+ /**
961
+ * Strategy for encoding/decoding cookie cache
962
+ *
963
+ * - "compact": Uses base64url encoding with HMAC-SHA256 signature (compact format, no JWT spec overhead)
964
+ * - "jwt": Uses JWT with HMAC signature (no encryption, follows JWT spec)
965
+ * - "jwe": Uses JWE (JSON Web Encryption) with A256CBC-HS512 and HKDF key derivation for secure encrypted tokens
966
+ *
967
+ * @default "compact"
968
+ */
969
+ strategy?: "compact" | "jwt" | "jwe";
970
+ /**
971
+ * Controls stateless cookie cache refresh behavior.
972
+ *
973
+ * When enabled, the cookie cache will be automatically refreshed before expiry
974
+ * WITHOUT querying the database. This is essential for fully stateless or DB-less scenarios.
975
+ *
976
+ * - `false`: Disable automatic refresh. Cache is only invalidated when it reaches maxAge expiry.
977
+ * - `true`: Enable automatic refresh with default settings (refreshes when 80% of maxAge is reached).
978
+ * - `object`: Custom refresh configuration with either `updateAge` or `shouldRefresh` function
979
+ *
980
+ * Note: When the cache expires (reaches maxAge), it will attempt to fetch from database if available.
981
+ * The refreshCache option is specifically for refreshing BEFORE expiry in a stateless manner.
982
+ *
983
+ * @default false
984
+ */
985
+ refreshCache?:
986
+ | boolean
987
+ | {
988
+ /**
989
+ * Time in seconds before expiry when the cache should be refreshed.
990
+ * For example, if maxAge is 300 (5 minutes) and updateAge is 60,
991
+ * the cache will be refreshed when it has 60 seconds left before expiry.
992
+ *
993
+ * @default 20% of maxAge
994
+ */
995
+ updateAge?: number;
996
+ };
997
+ /**
998
+ * Version of the cookie cache
999
+ *
1000
+ * If a cookie cache version is changed, all existing cookie caches with the old version
1001
+ * will be invalidated.
1002
+ *
1003
+ * It can be a string or a function that returns a string or a promise that returns a string.
1004
+ * If it's a function, it will be called with the session and user data
1005
+ *
1006
+ * @default "1"
1007
+ */
1008
+ version?:
1009
+ | string
1010
+ | ((
1011
+ session: Session & Record<string, any>,
1012
+ user: User & Record<string, any>,
1013
+ ) => string)
1014
+ | ((
1015
+ session: Session & Record<string, any>,
1016
+ user: User & Record<string, any>,
1017
+ ) => Promise<string>);
1018
+ };
1019
+ /**
1020
+ * The age of the session to consider it fresh.
1021
+ *
1022
+ * This is used to check if the session is fresh
1023
+ * for sensitive operations. (e.g. deleting an account)
1024
+ *
1025
+ * If the session is not fresh, the user should be prompted
1026
+ * to sign in again.
1027
+ *
1028
+ * If set to 0, the session will be considered fresh every time. (⚠︎ not recommended)
1029
+ *
1030
+ * @default 1 day (60 * 60 * 24)
1031
+ */
1032
+ freshAge?: number;
1033
+ })
1034
+ | undefined;
1035
+ account?:
1036
+ | (BetterAuthDBOptions<"account", keyof BaseAccount> & {
1037
+ /**
1038
+ * When enabled (true), the user account data (accessToken, idToken, refreshToken, etc.)
1039
+ * will be updated on sign in with the latest data from the provider.
1040
+ *
1041
+ * @default true
1042
+ */
1043
+ updateAccountOnSignIn?: boolean;
1044
+ /**
1045
+ * Configuration for account linking.
1046
+ */
1047
+ accountLinking?: {
1048
+ /**
1049
+ * Enable account linking
1050
+ *
1051
+ * @default true
1052
+ */
1053
+ enabled?: boolean;
1054
+ /**
1055
+ * Disable implicit account linking on sign-in.
1056
+ *
1057
+ * When enabled, accounts will not be automatically linked
1058
+ * during OAuth sign-in, even if the email is verified or
1059
+ * the provider is trusted. Users must explicitly link
1060
+ * accounts using `linkSocial()` while authenticated.
1061
+ *
1062
+ * @default false
1063
+ */
1064
+ disableImplicitLinking?: boolean;
1065
+ /**
1066
+ * Require the existing local user row to have
1067
+ * `emailVerified: true` before implicit account linking
1068
+ * uses the IdP's `email_verified` claim as ownership
1069
+ * proof. Defaults to `true` so an attacker who
1070
+ * pre-registers an unverified account at a victim's
1071
+ * email cannot have the victim's OAuth identity linked
1072
+ * into the attacker-owned row on first sign-in. Set to
1073
+ * `false` for backward compatibility on apps whose
1074
+ * users sign up via OAuth without verifying their email
1075
+ * locally; understand the takeover risk before doing
1076
+ * so.
1077
+ *
1078
+ * @default true
1079
+ *
1080
+ * @deprecated The option will be removed on the next
1081
+ * minor; the gate will become unconditional.
1082
+ */
1083
+ requireLocalEmailVerified?: boolean;
1084
+ /**
1085
+ * List of trusted providers. Can be a static array or a function
1086
+ * that returns providers dynamically. The function is called
1087
+ * during context init (with `request` undefined) and again
1088
+ * on each request (with the incoming Request). It must be
1089
+ * resilient to `request` being undefined.
1090
+ *
1091
+ * @example
1092
+ * ```ts
1093
+ * trustedProviders: ["google", "github"]
1094
+ * ```
1095
+ *
1096
+ * @example
1097
+ * ```ts
1098
+ * trustedProviders: async (request) => {
1099
+ * if (!request) return [];
1100
+ * const providers = await getTrustedProvidersForTenant(request);
1101
+ * return providers;
1102
+ * }
1103
+ * ```
1104
+ */
1105
+ trustedProviders?:
1106
+ | Array<
1107
+ LiteralUnion<
1108
+ SocialProviderList[number] | "email-password",
1109
+ string
1110
+ >
1111
+ >
1112
+ | ((
1113
+ request?: Request | undefined,
1114
+ ) => Awaitable<
1115
+ Array<
1116
+ LiteralUnion<
1117
+ SocialProviderList[number] | "email-password",
1118
+ string
1119
+ >
1120
+ >
1121
+ >);
1122
+ /**
1123
+ * If enabled (true), this will allow users to manually linking accounts with different email addresses than the main user.
1124
+ *
1125
+ * @default false
1126
+ *
1127
+ * ⚠️ Warning: enabling this might lead to account takeovers, so proceed with caution.
1128
+ */
1129
+ allowDifferentEmails?: boolean;
1130
+ /**
1131
+ * If enabled (true), this will allow users to unlink all accounts.
1132
+ *
1133
+ * @default false
1134
+ */
1135
+ allowUnlinkingAll?: boolean;
1136
+ /**
1137
+ * When enabled, linking an account copies the provider's profile onto
1138
+ * the local user, matching the fields persisted on sign-up (`name`,
1139
+ * `image`, and any `mapProfileToUser` fields). The local `email` and
1140
+ * `emailVerified` are never changed, so a link cannot rebind the
1141
+ * account's identity.
1142
+ *
1143
+ * @default false
1144
+ */
1145
+ updateUserInfoOnLink?: boolean;
1146
+ };
1147
+ /**
1148
+ * Encrypt OAuth tokens
1149
+ *
1150
+ * By default, OAuth tokens (access tokens, refresh tokens, ID tokens) are stored in plain text in the database.
1151
+ * This poses a security risk if your database is compromised, as attackers could gain access to user accounts
1152
+ * on external services.
1153
+ *
1154
+ * When enabled, tokens are encrypted using AES-256-GCM before storage, providing protection against:
1155
+ * - Database breaches and unauthorized access to raw token data
1156
+ * - Internal threats from database administrators or compromised credentials
1157
+ * - Token exposure in database backups and logs
1158
+ * @default false
1159
+ */
1160
+ encryptOAuthTokens?: boolean;
1161
+ /**
1162
+ * Skip state cookie check
1163
+ *
1164
+ * ⚠︎ this has security implications and should only be enabled if you know what you are doing.
1165
+ * @default false
1166
+ */
1167
+ skipStateCookieCheck?: boolean;
1168
+ /**
1169
+ * Strategy for storing OAuth state
1170
+ *
1171
+ * - "cookie": Store state in an encrypted cookie (stateless)
1172
+ * - "database": Store state in the database
1173
+ *
1174
+ * @default "database" when `database` or `secondaryStorage` is configured, "cookie" otherwise
1175
+ */
1176
+ storeStateStrategy?: "database" | "cookie";
1177
+ /**
1178
+ * Store provider account data after an OAuth flow in an encrypted
1179
+ * cookie. This includes OAuth token material such as access tokens,
1180
+ * refresh tokens, ID tokens, scopes, and token expiry.
1181
+ *
1182
+ * This is useful for database-less flows, but large provider tokens can
1183
+ * still hit browser or proxy cookie/header limits even though Better Auth
1184
+ * chunks oversized account cookies.
1185
+ *
1186
+ * @default false
1187
+ *
1188
+ * @note This is automatically set to true if you haven't passed a database
1189
+ */
1190
+ storeAccountCookie?: boolean;
1191
+ })
1192
+ | undefined;
1193
+ verification?:
1194
+ | (BetterAuthDBOptions<"verification", keyof BaseVerification> & {
1195
+ /**
1196
+ * disable cleaning up expired values when a verification value is
1197
+ * fetched
1198
+ */
1199
+ disableCleanup?: boolean;
1200
+ /**
1201
+ * How to store verification identifiers (tokens, OTPs, etc.)
1202
+ *
1203
+ * @example "hashed"
1204
+ *
1205
+ * @default "plain"
1206
+ */
1207
+ storeIdentifier?:
1208
+ | StoreIdentifierOption
1209
+ | {
1210
+ default: StoreIdentifierOption;
1211
+ overrides?: Record<string, StoreIdentifierOption>;
1212
+ };
1213
+ /**
1214
+ * Store verification data in database even when secondary storage is configured.
1215
+ * @default false
1216
+ */
1217
+ storeInDatabase?: boolean;
1218
+ })
1219
+ | undefined;
1220
+ /**
1221
+ * Additional trusted origins. By default, Better Auth trusts your
1222
+ * app's {@link baseURL}. Use this option to allow additional origins
1223
+ * (e.g. a separate frontend domain).
1224
+ *
1225
+ * Can be a static array, a function that returns origins dynamically,
1226
+ * or use wildcard patterns (e.g. `"https://*.example.com"`).
1227
+ *
1228
+ * @param request - The request object.
1229
+ * It'll be undefined if no request was
1230
+ * made. Like during a create context call
1231
+ * or `auth.api` call.
1232
+ *
1233
+ * Trusted origins will be dynamically
1234
+ * calculated based on the request.
1235
+ *
1236
+ * @example
1237
+ * ```ts
1238
+ * trustedOrigins: async (request) => {
1239
+ * return [
1240
+ * "https://better-auth.com",
1241
+ * "https://*.better-auth.com",
1242
+ * request.headers.get("x-custom-origin")
1243
+ * ];
1244
+ * }
1245
+ * ```
1246
+ * @returns An array of trusted origins.
1247
+ */
1248
+ trustedOrigins?:
1249
+ | (
1250
+ | string[]
1251
+ | ((
1252
+ request?: Request | undefined,
1253
+ ) => Awaitable<(string | undefined | null)[]>)
1254
+ )
1255
+ | undefined;
1256
+ /**
1257
+ * Rate limiting configuration
1258
+ */
1259
+ rateLimit?: BetterAuthRateLimitOptions | undefined;
1260
+ /**
1261
+ * Advanced options
1262
+ */
1263
+ advanced?: BetterAuthAdvancedOptions | undefined;
1264
+ logger?: Logger | undefined;
1265
+ /**
1266
+ * allows you to define custom hooks that can be
1267
+ * executed during lifecycle of core database
1268
+ * operations.
1269
+ */
1270
+ databaseHooks?:
1271
+ | {
1272
+ /**
1273
+ * User hooks
1274
+ */
1275
+ user?: {
1276
+ create?: {
1277
+ /**
1278
+ * Hook that is called before a user is created.
1279
+ * if the hook returns false, the user will not be created.
1280
+ * If the hook returns an object, it'll be used instead of the original data
1281
+ */
1282
+ before?: (
1283
+ user: User & Record<string, unknown>,
1284
+ context: GenericEndpointContext | null,
1285
+ ) => Promise<
1286
+ | boolean
1287
+ | void
1288
+ | {
1289
+ data: Optional<User> & Record<string, any>;
1290
+ }
1291
+ >;
1292
+ /**
1293
+ * Hook that is called after a user is created.
1294
+ */
1295
+ after?: (
1296
+ user: User & Record<string, unknown>,
1297
+ context: GenericEndpointContext | null,
1298
+ ) => Promise<void>;
1299
+ };
1300
+ update?: {
1301
+ /**
1302
+ * Hook that is called before a user is updated.
1303
+ * if the hook returns false, the user will not be updated.
1304
+ * If the hook returns an object, it'll be used instead of the original data
1305
+ */
1306
+ before?: (
1307
+ user: Partial<User> & Record<string, unknown>,
1308
+ context: GenericEndpointContext | null,
1309
+ ) => Promise<
1310
+ | boolean
1311
+ | void
1312
+ | {
1313
+ data: Optional<User & Record<string, any>>;
1314
+ }
1315
+ >;
1316
+ /**
1317
+ * Hook that is called after a user is updated.
1318
+ */
1319
+ after?: (
1320
+ user: User & Record<string, unknown>,
1321
+ context: GenericEndpointContext | null,
1322
+ ) => Promise<void>;
1323
+ };
1324
+ delete?: {
1325
+ /**
1326
+ * Hook that is called before a user is deleted.
1327
+ * if the hook returns false, the user will not be deleted.
1328
+ */
1329
+ before?: (
1330
+ user: User & Record<string, unknown>,
1331
+ context: GenericEndpointContext | null,
1332
+ ) => Promise<boolean | void>;
1333
+ /**
1334
+ * Hook that is called after a user is deleted.
1335
+ */
1336
+ after?: (
1337
+ user: User & Record<string, unknown>,
1338
+ context: GenericEndpointContext | null,
1339
+ ) => Promise<void>;
1340
+ };
1341
+ };
1342
+ /**
1343
+ * Session Hook
1344
+ */
1345
+ session?: {
1346
+ create?: {
1347
+ /**
1348
+ * Hook that is called before a session is created.
1349
+ * if the hook returns false, the session will not be created.
1350
+ * If the hook returns an object, it'll be used instead of the original data
1351
+ */
1352
+ before?: (
1353
+ session: Session & Record<string, unknown>,
1354
+ context: GenericEndpointContext | null,
1355
+ ) => Promise<
1356
+ | boolean
1357
+ | void
1358
+ | {
1359
+ data: Optional<Session> & Record<string, any>;
1360
+ }
1361
+ >;
1362
+ /**
1363
+ * Hook that is called after a session is created.
1364
+ */
1365
+ after?: (
1366
+ session: Session & Record<string, unknown>,
1367
+ context: GenericEndpointContext | null,
1368
+ ) => Promise<void>;
1369
+ };
1370
+ /**
1371
+ * Update hook
1372
+ */
1373
+ update?: {
1374
+ /**
1375
+ * Hook that is called before a user is updated.
1376
+ * if the hook returns false, the session will not be updated.
1377
+ * If the hook returns an object, it'll be used instead of the original data
1378
+ */
1379
+ before?: (
1380
+ session: Partial<Session> & Record<string, unknown>,
1381
+ context: GenericEndpointContext | null,
1382
+ ) => Promise<
1383
+ | boolean
1384
+ | void
1385
+ | {
1386
+ data: Optional<Session & Record<string, any>>;
1387
+ }
1388
+ >;
1389
+ /**
1390
+ * Hook that is called after a session is updated.
1391
+ */
1392
+ after?: (
1393
+ session: Session & Record<string, unknown>,
1394
+ context: GenericEndpointContext | null,
1395
+ ) => Promise<void>;
1396
+ };
1397
+ delete?: {
1398
+ /**
1399
+ * Hook that is called before a session is deleted.
1400
+ * if the hook returns false, the session will not be deleted.
1401
+ */
1402
+ before?: (
1403
+ session: Session & Record<string, unknown>,
1404
+ context: GenericEndpointContext | null,
1405
+ ) => Promise<boolean | void>;
1406
+ /**
1407
+ * Hook that is called after a session is deleted.
1408
+ */
1409
+ after?: (
1410
+ session: Session & Record<string, unknown>,
1411
+ context: GenericEndpointContext | null,
1412
+ ) => Promise<void>;
1413
+ };
1414
+ };
1415
+ /**
1416
+ * Account Hook
1417
+ */
1418
+ account?: {
1419
+ create?: {
1420
+ /**
1421
+ * Hook that is called before a account is created.
1422
+ * If the hook returns false, the account will not be created.
1423
+ * If the hook returns an object, it'll be used instead of the original data
1424
+ */
1425
+ before?: (
1426
+ account: Account,
1427
+ context: GenericEndpointContext | null,
1428
+ ) => Promise<
1429
+ | boolean
1430
+ | void
1431
+ | {
1432
+ data: Optional<Account> & Record<string, any>;
1433
+ }
1434
+ >;
1435
+ /**
1436
+ * Hook that is called after a account is created.
1437
+ */
1438
+ after?: (
1439
+ account: Account,
1440
+ context: GenericEndpointContext | null,
1441
+ ) => Promise<void>;
1442
+ };
1443
+ /**
1444
+ * Update hook
1445
+ */
1446
+ update?: {
1447
+ /**
1448
+ * Hook that is called before a account is update.
1449
+ * If the hook returns false, the user will not be updated.
1450
+ * If the hook returns an object, it'll be used instead of the original data
1451
+ */
1452
+ before?: (
1453
+ account: Partial<Account> & Record<string, unknown>,
1454
+ context: GenericEndpointContext | null,
1455
+ ) => Promise<
1456
+ | boolean
1457
+ | void
1458
+ | {
1459
+ data: Optional<Account & Record<string, any>>;
1460
+ }
1461
+ >;
1462
+ /**
1463
+ * Hook that is called after a account is updated.
1464
+ */
1465
+ after?: (
1466
+ account: Account & Record<string, unknown>,
1467
+ context: GenericEndpointContext | null,
1468
+ ) => Promise<void>;
1469
+ };
1470
+ delete?: {
1471
+ /**
1472
+ * Hook that is called before an account is deleted.
1473
+ * if the hook returns false, the account will not be deleted.
1474
+ */
1475
+ before?: (
1476
+ account: Account & Record<string, unknown>,
1477
+ context: GenericEndpointContext | null,
1478
+ ) => Promise<boolean | void>;
1479
+ /**
1480
+ * Hook that is called after an account is deleted.
1481
+ */
1482
+ after?: (
1483
+ account: Account & Record<string, unknown>,
1484
+ context: GenericEndpointContext | null,
1485
+ ) => Promise<void>;
1486
+ };
1487
+ };
1488
+ /**
1489
+ * Verification Hook
1490
+ */
1491
+ verification?: {
1492
+ create?: {
1493
+ /**
1494
+ * Hook that is called before a verification is created.
1495
+ * if the hook returns false, the verification will not be created.
1496
+ * If the hook returns an object, it'll be used instead of the original data
1497
+ */
1498
+ before?: (
1499
+ verification: Verification & Record<string, unknown>,
1500
+ context: GenericEndpointContext | null,
1501
+ ) => Promise<
1502
+ | boolean
1503
+ | void
1504
+ | {
1505
+ data: Optional<Verification> & Record<string, any>;
1506
+ }
1507
+ >;
1508
+ /**
1509
+ * Hook that is called after a verification is created.
1510
+ */
1511
+ after?: (
1512
+ verification: Verification & Record<string, unknown>,
1513
+ context: GenericEndpointContext | null,
1514
+ ) => Promise<void>;
1515
+ };
1516
+ update?: {
1517
+ /**
1518
+ * Hook that is called before a verification is updated.
1519
+ * if the hook returns false, the verification will not be updated.
1520
+ * If the hook returns an object, it'll be used instead of the original data
1521
+ */
1522
+ before?: (
1523
+ verification: Partial<Verification> & Record<string, unknown>,
1524
+ context: GenericEndpointContext | null,
1525
+ ) => Promise<
1526
+ | boolean
1527
+ | void
1528
+ | {
1529
+ data: Optional<Verification & Record<string, any>>;
1530
+ }
1531
+ >;
1532
+ /**
1533
+ * Hook that is called after a verification is updated.
1534
+ */
1535
+ after?: (
1536
+ verification: Verification & Record<string, unknown>,
1537
+ context: GenericEndpointContext | null,
1538
+ ) => Promise<void>;
1539
+ };
1540
+ delete?: {
1541
+ /**
1542
+ * Hook that is called before a verification is deleted.
1543
+ * if the hook returns false, the verification will not be deleted.
1544
+ */
1545
+ before?: (
1546
+ verification: Verification & Record<string, unknown>,
1547
+ context: GenericEndpointContext | null,
1548
+ ) => Promise<boolean | void>;
1549
+ /**
1550
+ * Hook that is called after a verification is deleted.
1551
+ */
1552
+ after?: (
1553
+ verification: Verification & Record<string, unknown>,
1554
+ context: GenericEndpointContext | null,
1555
+ ) => Promise<void>;
1556
+ };
1557
+ };
1558
+ }
1559
+ | undefined;
1560
+ /**
1561
+ * API error handling
1562
+ */
1563
+ onAPIError?:
1564
+ | {
1565
+ /**
1566
+ * Throw an error on API error
1567
+ *
1568
+ * @default false
1569
+ */
1570
+ throw?: boolean;
1571
+ /**
1572
+ * Custom error handler
1573
+ *
1574
+ * @param error
1575
+ * @param ctx - Auth context
1576
+ */
1577
+ onError?: (error: unknown, ctx: AuthContext) => void | Promise<void>;
1578
+ /**
1579
+ * The URL to redirect to on error
1580
+ *
1581
+ * When errorURL is provided, the error will be added to the URL as a query parameter
1582
+ * and the user will be redirected to the errorURL.
1583
+ *
1584
+ * @default - "/api/auth/error"
1585
+ */
1586
+ errorURL?: string;
1587
+ /**
1588
+ * Configure the default error page provided by Better-Auth
1589
+ * Start your dev server and go to /api/auth/error to see the error page.
1590
+ */
1591
+ customizeDefaultErrorPage?: {
1592
+ colors?: {
1593
+ background?: string;
1594
+ foreground?: string;
1595
+ primary?: string;
1596
+ primaryForeground?: string;
1597
+ mutedForeground?: string;
1598
+ border?: string;
1599
+ destructive?: string;
1600
+ titleBorder?: string;
1601
+ titleColor?: string;
1602
+ gridColor?: string;
1603
+ cardBackground?: string;
1604
+ cornerBorder?: string;
1605
+ };
1606
+ size?: {
1607
+ radiusSm?: string;
1608
+ radiusMd?: string;
1609
+ radiusLg?: string;
1610
+ textSm?: string;
1611
+ text2xl?: string;
1612
+ text4xl?: string;
1613
+ text6xl?: string;
1614
+ };
1615
+ font?: {
1616
+ defaultFamily?: string;
1617
+ monoFamily?: string;
1618
+ };
1619
+ disableTitleBorder?: boolean;
1620
+ disableCornerDecorations?: boolean;
1621
+ disableBackgroundGrid?: boolean;
1622
+ };
1623
+ }
1624
+ | undefined;
1625
+ /**
1626
+ * Hooks
1627
+ */
1628
+ hooks?:
1629
+ | {
1630
+ /**
1631
+ * Before a request is processed
1632
+ */
1633
+ before?: AuthMiddleware;
1634
+ /**
1635
+ * After a request is processed
1636
+ */
1637
+ after?: AuthMiddleware;
1638
+ }
1639
+ | undefined;
1640
+ /**
1641
+ * Disabled paths
1642
+ *
1643
+ * Paths you want to disable.
1644
+ */
1645
+ disabledPaths?: string[] | undefined;
1646
+ /**
1647
+ * Telemetry configuration
1648
+ */
1649
+ telemetry?:
1650
+ | {
1651
+ /**
1652
+ * Enable telemetry collection
1653
+ *
1654
+ * @default false
1655
+ */
1656
+ enabled?: boolean;
1657
+ /**
1658
+ * Enable debug mode
1659
+ *
1660
+ * @default false
1661
+ */
1662
+ debug?: boolean;
1663
+ }
1664
+ | undefined;
1665
+ /**
1666
+ * Experimental features
1667
+ */
1668
+ experimental?: {
1669
+ /**
1670
+ * Enable experimental joins for your database adapter.
1671
+ *
1672
+ * Please read the adapter documentation for more information regarding joins before enabling this.
1673
+ * Not all adapters support joins.
1674
+ *
1675
+ * @default false
1676
+ */
1677
+ joins?: boolean;
1678
+ };
1679
+ };