@better-auth/core 1.3.26 → 1.4.0-beta.10

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 (138) hide show
  1. package/.turbo/turbo-build.log +72 -24
  2. package/dist/async_hooks/index.cjs +12 -20
  3. package/dist/async_hooks/index.d.cts +4 -7
  4. package/dist/async_hooks/index.d.ts +4 -7
  5. package/dist/async_hooks/index.js +18 -0
  6. package/dist/chunk-CUT6urMc.cjs +30 -0
  7. package/dist/db/adapter/index.cjs +0 -0
  8. package/dist/db/adapter/index.d.cts +7 -0
  9. package/dist/db/adapter/index.d.ts +7 -0
  10. package/dist/db/adapter/index.js +1 -0
  11. package/dist/db/index.cjs +67 -1
  12. package/dist/db/index.d.cts +3 -130
  13. package/dist/db/index.d.ts +3 -130
  14. package/dist/db/index.js +61 -0
  15. package/dist/env/index.cjs +16 -0
  16. package/dist/env/index.d.cts +2 -0
  17. package/dist/env/index.d.ts +2 -0
  18. package/dist/env/index.js +3 -0
  19. package/dist/env-B05JceKx.cjs +330 -0
  20. package/dist/env-BZ5Nwx0e.js +246 -0
  21. package/dist/error/index.cjs +5 -0
  22. package/dist/error/index.d.cts +35 -0
  23. package/dist/error/index.d.ts +35 -0
  24. package/dist/error/index.js +4 -0
  25. package/dist/error-Hbg10Ynz.cjs +56 -0
  26. package/dist/error-ULaqTKlI.js +45 -0
  27. package/dist/helper-5oNxdxzu.d.ts +6 -0
  28. package/dist/helper-DVgWo5zB.d.cts +6 -0
  29. package/dist/index-B7m2jDWm.d.cts +344 -0
  30. package/dist/index-CESTxPyW.d.cts +82 -0
  31. package/dist/index-Cw9Gfaxd.d.cts +4410 -0
  32. package/dist/index-Cx8dCSTo.d.ts +82 -0
  33. package/dist/index-DJdmnKQr.d.ts +4410 -0
  34. package/dist/index-DNvIh1jX.d.cts +1870 -0
  35. package/dist/index-DoyF8K2U.d.ts +344 -0
  36. package/dist/index-ujq2DkG7.d.ts +1870 -0
  37. package/dist/index.cjs +0 -2
  38. package/dist/index.d.cts +7 -2
  39. package/dist/index.d.ts +7 -2
  40. package/dist/index.js +1 -0
  41. package/dist/middleware/index.cjs +22 -0
  42. package/dist/middleware/index.d.cts +7 -0
  43. package/dist/middleware/index.d.ts +7 -0
  44. package/dist/middleware/index.js +18 -0
  45. package/dist/oauth2/index.cjs +12 -0
  46. package/dist/oauth2/index.d.cts +3 -0
  47. package/dist/oauth2/index.d.ts +3 -0
  48. package/dist/oauth2/index.js +3 -0
  49. package/dist/oauth2-BokgssHJ.js +239 -0
  50. package/dist/oauth2-CLON8fY4.cjs +302 -0
  51. package/dist/social-providers/index.cjs +2410 -0
  52. package/dist/social-providers/index.d.cts +4 -0
  53. package/dist/social-providers/index.d.ts +4 -0
  54. package/dist/social-providers/index.js +2370 -0
  55. package/dist/type-BNCR-kIK.d.cts +262 -0
  56. package/dist/type-eT5TjHFp.d.ts +262 -0
  57. package/dist/utils/index.cjs +3 -0
  58. package/dist/utils/index.d.cts +9 -0
  59. package/dist/utils/index.d.ts +9 -0
  60. package/dist/utils/index.js +3 -0
  61. package/dist/utils-AcCtPmwG.cjs +13 -0
  62. package/dist/utils-BQjFFU97.js +7 -0
  63. package/package.json +116 -10
  64. package/src/async_hooks/index.ts +1 -9
  65. package/src/db/adapter/index.ts +448 -0
  66. package/src/db/index.ts +15 -0
  67. package/src/db/plugin.ts +11 -0
  68. package/src/db/schema/account.ts +34 -0
  69. package/src/db/schema/rate-limit.ts +21 -0
  70. package/src/db/schema/session.ts +17 -0
  71. package/src/db/schema/shared.ts +7 -0
  72. package/src/db/schema/user.ts +16 -0
  73. package/src/db/schema/verification.ts +15 -0
  74. package/src/db/type.ts +41 -0
  75. package/src/env/color-depth.ts +171 -0
  76. package/src/env/env-impl.ts +123 -0
  77. package/src/env/index.ts +23 -0
  78. package/src/env/logger.test.ts +33 -0
  79. package/src/env/logger.ts +145 -0
  80. package/src/error/codes.ts +31 -0
  81. package/src/error/index.ts +11 -0
  82. package/src/index.ts +1 -1
  83. package/src/middleware/index.ts +33 -0
  84. package/src/oauth2/client-credentials-token.ts +102 -0
  85. package/src/oauth2/create-authorization-url.ts +85 -0
  86. package/src/oauth2/index.ts +22 -0
  87. package/src/oauth2/oauth-provider.ts +194 -0
  88. package/src/oauth2/refresh-access-token.ts +124 -0
  89. package/src/oauth2/utils.ts +36 -0
  90. package/src/oauth2/validate-authorization-code.ts +156 -0
  91. package/src/social-providers/apple.ts +213 -0
  92. package/src/social-providers/atlassian.ts +127 -0
  93. package/src/social-providers/cognito.ts +266 -0
  94. package/src/social-providers/discord.ts +169 -0
  95. package/src/social-providers/dropbox.ts +112 -0
  96. package/src/social-providers/facebook.ts +201 -0
  97. package/src/social-providers/figma.ts +112 -0
  98. package/src/social-providers/github.ts +154 -0
  99. package/src/social-providers/gitlab.ts +152 -0
  100. package/src/social-providers/google.ts +168 -0
  101. package/src/social-providers/huggingface.ts +116 -0
  102. package/src/social-providers/index.ts +118 -0
  103. package/src/social-providers/kakao.ts +178 -0
  104. package/src/social-providers/kick.ts +92 -0
  105. package/src/social-providers/line.ts +169 -0
  106. package/src/social-providers/linear.ts +120 -0
  107. package/src/social-providers/linkedin.ts +110 -0
  108. package/src/social-providers/microsoft-entra-id.ts +243 -0
  109. package/src/social-providers/naver.ts +112 -0
  110. package/src/social-providers/notion.ts +106 -0
  111. package/src/social-providers/paypal.ts +261 -0
  112. package/src/social-providers/reddit.ts +122 -0
  113. package/src/social-providers/roblox.ts +107 -0
  114. package/src/social-providers/salesforce.ts +154 -0
  115. package/src/social-providers/slack.ts +111 -0
  116. package/src/social-providers/spotify.ts +93 -0
  117. package/src/social-providers/tiktok.ts +208 -0
  118. package/src/social-providers/twitch.ts +111 -0
  119. package/src/social-providers/twitter.ts +194 -0
  120. package/src/social-providers/vk.ts +125 -0
  121. package/src/social-providers/zoom.ts +215 -0
  122. package/src/types/context.ts +270 -0
  123. package/src/types/cookie.ts +7 -0
  124. package/src/types/helper.ts +5 -0
  125. package/src/types/index.ts +20 -1
  126. package/src/types/init-options.ts +1156 -0
  127. package/src/types/plugin-client.ts +69 -0
  128. package/src/types/plugin.ts +134 -0
  129. package/src/utils/error-codes.ts +51 -0
  130. package/src/utils/index.ts +1 -0
  131. package/tsdown.config.ts +19 -0
  132. package/build.config.ts +0 -16
  133. package/dist/async_hooks/index.d.mts +0 -10
  134. package/dist/async_hooks/index.mjs +0 -25
  135. package/dist/db/index.d.mts +0 -130
  136. package/dist/db/index.mjs +0 -1
  137. package/dist/index.d.mts +0 -2
  138. package/dist/index.mjs +0 -1
