better-auth 1.7.4 → 1.7.6

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 (46) hide show
  1. package/dist/api/index.d.mts +6 -6
  2. package/dist/api/routes/account.d.mts +1 -1
  3. package/dist/api/routes/callback.mjs +16 -64
  4. package/dist/api/routes/password.mjs +3 -5
  5. package/dist/api/routes/sign-in.d.mts +2 -2
  6. package/dist/api/routes/sign-in.mjs +2 -0
  7. package/dist/api/routes/sign-up.mjs +3 -10
  8. package/dist/api/routes/update-user.mjs +7 -20
  9. package/dist/client/config.d.mts +2 -2
  10. package/dist/client/query-atom.mjs +13 -0
  11. package/dist/client/query.mjs +37 -27
  12. package/dist/client/react/react-store.mjs +2 -1
  13. package/dist/client/session-atom.mjs +2 -1
  14. package/dist/context/create-context.mjs +3 -2
  15. package/dist/cookies/index.d.mts +3 -2
  16. package/dist/cookies/index.mjs +15 -36
  17. package/dist/db/get-migration.mjs +81 -60
  18. package/dist/oauth2/index.d.mts +2 -2
  19. package/dist/oauth2/index.mjs +2 -2
  20. package/dist/oauth2/link-account.d.mts +42 -14
  21. package/dist/oauth2/link-account.mjs +61 -1
  22. package/dist/package.mjs +1 -1
  23. package/dist/plugins/admin/admin.d.mts +3 -3
  24. package/dist/plugins/admin/admin.mjs +3 -1
  25. package/dist/plugins/admin/routes.mjs +4 -10
  26. package/dist/plugins/admin/types.d.mts +4 -1
  27. package/dist/plugins/captcha/constants.d.mts +1 -0
  28. package/dist/plugins/captcha/constants.mjs +2 -1
  29. package/dist/plugins/captcha/index.d.mts +2 -2
  30. package/dist/plugins/captcha/index.mjs +7 -0
  31. package/dist/plugins/captcha/types.d.mts +44 -2
  32. package/dist/plugins/captcha/utils.mjs +11 -1
  33. package/dist/plugins/captcha/verify-handlers/cloudflare-turnstile.mjs +27 -8
  34. package/dist/plugins/captcha/verify-handlers/vercel-botid.mjs +27 -0
  35. package/dist/plugins/email-otp/routes.mjs +3 -4
  36. package/dist/plugins/index.d.mts +2 -2
  37. package/dist/plugins/oauth-proxy/index.mjs +19 -5
  38. package/dist/plugins/organization/routes/crud-members.d.mts +3 -3
  39. package/dist/plugins/organization/schema.d.mts +2 -2
  40. package/dist/plugins/phone-number/routes.mjs +4 -4
  41. package/dist/plugins/username/index.d.mts +4 -4
  42. package/dist/plugins/username/index.mjs +2 -0
  43. package/dist/plugins/username/schema.d.mts +4 -4
  44. package/dist/test-utils/http-test-instance.d.mts +2 -2
  45. package/dist/utils/password.mjs +16 -2
  46. package/package.json +10 -13
@@ -93,7 +93,7 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
93
93
  callbackURL: _$zod.ZodOptional<_$zod.ZodString>;
94
94
  newUserCallbackURL: _$zod.ZodOptional<_$zod.ZodString>;
95
95
  errorCallbackURL: _$zod.ZodOptional<_$zod.ZodString>;
96
- provider: _$zod.ZodType<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
96
+ provider: _$zod.ZodType<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
97
97
  disableRedirect: _$zod.ZodOptional<_$zod.ZodBoolean>;
