@masheev/better-auth 0.0.0-stage → 1.7.5

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 (465) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +31 -2
  3. package/TYPE-PATCH-NOTICE.md +9 -0
  4. package/TYPE-PATCH-PROVENANCE.json +267 -0
  5. package/dist/_virtual/_rolldown/runtime.mjs +27 -0
  6. package/dist/adapters/drizzle-adapter/index.d.mts +1 -0
  7. package/dist/adapters/drizzle-adapter/index.mjs +2 -0
  8. package/dist/adapters/index.d.mts +26 -0
  9. package/dist/adapters/index.mjs +9 -0
  10. package/dist/adapters/kysely-adapter/index.d.mts +1 -0
  11. package/dist/adapters/kysely-adapter/index.mjs +2 -0
  12. package/dist/adapters/memory-adapter/index.d.mts +1 -0
  13. package/dist/adapters/memory-adapter/index.mjs +2 -0
  14. package/dist/adapters/mongodb-adapter/index.d.mts +1 -0
  15. package/dist/adapters/mongodb-adapter/index.mjs +2 -0
  16. package/dist/adapters/prisma-adapter/index.d.mts +1 -0
  17. package/dist/adapters/prisma-adapter/index.mjs +2 -0
  18. package/dist/api/dispatch.d.mts +34 -0
  19. package/dist/api/dispatch.mjs +275 -0
  20. package/dist/api/index.d.mts +4053 -0
  21. package/dist/api/index.mjs +220 -0
  22. package/dist/api/middlewares/authorization.d.mts +69 -0
  23. package/dist/api/middlewares/authorization.mjs +78 -0
  24. package/dist/api/middlewares/index.d.mts +2 -0
  25. package/dist/api/middlewares/origin-check.d.mts +17 -0
  26. package/dist/api/middlewares/origin-check.mjs +155 -0
  27. package/dist/api/rate-limiter/index.mjs +318 -0
  28. package/dist/api/routes/account.d.mts +413 -0
  29. package/dist/api/routes/account.mjs +619 -0
  30. package/dist/api/routes/callback.d.mts +32 -0
  31. package/dist/api/routes/callback.mjs +261 -0
  32. package/dist/api/routes/email-verification.d.mts +160 -0
  33. package/dist/api/routes/email-verification.mjs +324 -0
  34. package/dist/api/routes/error.d.mts +27 -0
  35. package/dist/api/routes/error.mjs +387 -0
  36. package/dist/api/routes/index.d.mts +12 -0
  37. package/dist/api/routes/ok.d.mts +35 -0
  38. package/dist/api/routes/ok.mjs +27 -0
  39. package/dist/api/routes/password.d.mts +182 -0
  40. package/dist/api/routes/password.mjs +206 -0
  41. package/dist/api/routes/session.d.mts +450 -0
  42. package/dist/api/routes/session.mjs +481 -0
  43. package/dist/api/routes/sign-in.d.mts +186 -0
  44. package/dist/api/routes/sign-in.mjs +368 -0
  45. package/dist/api/routes/sign-out.d.mts +51 -0
  46. package/dist/api/routes/sign-out.mjs +96 -0
  47. package/dist/api/routes/sign-up.d.mts +159 -0
  48. package/dist/api/routes/sign-up.mjs +275 -0
  49. package/dist/api/routes/update-session.d.mts +74 -0
  50. package/dist/api/routes/update-session.mjs +57 -0
  51. package/dist/api/routes/update-user.d.mts +428 -0
  52. package/dist/api/routes/update-user.mjs +522 -0
  53. package/dist/api/state/oauth.d.mts +53 -0
  54. package/dist/api/state/oauth.mjs +38 -0
  55. package/dist/api/state/should-session-refresh.d.mts +12 -0
  56. package/dist/api/state/should-session-refresh.mjs +13 -0
  57. package/dist/api/to-auth-endpoints.mjs +60 -0
  58. package/dist/auth/base.mjs +66 -0
  59. package/dist/auth/full.d.mts +28 -0
  60. package/dist/auth/full.mjs +29 -0
  61. package/dist/auth/minimal.d.mts +10 -0
  62. package/dist/auth/minimal.mjs +11 -0
  63. package/dist/auth/trusted-origins.mjs +106 -0
  64. package/dist/client/broadcast-channel.d.mts +19 -0
  65. package/dist/client/broadcast-channel.mjs +44 -0
  66. package/dist/client/config.d.mts +90 -0
  67. package/dist/client/config.mjs +113 -0
  68. package/dist/client/equality.d.mts +19 -0
  69. package/dist/client/equality.mjs +42 -0
  70. package/dist/client/fetch-plugins.mjs +17 -0
  71. package/dist/client/focus-manager.d.mts +10 -0
  72. package/dist/client/focus-manager.mjs +30 -0
  73. package/dist/client/index.d.mts +35 -0
  74. package/dist/client/index.mjs +22 -0
  75. package/dist/client/lynx/index.d.mts +43 -0
  76. package/dist/client/lynx/index.mjs +22 -0
  77. package/dist/client/lynx/lynx-store.d.mts +46 -0
  78. package/dist/client/lynx/lynx-store.mjs +44 -0
  79. package/dist/client/online-manager.d.mts +11 -0
  80. package/dist/client/online-manager.mjs +33 -0
  81. package/dist/client/parser.d.mts +10 -0
  82. package/dist/client/parser.mjs +70 -0
  83. package/dist/client/path-to-object.d.mts +113 -0
  84. package/dist/client/plugins/index.d.mts +44 -0
  85. package/dist/client/plugins/index.mjs +30 -0
  86. package/dist/client/plugins/infer-plugin.d.mts +16 -0
  87. package/dist/client/plugins/infer-plugin.mjs +11 -0
  88. package/dist/client/proxy.mjs +78 -0
  89. package/dist/client/query.d.mts +23 -0
  90. package/dist/client/query.mjs +124 -0
  91. package/dist/client/react/index.d.mts +44 -0
  92. package/dist/client/react/index.mjs +22 -0
  93. package/dist/client/react/react-store.d.mts +46 -0
  94. package/dist/client/react/react-store.mjs +44 -0
  95. package/dist/client/session-atom.d.mts +11 -0
  96. package/dist/client/session-atom.mjs +178 -0
  97. package/dist/client/session-refresh.d.mts +20 -0
  98. package/dist/client/session-refresh.mjs +131 -0
  99. package/dist/client/solid/index.d.mts +44 -0
  100. package/dist/client/solid/index.mjs +22 -0
  101. package/dist/client/solid/solid-store.mjs +21 -0
  102. package/dist/client/svelte/index.d.mts +44 -0
  103. package/dist/client/svelte/index.mjs +18 -0
  104. package/dist/client/types.d.mts +51 -0
  105. package/dist/client/vanilla.d.mts +42 -0
  106. package/dist/client/vanilla.mjs +18 -0
  107. package/dist/client/vue/index.d.mts +67 -0
  108. package/dist/client/vue/index.mjs +54 -0
  109. package/dist/client/vue/vue-store.mjs +23 -0
  110. package/dist/context/create-context.mjs +235 -0
  111. package/dist/context/helpers.mjs +158 -0
  112. package/dist/context/init-minimal.mjs +17 -0
  113. package/dist/context/init.mjs +19 -0
  114. package/dist/context/secret-utils.mjs +53 -0
  115. package/dist/context/store-capabilities.mjs +12 -0
  116. package/dist/cookies/cache.mjs +33 -0
  117. package/dist/cookies/cookie-utils.d.mts +72 -0
  118. package/dist/cookies/cookie-utils.mjs +203 -0
  119. package/dist/cookies/index.d.mts +124 -0
  120. package/dist/cookies/index.mjs +350 -0
  121. package/dist/cookies/jwt.mjs +44 -0
  122. package/dist/cookies/session-store.d.mts +32 -0
  123. package/dist/cookies/session-store.mjs +183 -0
  124. package/dist/crypto/buffer.d.mts +7 -0
  125. package/dist/crypto/buffer.mjs +16 -0
  126. package/dist/crypto/index.d.mts +32 -0
  127. package/dist/crypto/index.mjs +69 -0
  128. package/dist/crypto/jwt.d.mts +9 -0
  129. package/dist/crypto/jwt.mjs +141 -0
  130. package/dist/crypto/password.d.mts +13 -0
  131. package/dist/crypto/password.mjs +14 -0
  132. package/dist/crypto/random.d.mts +4 -0
  133. package/dist/crypto/random.mjs +5 -0
  134. package/dist/db/adapter-base.d.mts +7 -0
  135. package/dist/db/adapter-base.mjs +25 -0
  136. package/dist/db/adapter-kysely.d.mts +7 -0
  137. package/dist/db/adapter-kysely.mjs +17 -0
  138. package/dist/db/field-converter.d.mts +7 -0
  139. package/dist/db/field-converter.mjs +19 -0
  140. package/dist/db/field.d.mts +41 -0
  141. package/dist/db/get-migration.d.mts +56 -0
  142. package/dist/db/get-migration.mjs +685 -0
  143. package/dist/db/get-schema.d.mts +13 -0
  144. package/dist/db/get-schema.mjs +39 -0
  145. package/dist/db/index.d.mts +10 -0
  146. package/dist/db/index.mjs +35 -0
  147. package/dist/db/internal-adapter.d.mts +14 -0
  148. package/dist/db/internal-adapter.mjs +951 -0
  149. package/dist/db/revoke-unproven-account-access.d.mts +21 -0
  150. package/dist/db/revoke-unproven-account-access.mjs +58 -0
  151. package/dist/db/schema.d.mts +62 -0
  152. package/dist/db/schema.mjs +161 -0
  153. package/dist/db/to-zod.d.mts +35 -0
  154. package/dist/db/to-zod.mjs +23 -0
  155. package/dist/db/verification-token-storage.mjs +25 -0
  156. package/dist/db/with-hooks.d.mts +37 -0
  157. package/dist/db/with-hooks.mjs +255 -0
  158. package/dist/index.d.mts +30 -0
  159. package/dist/index.mjs +17 -0
  160. package/dist/integrations/cookie-plugin-guard.mjs +18 -0
  161. package/dist/integrations/next-js.d.mts +29 -0
  162. package/dist/integrations/next-js.mjs +105 -0
  163. package/dist/integrations/node.d.mts +11 -0
  164. package/dist/integrations/node.mjs +13 -0
  165. package/dist/integrations/solid-start.d.mts +22 -0
  166. package/dist/integrations/solid-start.mjs +15 -0
  167. package/dist/integrations/svelte-kit.d.mts +38 -0
  168. package/dist/integrations/svelte-kit.mjs +57 -0
  169. package/dist/integrations/tanstack-start-solid.d.mts +33 -0
  170. package/dist/integrations/tanstack-start-solid.mjs +57 -0
  171. package/dist/integrations/tanstack-start.d.mts +33 -0
  172. package/dist/integrations/tanstack-start.mjs +57 -0
  173. package/dist/oauth2/account-key.mjs +43 -0
  174. package/dist/oauth2/errors.mjs +49 -0
  175. package/dist/oauth2/index.d.mts +5 -0
  176. package/dist/oauth2/index.mjs +5 -0
  177. package/dist/oauth2/link-account.d.mts +96 -0
  178. package/dist/oauth2/link-account.mjs +329 -0
  179. package/dist/oauth2/state.d.mts +54 -0
  180. package/dist/oauth2/state.mjs +67 -0
  181. package/dist/oauth2/utils.d.mts +11 -0
  182. package/dist/oauth2/utils.mjs +33 -0
  183. package/dist/package.mjs +4 -0
  184. package/dist/plugins/access/access.d.mts +17 -0
  185. package/dist/plugins/access/access.mjs +78 -0
  186. package/dist/plugins/access/index.d.mts +3 -0
  187. package/dist/plugins/access/index.mjs +2 -0
  188. package/dist/plugins/access/types.d.mts +24 -0
  189. package/dist/plugins/additional-fields/client.d.mts +100 -0
  190. package/dist/plugins/additional-fields/client.mjs +11 -0
  191. package/dist/plugins/admin/access/index.d.mts +2 -0
  192. package/dist/plugins/admin/access/index.mjs +2 -0
  193. package/dist/plugins/admin/access/statement.d.mts +51 -0
  194. package/dist/plugins/admin/access/statement.mjs +52 -0
  195. package/dist/plugins/admin/admin.d.mts +911 -0
  196. package/dist/plugins/admin/admin.mjs +89 -0
  197. package/dist/plugins/admin/client.d.mts +81 -0
  198. package/dist/plugins/admin/client.mjs +39 -0
  199. package/dist/plugins/admin/error-codes.d.mts +30 -0
  200. package/dist/plugins/admin/error-codes.mjs +29 -0
  201. package/dist/plugins/admin/has-permission.mjs +12 -0
  202. package/dist/plugins/admin/index.d.mts +3 -0
  203. package/dist/plugins/admin/index.mjs +2 -0
  204. package/dist/plugins/admin/routes.mjs +919 -0
  205. package/dist/plugins/admin/schema.d.mts +40 -0
  206. package/dist/plugins/admin/schema.mjs +33 -0
  207. package/dist/plugins/admin/types.d.mts +88 -0
  208. package/dist/plugins/anonymous/client.d.mts +32 -0
  209. package/dist/plugins/anonymous/client.mjs +21 -0
  210. package/dist/plugins/anonymous/error-codes.d.mts +15 -0
  211. package/dist/plugins/anonymous/error-codes.mjs +14 -0
  212. package/dist/plugins/anonymous/index.d.mts +175 -0
  213. package/dist/plugins/anonymous/index.mjs +219 -0
  214. package/dist/plugins/anonymous/schema.d.mts +15 -0
  215. package/dist/plugins/anonymous/schema.mjs +9 -0
  216. package/dist/plugins/anonymous/types.d.mts +65 -0
  217. package/dist/plugins/bearer/index.d.mts +45 -0
  218. package/dist/plugins/bearer/index.mjs +74 -0
  219. package/dist/plugins/captcha/constants.d.mts +9 -0
  220. package/dist/plugins/captcha/constants.mjs +27 -0
  221. package/dist/plugins/captcha/error-codes.mjs +13 -0
  222. package/dist/plugins/captcha/index.d.mts +27 -0
  223. package/dist/plugins/captcha/index.mjs +79 -0
  224. package/dist/plugins/captcha/types.d.mts +52 -0
  225. package/dist/plugins/captcha/utils.mjs +9 -0
  226. package/dist/plugins/captcha/verify-handlers/captchafox.mjs +27 -0
  227. package/dist/plugins/captcha/verify-handlers/cloudflare-turnstile.mjs +47 -0
  228. package/dist/plugins/captcha/verify-handlers/google-recaptcha.mjs +32 -0
  229. package/dist/plugins/captcha/verify-handlers/h-captcha.mjs +27 -0
  230. package/dist/plugins/custom-session/client.d.mts +17 -0
  231. package/dist/plugins/custom-session/client.mjs +7 -0
  232. package/dist/plugins/custom-session/index.d.mts +73 -0
  233. package/dist/plugins/custom-session/index.mjs +65 -0
  234. package/dist/plugins/device-authorization/client.d.mts +17 -0
  235. package/dist/plugins/device-authorization/client.mjs +18 -0
  236. package/dist/plugins/device-authorization/error-codes.mjs +19 -0
  237. package/dist/plugins/device-authorization/index.d.mts +558 -0
  238. package/dist/plugins/device-authorization/index.mjs +87 -0
  239. package/dist/plugins/device-authorization/routes.d.mts +32 -0
  240. package/dist/plugins/device-authorization/routes.mjs +725 -0
  241. package/dist/plugins/device-authorization/schema.d.mts +18 -0
  242. package/dist/plugins/device-authorization/schema.mjs +63 -0
  243. package/dist/plugins/email-otp/client.d.mts +21 -0
  244. package/dist/plugins/email-otp/client.mjs +17 -0
  245. package/dist/plugins/email-otp/error-codes.d.mts +10 -0
  246. package/dist/plugins/email-otp/error-codes.mjs +9 -0
  247. package/dist/plugins/email-otp/index.d.mts +551 -0
  248. package/dist/plugins/email-otp/index.mjs +145 -0
  249. package/dist/plugins/email-otp/otp-token.mjs +55 -0
  250. package/dist/plugins/email-otp/routes.mjs +784 -0
  251. package/dist/plugins/email-otp/types.d.mts +109 -0
  252. package/dist/plugins/email-otp/utils.mjs +17 -0
  253. package/dist/plugins/generic-oauth/error-codes.mjs +8 -0
  254. package/dist/plugins/generic-oauth/index.d.mts +52 -0
  255. package/dist/plugins/generic-oauth/index.mjs +279 -0
  256. package/dist/plugins/generic-oauth/providers/auth0.d.mts +36 -0
  257. package/dist/plugins/generic-oauth/providers/auth0.mjs +49 -0
  258. package/dist/plugins/generic-oauth/providers/gumroad.d.mts +31 -0
  259. package/dist/plugins/generic-oauth/providers/gumroad.mjs +62 -0
  260. package/dist/plugins/generic-oauth/providers/hubspot.d.mts +36 -0
  261. package/dist/plugins/generic-oauth/providers/hubspot.mjs +62 -0
  262. package/dist/plugins/generic-oauth/providers/index.d.mts +10 -0
  263. package/dist/plugins/generic-oauth/providers/keycloak.d.mts +36 -0
  264. package/dist/plugins/generic-oauth/providers/keycloak.mjs +47 -0
  265. package/dist/plugins/generic-oauth/providers/line.d.mts +54 -0
  266. package/dist/plugins/generic-oauth/providers/line.mjs +93 -0
  267. package/dist/plugins/generic-oauth/providers/microsoft-entra-id.d.mts +39 -0
  268. package/dist/plugins/generic-oauth/providers/microsoft-entra-id.mjs +104 -0
  269. package/dist/plugins/generic-oauth/providers/okta.d.mts +36 -0
  270. package/dist/plugins/generic-oauth/providers/okta.mjs +47 -0
  271. package/dist/plugins/generic-oauth/providers/patreon.d.mts +29 -0
  272. package/dist/plugins/generic-oauth/providers/patreon.mjs +61 -0
  273. package/dist/plugins/generic-oauth/providers/slack.d.mts +29 -0
  274. package/dist/plugins/generic-oauth/providers/slack.mjs +63 -0
  275. package/dist/plugins/generic-oauth/providers/yandex.d.mts +29 -0
  276. package/dist/plugins/generic-oauth/providers/yandex.mjs +67 -0
  277. package/dist/plugins/generic-oauth/types.d.mts +268 -0
  278. package/dist/plugins/haveibeenpwned/index.d.mts +63 -0
  279. package/dist/plugins/haveibeenpwned/index.mjs +81 -0
  280. package/dist/plugins/index.d.mts +69 -0
  281. package/dist/plugins/index.mjs +49 -0
  282. package/dist/plugins/jwt/adapter.mjs +68 -0
  283. package/dist/plugins/jwt/client.d.mts +41 -0
  284. package/dist/plugins/jwt/client.mjs +19 -0
  285. package/dist/plugins/jwt/cookie-cache.mjs +77 -0
  286. package/dist/plugins/jwt/index.d.mts +246 -0
  287. package/dist/plugins/jwt/index.mjs +214 -0
  288. package/dist/plugins/jwt/schema.d.mts +33 -0
  289. package/dist/plugins/jwt/schema.mjs +29 -0
  290. package/dist/plugins/jwt/sign.d.mts +128 -0
  291. package/dist/plugins/jwt/sign.mjs +130 -0
  292. package/dist/plugins/jwt/types.d.mts +256 -0
  293. package/dist/plugins/jwt/utils.d.mts +41 -0
  294. package/dist/plugins/jwt/utils.mjs +64 -0
  295. package/dist/plugins/jwt/verify.d.mts +11 -0
  296. package/dist/plugins/jwt/verify.mjs +45 -0
  297. package/dist/plugins/last-login-method/client.d.mts +48 -0
  298. package/dist/plugins/last-login-method/client.mjs +48 -0
  299. package/dist/plugins/last-login-method/index.d.mts +127 -0
  300. package/dist/plugins/last-login-method/index.mjs +98 -0
  301. package/dist/plugins/magic-link/client.d.mts +10 -0
  302. package/dist/plugins/magic-link/client.mjs +11 -0
  303. package/dist/plugins/magic-link/index.d.mts +213 -0
  304. package/dist/plugins/magic-link/index.mjs +208 -0
  305. package/dist/plugins/magic-link/utils.mjs +9 -0
  306. package/dist/plugins/multi-session/client.d.mts +19 -0
  307. package/dist/plugins/multi-session/client.mjs +19 -0
  308. package/dist/plugins/multi-session/error-codes.d.mts +8 -0
  309. package/dist/plugins/multi-session/error-codes.mjs +5 -0
  310. package/dist/plugins/multi-session/index.d.mts +212 -0
  311. package/dist/plugins/multi-session/index.mjs +217 -0
  312. package/dist/plugins/oauth-popup/client.d.mts +82 -0
  313. package/dist/plugins/oauth-popup/client.mjs +203 -0
  314. package/dist/plugins/oauth-popup/constants.d.mts +11 -0
  315. package/dist/plugins/oauth-popup/constants.mjs +11 -0
  316. package/dist/plugins/oauth-popup/error-codes.d.mts +11 -0
  317. package/dist/plugins/oauth-popup/error-codes.mjs +10 -0
  318. package/dist/plugins/oauth-popup/index.d.mts +67 -0
  319. package/dist/plugins/oauth-popup/index.mjs +232 -0
  320. package/dist/plugins/oauth-popup/types.d.mts +30 -0
  321. package/dist/plugins/oauth-proxy/index.d.mts +130 -0
  322. package/dist/plugins/oauth-proxy/index.mjs +407 -0
  323. package/dist/plugins/oauth-proxy/utils.mjs +55 -0
  324. package/dist/plugins/one-tap/client.d.mts +174 -0
  325. package/dist/plugins/one-tap/client.mjs +208 -0
  326. package/dist/plugins/one-tap/index.d.mts +82 -0
  327. package/dist/plugins/one-tap/index.mjs +100 -0
  328. package/dist/plugins/one-time-token/client.d.mts +10 -0
  329. package/dist/plugins/one-time-token/client.mjs +11 -0
  330. package/dist/plugins/one-time-token/index.d.mts +132 -0
  331. package/dist/plugins/one-time-token/index.mjs +107 -0
  332. package/dist/plugins/one-time-token/utils.mjs +9 -0
  333. package/dist/plugins/open-api/generator.d.mts +126 -0
  334. package/dist/plugins/open-api/generator.mjs +557 -0
  335. package/dist/plugins/open-api/index.d.mts +97 -0
  336. package/dist/plugins/open-api/index.mjs +65 -0
  337. package/dist/plugins/open-api/logo.mjs +13 -0
  338. package/dist/plugins/organization/access/index.d.mts +2 -0
  339. package/dist/plugins/organization/access/index.mjs +2 -0
  340. package/dist/plugins/organization/access/statement.d.mts +113 -0
  341. package/dist/plugins/organization/access/statement.mjs +77 -0
  342. package/dist/plugins/organization/adapter.d.mts +815 -0
  343. package/dist/plugins/organization/adapter.mjs +813 -0
  344. package/dist/plugins/organization/call.mjs +15 -0
  345. package/dist/plugins/organization/client.d.mts +375 -0
  346. package/dist/plugins/organization/client.mjs +104 -0
  347. package/dist/plugins/organization/error-codes.d.mts +66 -0
  348. package/dist/plugins/organization/error-codes.mjs +65 -0
  349. package/dist/plugins/organization/has-permission.d.mts +17 -0
  350. package/dist/plugins/organization/has-permission.mjs +34 -0
  351. package/dist/plugins/organization/index.d.mts +6 -0
  352. package/dist/plugins/organization/index.mjs +4 -0
  353. package/dist/plugins/organization/organization.d.mts +420 -0
  354. package/dist/plugins/organization/organization.mjs +886 -0
  355. package/dist/plugins/organization/permission.d.mts +15 -0
  356. package/dist/plugins/organization/permission.mjs +14 -0
  357. package/dist/plugins/organization/routes/crud-access-control.d.mts +511 -0
  358. package/dist/plugins/organization/routes/crud-access-control.mjs +674 -0
  359. package/dist/plugins/organization/routes/crud-invites.d.mts +1154 -0
  360. package/dist/plugins/organization/routes/crud-invites.mjs +602 -0
  361. package/dist/plugins/organization/routes/crud-members.d.mts +1057 -0
  362. package/dist/plugins/organization/routes/crud-members.mjs +518 -0
  363. package/dist/plugins/organization/routes/crud-org.d.mts +918 -0
  364. package/dist/plugins/organization/routes/crud-org.mjs +455 -0
  365. package/dist/plugins/organization/routes/crud-team.d.mts +1238 -0
  366. package/dist/plugins/organization/routes/crud-team.mjs +766 -0
  367. package/dist/plugins/organization/schema.d.mts +390 -0
  368. package/dist/plugins/organization/schema.mjs +65 -0
  369. package/dist/plugins/organization/types.d.mts +691 -0
  370. package/dist/plugins/phone-number/client.d.mts +31 -0
  371. package/dist/plugins/phone-number/client.mjs +19 -0
  372. package/dist/plugins/phone-number/error-codes.d.mts +19 -0
  373. package/dist/plugins/phone-number/error-codes.mjs +18 -0
  374. package/dist/plugins/phone-number/index.d.mts +360 -0
  375. package/dist/plugins/phone-number/index.mjs +57 -0
  376. package/dist/plugins/phone-number/routes.mjs +529 -0
  377. package/dist/plugins/phone-number/schema.d.mts +22 -0
  378. package/dist/plugins/phone-number/schema.mjs +18 -0
  379. package/dist/plugins/phone-number/types.d.mts +116 -0
  380. package/dist/plugins/siwe/client.d.mts +14 -0
  381. package/dist/plugins/siwe/client.mjs +15 -0
  382. package/dist/plugins/siwe/index.d.mts +62 -0
  383. package/dist/plugins/siwe/index.mjs +272 -0
  384. package/dist/plugins/siwe/parse-message.mjs +60 -0
  385. package/dist/plugins/siwe/schema.d.mts +35 -0
  386. package/dist/plugins/siwe/schema.mjs +30 -0
  387. package/dist/plugins/siwe/types.d.mts +43 -0
  388. package/dist/plugins/test-utils/auth-helpers.mjs +33 -0
  389. package/dist/plugins/test-utils/cookie-builder.mjs +55 -0
  390. package/dist/plugins/test-utils/db-helpers.mjs +65 -0
  391. package/dist/plugins/test-utils/factories.mjs +38 -0
  392. package/dist/plugins/test-utils/index.d.mts +73 -0
  393. package/dist/plugins/test-utils/index.mjs +97 -0
  394. package/dist/plugins/test-utils/otp-sink.mjs +21 -0
  395. package/dist/plugins/test-utils/types.d.mts +51 -0
  396. package/dist/plugins/two-factor/backup-codes/index.d.mts +291 -0
  397. package/dist/plugins/two-factor/backup-codes/index.mjs +341 -0
  398. package/dist/plugins/two-factor/client.d.mts +76 -0
  399. package/dist/plugins/two-factor/client.mjs +41 -0
  400. package/dist/plugins/two-factor/constant.mjs +6 -0
  401. package/dist/plugins/two-factor/error-code.d.mts +20 -0
  402. package/dist/plugins/two-factor/error-code.mjs +19 -0
  403. package/dist/plugins/two-factor/index.d.mts +720 -0
  404. package/dist/plugins/two-factor/index.mjs +349 -0
  405. package/dist/plugins/two-factor/otp/index.d.mts +216 -0
  406. package/dist/plugins/two-factor/otp/index.mjs +252 -0
  407. package/dist/plugins/two-factor/schema.d.mts +59 -0
  408. package/dist/plugins/two-factor/schema.mjs +53 -0
  409. package/dist/plugins/two-factor/totp/index.d.mts +219 -0
  410. package/dist/plugins/two-factor/totp/index.mjs +230 -0
  411. package/dist/plugins/two-factor/types.d.mts +111 -0
  412. package/dist/plugins/two-factor/utils.mjs +9 -0
  413. package/dist/plugins/two-factor/verify-two-factor.mjs +205 -0
  414. package/dist/plugins/username/client.d.mts +38 -0
  415. package/dist/plugins/username/client.mjs +17 -0
  416. package/dist/plugins/username/error-codes.d.mts +16 -0
  417. package/dist/plugins/username/error-codes.mjs +15 -0
  418. package/dist/plugins/username/index.d.mts +326 -0
  419. package/dist/plugins/username/index.mjs +312 -0
  420. package/dist/plugins/username/schema.d.mts +50 -0
  421. package/dist/plugins/username/schema.mjs +25 -0
  422. package/dist/social-providers/index.d.mts +1 -0
  423. package/dist/social-providers/index.mjs +2 -0
  424. package/dist/state.d.mts +48 -0
  425. package/dist/state.mjs +149 -0
  426. package/dist/test-utils/headers.d.mts +8 -0
  427. package/dist/test-utils/headers.mjs +17 -0
  428. package/dist/test-utils/http-test-instance.d.mts +413 -0
  429. package/dist/test-utils/http-test-instance.mjs +107 -0
  430. package/dist/test-utils/index.d.mts +4 -0
  431. package/dist/test-utils/index.mjs +4 -0
  432. package/dist/test-utils/test-instance.d.mts +56 -0
  433. package/dist/test-utils/test-instance.mjs +242 -0
  434. package/dist/types/adapter.d.mts +2 -0
  435. package/dist/types/api.d.mts +28 -0
  436. package/dist/types/auth.d.mts +32 -0
  437. package/dist/types/helper.d.mts +26 -0
  438. package/dist/types/index.d.mts +10 -0
  439. package/dist/types/index.mjs +1 -0
  440. package/dist/types/models.d.mts +10 -0
  441. package/dist/types/plugins.d.mts +19 -0
  442. package/dist/utils/boolean.mjs +6 -0
  443. package/dist/utils/constants.mjs +4 -0
  444. package/dist/utils/date.mjs +6 -0
  445. package/dist/utils/hashing.mjs +18 -0
  446. package/dist/utils/hide-metadata.d.mts +6 -0
  447. package/dist/utils/hide-metadata.mjs +4 -0
  448. package/dist/utils/index.d.mts +4 -0
  449. package/dist/utils/is-api-error.d.mts +2 -0
  450. package/dist/utils/is-api-error.mjs +2 -0
  451. package/dist/utils/is-atom.mjs +6 -0
  452. package/dist/utils/is-promise.mjs +6 -0
  453. package/dist/utils/middleware-response.mjs +7 -0
  454. package/dist/utils/password.mjs +32 -0
  455. package/dist/utils/plugin-helper.mjs +14 -0
  456. package/dist/utils/request.mjs +23 -0
  457. package/dist/utils/shim.mjs +22 -0
  458. package/dist/utils/time.d.mts +48 -0
  459. package/dist/utils/time.mjs +98 -0
  460. package/dist/utils/url.d.mts +78 -0
  461. package/dist/utils/url.mjs +238 -0
  462. package/dist/utils/validate-user-info.mjs +44 -0
  463. package/dist/utils/wildcard.mjs +106 -0
  464. package/dist/version.mjs +5 -0
  465. package/package.json +595 -3
@@ -0,0 +1,522 @@
1
+ import { originCheck } from "../middlewares/origin-check.mjs";
2
+ import { parseUserInput, parseUserOutput } from "../../db/schema.mjs";
3
+ import { generateRandomString } from "../../crypto/random.mjs";
4
+ import { deleteSessionCookie, setSessionCookie } from "../../cookies/index.mjs";
5
+ import { getSessionFromCtx, isStateful, sensitiveSessionMiddleware, sessionMiddleware } from "./session.mjs";
6
+ import { createEmailVerificationToken } from "./email-verification.mjs";
7
+ import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
8
+ import { createAuthEndpoint } from "@better-auth/core/api";
9
+ import * as z from "zod";
10
+ //#region src/api/routes/update-user.ts
11
+ const updateUserBodySchema = z.record(z.string().meta({ description: "Field name must be a string" }), z.any());
12
+ const updateUser = () => createAuthEndpoint("/update-user", {
13
+ method: "POST",
14
+ operationId: "updateUser",
15
+ body: updateUserBodySchema,
16
+ use: [sessionMiddleware],
17
+ metadata: {
18
+ $Infer: { body: {} },
19
+ openapi: {
20
+ operationId: "updateUser",
21
+ description: "Update the current user",
22
+ requestBody: { content: { "application/json": { schema: {
23
+ type: "object",
24
+ properties: {
25
+ name: {
26
+ type: "string",
27
+ description: "The name of the user"
28
+ },
29
+ image: {
30
+ type: "string",
31
+ description: "The image of the user",
32
+ nullable: true
33
+ }
34
+ }
35
+ } } } },
36
+ responses: { "200": {
37
+ description: "Success",
38
+ content: { "application/json": { schema: {
39
+ type: "object",
40
+ properties: { user: {
41
+ type: "object",
42
+ $ref: "#/components/schemas/User"
43
+ } }
44
+ } } }
45
+ } }
46
+ }
47
+ }
48
+ }, async (ctx) => {
49
+ const body = ctx.body;
50
+ if (typeof body !== "object" || Array.isArray(body)) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.BODY_MUST_BE_AN_OBJECT);
51
+ if (body.email) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.EMAIL_CAN_NOT_BE_UPDATED);
52
+ const { name, image, ...rest } = body;
53
+ const session = ctx.context.session;
54
+ const additionalFields = parseUserInput(ctx.context.options, rest, "update");
55
+ if (image === void 0 && name === void 0 && Object.keys(additionalFields).length === 0) throw APIError.fromStatus("BAD_REQUEST", { message: "No fields to update" });
56
+ const updatedUser = await ctx.context.internalAdapter.updateUser(session.user.id, {
57
+ name,
58
+ image,
59
+ ...additionalFields
60
+ }) ?? {
61
+ ...session.user,
62
+ ...name !== void 0 && { name },
63
+ ...image !== void 0 && { image },
64
+ ...additionalFields
65
+ };
66
+ /**
67
+ * Update the session cookie with the new user data
68
+ */
69
+ await setSessionCookie(ctx, {
70
+ session: session.session,
71
+ user: updatedUser
72
+ });
73
+ return ctx.json({ status: true });
74
+ });
75
+ const changePassword = createAuthEndpoint("/change-password", {
76
+ method: "POST",
77
+ operationId: "changePassword",
78
+ body: z.object({
79
+ /**
80
+ * The new password to set
81
+ */
82
+ newPassword: z.string().meta({ description: "The new password to set" }),
83
+ /**
84
+ * The current password of the user
85
+ */
86
+ currentPassword: z.string().meta({ description: "The current password is required" }),
87
+ /**
88
+ * revoke all sessions that are not the
89
+ * current one logged in by the user
90
+ */
91
+ revokeOtherSessions: z.boolean().meta({ description: "Must be a boolean value" }).optional()
92
+ }),
93
+ use: [sensitiveSessionMiddleware],
94
+ metadata: { openapi: {
95
+ operationId: "changePassword",
96
+ description: "Change the password of the user",
97
+ responses: { "200": {
98
+ description: "Password successfully changed",
99
+ content: { "application/json": { schema: {
100
+ type: "object",
101
+ properties: {
102
+ token: {
103
+ type: "string",
104
+ nullable: true,
105
+ description: "New session token if other sessions were revoked"
106
+ },
107
+ user: {
108
+ type: "object",
109
+ properties: {
110
+ id: {
111
+ type: "string",
112
+ description: "The unique identifier of the user"
113
+ },
114
+ email: {
115
+ type: "string",
116
+ format: "email",
117
+ description: "The email address of the user"
118
+ },
119
+ name: {
120
+ type: "string",
121
+ description: "The name of the user"
122
+ },
123
+ image: {
124
+ type: "string",
125
+ format: "uri",
126
+ nullable: true,
127
+ description: "The profile image URL of the user"
128
+ },
129
+ emailVerified: {
130
+ type: "boolean",
131
+ description: "Whether the email has been verified"
132
+ },
133
+ createdAt: {
134
+ type: "string",
135
+ format: "date-time",
136
+ description: "When the user was created"
137
+ },
138
+ updatedAt: {
139
+ type: "string",
140
+ format: "date-time",
141
+ description: "When the user was last updated"
142
+ }
143
+ },
144
+ required: [
145
+ "id",
146
+ "email",
147
+ "name",
148
+ "emailVerified",
149
+ "createdAt",
150
+ "updatedAt"
151
+ ]
152
+ }
153
+ },
154
+ required: ["user"]
155
+ } } }
156
+ } }
157
+ } }
158
+ }, async (ctx) => {
159
+ const { newPassword, currentPassword, revokeOtherSessions } = ctx.body;
160
+ 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
+ }
171
+ const account = await ctx.context.internalAdapter.findCredentialAccount(session.user.id);
172
+ if (!account || !account.password) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.CREDENTIAL_ACCOUNT_NOT_FOUND);
173
+ const passwordHash = await ctx.context.password.hash(newPassword);
174
+ if (!await ctx.context.password.verify({
175
+ hash: account.password,
176
+ password: currentPassword
177
+ })) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_PASSWORD);
178
+ await ctx.context.internalAdapter.updateAccount(account.id, { password: passwordHash });
179
+ let token = null;
180
+ if (revokeOtherSessions) {
181
+ await ctx.context.internalAdapter.deleteUserSessions(session.user.id);
182
+ const newSession = await ctx.context.internalAdapter.createSession(session.user.id);
183
+ if (!newSession) throw APIError.from("INTERNAL_SERVER_ERROR", BASE_ERROR_CODES.FAILED_TO_GET_SESSION);
184
+ await setSessionCookie(ctx, {
185
+ session: newSession,
186
+ user: session.user
187
+ });
188
+ token = newSession.token;
189
+ }
190
+ return ctx.json({
191
+ token,
192
+ user: parseUserOutput(ctx.context.options, session.user)
193
+ });
194
+ });
195
+ const setPassword = createAuthEndpoint.serverOnly({
196
+ method: "POST",
197
+ body: z.object({
198
+ /**
199
+ * The new password to set
200
+ */
201
+ newPassword: z.string().meta({ description: "The new password to set is required" }) }),
202
+ use: [sensitiveSessionMiddleware]
203
+ }, async (ctx) => {
204
+ const { newPassword } = ctx.body;
205
+ 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
+ }
216
+ const account = await ctx.context.internalAdapter.findCredentialAccount(session.user.id);
217
+ const passwordHash = await ctx.context.password.hash(newPassword);
218
+ if (!account) {
219
+ await ctx.context.internalAdapter.linkAccount({
220
+ userId: session.user.id,
221
+ providerId: "credential",
222
+ accountId: session.user.id,
223
+ password: passwordHash
224
+ });
225
+ return ctx.json({ status: true });
226
+ }
227
+ if (!account.password) {
228
+ await ctx.context.internalAdapter.updateAccount(account.id, { password: passwordHash });
229
+ return ctx.json({ status: true });
230
+ }
231
+ throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_ALREADY_SET);
232
+ });
233
+ const deleteUser = createAuthEndpoint("/delete-user", {
234
+ method: "POST",
235
+ use: [sensitiveSessionMiddleware],
236
+ body: z.object({
237
+ /**
238
+ * The callback URL to redirect to after the user is deleted
239
+ * this is only used on delete user callback
240
+ */
241
+ callbackURL: z.string().meta({ description: "The callback URL to redirect to after the user is deleted" }).optional(),
242
+ /**
243
+ * The password of the user. If the password isn't provided, session freshness
244
+ * will be checked.
245
+ */
246
+ password: z.string().meta({ description: "The password of the user is required to delete the user" }).optional(),
247
+ /**
248
+ * The token to delete the user. If the token is provided, the user will be deleted
249
+ */
250
+ token: z.string().meta({ description: "The token to delete the user is required" }).optional()
251
+ }),
252
+ metadata: { openapi: {
253
+ operationId: "deleteUser",
254
+ description: "Delete the user",
255
+ requestBody: { content: { "application/json": { schema: {
256
+ type: "object",
257
+ properties: {
258
+ callbackURL: {
259
+ type: "string",
260
+ description: "The callback URL to redirect to after the user is deleted"
261
+ },
262
+ password: {
263
+ type: "string",
264
+ description: "The user's password. Required if session is not fresh"
265
+ },
266
+ token: {
267
+ type: "string",
268
+ description: "The deletion verification token"
269
+ }
270
+ }
271
+ } } } },
272
+ responses: { "200": {
273
+ description: "User deletion processed successfully",
274
+ content: { "application/json": { schema: {
275
+ type: "object",
276
+ properties: {
277
+ success: {
278
+ type: "boolean",
279
+ description: "Indicates if the operation was successful"
280
+ },
281
+ message: {
282
+ type: "string",
283
+ enum: ["User deleted", "Verification email sent"],
284
+ description: "Status message of the deletion process"
285
+ }
286
+ },
287
+ required: ["success", "message"]
288
+ } } }
289
+ } }
290
+ } }
291
+ }, async (ctx) => {
292
+ if (!ctx.context.options.user?.deleteUser?.enabled) {
293
+ ctx.context.logger.error("Delete user is disabled. Enable it in the options");
294
+ throw APIError.fromStatus("NOT_FOUND");
295
+ }
296
+ const session = ctx.context.session;
297
+ if (ctx.body.password) {
298
+ const account = await ctx.context.internalAdapter.findCredentialAccount(session.user.id);
299
+ if (!account || !account.password) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.CREDENTIAL_ACCOUNT_NOT_FOUND);
300
+ if (!await ctx.context.password.verify({
301
+ hash: account.password,
302
+ password: ctx.body.password
303
+ })) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_PASSWORD);
304
+ }
305
+ if (ctx.body.token) {
306
+ await deleteUserCallback({
307
+ ...ctx,
308
+ query: { token: ctx.body.token }
309
+ });
310
+ return ctx.json({
311
+ success: true,
312
+ message: "User deleted"
313
+ });
314
+ }
315
+ if (ctx.context.options.user.deleteUser?.sendDeleteAccountVerification) {
316
+ const token = generateRandomString(32, "0-9", "a-z");
317
+ await ctx.context.internalAdapter.createVerificationValue({
318
+ value: session.user.id,
319
+ identifier: `delete-account-${token}`,
320
+ expiresAt: new Date(Date.now() + (ctx.context.options.user.deleteUser?.deleteTokenExpiresIn || 3600 * 24) * 1e3)
321
+ });
322
+ const url = `${ctx.context.baseURL}/delete-user/callback?token=${token}&callbackURL=${encodeURIComponent(ctx.body.callbackURL || "/")}`;
323
+ await ctx.context.runInBackgroundOrAwait(ctx.context.options.user.deleteUser.sendDeleteAccountVerification({
324
+ user: session.user,
325
+ url,
326
+ token
327
+ }, ctx.request));
328
+ return ctx.json({
329
+ success: true,
330
+ message: "Verification email sent"
331
+ });
332
+ }
333
+ if (!ctx.body.password && ctx.context.sessionConfig.freshAge !== 0) {
334
+ const createdAt = new Date(session.session.createdAt).getTime();
335
+ const freshAge = ctx.context.sessionConfig.freshAge * 1e3;
336
+ if (Date.now() - createdAt >= freshAge) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.SESSION_EXPIRED);
337
+ }
338
+ const beforeDelete = ctx.context.options.user.deleteUser?.beforeDelete;
339
+ if (beforeDelete) await beforeDelete(session.user, ctx.request);
340
+ await ctx.context.internalAdapter.deleteUser(session.user.id);
341
+ await ctx.context.internalAdapter.deleteUserSessions(session.user.id);
342
+ deleteSessionCookie(ctx);
343
+ const afterDelete = ctx.context.options.user.deleteUser?.afterDelete;
344
+ if (afterDelete) await afterDelete(session.user, ctx.request);
345
+ return ctx.json({
346
+ success: true,
347
+ message: "User deleted"
348
+ });
349
+ });
350
+ const deleteUserCallback = createAuthEndpoint("/delete-user/callback", {
351
+ method: "GET",
352
+ query: z.object({
353
+ token: z.string().meta({ description: "The token to verify the deletion request" }),
354
+ callbackURL: z.string().meta({ description: "The URL to redirect to after deletion" }).optional()
355
+ }),
356
+ use: [originCheck((ctx) => ctx.query.callbackURL)],
357
+ metadata: { openapi: {
358
+ description: "Callback to complete user deletion with verification token",
359
+ responses: { "200": {
360
+ description: "User successfully deleted",
361
+ content: { "application/json": { schema: {
362
+ type: "object",
363
+ properties: {
364
+ success: {
365
+ type: "boolean",
366
+ description: "Indicates if the deletion was successful"
367
+ },
368
+ message: {
369
+ type: "string",
370
+ enum: ["User deleted"],
371
+ description: "Confirmation message"
372
+ }
373
+ },
374
+ required: ["success", "message"]
375
+ } } }
376
+ } }
377
+ } }
378
+ }, async (ctx) => {
379
+ if (!ctx.context.options.user?.deleteUser?.enabled) {
380
+ ctx.context.logger.error("Delete user is disabled. Enable it in the options");
381
+ throw APIError.from("NOT_FOUND", {
382
+ message: "Not found",
383
+ code: "NOT_FOUND"
384
+ });
385
+ }
386
+ const session = await getSessionFromCtx(ctx, { disableCookieCache: isStateful(ctx) });
387
+ if (!session) throw APIError.from("NOT_FOUND", BASE_ERROR_CODES.FAILED_TO_GET_USER_INFO);
388
+ const token = await ctx.context.internalAdapter.consumeVerificationValue(`delete-account-${ctx.query.token}`);
389
+ if (!token || token.value !== session.user.id) throw APIError.from("NOT_FOUND", BASE_ERROR_CODES.INVALID_TOKEN);
390
+ const beforeDelete = ctx.context.options.user.deleteUser?.beforeDelete;
391
+ if (beforeDelete) await beforeDelete(session.user, ctx.request);
392
+ await ctx.context.internalAdapter.deleteUser(session.user.id);
393
+ await ctx.context.internalAdapter.deleteUserSessions(session.user.id);
394
+ await ctx.context.internalAdapter.deleteAccounts(session.user.id);
395
+ deleteSessionCookie(ctx);
396
+ const afterDelete = ctx.context.options.user.deleteUser?.afterDelete;
397
+ if (afterDelete) await afterDelete(session.user, ctx.request);
398
+ if (ctx.query.callbackURL) throw ctx.redirect(ctx.query.callbackURL || "/");
399
+ return ctx.json({
400
+ success: true,
401
+ message: "User deleted"
402
+ });
403
+ });
404
+ const changeEmail = createAuthEndpoint("/change-email", {
405
+ method: "POST",
406
+ body: z.object({
407
+ newEmail: z.email().meta({ description: "The new email address to set must be a valid email address" }),
408
+ callbackURL: z.string().meta({ description: "The URL to redirect to after email verification" }).optional()
409
+ }),
410
+ use: [sensitiveSessionMiddleware],
411
+ metadata: { openapi: {
412
+ operationId: "changeEmail",
413
+ responses: { "200": {
414
+ description: "Email change request processed successfully",
415
+ content: { "application/json": { schema: {
416
+ type: "object",
417
+ properties: {
418
+ user: {
419
+ type: "object",
420
+ $ref: "#/components/schemas/User"
421
+ },
422
+ status: {
423
+ type: "boolean",
424
+ description: "Indicates if the request was successful"
425
+ },
426
+ message: {
427
+ type: "string",
428
+ enum: ["Email updated", "Verification email sent"],
429
+ description: "Status message of the email change process",
430
+ nullable: true
431
+ }
432
+ },
433
+ required: ["status"]
434
+ } } }
435
+ } }
436
+ } }
437
+ }, async (ctx) => {
438
+ if (!ctx.context.options.user?.changeEmail?.enabled) {
439
+ ctx.context.logger.error("Change email is disabled.");
440
+ throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.CHANGE_EMAIL_DISABLED);
441
+ }
442
+ const newEmail = ctx.body.newEmail.toLowerCase();
443
+ if (newEmail === ctx.context.session.user.email) {
444
+ ctx.context.logger.warn("Email is the same");
445
+ throw APIError.fromStatus("BAD_REQUEST", { message: "Email is the same" });
446
+ }
447
+ /**
448
+ * Early config check: ensure at least one email-change flow is
449
+ * available for the current session state. Without this, an
450
+ * existing-email lookup would return 200 while a non-existing
451
+ * email would later throw 400, leaking email existence.
452
+ */
453
+ const canUpdateWithoutVerification = ctx.context.session.user.emailVerified !== true && ctx.context.options.user.changeEmail.updateEmailWithoutVerification;
454
+ const canSendVerification = ctx.context.options.emailVerification?.sendVerificationEmail;
455
+ const canSendConfirmation = canSendVerification && ctx.context.session.user.emailVerified && ctx.context.options.user.changeEmail.sendChangeEmailConfirmation;
456
+ if (!canUpdateWithoutVerification && !canSendConfirmation && !canSendVerification) {
457
+ ctx.context.logger.error("Verification email isn't enabled.");
458
+ throw APIError.fromStatus("BAD_REQUEST", { message: "Verification email isn't enabled" });
459
+ }
460
+ if (await ctx.context.internalAdapter.findUserByEmail(newEmail)) {
461
+ await createEmailVerificationToken(ctx.context.secret, ctx.context.session.user.email, newEmail, ctx.context.options.emailVerification?.expiresIn);
462
+ ctx.context.logger.info("Change email attempt for existing email");
463
+ return ctx.json({ status: true });
464
+ }
465
+ /**
466
+ * If the email is not verified, we can update the email if the option is enabled
467
+ */
468
+ if (canUpdateWithoutVerification) {
469
+ await ctx.context.internalAdapter.updateUser(ctx.context.session.user.id, { email: newEmail });
470
+ await setSessionCookie(ctx, {
471
+ session: ctx.context.session.session,
472
+ user: {
473
+ ...ctx.context.session.user,
474
+ email: newEmail
475
+ }
476
+ });
477
+ if (canSendVerification) {
478
+ const token = await createEmailVerificationToken(ctx.context.secret, newEmail, void 0, ctx.context.options.emailVerification?.expiresIn);
479
+ const url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${encodeURIComponent(ctx.body.callbackURL || "/")}`;
480
+ await ctx.context.runInBackgroundOrAwait(canSendVerification({
481
+ user: {
482
+ ...ctx.context.session.user,
483
+ email: newEmail
484
+ },
485
+ url,
486
+ token
487
+ }, ctx.request));
488
+ }
489
+ return ctx.json({ status: true });
490
+ }
491
+ /**
492
+ * If the email is verified, we need to send a verification email
493
+ */
494
+ if (canSendConfirmation) {
495
+ const token = await createEmailVerificationToken(ctx.context.secret, ctx.context.session.user.email, newEmail, ctx.context.options.emailVerification?.expiresIn, { requestType: "change-email-confirmation" });
496
+ const url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${encodeURIComponent(ctx.body.callbackURL || "/")}`;
497
+ await ctx.context.runInBackgroundOrAwait(canSendConfirmation({
498
+ user: ctx.context.session.user,
499
+ newEmail,
500
+ url,
501
+ token
502
+ }, ctx.request));
503
+ return ctx.json({ status: true });
504
+ }
505
+ if (!canSendVerification) {
506
+ ctx.context.logger.error("Verification email isn't enabled.");
507
+ throw APIError.fromStatus("BAD_REQUEST", { message: "Verification email isn't enabled" });
508
+ }
509
+ const token = await createEmailVerificationToken(ctx.context.secret, ctx.context.session.user.email, newEmail, ctx.context.options.emailVerification?.expiresIn, { requestType: "change-email-verification" });
510
+ const url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${encodeURIComponent(ctx.body.callbackURL || "/")}`;
511
+ await ctx.context.runInBackgroundOrAwait(canSendVerification({
512
+ user: {
513
+ ...ctx.context.session.user,
514
+ email: newEmail
515
+ },
516
+ url,
517
+ token
518
+ }, ctx.request));
519
+ return ctx.json({ status: true });
520
+ });
521
+ //#endregion
522
+ export { changeEmail, changePassword, deleteUser, deleteUserCallback, setPassword, updateUser };
@@ -0,0 +1,53 @@
1
+ //#region src/api/state/oauth.d.ts
2
+ type OAuthState = {
3
+ callbackURL: string;
4
+ codeVerifier: string;
5
+ errorURL?: string;
6
+ newUserURL?: string;
7
+ link?: {
8
+ email: string;
9
+ userId: string;
10
+ };
11
+ expiresAt: number;
12
+ requestSignUp?: boolean;
13
+ /**
14
+ * Server-controlled values that ride the OAuth state across the provider
15
+ * redirect. Nothing here is reachable from the request body: plugins write it
16
+ * with `addOAuthServerContext` and read it back on the callback. Use this for
17
+ * data the server must trust (identity, flow continuation), unlike the
18
+ * top-level `additionalData` keys below.
19
+ */
20
+ serverContext?: Record<string, unknown>;
21
+ /**
22
+ * Client-supplied `additionalData` is spread onto the top level. Treat every
23
+ * key here as untrusted input: it originates from the request body.
24
+ */
25
+ [key: string]: any;
26
+ };
27
+ /**
28
+ * Reads the OAuth state for the current request. During a callback it holds the
29
+ * state parsed from the provider redirect; during sign-in it holds the state
30
+ * just generated.
31
+ *
32
+ * Top-level keys beyond the documented fields are client-supplied
33
+ * (`additionalData`) and must not be trusted. Server-trusted values live under
34
+ * {@link OAuthState.serverContext}.
35
+ */
36
+ declare const getOAuthState: <T extends Record<string, unknown> = Record<string, unknown>>() => Promise<(OAuthState & T) | null>;
37
+ /**
38
+ * @internal Read accumulated server context to embed during state generation.
39
+ */
40
+ /**
41
+ * Attaches server-trusted data to the current OAuth flow so it survives the
42
+ * provider redirect. Call this from a `before` hook on an OAuth sign-in path
43
+ * (for example `/sign-in/social` or `/sign-in/oauth2`). `generateState` embeds
44
+ * the accumulated values into the state, and they become readable on the
45
+ * callback via `getOAuthState().serverContext`.
46
+ *
47
+ * Unlike the request body's `additionalData`, values set here cannot be spoofed
48
+ * by the client. Multiple callers merge: each call adds its own keys. Values are
49
+ * stored as `unknown`, so narrow their shape when reading them back.
50
+ */
51
+ declare const addOAuthServerContext: (values: Record<string, unknown>) => Promise<void>;
52
+ //#endregion
53
+ export { addOAuthServerContext, getOAuthState };
@@ -0,0 +1,38 @@
1
+ import { defineRequestState } from "@better-auth/core/context";
2
+ //#region src/api/state/oauth.ts
3
+ const { get: getRawOAuthState, set: setOAuthState } = defineRequestState(() => null);
4
+ /**
5
+ * Reads the OAuth state for the current request. During a callback it holds the
6
+ * state parsed from the provider redirect; during sign-in it holds the state
7
+ * just generated.
8
+ *
9
+ * Top-level keys beyond the documented fields are client-supplied
10
+ * (`additionalData`) and must not be trusted. Server-trusted values live under
11
+ * {@link OAuthState.serverContext}.
12
+ */
13
+ const getOAuthState = async () => {
14
+ return await getRawOAuthState();
15
+ };
16
+ /**
17
+ * @internal Read accumulated server context to embed during state generation.
18
+ */
19
+ const { get: getOAuthServerContext, set: setOAuthServerContext } = defineRequestState(() => null);
20
+ /**
21
+ * Attaches server-trusted data to the current OAuth flow so it survives the
22
+ * provider redirect. Call this from a `before` hook on an OAuth sign-in path
23
+ * (for example `/sign-in/social` or `/sign-in/oauth2`). `generateState` embeds
24
+ * the accumulated values into the state, and they become readable on the
25
+ * callback via `getOAuthState().serverContext`.
26
+ *
27
+ * Unlike the request body's `additionalData`, values set here cannot be spoofed
28
+ * by the client. Multiple callers merge: each call adds its own keys. Values are
29
+ * stored as `unknown`, so narrow their shape when reading them back.
30
+ */
31
+ const addOAuthServerContext = async (values) => {
32
+ await setOAuthServerContext({
33
+ ...await getOAuthServerContext() ?? {},
34
+ ...values
35
+ });
36
+ };
37
+ //#endregion
38
+ export { addOAuthServerContext, getOAuthServerContext, getOAuthState, setOAuthState };
@@ -0,0 +1,12 @@
1
+ //#region src/api/state/should-session-refresh.d.ts
2
+ /**
3
+ * State for skipping session refresh
4
+ *
5
+ * In some cases, such as when using server-side rendering (SSR) or when dealing with
6
+ * certain types of requests, it may be necessary to skip session refresh to prevent
7
+ * potential inconsistencies between the session data in the database and the session
8
+ * data stored in cookies.
9
+ */
10
+ declare const getShouldSkipSessionRefresh: () => Promise<boolean | null>, setShouldSkipSessionRefresh: (value: boolean | null) => Promise<void>;
11
+ //#endregion
12
+ export { getShouldSkipSessionRefresh, setShouldSkipSessionRefresh };
@@ -0,0 +1,13 @@
1
+ import { defineRequestState } from "@better-auth/core/context";
2
+ //#region src/api/state/should-session-refresh.ts
3
+ /**
4
+ * State for skipping session refresh
5
+ *
6
+ * In some cases, such as when using server-side rendering (SSR) or when dealing with
7
+ * certain types of requests, it may be necessary to skip session refresh to prevent
8
+ * potential inconsistencies between the session data in the database and the session
9
+ * data stored in cookies.
10
+ */
11
+ const { get: getShouldSkipSessionRefresh, set: setShouldSkipSessionRefresh } = defineRequestState(() => false);
12
+ //#endregion
13
+ export { getShouldSkipSessionRefresh, setShouldSkipSessionRefresh };