@@ -0,0 +1,1870 @@
1
+ import { LiteralString, LiteralUnion } from "./helper-5oNxdxzu.js";
2
+ import { Account, BetterAuthDBSchema, BetterAuthPluginDBSchema, DBFieldAttribute, DBPreservedModels, RateLimit, SecondaryStorage, Session, User, Verification } from "./type-eT5TjHFp.js";
3
+ import { OAuthProvider } from "./index-DoyF8K2U.js";
4
+ import { SocialProviderList, SocialProviders } from "./index-DJdmnKQr.js";
5
+ import { Logger, createLogger } from "./index-Cx8dCSTo.js";
6
+ import * as better_call0 from "better-call";
7
+ import { CookieOptions, Endpoint, EndpointContext, InputContext, Middleware } from "better-call";
8
+ import { BetterFetch, BetterFetchOption, BetterFetchPlugin } from "@better-fetch/fetch";
9
+ import { Dialect, Kysely, Migration, MysqlPool, PostgresPool } from "kysely";
10
+ import { Database } from "better-sqlite3";
11
+ import { Database as Database$1 } from "bun:sqlite";
12
+ import { DatabaseSync } from "node:sqlite";
13
+ import { Atom, WritableAtom } from "nanostores";
14
+
15
+ //#region src/types/cookie.d.ts
16
+ type BetterAuthCookies = {
17
+ sessionToken: {
18
+ name: string;
19
+ options: CookieOptions;
20
+ };
21
+ sessionData: {
22
+ name: string;
23
+ options: CookieOptions;
24
+ };
25
+ dontRememberToken: {
26
+ name: string;
27
+ options: CookieOptions;
28
+ };
29
+ };
30
+ //#endregion
31
+ //#region src/types/context.d.ts
32
+ type GenericEndpointContext<Options extends BetterAuthOptions = BetterAuthOptions> = EndpointContext<string, any> & {
33
+ context: AuthContext<Options>;
34
+ };
35
+ interface InternalAdapter<Options extends BetterAuthOptions = BetterAuthOptions> {
36
+ createOAuthUser(user: Omit<User, "id" | "createdAt" | "updatedAt">, account: Omit<Account, "userId" | "id" | "createdAt" | "updatedAt"> & Partial<Account>, context?: GenericEndpointContext<Options>): Promise<{
37
+ user: User;
38
+ account: Account;
39
+ }>;
40
+ createUser<T extends Record<string, any>>(user: Omit<User, "id" | "createdAt" | "updatedAt" | "emailVerified"> & Partial<User> & Record<string, any>, context?: GenericEndpointContext<Options>): Promise<T & User>;
41
+ createAccount<T extends Record<string, any>>(account: Omit<Account, "id" | "createdAt" | "updatedAt"> & Partial<Account> & T, context?: GenericEndpointContext<Options>): Promise<T & Account>;
42
+ listSessions(userId: string): Promise<Session[]>;
43
+ listUsers(limit?: number, offset?: number, sortBy?: {
44
+ field: string;
45
+ direction: "asc" | "desc";
46
+ }, where?: Where[]): Promise<User[]>;
47
+ countTotalUsers(where?: Where[]): Promise<number>;
48
+ deleteUser(userId: string, context?: GenericEndpointContext<Options>): Promise<void>;
49
+ createSession(userId: string, ctx: GenericEndpointContext<Options>, dontRememberMe?: boolean, override?: Partial<Session> & Record<string, any>, overrideAll?: boolean): Promise<Session>;
50
+ findSession(token: string): Promise<{
51
+ session: Session & Record<string, any>;
52
+ user: User & Record<string, any>;
53
+ } | null>;
54
+ findSessions(sessionTokens: string[]): Promise<{
55
+ session: Session;
56
+ user: User;
57
+ }[]>;
58
+ updateSession(sessionToken: string, session: Partial<Session> & Record<string, any>, context?: GenericEndpointContext<Options>): Promise<Session | null>;
59
+ deleteSession(token: string): Promise<void>;
60
+ deleteAccounts(userId: string, context?: GenericEndpointContext<Options>): Promise<void>;
61
+ deleteAccount(accountId: string, context?: GenericEndpointContext<Options>): Promise<void>;
62
+ deleteSessions(userIdOrSessionTokens: string | string[], context?: GenericEndpointContext<Options>): Promise<void>;
63
+ findOAuthUser(email: string, accountId: string, providerId: string): Promise<{
64
+ user: User;
65
+ accounts: Account[];
66
+ } | null>;
67
+ findUserByEmail(email: string, options?: {
68
+ includeAccounts: boolean;
69
+ }): Promise<{
70
+ user: User;
71
+ accounts: Account[];
72
+ } | null>;
73
+ findUserById(userId: string): Promise<User | null>;
74
+ linkAccount(account: Omit<Account, "id" | "createdAt" | "updatedAt"> & Partial<Account>, context?: GenericEndpointContext<Options>): Promise<Account>;
75
+ updateUser(userId: string, data: Partial<User> & Record<string, any>, context?: GenericEndpointContext<Options>): Promise<any>;
76
+ updateUserByEmail(email: string, data: Partial<User & Record<string, any>>, context?: GenericEndpointContext<Options>): Promise<User>;
77
+ updatePassword(userId: string, password: string, context?: GenericEndpointContext<Options>): Promise<void>;
78
+ findAccounts(userId: string): Promise<Account[]>;
79
+ findAccount(accountId: string): Promise<Account | null>;
80
+ findAccountByProviderId(accountId: string, providerId: string): Promise<Account | null>;
81
+ findAccountByUserId(userId: string): Promise<Account[]>;
82
+ updateAccount(id: string, data: Partial<Account>, context?: GenericEndpointContext<Options>): Promise<Account>;
83
+ createVerificationValue(data: Omit<Verification, "createdAt" | "id" | "updatedAt"> & Partial<Verification>, context?: GenericEndpointContext<Options>): Promise<Verification>;
84
+ findVerificationValue(identifier: string): Promise<Verification | null>;
85
+ deleteVerificationValue(id: string, context?: GenericEndpointContext<Options>): Promise<void>;
86
+ deleteVerificationByIdentifier(identifier: string, context?: GenericEndpointContext<Options>): Promise<void>;
87
+ updateVerificationValue(id: string, data: Partial<Verification>, context?: GenericEndpointContext<Options>): Promise<Verification>;
88
+ }
89
+ type CreateCookieGetterFn = (cookieName: string, overrideAttributes?: Partial<CookieOptions>) => {
90
+ name: string;
91
+ attributes: CookieOptions;
92
+ };
93
+ type CheckPasswordFn<Options extends BetterAuthOptions = BetterAuthOptions> = (userId: string, ctx: GenericEndpointContext<Options>) => Promise<boolean>;
94
+ type AuthContext<Options extends BetterAuthOptions = BetterAuthOptions> = {
95
+ options: Options;
96
+ appName: string;
97
+ baseURL: string;
98
+ trustedOrigins: string[];
99
+ oauthConfig?: {
100
+ /**
101
+ * This is dangerous and should only be used in dev or staging environments.
102
+ */
103
+ skipStateCookieCheck?: boolean;
104
+ };
105
+ /**
106
+ * New session that will be set after the request
107
+ * meaning: there is a `set-cookie` header that will set
108
+ * the session cookie. This is the fetched session. And it's set
109
+ * by `setNewSession` method.
110
+ */
111
+ newSession: {
112
+ session: Session & Record<string, any>;
113
+ user: User & Record<string, any>;
114
+ } | null;
115
+ session: {
116
+ session: Session & Record<string, any>;
117
+ user: User & Record<string, any>;
118
+ } | null;
119
+ setNewSession: (session: {
120
+ session: Session & Record<string, any>;
121
+ user: User & Record<string, any>;
122
+ } | null) => void;
123
+ socialProviders: OAuthProvider[];
124
+ authCookies: BetterAuthCookies;
125
+ logger: ReturnType<typeof createLogger>;
126
+ rateLimit: {
127
+ enabled: boolean;
128
+ window: number;
129
+ max: number;
130
+ storage: "memory" | "database" | "secondary-storage";
131
+ } & BetterAuthRateLimitOptions;
132
+ adapter: DBAdapter<Options>;
133
+ internalAdapter: InternalAdapter<Options>;
134
+ createAuthCookie: CreateCookieGetterFn;
135
+ secret: string;
136
+ sessionConfig: {
137
+ updateAge: number;
138
+ expiresIn: number;
139
+ freshAge: number;
140
+ };
141
+ generateId: (options: {
142
+ model: LiteralUnion<DBPreservedModels, string>;
143
+ size?: number;
144
+ }) => string | false;
145
+ secondaryStorage: SecondaryStorage | undefined;
146
+ password: {
147
+ hash: (password: string) => Promise<string>;
148
+ verify: (data: {
149
+ password: string;
150
+ hash: string;
151
+ }) => Promise<boolean>;
152
+ config: {
153
+ minPasswordLength: number;
154
+ maxPasswordLength: number;
155
+ };
156
+ checkPassword: CheckPasswordFn<Options>;
157
+ };
158
+ tables: BetterAuthDBSchema;
159
+ runMigrations: () => Promise<void>;
160
+ publishTelemetry: (event: {
161
+ type: string;
162
+ anonymousId?: string;
163
+ payload: Record<string, any>;
164
+ }) => Promise<void>;
165
+ };
166
+ //#endregion
167
+ //#region src/middleware/index.d.ts
168
+ declare const optionsMiddleware: <InputCtx extends better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>>(inputContext: InputCtx) => Promise<AuthContext>;
169
+ declare const createAuthMiddleware: {
170
+ <Options extends better_call0.MiddlewareOptions, R>(options: Options, handler: (ctx: better_call0.MiddlewareContext<Options, AuthContext & {
171
+ returned?: unknown;
172
+ responseHeaders?: Headers;
173
+ }>) => Promise<R>): (inputContext: better_call0.MiddlewareInputContext<Options>) => Promise<R>;
174
+ <Options extends better_call0.MiddlewareOptions, R_1>(handler: (ctx: better_call0.MiddlewareContext<Options, AuthContext & {
175
+ returned?: unknown;
176
+ responseHeaders?: Headers;
177
+ }>) => Promise<R_1>): (inputContext: better_call0.MiddlewareInputContext<Options>) => Promise<R_1>;
178
+ };
179
+ declare const createAuthEndpoint: <Path extends string, Opts extends better_call0.EndpointOptions, R>(path: Path, options: Opts, handler: (ctx: better_call0.EndpointContext<Path, Opts, AuthContext>) => Promise<R>) => {
180
+ <AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(...inputCtx: better_call0.HasRequiredKeys<better_call0.InputContext<Path, Opts & {
181
+ use: any[];
182
+ }>> extends true ? [better_call0.InferBodyInput<Opts & {
183
+ use: any[];
184
+ }, (Opts & {
185
+ use: any[];
186
+ })["metadata"] extends {
187
+ $Infer: {
188
+ body: infer B;
189
+ };
190
+ } ? B : (Opts & {
191
+ use: any[];
192
+ })["body"] extends better_call0.StandardSchemaV1<unknown, unknown> ? better_call0.StandardSchemaV1.InferInput<(Opts & {
193
+ use: any[];
194
+ })["body"]> : undefined> & better_call0.InferInputMethod<Opts & {
195
+ use: any[];
196
+ }, (Opts & {
197
+ use: any[];
198
+ })["method"] extends any[] ? (Opts & {
199
+ use: any[];
200
+ })["method"][number] : (Opts & {
201
+ use: any[];
202
+ })["method"] extends "*" ? better_call0.HTTPMethod : (Opts & {
203
+ use: any[];
204
+ })["method"] | undefined> & better_call0.InferQueryInput<Opts & {
205
+ use: any[];
206
+ }, (Opts & {
207
+ use: any[];
208
+ })["metadata"] extends {
209
+ $Infer: {
210
+ query: infer Query;
211
+ };
212
+ } ? Query : (Opts & {
213
+ use: any[];
214
+ })["query"] extends better_call0.StandardSchemaV1<unknown, unknown> ? better_call0.StandardSchemaV1.InferInput<(Opts & {
215
+ use: any[];
216
+ })["query"]> : Record<string, any> | undefined> & better_call0.InferParamInput<Path> & better_call0.InferRequestInput<Opts & {
217
+ use: any[];
218
+ }> & better_call0.InferHeadersInput<Opts & {
219
+ use: any[];
220
+ }> & {
221
+ asResponse?: boolean;
222
+ returnHeaders?: boolean;
223
+ use?: better_call0.Middleware[];
224
+ path?: string;
225
+ } & {
226
+ asResponse?: AsResponse | undefined;
227
+ returnHeaders?: ReturnHeaders | undefined;
228
+ }] : [((better_call0.InferBodyInput<Opts & {
229
+ use: any[];
230
+ }, (Opts & {
231
+ use: any[];
232
+ })["metadata"] extends {
233
+ $Infer: {
234
+ body: infer B_1;
235
+ };
236
+ } ? B_1 : (Opts & {
237
+ use: any[];
238
+ })["body"] extends better_call0.StandardSchemaV1<unknown, unknown> ? better_call0.StandardSchemaV1.InferInput<(Opts & {
239
+ use: any[];
240
+ })["body"]> : undefined> & better_call0.InferInputMethod<Opts & {
241
+ use: any[];
242
+ }, (Opts & {
243
+ use: any[];
244
+ })["method"] extends any[] ? (Opts & {
245
+ use: any[];
246
+ })["method"][number] : (Opts & {
247
+ use: any[];
248
+ })["method"] extends "*" ? better_call0.HTTPMethod : (Opts & {
249
+ use: any[];
250
+ })["method"] | undefined> & better_call0.InferQueryInput<Opts & {
251
+ use: any[];
252
+ }, (Opts & {
253
+ use: any[];
254
+ })["metadata"] extends {
255
+ $Infer: {
256
+ query: infer Query_1;
257
+ };
258
+ } ? Query_1 : (Opts & {
259
+ use: any[];
260
+ })["query"] extends better_call0.StandardSchemaV1<unknown, unknown> ? better_call0.StandardSchemaV1.InferInput<(Opts & {
261
+ use: any[];
262
+ })["query"]> : Record<string, any> | undefined> & better_call0.InferParamInput<Path> & better_call0.InferRequestInput<Opts & {
263
+ use: any[];
264
+ }> & better_call0.InferHeadersInput<Opts & {
265
+ use: any[];
266
+ }> & {
267
+ asResponse?: boolean;
268
+ returnHeaders?: boolean;
269
+ use?: better_call0.Middleware[];
270
+ path?: string;
271
+ } & {
272
+ asResponse?: AsResponse | undefined;
273
+ returnHeaders?: ReturnHeaders | undefined;
274
+ }) | undefined)?]): Promise<[AsResponse] extends [true] ? Response : [ReturnHeaders] extends [true] ? {
275
+ headers: Headers;
276
+ response: R;
277
+ } : R>;
278
+ options: Opts & {
279
+ use: any[];
280
+ };
281
+ path: Path;
282
+ };
283
+ type AuthEndpoint = ReturnType<typeof createAuthEndpoint>;
284
+ type AuthMiddleware = ReturnType<typeof createAuthMiddleware>;
285
+ //#endregion
286
+ //#region src/types/init-options.d.ts
287
+ type KyselyDatabaseType = "postgres" | "mysql" | "sqlite" | "mssql";
288
+ type OmitId<T extends {
289
+ id: unknown;
290
+ }> = Omit<T, "id">;
291
+ type GenerateIdFn = (options: {
292
+ model: LiteralUnion<DBPreservedModels, string>;
293
+ size?: number;
294
+ }) => string | false;
295
+ type BetterAuthRateLimitOptions = {
296
+ /**
297
+ * By default, rate limiting is only
298
+ * enabled on production.
299
+ */
300
+ enabled?: boolean;
301
+ /**
302
+ * Default window to use for rate limiting. The value
303
+ * should be in seconds.
304
+ *
305
+ * @default 10 seconds
306
+ */
307
+ window?: number;
308
+ /**
309
+ * The default maximum number of requests allowed within the window.
310
+ *
311
+ * @default 100 requests
312
+ */
313
+ max?: number;
314
+ /**
315
+ * Custom rate limit rules to apply to
316
+ * specific paths.
317
+ */
318
+ customRules?: {
319
+ [key: string]: {
320
+ /**
321
+ * The window to use for the custom rule.
322
+ */
323
+ window: number;
324
+ /**
325
+ * The maximum number of requests allowed within the window.
326
+ */
327
+ max: number;
328
+ } | false | ((request: Request) => {
329
+ window: number;
330
+ max: number;
331
+ } | false | Promise<{
332
+ window: number;
333
+ max: number;
334
+ } | false>);
335
+ };
336
+ /**
337
+ * Storage configuration
338
+ *
339
+ * By default, rate limiting is stored in memory. If you passed a
340
+ * secondary storage, rate limiting will be stored in the secondary
341
+ * storage.
342
+ *
343
+ * @default "memory"
344
+ */
345
+ storage?: "memory" | "database" | "secondary-storage";
346
+ /**
347
+ * If database is used as storage, the name of the table to
348
+ * use for rate limiting.
349
+ *
350
+ * @default "rateLimit"
351
+ */
352
+ modelName?: string;
353
+ /**
354
+ * Custom field names for the rate limit table
355
+ */
356
+ fields?: Record<keyof RateLimit, string>;
357
+ /**
358
+ * custom storage configuration.
359
+ *
360
+ * NOTE: If custom storage is used storage
361
+ * is ignored
362
+ */
363
+ customStorage?: {
364
+ get: (key: string) => Promise<RateLimit | undefined>;
365
+ set: (key: string, value: RateLimit) => Promise<void>;
366
+ };
367
+ };
368
+ type BetterAuthAdvancedOptions = {
369
+ /**
370
+ * Ip address configuration
371
+ */
372
+ ipAddress?: {
373
+ /**
374
+ * List of headers to use for ip address
375
+ *
376
+ * Ip address is used for rate limiting and session tracking
377
+ *
378
+ * @example ["x-client-ip", "x-forwarded-for", "cf-connecting-ip"]
379
+ *
380
+ * @default
381
+ * @link https://github.com/better-auth/better-auth/blob/main/packages/better-auth/src/utils/get-request-ip.ts#L8
382
+ */
383
+ ipAddressHeaders?: string[];
384
+ /**
385
+ * Disable ip tracking
386
+ *
387
+ * ⚠︎ This is a security risk and it may expose your application to abuse
388
+ */
389
+ disableIpTracking?: boolean;
390
+ };
391
+ /**
392
+ * Use secure cookies
393
+ *
394
+ * @default false
395
+ */
396
+ useSecureCookies?: boolean;
397
+ /**
398
+ * Disable trusted origins check
399
+ *
400
+ * ⚠︎ This is a security risk and it may expose your application to CSRF attacks
401
+ */
402
+ disableCSRFCheck?: boolean;
403
+ /**
404
+ * Configure cookies to be cross subdomains
405
+ */
406
+ crossSubDomainCookies?: {
407
+ /**
408
+ * Enable cross subdomain cookies
409
+ */
410
+ enabled: boolean;
411
+ /**
412
+ * Additional cookies to be shared across subdomains
413
+ */
414
+ additionalCookies?: string[];
415
+ /**
416
+ * The domain to use for the cookies
417
+ *
418
+ * By default, the domain will be the root
419
+ * domain from the base URL.
420
+ */
421
+ domain?: string;
422
+ };
423
+ cookies?: {
424
+ [key: string]: {
425
+ name?: string;
426
+ attributes?: CookieOptions;
427
+ };
428
+ };
429
+ defaultCookieAttributes?: CookieOptions;
430
+ /**
431
+ * Prefix for cookies. If a cookie name is provided
432
+ * in cookies config, this will be overridden.
433
+ *
434
+ * @default
435
+ * ```txt
436
+ * "appName" -> which defaults to "better-auth"
437
+ * ```
438
+ */
439
+ cookiePrefix?: string;
440
+ /**
441
+ * Database configuration.
442
+ */
443
+ database?: {
444
+ /**
445
+ * The default number of records to return from the database
446
+ * when using the `findMany` adapter method.
447
+ *
448
+ * @default 100
449
+ */
450
+ defaultFindManyLimit?: number;
451
+ /**
452
+ * If your database auto increments number ids, set this to `true`.
453
+ *
454
+ * Note: If enabled, we will not handle ID generation (including if you use `generateId`), and it would be expected that your database will provide the ID automatically.
455
+ *
456
+ * @default false
457
+ */
458
+ useNumberId?: boolean;
459
+ /**
460
+ * Custom generateId function.
461
+ *
462
+ * If not provided, random ids will be generated.
463
+ * If set to false, the database's auto generated id will be used.
464
+ */
465
+ generateId?: GenerateIdFn | false;
466
+ };
467
+ };
468
+ type BetterAuthOptions = {
469
+ /**
470
+ * The name of the application
471
+ *
472
+ * process.env.APP_NAME
473
+ *
474
+ * @default "Better Auth"
475
+ */
476
+ appName?: string;
477
+ /**
478
+ * Base URL for the Better Auth. This is typically the
479
+ * root URL where your application server is hosted.
480
+ * If not explicitly set,
481
+ * the system will check the following environment variable:
482
+ *
483
+ * process.env.BETTER_AUTH_URL
484
+ */
485
+ baseURL?: string;
486
+ /**
487
+ * Base path for the Better Auth. This is typically
488
+ * the path where the
489
+ * Better Auth routes are mounted.
490
+ *
491
+ * @default "/api/auth"
492
+ */
493
+ basePath?: string;
494
+ /**
495
+ * The secret to use for encryption,
496
+ * signing and hashing.
497
+ *
498
+ * By default Better Auth will look for
499
+ * the following environment variables:
500
+ * process.env.BETTER_AUTH_SECRET,
501
+ * process.env.AUTH_SECRET
502
+ * If none of these environment
503
+ * variables are set,
504
+ * it will default to
505
+ * "better-auth-secret-123456789".
506
+ *
507
+ * on production if it's not set
508
+ * it will throw an error.
509
+ *
510
+ * you can generate a good secret
511
+ * using the following command:
512
+ * @example
513
+ * ```bash
514
+ * openssl rand -base64 32
515
+ * ```
516
+ */
517
+ secret?: string;
518
+ /**
519
+ * Database configuration
520
+ */
521
+ database?: PostgresPool | MysqlPool | Database | Dialect | DBAdapterInstance | Database$1 | DatabaseSync | {
522
+ dialect: Dialect;
523
+ type: KyselyDatabaseType;
524
+ /**
525
+ * casing for table names
526
+ *
527
+ * @default "camel"
528
+ */
529
+ casing?: "snake" | "camel";
530
+ /**
531
+ * Enable debug logs for the adapter
532
+ *
533
+ * @default false
534
+ */
535
+ debugLogs?: DBAdapterDebugLogOption;
536
+ /**
537
+ * Whether to execute multiple operations in a transaction.
538
+ * If the database doesn't support transactions,
539
+ * set this to `false` and operations will be executed sequentially.
540
+ * @default true
541
+ */
542
+ transaction?: boolean;
543
+ } | {
544
+ /**
545
+ * Kysely instance
546
+ */
547
+ db: Kysely<any>;
548
+ /**
549
+ * Database type between postgres, mysql and sqlite
550
+ */
551
+ type: KyselyDatabaseType;
552
+ /**
553
+ * casing for table names
554
+ *
555
+ * @default "camel"
556
+ */
557
+ casing?: "snake" | "camel";
558
+ /**
559
+ * Enable debug logs for the adapter
560
+ *
561
+ * @default false
562
+ */
563
+ debugLogs?: DBAdapterDebugLogOption;
564
+ /**
565
+ * Whether to execute multiple operations in a transaction.
566
+ * If the database doesn't support transactions,
567
+ * set this to `false` and operations will be executed sequentially.
568
+ * @default true
569
+ */
570
+ transaction?: boolean;
571
+ };
572
+ /**
573
+ * Secondary storage configuration
574
+ *
575
+ * This is used to store session and rate limit data.
576
+ */
577
+ secondaryStorage?: SecondaryStorage;
578
+ /**
579
+ * Email verification configuration
580
+ */
581
+ emailVerification?: {
582
+ /**
583
+ * Send a verification email
584
+ * @param data the data object
585
+ * @param request the request object
586
+ */
587
+ sendVerificationEmail?: (
588
+ /**
589
+ * @param user the user to send the
590
+ * verification email to
591
+ * @param url the URL to send the verification email to
592
+ * it contains the token as well
593
+ * @param token the token to send the verification email to
594
+ */
595
+ data: {
596
+ user: User;
597
+ url: string;
598
+ token: string;
599
+ },
600
+ /**
601
+ * The request object
602
+ */
603
+ request?: Request) => Promise<void>;
604
+ /**
605
+ * Send a verification email automatically
606
+ * after sign up
607
+ *
608
+ * @default false
609
+ */
610
+ sendOnSignUp?: boolean;
611
+ /**
612
+ * Send a verification email automatically
613
+ * on sign in when the user's email is not verified
614
+ *
615
+ * @default false
616
+ */
617
+ sendOnSignIn?: boolean;
618
+ /**
619
+ * Auto signin the user after they verify their email
620
+ */
621
+ autoSignInAfterVerification?: boolean;
622
+ /**
623
+ * Number of seconds the verification token is
624
+ * valid for.
625
+ * @default 3600 seconds (1 hour)
626
+ */
627
+ expiresIn?: number;
628
+ /**
629
+ * A function that is called when a user verifies their email
630
+ * @param user the user that verified their email
631
+ * @param request the request object
632
+ */
633
+ onEmailVerification?: (user: User, request?: Request) => Promise<void>;
634
+ /**
635
+ * A function that is called when a user's email is updated to verified
636
+ * @param user the user that verified their email
637
+ * @param request the request object
638
+ */
639
+ afterEmailVerification?: (user: User, request?: Request) => Promise<void>;
640
+ };
641
+ /**
642
+ * Email and password authentication
643
+ */
644
+ emailAndPassword?: {
645
+ /**
646
+ * Enable email and password authentication
647
+ *
648
+ * @default false
649
+ */
650
+ enabled: boolean;
651
+ /**
652
+ * Disable email and password sign up
653
+ *
654
+ * @default false
655
+ */
656
+ disableSignUp?: boolean;
657
+ /**
658
+ * Require email verification before a session
659
+ * can be created for the user.
660
+ *
661
+ * if the user is not verified, the user will not be able to sign in
662
+ * and on sign in attempts, the user will be prompted to verify their email.
663
+ */
664
+ requireEmailVerification?: boolean;
665
+ /**
666
+ * The maximum length of the password.
667
+ *
668
+ * @default 128
669
+ */
670
+ maxPasswordLength?: number;
671
+ /**
672
+ * The minimum length of the password.
673
+ *
674
+ * @default 8
675
+ */
676
+ minPasswordLength?: number;
677
+ /**
678
+ * send reset password
679
+ */
680
+ sendResetPassword?: (
681
+ /**
682
+ * @param user the user to send the
683
+ * reset password email to
684
+ * @param url the URL to send the reset password email to
685
+ * @param token the token to send to the user (could be used instead of sending the url
686
+ * if you need to redirect the user to custom route)
687
+ */
688
+ data: {
689
+ user: User;
690
+ url: string;
691
+ token: string;
692
+ },
693
+ /**
694
+ * The request object
695
+ */
696
+ request?: Request) => Promise<void>;
697
+ /**
698
+ * Number of seconds the reset password token is
699
+ * valid for.
700
+ * @default 1 hour (60 * 60)
701
+ */
702
+ resetPasswordTokenExpiresIn?: number;
703
+ /**
704
+ * A callback function that is triggered
705
+ * when a user's password is changed successfully.
706
+ */
707
+ onPasswordReset?: (data: {
708
+ user: User;
709
+ }, request?: Request) => Promise<void>;
710
+ /**
711
+ * Password hashing and verification
712
+ *
713
+ * By default Scrypt is used for password hashing and
714
+ * verification. You can provide your own hashing and
715
+ * verification function. if you want to use a
716
+ * different algorithm.
717
+ */
718
+ password?: {
719
+ hash?: (password: string) => Promise<string>;
720
+ verify?: (data: {
721
+ hash: string;
722
+ password: string;
723
+ }) => Promise<boolean>;
724
+ };
725
+ /**
726
+ * Automatically sign in the user after sign up
727
+ *
728
+ * @default true
729
+ */
730
+ autoSignIn?: boolean;
731
+ /**
732
+ * Whether to revoke all other sessions when resetting password
733
+ * @default false
734
+ */
735
+ revokeSessionsOnPasswordReset?: boolean;
736
+ };
737
+ /**
738
+ * list of social providers
739
+ */
740
+ socialProviders?: SocialProviders;
741
+ /**
742
+ * List of Better Auth plugins
743
+ */
744
+ plugins?: [] | BetterAuthPlugin[];
745
+ /**
746
+ * User configuration
747
+ */
748
+ user?: {
749
+ /**
750
+ * The model name for the user. Defaults to "user".
751
+ */
752
+ modelName?: string;
753
+ /**
754
+ * Map fields
755
+ *
756
+ * @example
757
+ * ```ts
758
+ * {
759
+ * userId: "user_id"
760
+ * }
761
+ * ```
762
+ */
763
+ fields?: Partial<Record<keyof OmitId<User>, string>>;
764
+ /**
765
+ * Additional fields for the user
766
+ */
767
+ additionalFields?: {
768
+ [key: string]: DBFieldAttribute;
769
+ };
770
+ /**
771
+ * Changing email configuration
772
+ */
773
+ changeEmail?: {
774
+ /**
775
+ * Enable changing email
776
+ * @default false
777
+ */
778
+ enabled: boolean;
779
+ /**
780
+ * Send a verification email when the user changes their email.
781
+ * @param data the data object
782
+ * @param request the request object
783
+ */
784
+ sendChangeEmailVerification?: (data: {
785
+ user: User;
786
+ newEmail: string;
787
+ url: string;
788
+ token: string;
789
+ }, request?: Request) => Promise<void>;
790
+ };
791
+ /**
792
+ * User deletion configuration
793
+ */
794
+ deleteUser?: {
795
+ /**
796
+ * Enable user deletion
797
+ */
798
+ enabled?: boolean;
799
+ /**
800
+ * Send a verification email when the user deletes their account.
801
+ *
802
+ * if this is not set, the user will be deleted immediately.
803
+ * @param data the data object
804
+ * @param request the request object
805
+ */
806
+ sendDeleteAccountVerification?: (data: {
807
+ user: User;
808
+ url: string;
809
+ token: string;
810
+ }, request?: Request) => Promise<void>;
811
+ /**
812
+ * A function that is called before a user is deleted.
813
+ *
814
+ * to interrupt with error you can throw `APIError`
815
+ */
816
+ beforeDelete?: (user: User, request?: Request) => Promise<void>;
817
+ /**
818
+ * A function that is called after a user is deleted.
819
+ *
820
+ * This is useful for cleaning up user data
821
+ */
822
+ afterDelete?: (user: User, request?: Request) => Promise<void>;
823
+ /**
824
+ * The expiration time for the delete token.
825
+ *
826
+ * @default 1 day (60 * 60 * 24) in seconds
827
+ */
828
+ deleteTokenExpiresIn?: number;
829
+ };
830
+ };
831
+ session?: {
832
+ /**
833
+ * The model name for the session.
834
+ *
835
+ * @default "session"
836
+ */
837
+ modelName?: string;
838
+ /**
839
+ * Map fields
840
+ *
841
+ * @example
842
+ * ```ts
843
+ * {
844
+ * userId: "user_id"
845
+ * }
846
+ */
847
+ fields?: Partial<Record<keyof OmitId<Session>, string>>;
848
+ /**
849
+ * Expiration time for the session token. The value
850
+ * should be in seconds.
851
+ * @default 7 days (60 * 60 * 24 * 7)
852
+ */
853
+ expiresIn?: number;
854
+ /**
855
+ * How often the session should be refreshed. The value
856
+ * should be in seconds.
857
+ * If set 0 the session will be refreshed every time it is used.
858
+ * @default 1 day (60 * 60 * 24)
859
+ */
860
+ updateAge?: number;
861
+ /**
862
+ * Disable session refresh so that the session is not updated
863
+ * regardless of the `updateAge` option.
864
+ *
865
+ * @default false
866
+ */
867
+ disableSessionRefresh?: boolean;
868
+ /**
869
+ * Additional fields for the session
870
+ */
871
+ additionalFields?: {
872
+ [key: string]: DBFieldAttribute;
873
+ };
874
+ /**
875
+ * By default if secondary storage is provided
876
+ * the session is stored in the secondary storage.
877
+ *
878
+ * Set this to true to store the session in the database
879
+ * as well.
880
+ *
881
+ * Reads are always done from the secondary storage.
882
+ *
883
+ * @default false
884
+ */
885
+ storeSessionInDatabase?: boolean;
886
+ /**
887
+ * By default, sessions are deleted from the database when secondary storage
888
+ * is provided when session is revoked.
889
+ *
890
+ * Set this to true to preserve session records in the database,
891
+ * even if they are deleted from the secondary storage.
892
+ *
893
+ * @default false
894
+ */
895
+ preserveSessionInDatabase?: boolean;
896
+ /**
897
+ * Enable caching session in cookie
898
+ */
899
+ cookieCache?: {
900
+ /**
901
+ * max age of the cookie
902
+ * @default 5 minutes (5 * 60)
903
+ */
904
+ maxAge?: number;
905
+ /**
906
+ * Enable caching session in cookie
907
+ * @default false
908
+ */
909
+ enabled?: boolean;
910
+ };
911
+ /**
912
+ * The age of the session to consider it fresh.
913
+ *
914
+ * This is used to check if the session is fresh
915
+ * for sensitive operations. (e.g. deleting an account)
916
+ *
917
+ * If the session is not fresh, the user should be prompted
918
+ * to sign in again.
919
+ *
920
+ * If set to 0, the session will be considered fresh every time. (⚠︎ not recommended)
921
+ *
922
+ * @default 1 day (60 * 60 * 24)
923
+ */
924
+ freshAge?: number;
925
+ };
926
+ account?: {
927
+ /**
928
+ * The model name for the account. Defaults to "account".
929
+ */
930
+ modelName?: string;
931
+ /**
932
+ * Map fields
933
+ */
934
+ fields?: Partial<Record<keyof OmitId<Account>, string>>;
935
+ /**
936
+ * Additional fields for the account
937
+ */
938
+ additionalFields?: {
939
+ [key: string]: DBFieldAttribute;
940
+ };
941
+ /**
942
+ * When enabled (true), the user account data (accessToken, idToken, refreshToken, etc.)
943
+ * will be updated on sign in with the latest data from the provider.
944
+ *
945
+ * @default true
946
+ */
947
+ updateAccountOnSignIn?: boolean;
948
+ /**
949
+ * Configuration for account linking.
950
+ */
951
+ accountLinking?: {
952
+ /**
953
+ * Enable account linking
954
+ *
955
+ * @default true
956
+ */
957
+ enabled?: boolean;
958
+ /**
959
+ * List of trusted providers
960
+ */
961
+ trustedProviders?: Array<LiteralUnion<SocialProviderList[number] | "email-password", string>>;
962
+ /**
963
+ * If enabled (true), this will allow users to manually linking accounts with different email addresses than the main user.
964
+ *
965
+ * @default false
966
+ *
967
+ * ⚠️ Warning: enabling this might lead to account takeovers, so proceed with caution.
968
+ */
969
+ allowDifferentEmails?: boolean;
970
+ /**
971
+ * If enabled (true), this will allow users to unlink all accounts.
972
+ *
973
+ * @default false
974
+ */
975
+ allowUnlinkingAll?: boolean;
976
+ /**
977
+ * If enabled (true), this will update the user information based on the newly linked account
978
+ *
979
+ * @default false
980
+ */
981
+ updateUserInfoOnLink?: boolean;
982
+ };
983
+ /**
984
+ * Encrypt OAuth tokens
985
+ *
986
+ * By default, OAuth tokens (access tokens, refresh tokens, ID tokens) are stored in plain text in the database.
987
+ * This poses a security risk if your database is compromised, as attackers could gain access to user accounts
988
+ * on external services.
989
+ *
990
+ * When enabled, tokens are encrypted using AES-256-GCM before storage, providing protection against:
991
+ * - Database breaches and unauthorized access to raw token data
992
+ * - Internal threats from database administrators or compromised credentials
993
+ * - Token exposure in database backups and logs
994
+ * @default false
995
+ */
996
+ encryptOAuthTokens?: boolean;
997
+ };
998
+ /**
999
+ * Verification configuration
1000
+ */
1001
+ verification?: {
1002
+ /**
1003
+ * Change the modelName of the verification table
1004
+ */
1005
+ modelName?: string;
1006
+ /**
1007
+ * Map verification fields
1008
+ */
1009
+ fields?: Partial<Record<keyof OmitId<Verification>, string>>;
1010
+ /**
1011
+ * disable cleaning up expired values when a verification value is
1012
+ * fetched
1013
+ */
1014
+ disableCleanup?: boolean;
1015
+ };
1016
+ /**
1017
+ * List of trusted origins.
1018
+ */
1019
+ trustedOrigins?: string[] | ((request: Request) => string[] | Promise<string[]>);
1020
+ /**
1021
+ * Rate limiting configuration
1022
+ */
1023
+ rateLimit?: BetterAuthRateLimitOptions;
1024
+ /**
1025
+ * Advanced options
1026
+ */
1027
+ advanced?: BetterAuthAdvancedOptions & {
1028
+ /**
1029
+ * @deprecated Please use `database.generateId` instead.
1030
+ */
1031
+ generateId?: never;
1032
+ };
1033
+ logger?: Logger;
1034
+ /**
1035
+ * allows you to define custom hooks that can be
1036
+ * executed during lifecycle of core database
1037
+ * operations.
1038
+ */
1039
+ databaseHooks?: {
1040
+ /**
1041
+ * User hooks
1042
+ */
1043
+ user?: {
1044
+ create?: {
1045
+ /**
1046
+ * Hook that is called before a user is created.
1047
+ * if the hook returns false, the user will not be created.
1048
+ * If the hook returns an object, it'll be used instead of the original data
1049
+ */
1050
+ before?: (user: User & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void | {
1051
+ data: Partial<User> & Record<string, any>;
1052
+ }>;
1053
+ /**
1054
+ * Hook that is called after a user is created.
1055
+ */
1056
+ after?: (user: User & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1057
+ };
1058
+ update?: {
1059
+ /**
1060
+ * Hook that is called before a user is updated.
1061
+ * if the hook returns false, the user will not be updated.
1062
+ * If the hook returns an object, it'll be used instead of the original data
1063
+ */
1064
+ before?: (user: Partial<User> & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void | {
1065
+ data: Partial<User & Record<string, any>>;
1066
+ }>;
1067
+ /**
1068
+ * Hook that is called after a user is updated.
1069
+ */
1070
+ after?: (user: User & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1071
+ };
1072
+ delete?: {
1073
+ /**
1074
+ * Hook that is called before a user is deleted.
1075
+ * if the hook returns false, the user will not be deleted.
1076
+ */
1077
+ before?: (user: User & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void>;
1078
+ /**
1079
+ * Hook that is called after a user is deleted.
1080
+ */
1081
+ after?: (user: User & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1082
+ };
1083
+ };
1084
+ /**
1085
+ * Session Hook
1086
+ */
1087
+ session?: {
1088
+ create?: {
1089
+ /**
1090
+ * Hook that is called before a session is created.
1091
+ * if the hook returns false, the session will not be created.
1092
+ * If the hook returns an object, it'll be used instead of the original data
1093
+ */
1094
+ before?: (session: Session & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void | {
1095
+ data: Partial<Session> & Record<string, any>;
1096
+ }>;
1097
+ /**
1098
+ * Hook that is called after a session is created.
1099
+ */
1100
+ after?: (session: Session & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1101
+ };
1102
+ /**
1103
+ * Update hook
1104
+ */
1105
+ update?: {
1106
+ /**
1107
+ * Hook that is called before a user is updated.
1108
+ * if the hook returns false, the session will not be updated.
1109
+ * If the hook returns an object, it'll be used instead of the original data
1110
+ */
1111
+ before?: (session: Partial<Session> & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void | {
1112
+ data: Partial<Session & Record<string, any>>;
1113
+ }>;
1114
+ /**
1115
+ * Hook that is called after a session is updated.
1116
+ */
1117
+ after?: (session: Session & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1118
+ };
1119
+ delete?: {
1120
+ /**
1121
+ * Hook that is called before a session is deleted.
1122
+ * if the hook returns false, the session will not be deleted.
1123
+ */
1124
+ before?: (session: Session & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void>;
1125
+ /**
1126
+ * Hook that is called after a session is deleted.
1127
+ */
1128
+ after?: (session: Session & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1129
+ };
1130
+ };
1131
+ /**
1132
+ * Account Hook
1133
+ */
1134
+ account?: {
1135
+ create?: {
1136
+ /**
1137
+ * Hook that is called before a account is created.
1138
+ * If the hook returns false, the account will not be created.
1139
+ * If the hook returns an object, it'll be used instead of the original data
1140
+ */
1141
+ before?: (account: Account, context?: GenericEndpointContext) => Promise<boolean | void | {
1142
+ data: Partial<Account> & Record<string, any>;
1143
+ }>;
1144
+ /**
1145
+ * Hook that is called after a account is created.
1146
+ */
1147
+ after?: (account: Account, context?: GenericEndpointContext) => Promise<void>;
1148
+ };
1149
+ /**
1150
+ * Update hook
1151
+ */
1152
+ update?: {
1153
+ /**
1154
+ * Hook that is called before a account is update.
1155
+ * If the hook returns false, the user will not be updated.
1156
+ * If the hook returns an object, it'll be used instead of the original data
1157
+ */
1158
+ before?: (account: Partial<Account> & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void | {
1159
+ data: Partial<Account & Record<string, any>>;
1160
+ }>;
1161
+ /**
1162
+ * Hook that is called after a account is updated.
1163
+ */
1164
+ after?: (account: Account & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1165
+ };
1166
+ delete?: {
1167
+ /**
1168
+ * Hook that is called before an account is deleted.
1169
+ * if the hook returns false, the account will not be deleted.
1170
+ */
1171
+ before?: (account: Account & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void>;
1172
+ /**
1173
+ * Hook that is called after an account is deleted.
1174
+ */
1175
+ after?: (account: Account & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1176
+ };
1177
+ };
1178
+ /**
1179
+ * Verification Hook
1180
+ */
1181
+ verification?: {
1182
+ create?: {
1183
+ /**
1184
+ * Hook that is called before a verification is created.
1185
+ * if the hook returns false, the verification will not be created.
1186
+ * If the hook returns an object, it'll be used instead of the original data
1187
+ */
1188
+ before?: (verification: Verification & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void | {
1189
+ data: Partial<Verification> & Record<string, any>;
1190
+ }>;
1191
+ /**
1192
+ * Hook that is called after a verification is created.
1193
+ */
1194
+ after?: (verification: Verification & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1195
+ };
1196
+ update?: {
1197
+ /**
1198
+ * Hook that is called before a verification is updated.
1199
+ * if the hook returns false, the verification will not be updated.
1200
+ * If the hook returns an object, it'll be used instead of the original data
1201
+ */
1202
+ before?: (verification: Partial<Verification> & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void | {
1203
+ data: Partial<Verification & Record<string, any>>;
1204
+ }>;
1205
+ /**
1206
+ * Hook that is called after a verification is updated.
1207
+ */
1208
+ after?: (verification: Verification & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1209
+ };
1210
+ delete?: {
1211
+ /**
1212
+ * Hook that is called before a verification is deleted.
1213
+ * if the hook returns false, the verification will not be deleted.
1214
+ */
1215
+ before?: (verification: Verification & Record<string, unknown>, context?: GenericEndpointContext) => Promise<boolean | void>;
1216
+ /**
1217
+ * Hook that is called after a verification is deleted.
1218
+ */
1219
+ after?: (verification: Verification & Record<string, unknown>, context?: GenericEndpointContext) => Promise<void>;
1220
+ };
1221
+ };
1222
+ };
1223
+ /**
1224
+ * API error handling
1225
+ */
1226
+ onAPIError?: {
1227
+ /**
1228
+ * Throw an error on API error
1229
+ *
1230
+ * @default false
1231
+ */
1232
+ throw?: boolean;
1233
+ /**
1234
+ * Custom error handler
1235
+ *
1236
+ * @param error
1237
+ * @param ctx - Auth context
1238
+ */
1239
+ onError?: (error: unknown, ctx: AuthContext) => void | Promise<void>;
1240
+ /**
1241
+ * The URL to redirect to on error
1242
+ *
1243
+ * When errorURL is provided, the error will be added to the URL as a query parameter
1244
+ * and the user will be redirected to the errorURL.
1245
+ *
1246
+ * @default - "/api/auth/error"
1247
+ */
1248
+ errorURL?: string;
1249
+ };
1250
+ /**
1251
+ * Hooks
1252
+ */
1253
+ hooks?: {
1254
+ /**
1255
+ * Before a request is processed
1256
+ */
1257
+ before?: AuthMiddleware;
1258
+ /**
1259
+ * After a request is processed
1260
+ */
1261
+ after?: AuthMiddleware;
1262
+ };
1263
+ /**
1264
+ * Disabled paths
1265
+ *
1266
+ * Paths you want to disable.
1267
+ */
1268
+ disabledPaths?: string[];
1269
+ /**
1270
+ * Telemetry configuration
1271
+ */
1272
+ telemetry?: {
1273
+ /**
1274
+ * Enable telemetry collection
1275
+ *
1276
+ * @default false
1277
+ */
1278
+ enabled?: boolean;
1279
+ /**
1280
+ * Enable debug mode
1281
+ *
1282
+ * @default false
1283
+ */
1284
+ debug?: boolean;
1285
+ };
1286
+ };
1287
+ //#endregion
1288
+ //#region src/types/plugin.d.ts
1289
+ type Awaitable<T> = T | Promise<T>;
1290
+ type DeepPartial<T> = T extends Function ? T : T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T;
1291
+ type HookEndpointContext = EndpointContext<string, any> & Omit<InputContext<string, any>, "method"> & {
1292
+ context: AuthContext & {
1293
+ returned?: unknown;
1294
+ responseHeaders?: Headers;
1295
+ };
1296
+ headers?: Headers;
1297
+ };
1298
+ type BetterAuthPlugin = {
1299
+ id: LiteralString;
1300
+ /**
1301
+ * The init function is called when the plugin is initialized.
1302
+ * You can return a new context or modify the existing context.
1303
+ */
1304
+ init?: (ctx: AuthContext) => Awaitable<{
1305
+ context?: DeepPartial<Omit<AuthContext, "options">>;
1306
+ options?: Partial<BetterAuthOptions>;
1307
+ }> | void | Promise<void>;
1308
+ endpoints?: {
1309
+ [key: string]: Endpoint;
1310
+ };
1311
+ middlewares?: {
1312
+ path: string;
1313
+ middleware: Middleware;
1314
+ }[];
1315
+ onRequest?: (request: Request, ctx: AuthContext) => Promise<{
1316
+ response: Response;
1317
+ } | {
1318
+ request: Request;
1319
+ } | void>;
1320
+ onResponse?: (response: Response, ctx: AuthContext) => Promise<{
1321
+ response: Response;
1322
+ } | void>;
1323
+ hooks?: {
1324
+ before?: {
1325
+ matcher: (context: HookEndpointContext) => boolean;
1326
+ handler: AuthMiddleware;
1327
+ }[];
1328
+ after?: {
1329
+ matcher: (context: HookEndpointContext) => boolean;
1330
+ handler: AuthMiddleware;
1331
+ }[];
1332
+ };
1333
+ /**
1334
+ * Schema the plugin needs
1335
+ *
1336
+ * This will also be used to migrate the database. If the fields are dynamic from the plugins
1337
+ * configuration each time the configuration is changed a new migration will be created.
1338
+ *
1339
+ * NOTE: If you want to create migrations manually using
1340
+ * migrations option or any other way you
1341
+ * can disable migration per table basis.
1342
+ *
1343
+ * @example
1344
+ * ```ts
1345
+ * schema: {
1346
+ * user: {
1347
+ * fields: {
1348
+ * email: {
1349
+ * type: "string",
1350
+ * },
1351
+ * emailVerified: {
1352
+ * type: "boolean",
1353
+ * defaultValue: false,
1354
+ * },
1355
+ * },
1356
+ * }
1357
+ * } as AuthPluginSchema
1358
+ * ```
1359
+ */
1360
+ schema?: BetterAuthPluginDBSchema;
1361
+ /**
1362
+ * The migrations of the plugin. If you define schema that will automatically create
1363
+ * migrations for you.
1364
+ *
1365
+ * ⚠️ Only uses this if you dont't want to use the schema option and you disabled migrations for
1366
+ * the tables.
1367
+ */
1368
+ migrations?: Record<string, Migration>;
1369
+ /**
1370
+ * The options of the plugin
1371
+ */
1372
+ options?: Record<string, any> | undefined;
1373
+ /**
1374
+ * types to be inferred
1375
+ */
1376
+ $Infer?: Record<string, any>;
1377
+ /**
1378
+ * The rate limit rules to apply to specific paths.
1379
+ */
1380
+ rateLimit?: {
1381
+ window: number;
1382
+ max: number;
1383
+ pathMatcher: (path: string) => boolean;
1384
+ }[];
1385
+ /**
1386
+ * The error codes returned by the plugin
1387
+ */
1388
+ $ERROR_CODES?: Record<string, string>;
1389
+ };
1390
+ //#endregion
1391
+ //#region src/types/plugin-client.d.ts
1392
+ interface ClientStore {
1393
+ notify: (signal: string) => void;
1394
+ listen: (signal: string, listener: () => void) => void;
1395
+ atoms: Record<string, WritableAtom<any>>;
1396
+ }
1397
+ type ClientAtomListener = {
1398
+ matcher: (path: string) => boolean;
1399
+ signal: "$sessionSignal" | Omit<string, "$sessionSignal">;
1400
+ };
1401
+ interface BetterAuthClientOptions {
1402
+ fetchOptions?: BetterFetchOption;
1403
+ plugins?: BetterAuthClientPlugin[];
1404
+ baseURL?: string;
1405
+ basePath?: string;
1406
+ disableDefaultFetchPlugins?: boolean;
1407
+ $InferAuth?: BetterAuthOptions;
1408
+ }
1409
+ interface BetterAuthClientPlugin {
1410
+ id: LiteralString;
1411
+ /**
1412
+ * only used for type inference. don't pass the
1413
+ * actual plugin
1414
+ */
1415
+ $InferServerPlugin?: BetterAuthPlugin;
1416
+ /**
1417
+ * Custom actions
1418
+ */
1419
+ getActions?: ($fetch: BetterFetch, $store: ClientStore,
1420
+ /**
1421
+ * better-auth client options
1422
+ */
1423
+ options: BetterAuthClientOptions | undefined) => Record<string, any>;
1424
+ /**
1425
+ * State atoms that'll be resolved by each framework
1426
+ * auth store.
1427
+ */
1428
+ getAtoms?: ($fetch: BetterFetch) => Record<string, Atom<any>>;
1429
+ /**
1430
+ * specify path methods for server plugin inferred
1431
+ * endpoints to force a specific method.
1432
+ */
1433
+ pathMethods?: Record<string, "POST" | "GET">;
1434
+ /**
1435
+ * Better fetch plugins
1436
+ */
1437
+ fetchPlugins?: BetterFetchPlugin[];
1438
+ /**
1439
+ * a list of recaller based on a matcher function.
1440
+ * The signal name needs to match a signal in this
1441
+ * plugin or any plugin the user might have added.
1442
+ */
1443
+ atomListeners?: ClientAtomListener[];
1444
+ }
1445
+ //#endregion
1446
+ //#region src/db/adapter/index.d.ts
1447
+ type DBAdapterDebugLogOption = boolean | {
1448
+ /**
1449
+ * Useful when you want to log only certain conditions.
1450
+ */
1451
+ logCondition?: (() => boolean) | undefined;
1452
+ create?: boolean;
1453
+ update?: boolean;
1454
+ updateMany?: boolean;
1455
+ findOne?: boolean;
1456
+ findMany?: boolean;
1457
+ delete?: boolean;
1458
+ deleteMany?: boolean;
1459
+ count?: boolean;
1460
+ } | {
1461
+ /**
1462
+ * Only used for adapter tests to show debug logs if a test fails.
1463
+ *
1464
+ * @deprecated Not actually deprecated. Doing this for IDEs to show this option at the very bottom and stop end-users from using this.
1465
+ */
1466
+ isRunningAdapterTests: boolean;
1467
+ };
1468
+ type DBAdapterSchemaCreation = {
1469
+ /**
1470
+ * Code to be inserted into the file
1471
+ */
1472
+ code: string;
1473
+ /**
1474
+ * Path to the file, including the file name and extension.
1475
+ * Relative paths are supported, with the current working directory of the developer's project as the base.
1476
+ */
1477
+ path: string;
1478
+ /**
1479
+ * Append the file if it already exists.
1480
+ * Note: This will not apply if `overwrite` is set to true.
1481
+ */
1482
+ append?: boolean;
1483
+ /**
1484
+ * Overwrite the file if it already exists
1485
+ */
1486
+ overwrite?: boolean;
1487
+ };
1488
+ interface DBAdapterFactoryConfig<Options extends BetterAuthOptions = BetterAuthOptions> {
1489
+ /**
1490
+ * Use plural table names.
1491
+ *
1492
+ * All tables will be named with an `s` at the end.
1493
+ *
1494
+ * @default false
1495
+ */
1496
+ usePlural?: boolean;
1497
+ /**
1498
+ * Enable debug logs.
1499
+ *
1500
+ * @default false
1501
+ */
1502
+ debugLogs?: DBAdapterDebugLogOption;
1503
+ /**
1504
+ * Name of the adapter.
1505
+ *
1506
+ * This is used to identify the adapter in the debug logs.
1507
+ *
1508
+ * @default `adapterId`
1509
+ */
1510
+ adapterName?: string;
1511
+ /**
1512
+ * Adapter id
1513
+ */
1514
+ adapterId: string;
1515
+ /**
1516
+ * If the database supports numeric ids, set this to `true`.
1517
+ *
1518
+ * @default true
1519
+ */
1520
+ supportsNumericIds?: boolean;
1521
+ /**
1522
+ * If the database doesn't support JSON columns, set this to `false`.
1523
+ *
1524
+ * We will handle the translation between using `JSON` columns, and saving `string`s to the database.
1525
+ *
1526
+ * @default false
1527
+ */
1528
+ supportsJSON?: boolean;
1529
+ /**
1530
+ * If the database doesn't support dates, set this to `false`.
1531
+ *
1532
+ * We will handle the translation between using `Date` objects, and saving `string`s to the database.
1533
+ *
1534
+ * @default true
1535
+ */
1536
+ supportsDates?: boolean;
1537
+ /**
1538
+ * If the database doesn't support booleans, set this to `false`.
1539
+ *
1540
+ * We will handle the translation between using `boolean`s, and saving `0`s and `1`s to the database.
1541
+ *
1542
+ * @default true
1543
+ */
1544
+ supportsBooleans?: boolean;
1545
+ /**
1546
+ * Execute multiple operations in a transaction.
1547
+ *
1548
+ * If the database doesn't support transactions, set this to `false` and operations will be executed sequentially.
1549
+ *
1550
+ * @default false
1551
+ */
1552
+ transaction?: false | (<R>(callback: (trx: DBTransactionAdapter<Options>) => Promise<R>) => Promise<R>);
1553
+ /**
1554
+ * Disable id generation for the `create` method.
1555
+ *
1556
+ * This is useful for databases that don't support custom id values and would auto-generate them for you.
1557
+ *
1558
+ * @default false
1559
+ */
1560
+ disableIdGeneration?: boolean;
1561
+ /**
1562
+ * Map the keys of the input data.
1563
+ *
1564
+ * This is useful for databases that expect a different key name for a given situation.
1565
+ *
1566
+ * For example, MongoDB uses `_id` while in Better-Auth we use `id`.
1567
+ *
1568
+ *
1569
+ * @example
1570
+ * Each key represents the old key to replace.
1571
+ * The value represents the new key
1572
+ *
1573
+ * This can be a partial object that only transforms some keys.
1574
+ *
1575
+ * ```ts
1576
+ * mapKeysTransformInput: {
1577
+ * id: "_id" // We want to replace `id` to `_id` to save into MongoDB
1578
+ * }
1579
+ * ```
1580
+ */
1581
+ mapKeysTransformInput?: Record<string, string>;
1582
+ /**
1583
+ * Map the keys of the output data.
1584
+ *
1585
+ * This is useful for databases that expect a different key name for a given situation.
1586
+ *
1587
+ * For example, MongoDB uses `_id` while in Better-Auth we use `id`.
1588
+ *
1589
+ * @example
1590
+ * Each key represents the old key to replace.
1591
+ * The value represents the new key
1592
+ *
1593
+ * This can be a partial object that only transforms some keys.
1594
+ *
1595
+ * ```ts
1596
+ * mapKeysTransformOutput: {
1597
+ * _id: "id" // In MongoDB, we save `id` as `_id`. So we want to replace `_id` with `id` when we get the data back.
1598
+ * }
1599
+ * ```
1600
+ */
1601
+ mapKeysTransformOutput?: Record<string, string>;
1602
+ /**
1603
+ * Custom transform input function.
1604
+ *
1605
+ * This function is used to transform the input data before it is saved to the database.
1606
+ */
1607
+ customTransformInput?: (props: {
1608
+ data: any;
1609
+ /**
1610
+ * The fields of the model.
1611
+ */
1612
+ fieldAttributes: DBFieldAttribute;
1613
+ /**
1614
+ * The field to transform.
1615
+ */
1616
+ field: string;
1617
+ /**
1618
+ * The action which was called from the adapter.
1619
+ */
1620
+ action: "create" | "update";
1621
+ /**
1622
+ * The model name.
1623
+ */
1624
+ model: string;
1625
+ /**
1626
+ * The schema of the user's Better-Auth instance.
1627
+ */
1628
+ schema: BetterAuthDBSchema;
1629
+ /**
1630
+ * The options of the user's Better-Auth instance.
1631
+ */
1632
+ options: Options;
1633
+ }) => any;
1634
+ /**
1635
+ * Custom transform output function.
1636
+ *
1637
+ * This function is used to transform the output data before it is returned to the user.
1638
+ */
1639
+ customTransformOutput?: (props: {
1640
+ data: any;
1641
+ /**
1642
+ * The fields of the model.
1643
+ */
1644
+ fieldAttributes: DBFieldAttribute;
1645
+ /**
1646
+ * The field to transform.
1647
+ */
1648
+ field: string;
1649
+ /**
1650
+ * The fields to select.
1651
+ */
1652
+ select: string[];
1653
+ /**
1654
+ * The model name.
1655
+ */
1656
+ model: string;
1657
+ /**
1658
+ * The schema of the user's Better-Auth instance.
1659
+ */
1660
+ schema: BetterAuthDBSchema;
1661
+ /**
1662
+ * The options of the user's Better-Auth instance.
1663
+ */
1664
+ options: Options;
1665
+ }) => any;
1666
+ /**
1667
+ * Custom ID generator function.
1668
+ *
1669
+ * By default, we can handle ID generation for you, however if the database your adapter is for only supports a specific custom id generation,
1670
+ * then you can use this function to generate your own IDs.
1671
+ *
1672
+ *
1673
+ * Notes:
1674
+ * - If the user enabled `useNumberId`, then this option will be ignored. Unless this adapter config has `supportsNumericIds` set to `false`.
1675
+ * - If `generateId` is `false` in the user's Better-Auth config, then this option will be ignored.
1676
+ * - If `generateId` is a function, then it will override this option.
1677
+ *
1678
+ * @example
1679
+ *
1680
+ * ```ts
1681
+ * customIdGenerator: ({ model }) => {
1682
+ * return "my-super-unique-id";
1683
+ * }
1684
+ * ```
1685
+ */
1686
+ customIdGenerator?: (props: {
1687
+ model: string;
1688
+ }) => string;
1689
+ /**
1690
+ * Whether to disable the transform output.
1691
+ * Do not use this option unless you know what you are doing.
1692
+ * @default false
1693
+ */
1694
+ disableTransformOutput?: boolean;
1695
+ /**
1696
+ * Whether to disable the transform input.
1697
+ * Do not use this option unless you know what you are doing.
1698
+ * @default false
1699
+ */
1700
+ disableTransformInput?: boolean;
1701
+ }
1702
+ type Where = {
1703
+ /**
1704
+ * @default eq
1705
+ */
1706
+ operator?: "eq" | "ne" | "lt" | "lte" | "gt" | "gte" | "in" | "not_in" | "contains" | "starts_with" | "ends_with";
1707
+ value: string | number | boolean | string[] | number[] | Date | null;
1708
+ field: string;
1709
+ /**
1710
+ * @default AND
1711
+ */
1712
+ connector?: "AND" | "OR";
1713
+ };
1714
+ type DBTransactionAdapter<Options extends BetterAuthOptions = BetterAuthOptions> = Omit<DBAdapter<Options>, "transaction">;
1715
+ type DBAdapter<Options extends BetterAuthOptions = BetterAuthOptions> = {
1716
+ id: string;
1717
+ create: <T extends Record<string, any>, R = T>(data: {
1718
+ model: string;
1719
+ data: Omit<T, "id">;
1720
+ select?: string[];
1721
+ /**
1722
+ * By default, any `id` provided in `data` will be ignored.
1723
+ *
1724
+ * If you want to force the `id` to be the same as the `data.id`, set this to `true`.
1725
+ */
1726
+ forceAllowId?: boolean;
1727
+ }) => Promise<R>;
1728
+ findOne: <T>(data: {
1729
+ model: string;
1730
+ where: Where[];
1731
+ select?: string[];
1732
+ }) => Promise<T | null>;
1733
+ findMany: <T>(data: {
1734
+ model: string;
1735
+ where?: Where[];
1736
+ limit?: number;
1737
+ sortBy?: {
1738
+ field: string;
1739
+ direction: "asc" | "desc";
1740
+ };
1741
+ offset?: number;
1742
+ }) => Promise<T[]>;
1743
+ count: (data: {
1744
+ model: string;
1745
+ where?: Where[];
1746
+ }) => Promise<number>;
1747
+ /**
1748
+ * ⚠︎ Update may not return the updated data
1749
+ * if multiple where clauses are provided
1750
+ */
1751
+ update: <T>(data: {
1752
+ model: string;
1753
+ where: Where[];
1754
+ update: Record<string, any>;
1755
+ }) => Promise<T | null>;
1756
+ updateMany: (data: {
1757
+ model: string;
1758
+ where: Where[];
1759
+ update: Record<string, any>;
1760
+ }) => Promise<number>;
1761
+ delete: <T>(data: {
1762
+ model: string;
1763
+ where: Where[];
1764
+ }) => Promise<void>;
1765
+ deleteMany: (data: {
1766
+ model: string;
1767
+ where: Where[];
1768
+ }) => Promise<number>;
1769
+ /**
1770
+ * Execute multiple operations in a transaction.
1771
+ * If the adapter doesn't support transactions, operations will be executed sequentially.
1772
+ */
1773
+ transaction: <R>(callback: (trx: DBTransactionAdapter<Options>) => Promise<R>) => Promise<R>;
1774
+ /**
1775
+ *
1776
+ * @param options
1777
+ * @param file - file path if provided by the user
1778
+ */
1779
+ createSchema?: (options: Options, file?: string) => Promise<DBAdapterSchemaCreation>;
1780
+ options?: {
1781
+ adapterConfig: DBAdapterFactoryConfig<Options>;
1782
+ } & CustomAdapter["options"];
1783
+ };
1784
+ type CleanedWhere = Required<Where>;
1785
+ interface CustomAdapter {
1786
+ create: <T extends Record<string, any>>({
1787
+ data,
1788
+ model,
1789
+ select
1790
+ }: {
1791
+ model: string;
1792
+ data: T;
1793
+ select?: string[];
1794
+ }) => Promise<T>;
1795
+ update: <T>(data: {
1796
+ model: string;
1797
+ where: CleanedWhere[];
1798
+ update: T;
1799
+ }) => Promise<T | null>;
1800
+ updateMany: (data: {
1801
+ model: string;
1802
+ where: CleanedWhere[];
1803
+ update: Record<string, any>;
1804
+ }) => Promise<number>;
1805
+ findOne: <T>({
1806
+ model,
1807
+ where,
1808
+ select
1809
+ }: {
1810
+ model: string;
1811
+ where: CleanedWhere[];
1812
+ select?: string[];
1813
+ }) => Promise<T | null>;
1814
+ findMany: <T>({
1815
+ model,
1816
+ where,
1817
+ limit,
1818
+ sortBy,
1819
+ offset
1820
+ }: {
1821
+ model: string;
1822
+ where?: CleanedWhere[];
1823
+ limit: number;
1824
+ sortBy?: {
1825
+ field: string;
1826
+ direction: "asc" | "desc";
1827
+ };
1828
+ offset?: number;
1829
+ }) => Promise<T[]>;
1830
+ delete: ({
1831
+ model,
1832
+ where
1833
+ }: {
1834
+ model: string;
1835
+ where: CleanedWhere[];
1836
+ }) => Promise<void>;
1837
+ deleteMany: ({
1838
+ model,
1839
+ where
1840
+ }: {
1841
+ model: string;
1842
+ where: CleanedWhere[];
1843
+ }) => Promise<number>;
1844
+ count: ({
1845
+ model,
1846
+ where
1847
+ }: {
1848
+ model: string;
1849
+ where?: CleanedWhere[];
1850
+ }) => Promise<number>;
1851
+ createSchema?: (props: {
1852
+ /**
1853
+ * The file the user may have passed in to the `generate` command as the expected schema file output path.
1854
+ */
1855
+ file?: string;
1856
+ /**
1857
+ * The tables from the user's Better-Auth instance schema.
1858
+ */
1859
+ tables: BetterAuthDBSchema;
1860
+ }) => Promise<DBAdapterSchemaCreation>;
1861
+ /**
1862
+ * Your adapter's options.
1863
+ */
1864
+ options?: Record<string, any> | undefined;
1865
+ }
1866
+ interface DBAdapterInstance<Options extends BetterAuthOptions = BetterAuthOptions> {
1867
+ (options: BetterAuthOptions): DBAdapter<Options>;
1868
+ }
1869
+ //#endregion
1870
+ export { AuthContext, AuthEndpoint, AuthMiddleware, BetterAuthAdvancedOptions, BetterAuthClientOptions, BetterAuthClientPlugin, BetterAuthCookies, BetterAuthOptions, BetterAuthPlugin, BetterAuthRateLimitOptions, CleanedWhere, ClientAtomListener, ClientStore, CustomAdapter, DBAdapter, DBAdapterDebugLogOption, DBAdapterFactoryConfig, DBAdapterInstance, DBAdapterSchemaCreation, DBTransactionAdapter, GenerateIdFn, GenericEndpointContext, InternalAdapter, Where, createAuthEndpoint, createAuthMiddleware, optionsMiddleware };