98
98
  idToken: _$zod.ZodOptional<_$zod.ZodObject<{
99
99
  token: _$zod.ZodString;
@@ -121,7 +121,7 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
121
121
  callbackURL: _$zod.ZodOptional<_$zod.ZodString>;
122
122
  newUserCallbackURL: _$zod.ZodOptional<_$zod.ZodString>;
123
123
  errorCallbackURL: _$zod.ZodOptional<_$zod.ZodString>;
124
- provider: _$zod.ZodType<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
124
+ provider: _$zod.ZodType<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
125
125
  disableRedirect: _$zod.ZodOptional<_$zod.ZodBoolean>;
126
126
  idToken: _$zod.ZodOptional<_$zod.ZodObject<{
127
127
  token: _$zod.ZodString;
@@ -1592,7 +1592,7 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
1592
1592
  requireHeaders: true;
1593
1593
  body: _$zod.ZodObject<{
1594
1594
  callbackURL: _$zod.ZodOptional<_$zod.ZodString>;
1595
- provider: _$zod.ZodType<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
1595
+ provider: _$zod.ZodType<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
1596
1596
  idToken: _$zod.ZodOptional<_$zod.ZodObject<{
1597
1597
  token: _$zod.ZodString;
1598
1598
  nonce: _$zod.ZodOptional<_$zod.ZodString>;
@@ -2107,7 +2107,7 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
2107
2107
  callbackURL: _$zod.ZodOptional<_$zod.ZodString>;
2108
2108
  newUserCallbackURL: _$zod.ZodOptional<_$zod.ZodString>;
2109
2109
  errorCallbackURL: _$zod.ZodOptional<_$zod.ZodString>;
2110
- provider: _$zod.ZodType<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
2110
+ provider: _$zod.ZodType<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
2111
2111
  disableRedirect: _$zod.ZodOptional<_$zod.ZodBoolean>;
2112
2112
  idToken: _$zod.ZodOptional<_$zod.ZodObject<{
2113
2113
  token: _$zod.ZodString;
@@ -2135,7 +2135,7 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
2135
2135
  callbackURL: _$zod.ZodOptional<_$zod.ZodString>;
2136
2136
  newUserCallbackURL: _$zod.ZodOptional<_$zod.ZodString>;
2137
2137
  errorCallbackURL: _$zod.ZodOptional<_$zod.ZodString>;
2138
- provider: _$zod.ZodType<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
2138
+ provider: _$zod.ZodType<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
2139
2139
  disableRedirect: _$zod.ZodOptional<_$zod.ZodBoolean>;
2140
2140
  idToken: _$zod.ZodOptional<_$zod.ZodObject<{
2141
2141
  token: _$zod.ZodString;
@@ -3606,7 +3606,7 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
3606
3606
  requireHeaders: true;
3607
3607
  body: _$zod.ZodObject<{
3608
3608
  callbackURL: _$zod.ZodOptional<_$zod.ZodString>;
3609
- provider: _$zod.ZodType<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
3609
+ provider: _$zod.ZodType<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, _$zod_v4_core0.$ZodTypeInternals<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
3610
3610
  idToken: _$zod.ZodOptional<_$zod.ZodObject<{
3611
3611
  token: _$zod.ZodString;
3612
3612
  nonce: _$zod.ZodOptional<_$zod.ZodString>;
@@ -92,7 +92,7 @@ declare const linkSocialAccount: _$better_call0.StrictEndpoint<"/link-social", {
92
92
  requireHeaders: true;
93
93
  body: z.ZodObject<{
94
94
  callbackURL: z.ZodOptional<z.ZodString>;
95
- provider: z.ZodType<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, z.core.$ZodTypeInternals<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
95
+ provider: z.ZodType<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, z.core.$ZodTypeInternals<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
96
96
  idToken: z.ZodOptional<z.ZodObject<{
97
97
  token: z.ZodString;
98
98
  nonce: z.ZodOptional<z.ZodString>;
@@ -1,14 +1,12 @@
1
1
  import { isAPIError } from "../../utils/is-api-error.mjs";
2
2
  import { setSessionCookie } from "../../cookies/index.mjs";
3
- import { assertValidUserInfo } from "../../utils/validate-user-info.mjs";
4
3
  import { getAwaitableValue } from "../../context/helpers.mjs";
5
4
  import { resolveOAuthAccountKey, toOAuthProfileRecord } from "../../oauth2/account-key.mjs";
6
5
  import { OAUTH_CALLBACK_ERROR_CODES, missingEmailLogMessage } from "../../oauth2/errors.mjs";
7
- import { getOAuthCallbackPath, setTokenUtil } from "../../oauth2/utils.mjs";
8
- import { applyUpdateUserInfoOnLink, handleOAuthUserInfo } from "../../oauth2/link-account.mjs";
6
+ import { getOAuthCallbackPath } from "../../oauth2/utils.mjs";
7
+ import { handleOAuthUserInfo, linkOAuthAccount } from "../../oauth2/link-account.mjs";
9
8
  import { generateIdTokenNonce, generateState, parseState } from "../../oauth2/state.mjs";
10
9
  import { HIDE_METADATA } from "../../utils/hide-metadata.mjs";
11
- import { mergeScopes } from "@better-auth/core/oauth2";
12
10
  import { safeJSONParse } from "@better-auth/core/utils/json";
13
11
  import { appendQueryParams } from "@better-auth/core/utils/url";
14
12
  import { createAuthEndpoint } from "@better-auth/core/api";
@@ -149,72 +147,26 @@ const callbackOAuth = createAuthEndpoint("/callback/:id", {
149
147
  c.context.logger.error("No callback URL found");
150
148
  throw redirectOnError(OAUTH_CALLBACK_ERROR_CODES.NO_CALLBACK_URL);
151
149
  }
150
+ const accountData = {
151
+ ...accountKey,
152
+ ...tokens,
153
+ scope: tokens.scopes?.join(",")
154
+ };
152
155
  if (link) {
153
- try {
154
- await assertValidUserInfo(c, {
155
- user: {
156
- ...userInfo,
157
- id: link.userId,
158
- email: userInfo.email ?? void 0
159
- },
160
- source: {
161
- action: "link-account",
162
- method: "oauth",
163
- oauth: {
164
- providerId: provider.id,
165
- profile: providerProfile
166
- }
167
- }
168
- });
169
- } catch (e) {
170
- if (isAPIError(e) && e.body?.code) throw redirectOnError(e.body.code, e.body.message);
171
- throw e;
172
- }
173
- if (!c.context.trustedProviders.includes(provider.id) && !userInfo.emailVerified || c.context.options.account?.accountLinking?.enabled === false) {
174
- c.context.logger.error("Unable to link account - untrusted provider");
175
- return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.UNABLE_TO_LINK_ACCOUNT);
176
- }
177
- if (userInfo.email?.toLowerCase() !== link.email.toLowerCase() && c.context.options.account?.accountLinking?.allowDifferentEmails !== true) return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.EMAIL_DOES_NOT_MATCH);
178
- const existingAccount = await c.context.internalAdapter.findAccountByKey(accountKey);
179
- if (existingAccount) {
180
- if (existingAccount.userId.toString() !== link.userId.toString()) return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.ACCOUNT_ALREADY_LINKED_TO_DIFFERENT_USER);
181
- const mergedScope = mergeScopes(existingAccount.scope, tokens.scopes);
182
- const updateData = Object.fromEntries(Object.entries({
183
- providerId: provider.id,
184
- accessToken: await setTokenUtil(tokens.accessToken, c.context),
185
- refreshToken: await setTokenUtil(tokens.refreshToken, c.context),
186
- idToken: tokens.idToken,
187
- accessTokenExpiresAt: tokens.accessTokenExpiresAt,
188
- refreshTokenExpiresAt: tokens.refreshTokenExpiresAt,
189
- scope: mergedScope || void 0
190
- }).filter(([_, value]) => value !== void 0));
191
- await c.context.internalAdapter.updateAccount(existingAccount.id, updateData);
192
- } else if (!await c.context.internalAdapter.createAccount({
193
- userId: link.userId,
194
- ...accountKey,
195
- ...tokens,
196
- accessToken: await setTokenUtil(tokens.accessToken, c.context),
197
- refreshToken: await setTokenUtil(tokens.refreshToken, c.context),
198
- scope: tokens.scopes?.join(",")
199
- })) return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.UNABLE_TO_LINK_ACCOUNT);
200
- await applyUpdateUserInfoOnLink(c, link.userId, userInfo);
201
- let toRedirectTo;
202
- try {
203
- toRedirectTo = callbackURL.toString();
204
- } catch {
205
- toRedirectTo = callbackURL;
206
- }
207
- throw c.redirect(toRedirectTo);
156
+ const linkResult = await linkOAuthAccount(c, {
157
+ link,
158
+ userInfo,
159
+ account: accountData,
160
+ profile: providerProfile,
161
+ scopes: tokens.scopes
162
+ });
163
+ if (!linkResult.linked) return redirectOnError(linkResult.error.code, linkResult.error.message);
164
+ throw c.redirect(callbackURL);
208
165
  }
209
166
  if (!userInfo.email) {
210
167
  c.context.logger.error(missingEmailLogMessage(provider.id));
211
168
  return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.EMAIL_NOT_FOUND);
212
169
  }
213
- const accountData = {
214
- ...accountKey,
215
- ...tokens,
216
- scope: tokens.scopes?.join(",")
217
- };
218
170
  let result;
219
171
  try {
220
172
  result = await handleOAuthUserInfo(c, {
@@ -1,7 +1,7 @@
1
1
  import { originCheck } from "../middlewares/origin-check.mjs";
2
2
  import { getDate } from "../../utils/date.mjs";
3
3
  import { sensitiveSessionMiddleware } from "./session.mjs";
4
- import { validatePassword } from "../../utils/password.mjs";
4
+ import { assertPasswordNotTooLong, assertPasswordNotTooShort, validatePassword } from "../../utils/password.mjs";
5
5
  import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
6
6
  import { generateId } from "@better-auth/core/utils/id";
7
7
  import { createAuthEndpoint } from "@better-auth/core/api";
@@ -149,10 +149,8 @@ const resetPassword = createAuthEndpoint("/reset-password", {
149
149
  const token = ctx.body.token || ctx.query?.token;
150
150
  if (!token) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_TOKEN);
151
151
  const { newPassword } = ctx.body;
152
- const minLength = ctx.context.password?.config.minPasswordLength;
153
- const maxLength = ctx.context.password?.config.maxPasswordLength;
154
- if (newPassword.length < minLength) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);
155
- if (newPassword.length > maxLength) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_LONG);
152
+ assertPasswordNotTooShort(ctx, newPassword);
153
+ assertPasswordNotTooLong(ctx, newPassword);
156
154
  const id = `reset-password:${token}`;
157
155
  const verification = await ctx.context.internalAdapter.consumeVerificationValue(id);
158
156
  if (!verification) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_TOKEN);
@@ -8,7 +8,7 @@ declare const socialSignInBodySchema: z.ZodObject<{
8
8
  callbackURL: z.ZodOptional<z.ZodString>;
9
9
  newUserCallbackURL: z.ZodOptional<z.ZodString>;
10
10
  errorCallbackURL: z.ZodOptional<z.ZodString>;
11
- provider: z.ZodType<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, z.core.$ZodTypeInternals<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
11
+ provider: z.ZodType<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, z.core.$ZodTypeInternals<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
12
12
  disableRedirect: z.ZodOptional<z.ZodBoolean>;
13
13
  idToken: z.ZodOptional<z.ZodObject<{
14
14
  token: z.ZodString;
@@ -37,7 +37,7 @@ declare const signInSocial: <O extends BetterAuthOptions>() => _$better_call0.St
37
37
  callbackURL: z.ZodOptional<z.ZodString>;
38
38
  newUserCallbackURL: z.ZodOptional<z.ZodString>;
39
39
  errorCallbackURL: z.ZodOptional<z.ZodString>;
40
- provider: z.ZodType<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, z.core.$ZodTypeInternals<(string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
40
+ provider: z.ZodType<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown, z.core.$ZodTypeInternals<(string & {}) | "github" | "apple" | "atlassian" | "cloudflare" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat", unknown>>;
41
41
  disableRedirect: z.ZodOptional<z.ZodBoolean>;
42
42
  idToken: z.ZodOptional<z.ZodObject<{
43
43
  token: z.ZodString;
@@ -9,6 +9,7 @@ import { handleOAuthUserInfo } from "../../oauth2/link-account.mjs";
9
9
  import { generateIdTokenNonce, generateState } from "../../oauth2/state.mjs";
10
10
  import { safeCloneRequest } from "../../utils/request.mjs";
11
11
  import { createEmailVerificationToken } from "./email-verification.mjs";
12
+ import { assertPasswordNotTooLong } from "../../utils/password.mjs";
12
13
  import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
13
14
  import { additionalAuthorizationParamsSchema, supportsIdTokenSignIn, verifyProviderIdToken } from "@better-auth/core/oauth2";
14
15
  import { SocialProviderListEnum } from "@better-auth/core/social-providers";
@@ -312,6 +313,7 @@ const signInEmail = () => createAuthEndpoint("/sign-in/email", {
312
313
  }
313
314
  const { email, password } = ctx.body;
314
315
  if (!z.email().safeParse(email).success) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_EMAIL);
316
+ assertPasswordNotTooLong(ctx, password);
315
317
  const userRecord = await ctx.context.internalAdapter.findUserByEmail(email.toLowerCase(), { includeAccounts: true });
316
318
  const credentialAccount = userRecord?.accounts.find((account) => account.providerId === "credential" && account.accountId === userRecord.user.id);
317
319
  if (!userRecord || !credentialAccount) {
@@ -4,6 +4,7 @@ import { buildSyntheticUserOutput, parseUserInput, parseUserOutput } from "../..
4
4
  import { setSessionCookie } from "../../cookies/index.mjs";
5
5
  import { safeCloneRequest } from "../../utils/request.mjs";
6
6
  import { createEmailVerificationToken } from "./email-verification.mjs";
7
+ import { assertPasswordNotTooLong, assertPasswordNotTooShort } from "../../utils/password.mjs";
7
8
  import { runWithTransaction } from "@better-auth/core/context";
8
9
  import { isDevelopment } from "@better-auth/core/env";
9
10
  import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
@@ -149,16 +150,8 @@ const signUpEmail = () => createAuthEndpoint("/sign-up/email", {
149
150
  const { name, email, password, image, callbackURL: _callbackURL, rememberMe, ...rest } = body;
150
151
  if (!z.email().safeParse(email).success) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_EMAIL);
151
152
  if (!password || typeof password !== "string") throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_PASSWORD);
152
- const minPasswordLength = ctx.context.password.config.minPasswordLength;
153
- if (password.length < minPasswordLength) {
154
- ctx.context.logger.warn("Password is too short");
155
- throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);
156
- }
157
- const maxPasswordLength = ctx.context.password.config.maxPasswordLength;
158
- if (password.length > maxPasswordLength) {
159
- ctx.context.logger.warn("Password is too long");
160
- throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_LONG);
161
- }
153
+ assertPasswordNotTooShort(ctx, password);
154
+ assertPasswordNotTooLong(ctx, password);
162
155
  const shouldReturnGenericDuplicateResponse = ctx.context.options.emailAndPassword.requireEmailVerification || ctx.context.options.emailAndPassword.autoSignIn === false;
163
156
  const shouldSkipAutoSignIn = ctx.context.options.emailAndPassword.autoSignIn === false || shouldReturnGenericDuplicateResponse;
164
157
  const additionalUserFields = parseUserInput(ctx.context.options, rest, "create");
@@ -4,6 +4,7 @@ import { generateRandomString } from "../../crypto/random.mjs";
4
4
  import { deleteSessionCookie, setSessionCookie } from "../../cookies/index.mjs";
5
5
  import { getSessionFromCtx, isStateful, sensitiveSessionMiddleware, sessionMiddleware } from "./session.mjs";
6
6
  import { createEmailVerificationToken } from "./email-verification.mjs";
7
+ import { assertPasswordNotTooLong, assertPasswordNotTooShort } from "../../utils/password.mjs";
7
8
  import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
8
9
  import { createAuthEndpoint } from "@better-auth/core/api";
9
10
  import * as z from "zod";
@@ -158,16 +159,9 @@ const changePassword = createAuthEndpoint("/change-password", {
158
159
  }, async (ctx) => {
159
160
  const { newPassword, currentPassword, revokeOtherSessions } = ctx.body;
160
161
  const session = ctx.context.session;
161
- const minPasswordLength = ctx.context.password.config.minPasswordLength;
162
- if (newPassword.length < minPasswordLength) {
163
- ctx.context.logger.warn("Password is too short");
164
- throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);
165
- }
166
- const maxPasswordLength = ctx.context.password.config.maxPasswordLength;
167
- if (newPassword.length > maxPasswordLength) {
168
- ctx.context.logger.warn("Password is too long");
169
- throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_LONG);
170
- }
162
+ assertPasswordNotTooShort(ctx, newPassword);
163
+ assertPasswordNotTooLong(ctx, newPassword);
164
+ assertPasswordNotTooLong(ctx, currentPassword);
171
165
  const account = await ctx.context.internalAdapter.findCredentialAccount(session.user.id);
172
166
  if (!account || !account.password) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.CREDENTIAL_ACCOUNT_NOT_FOUND);
173
167
  const passwordHash = await ctx.context.password.hash(newPassword);
@@ -203,16 +197,8 @@ newPassword: z.string().meta({ description: "The new password to set is required
203
197
  }, async (ctx) => {
204
198
  const { newPassword } = ctx.body;
205
199
  const session = ctx.context.session;
206
- const minPasswordLength = ctx.context.password.config.minPasswordLength;
207
- if (newPassword.length < minPasswordLength) {
208
- ctx.context.logger.warn("Password is too short");
209
- throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);
210
- }
211
- const maxPasswordLength = ctx.context.password.config.maxPasswordLength;
212
- if (newPassword.length > maxPasswordLength) {
213
- ctx.context.logger.warn("Password is too long");
214
- throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_LONG);
215
- }
200
+ assertPasswordNotTooShort(ctx, newPassword);
201
+ assertPasswordNotTooLong(ctx, newPassword);
216
202
  const account = await ctx.context.internalAdapter.findCredentialAccount(session.user.id);
217
203
  const passwordHash = await ctx.context.password.hash(newPassword);
218
204
  if (!account) {
@@ -295,6 +281,7 @@ const deleteUser = createAuthEndpoint("/delete-user", {
295
281
  }
296
282
  const session = ctx.context.session;
297
283
  if (ctx.body.password) {
284
+ assertPasswordNotTooLong(ctx, ctx.body.password);
298
285
  const account = await ctx.context.internalAdapter.findCredentialAccount(session.user.id);
299
286
  if (!account || !account.password) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.CREDENTIAL_ACCOUNT_NOT_FOUND);
300
287
  if (!await ctx.context.password.verify({
@@ -30,17 +30,17 @@ declare const getClientConfig: (options?: BetterAuthClientOptions | undefined, l
30
30
  onResponse: ((context: _$_better_fetch_fetch0.ResponseContext) => Promise<Response | void | _$_better_fetch_fetch0.ResponseContext> | Response | _$_better_fetch_fetch0.ResponseContext | void) | undefined;
31
31
  };
32
32
  })[];
33
- priority?: RequestPriority | undefined;
34
33
  cache?: RequestCache | undefined;
35
34
  credentials?: RequestCredentials;
36
35
  integrity?: string | undefined;
37
36
  keepalive?: boolean | undefined;
38
37
  method: string;
39
38
  mode?: RequestMode | undefined;
39
+ priority?: RequestPriority | undefined;
40
40
  redirect?: RequestRedirect | undefined;
41
41
  referrer?: string | undefined;
42
42
  referrerPolicy?: ReferrerPolicy | undefined;
43
- signal?: (AbortSignal | null) | undefined;
43
+ signal?: AbortSignal | null;
44
44
  window?: null | undefined;
45
45
  onRetry?: ((response: _$_better_fetch_fetch0.ResponseContext) => Promise<void> | void) | undefined;
46
46
  hookOptions?: {
@@ -0,0 +1,13 @@
1
+ import { atom } from "nanostores";
2
+ //#region src/client/query-atom.ts
3
+ const kAuthQuery = Symbol.for("better-auth:auth-query");
4
+ function isAuthQueryStore(store) {
5
+ return kAuthQuery in store && store[kAuthQuery] === true;
6
+ }
7
+ function createAuthQueryAtom(initialValue) {
8
+ const queryAtom = atom(initialValue);
9
+ Object.defineProperty(queryAtom, kAuthQuery, { value: true });
10
+ return queryAtom;
11
+ }
12
+ //#endregion
13
+ export { createAuthQueryAtom, isAuthQueryStore };
@@ -1,12 +1,13 @@
1
1
  import { isJsonEqual, withEquality } from "./equality.mjs";
2
- import { atom, onMount } from "nanostores";
2
+ import { createAuthQueryAtom } from "./query-atom.mjs";
3
+ import { onMount } from "nanostores";
3
4
  //#region src/client/query.ts
4
5
  const isServer = () => typeof window === "undefined";
5
6
  function isAuthQueryStateEqual(a, b) {
6
7
  return isJsonEqual(a.data, b.data) && a.error === b.error && a.isPending === b.isPending && a.isRefetching === b.isRefetching && a.refetch === b.refetch;
7
8
  }
8
9
  const useAuthQuery = (initializedAtom, path, $fetch, options) => {
9
- const value = atom({
10
+ const value = createAuthQueryAtom({
10
11
  data: null,
11
12
  error: null,
12
13
  isPending: true,
@@ -14,7 +15,9 @@ const useAuthQuery = (initializedAtom, path, $fetch, options) => {
14
15
  refetch: (queryParams) => fn(queryParams)
15
16
  });
16
17
  onMount(value, () => withEquality(value, isAuthQueryStateEqual));
18
+ let latestRequestId = 0;
17
19
  const fn = async (queryParams) => {
20
+ const requestId = ++latestRequestId;
18
21
  return new Promise((resolve) => {
19
22
  const opts = typeof options === "function" ? options({
20
23
  data: value.get().data,
@@ -28,15 +31,17 @@ const useAuthQuery = (initializedAtom, path, $fetch, options) => {
28
31
  ...queryParams?.query
29
32
  },
30
33
  async onSuccess(context) {
31
- const current = value.get();
32
- const stableData = current.data != null && context.data != null && isJsonEqual(current.data, context.data) ? current.data : context.data;
33
- value.set({
34
- data: stableData,
35
- error: null,
36
- isPending: false,
37
- isRefetching: false,
38
- refetch: value.value.refetch
39
- });
34
+ if (requestId === latestRequestId) {
35
+ const current = value.get();
36
+ const stableData = current.data != null && context.data != null && isJsonEqual(current.data, context.data) ? current.data : context.data;
37
+ value.set({
38
+ data: stableData,
39
+ error: null,
40
+ isPending: false,
41
+ isRefetching: false,
42
+ refetch: value.value.refetch
43
+ });
44
+ }
40
45
  await opts?.onSuccess?.(context);
41
46
  },
42
47
  async onError(context) {
@@ -44,28 +49,33 @@ const useAuthQuery = (initializedAtom, path, $fetch, options) => {
44
49
  const retryAttempts = typeof request.retry === "number" ? request.retry : request.retry?.attempts;
45
50
  const retryAttempt = request.retryAttempt || 0;
46
51
  if (retryAttempts && retryAttempt < retryAttempts) return;
47
- const isUnauthorized = context.error.status === 401;
48
- value.set({
49
- error: context.error,
50
- data: isUnauthorized ? null : value.get().data,
51
- isPending: false,
52
- isRefetching: false,
53
- refetch: value.value.refetch
54
- });
52
+ if (requestId === latestRequestId) {
53
+ const isUnauthorized = context.error.status === 401;
54
+ value.set({
55
+ error: context.error,
56
+ data: isUnauthorized ? null : value.get().data,
57
+ isPending: false,
58
+ isRefetching: false,
59
+ refetch: value.value.refetch
60
+ });
61
+ }
55
62
  await opts?.onError?.(context);
56
63
  },
57
64
  async onRequest(context) {
58
- const currentValue = value.get();
59
- value.set({
60
- isPending: currentValue.data === null,
61
- data: currentValue.data,
62
- error: null,
63
- isRefetching: true,
64
- refetch: value.value.refetch
65
- });
65
+ if (requestId === latestRequestId) {
66
+ const currentValue = value.get();
67
+ value.set({
68
+ isPending: currentValue.data === null,
69
+ data: currentValue.data,
70
+ error: null,
71
+ isRefetching: true,
72
+ refetch: value.value.refetch
73
+ });
74
+ }
66
75
  await opts?.onRequest?.(context);
67
76
  }
68
77
  }).catch((error) => {
78
+ if (requestId !== latestRequestId) return;
69
79
  value.set({
70
80
  error,
71
81
  data: value.get().data,
@@ -1,3 +1,4 @@
1
+ import { isAuthQueryStore } from "../query-atom.mjs";
1
2
  import { listenKeys } from "nanostores";
2
3
  import { useCallback, useRef, useSyncExternalStore } from "react";
3
4
  //#region src/client/react/react-store.ts
@@ -38,7 +39,7 @@ function useStore(store, options = {}) {
38
39
  return store.listen(emitChange);
39
40
  }, deps);
40
41
  const get = () => snapshotRef.current;
41
- return useSyncExternalStore(subscribe, get, get);
42
+ return useSyncExternalStore(subscribe, get, isAuthQueryStore(store) ? () => store.init : get);
42
43
  }
43
44
  //#endregion
44
45
  export { useStore };
@@ -1,4 +1,5 @@
1
1
  import { isJsonEqual, withEquality } from "./equality.mjs";
2
+ import { createAuthQueryAtom } from "./query-atom.mjs";
2
3
  import { createSessionRefreshManager } from "./session-refresh.mjs";
3
4
  import { STORE_UNMOUNT_DELAY, atom, onMount } from "nanostores";
4
5
  //#region src/client/session-atom.ts
@@ -44,7 +45,7 @@ function getSessionAtom($fetch, options) {
44
45
  freshUntil = 0;
45
46
  });
46
47
  const refetch = (queryParams) => fetchSession(queryParams);
47
- const session = atom({
48
+ const session = createAuthQueryAtom({
48
49
  data: null,
49
50
  error: null,
50
51
  isPending: true,
@@ -15,7 +15,7 @@ import { getAuthTables } from "@better-auth/core/db";
15
15
  import { createLogger, env, isProduction, isTest } from "@better-auth/core/env";
16
16
  import { BetterAuthError } from "@better-auth/core/error";
17
17
  import { generateId } from "@better-auth/core/utils/id";
18
- import { schemaCheckFor } from "@better-auth/core/db/internal";
18
+ import { runtimeSchemaCheckFor, schemaCheckFor } from "@better-auth/core/db/internal";
19
19
  import { socialProviders } from "@better-auth/core/social-providers";
20
20
  import { findInvalidTrustedProxies } from "@better-auth/core/utils/ip";
21
21
  import { createTelemetry } from "@better-auth/telemetry";
@@ -228,7 +228,8 @@ Most of the features of Better Auth will not work correctly.`);
228
228
  };
229
229
  const initOrPromise = runPluginInit(ctx);
230
230
  if (isPromise(initOrPromise)) await initOrPromise;
231
- ctx.checkSchema = schemaCheckFor(ctx.adapter);
231
+ ctx.checkSchema = runtimeSchemaCheckFor(ctx.adapter);
232
+ ctx.explicitSchemaCheck = schemaCheckFor(ctx.adapter);
232
233
  return ctx;
233
234
  }
234
235
  //#endregion
@@ -1,7 +1,7 @@
1
1
  import { Session, User } from "../types/models.mjs";
2
2
  import { CookieAttributes, HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, applySetCookies, cookieNameRegex, parseCookies, parseSetCookieHeader, setCookieToHeader, setRequestCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions } from "./cookie-utils.mjs";
3
3
  import { createSessionStore, getAccountCookie, getChunkedCookie, setAccountCookie } from "./session-store.mjs";
4
- import { BetterAuthCookie, BetterAuthCookies, BetterAuthOptions, CookieCachePayload, GenericEndpointContext } from "@better-auth/core";
4
+ import { Awaitable, BetterAuthCookie, BetterAuthCookies, BetterAuthOptions, CookieCachePayload, GenericEndpointContext } from "@better-auth/core";
5
5
  import * as _$better_call0 from "better-call";
6
6
  import { CookieOptions } from "better-call";
7
7
  import { JSONWebKeySet } from "jose";
@@ -106,6 +106,7 @@ declare const getSessionCookie: (request: Request | Headers, config?: {
106
106
  cookieName?: string;
107
107
  path?: string;
108
108
  } | undefined) => string | null;
109
+ type CookieCacheVersion = string | ((session: CookieCachePayload["session"], user: CookieCachePayload["user"]) => Awaitable<string>);
109
110
  declare const getCookieCache: <S extends CookieCachePayload = CookieCachePayload>(request: Request | Headers, config?: {
110
111
  cookiePrefix?: string;
111
112
  cookieName?: string;
@@ -117,7 +118,7 @@ declare const getCookieCache: <S extends CookieCachePayload = CookieCachePayload
117
118
  issuer?: string;
118
119
  audience?: string;
119
120
  } | undefined;
120
- version?: string | ((session: CookieCachePayload["session"], user: CookieCachePayload["user"]) => string) | ((session: CookieCachePayload["session"], user: CookieCachePayload["user"]) => Promise<string>);
121
+ version?: CookieCacheVersion;
121
122
  } | undefined) => Promise<S | null>;
122
123
  //#endregion
123
124
  export { CookieAttributes, EligibleCookies, HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, applySetCookies, cookieNameRegex, createCookieGetter, createSessionStore, decodeCookieCache, deleteSessionCookie, expireCookie, getAccountCookie, getChunkedCookie, getCookieCache, getCookies, getSessionCookie, parseCookies, parseSetCookieHeader, setAccountCookie, setCookieCache, setCookieToHeader, setRequestCookie, setSessionCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions };