@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,784 @@
1
+ import { formCsrfMiddleware } from "../../api/middlewares/origin-check.mjs";
2
+ import { parseUserInput, parseUserOutput } from "../../db/schema.mjs";
3
+ import { getDate } from "../../utils/date.mjs";
4
+ import { generateRandomString } from "../../crypto/random.mjs";
5
+ import { symmetricDecrypt } from "../../crypto/index.mjs";
6
+ import { setCookieCache, setSessionCookie } from "../../cookies/index.mjs";
7
+ import { revokeUnprovenAccountAccess } from "../../db/revoke-unproven-account-access.mjs";
8
+ import { getSessionFromCtx, sensitiveSessionMiddleware } from "../../api/routes/session.mjs";
9
+ import { APIError as APIError$1 } from "../../api/index.mjs";
10
+ import { EMAIL_OTP_ERROR_CODES } from "./error-codes.mjs";
11
+ import { splitAtLastColon, toOTPIdentifier } from "./utils.mjs";
12
+ import { storeOTP, tryReuseOTP, verifyStoredOTP } from "./otp-token.mjs";
13
+ import { BASE_ERROR_CODES } from "@better-auth/core/error";
14
+ import { createAuthEndpoint } from "@better-auth/core/api";
15
+ import { deprecate } from "@better-auth/core/utils/deprecate";
16
+ import * as z from "zod";
17
+ //#region src/plugins/email-otp/routes.ts
18
+ const types = [
19
+ "email-verification",
20
+ "sign-in",
21
+ "forget-password",
22
+ "change-email"
23
+ ];
24
+ /**
25
+ * Resolves the OTP to send: reuses an existing one if possible,
26
+ * otherwise generates and stores a new one.
27
+ *
28
+ * @internal
29
+ */
30
+ async function resolveOTP(ctx, opts, email, type) {
31
+ const identifier = toOTPIdentifier(type, email);
32
+ if (opts.resendStrategy === "reuse") {
33
+ const reused = await tryReuseOTP(ctx, opts, identifier);
34
+ if (reused) return reused;
35
+ }
36
+ const otp = opts.generateOTP({
37
+ email,
38
+ type
39
+ }, ctx) || defaultOTPGenerator(opts);
40
+ const storedOTP = await storeOTP(ctx, opts, otp);
41
+ await ctx.context.internalAdapter.createVerificationValue({
42
+ value: `${storedOTP}:0`,
43
+ identifier,
44
+ expiresAt: getDate(opts.expiresIn, "sec")
45
+ }).catch(async () => {
46
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(identifier);
47
+ await ctx.context.internalAdapter.createVerificationValue({
48
+ value: `${storedOTP}:0`,
49
+ identifier,
50
+ expiresAt: getDate(opts.expiresIn, "sec")
51
+ });
52
+ });
53
+ return otp;
54
+ }
55
+ const sendVerificationOTPBodySchema = z.object({
56
+ email: z.string({}).meta({ description: "Email address to send the OTP" }),
57
+ type: z.enum(types).meta({ description: "Type of the OTP" })
58
+ });
59
+ /**
60
+ * ### Endpoint
61
+ *
62
+ * POST `/email-otp/send-verification-otp`
63
+ *
64
+ * ### API Methods
65
+ *
66
+ * **server:**
67
+ * `auth.api.sendVerificationOTP`
68
+ *
69
+ * **client:**
70
+ * `authClient.emailOtp.sendVerificationOtp`
71
+ *
72
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-email-otp-send-verification-otp)
73
+ */
74
+ const sendVerificationOTP = (opts) => createAuthEndpoint("/email-otp/send-verification-otp", {
75
+ method: "POST",
76
+ use: [formCsrfMiddleware],
77
+ body: sendVerificationOTPBodySchema,
78
+ metadata: { openapi: {
79
+ operationId: "sendEmailVerificationOTP",
80
+ description: "Send a verification OTP to an email",
81
+ responses: { 200: {
82
+ description: "Success",
83
+ content: { "application/json": { schema: {
84
+ type: "object",
85
+ properties: { success: { type: "boolean" } }
86
+ } } }
87
+ } }
88
+ } }
89
+ }, async (ctx) => {
90
+ if (!opts?.sendVerificationOTP) {
91
+ ctx.context.logger.error("send email verification is not implemented");
92
+ throw APIError$1.fromStatus("BAD_REQUEST", { message: "send email verification is not implemented" });
93
+ }
94
+ const email = ctx.body.email.toLowerCase();
95
+ if (!z.email().safeParse(email).success) throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_EMAIL);
96
+ if (ctx.body.type === "change-email") {
97
+ ctx.context.logger.error("Use the /email-otp/request-email-change endpoint to send OTP for changing email");
98
+ throw APIError$1.fromStatus("BAD_REQUEST", { message: "Invalid OTP type" });
99
+ }
100
+ const identifier = toOTPIdentifier(ctx.body.type, email);
101
+ const otp = await resolveOTP(ctx, opts, email, ctx.body.type);
102
+ const shouldSendOTP = ctx.body.type === "sign-in" && !opts.disableSignUp;
103
+ if (!await ctx.context.internalAdapter.findUserByEmail(email) && !shouldSendOTP) {
104
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(identifier);
105
+ return ctx.json({ success: true });
106
+ }
107
+ await ctx.context.runInBackgroundOrAwait(opts.sendVerificationOTP({
108
+ email,
109
+ otp,
110
+ type: ctx.body.type
111
+ }, ctx));
112
+ return ctx.json({ success: true });
113
+ });
114
+ const createVerificationOTPBodySchema = z.object({
115
+ email: z.string({}).meta({ description: "Email address to send the OTP" }),
116
+ type: z.enum(types).meta({
117
+ required: true,
118
+ description: "Type of the OTP"
119
+ })
120
+ });
121
+ const createVerificationOTP = (opts) => createAuthEndpoint.serverOnly({
122
+ method: "POST",
123
+ body: createVerificationOTPBodySchema,
124
+ metadata: { openapi: {
125
+ operationId: "createEmailVerificationOTP",
126
+ description: "Create a verification OTP for an email",
127
+ responses: { 200: {
128
+ description: "Success",
129
+ content: { "application/json": { schema: { type: "string" } } }
130
+ } }
131
+ } }
132
+ }, async (ctx) => {
133
+ const email = ctx.body.email.toLowerCase();
134
+ const otp = opts.generateOTP({
135
+ email,
136
+ type: ctx.body.type
137
+ }, ctx) || defaultOTPGenerator(opts);
138
+ const storedOTP = await storeOTP(ctx, opts, otp);
139
+ await ctx.context.internalAdapter.createVerificationValue({
140
+ value: `${storedOTP}:0`,
141
+ identifier: toOTPIdentifier(ctx.body.type, email),
142
+ expiresAt: getDate(opts.expiresIn, "sec")
143
+ });
144
+ return otp;
145
+ });
146
+ const getVerificationOTPBodySchema = z.object({
147
+ email: z.string({}).meta({ description: "Email address the OTP was sent to" }),
148
+ type: z.enum(types).meta({
149
+ required: true,
150
+ description: "Type of the OTP"
151
+ })
152
+ });
153
+ /**
154
+ * ### Endpoint
155
+ *
156
+ * GET `/email-otp/get-verification-otp`
157
+ *
158
+ * ### API Methods
159
+ *
160
+ * **server:**
161
+ * `auth.api.getVerificationOTP`
162
+ *
163
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-email-otp-get-verification-otp)
164
+ */
165
+ const getVerificationOTP = (opts) => createAuthEndpoint.serverOnly({
166
+ method: "GET",
167
+ query: getVerificationOTPBodySchema,
168
+ metadata: { openapi: {
169
+ operationId: "getEmailVerificationOTP",
170
+ description: "Get a verification OTP for an email",
171
+ responses: { "200": {
172
+ description: "OTP retrieved successfully or not found/expired",
173
+ content: { "application/json": { schema: {
174
+ type: "object",
175
+ properties: { otp: {
176
+ type: "string",
177
+ nullable: true,
178
+ description: "The stored OTP, or null if not found or expired"
179
+ } },
180
+ required: ["otp"]
181
+ } } }
182
+ } }
183
+ } }
184
+ }, async (ctx) => {
185
+ const email = ctx.query.email.toLowerCase();
186
+ const verificationValue = await ctx.context.internalAdapter.findVerificationValue(toOTPIdentifier(ctx.query.type, email));
187
+ if (!verificationValue || verificationValue.expiresAt < /* @__PURE__ */ new Date()) return ctx.json({ otp: null });
188
+ if (opts.storeOTP === "hashed" || typeof opts.storeOTP === "object" && "hash" in opts.storeOTP) throw APIError$1.fromStatus("BAD_REQUEST", { message: "OTP is hashed, cannot return the plain text OTP" });
189
+ const [storedOtp, _attempts] = splitAtLastColon(verificationValue.value);
190
+ let otp = storedOtp;
191
+ if (opts.storeOTP === "encrypted") otp = await symmetricDecrypt({
192
+ key: ctx.context.secretConfig,
193
+ data: storedOtp
194
+ });
195
+ if (typeof opts.storeOTP === "object" && "decrypt" in opts.storeOTP) otp = await opts.storeOTP.decrypt(storedOtp);
196
+ return ctx.json({ otp });
197
+ });
198
+ const checkVerificationOTPBodySchema = z.object({
199
+ email: z.string().meta({ description: "Email address the OTP was sent to" }),
200
+ type: z.enum(types).meta({
201
+ required: true,
202
+ description: "Type of the OTP"
203
+ }),
204
+ otp: z.string().meta({
205
+ required: true,
206
+ description: "OTP to verify"
207
+ })
208
+ });
209
+ /**
210
+ * ### Endpoint
211
+ *
212
+ * GET `/email-otp/check-verification-otp`
213
+ *
214
+ * ### API Methods
215
+ *
216
+ * **server:**
217
+ * `auth.api.checkVerificationOTP`
218
+ *
219
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-email-otp-check-verification-otp)
220
+ */
221
+ const checkVerificationOTP = (opts) => createAuthEndpoint("/email-otp/check-verification-otp", {
222
+ method: "POST",
223
+ body: checkVerificationOTPBodySchema,
224
+ metadata: { openapi: {
225
+ operationId: "verifyEmailWithOTP",
226
+ description: "Verify an email with an OTP",
227
+ responses: { 200: {
228
+ description: "Success",
229
+ content: { "application/json": { schema: {
230
+ type: "object",
231
+ properties: { success: { type: "boolean" } }
232
+ } } }
233
+ } }
234
+ } }
235
+ }, async (ctx) => {
236
+ const email = ctx.body.email.toLowerCase();
237
+ if (!z.email().safeParse(email).success) throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_EMAIL);
238
+ const identifier = toOTPIdentifier(ctx.body.type, email);
239
+ const verificationValue = await ctx.context.internalAdapter.findVerificationValue(identifier);
240
+ if (!verificationValue) throw APIError$1.from("BAD_REQUEST", EMAIL_OTP_ERROR_CODES.INVALID_OTP);
241
+ if (verificationValue.expiresAt < /* @__PURE__ */ new Date()) {
242
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(identifier);
243
+ throw APIError$1.from("BAD_REQUEST", EMAIL_OTP_ERROR_CODES.OTP_EXPIRED);
244
+ }
245
+ const [otpValue, attempts] = splitAtLastColon(verificationValue.value);
246
+ const allowedAttempts = opts?.allowedAttempts || 3;
247
+ if (attempts && parseInt(attempts) >= allowedAttempts) {
248
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(identifier);
249
+ throw APIError$1.from("FORBIDDEN", EMAIL_OTP_ERROR_CODES.TOO_MANY_ATTEMPTS);
250
+ }
251
+ if (!await verifyStoredOTP(ctx, opts, otpValue, ctx.body.otp)) {
252
+ await ctx.context.internalAdapter.updateVerificationByIdentifier(identifier, { value: `${otpValue}:${parseInt(attempts || "0") + 1}` });
253
+ throw APIError$1.from("BAD_REQUEST", EMAIL_OTP_ERROR_CODES.INVALID_OTP);
254
+ }
255
+ if (!await ctx.context.internalAdapter.findUserByEmail(email))
256
+ /**
257
+ * safe to leak the existence of a user, given the user has already the OTP from the
258
+ * email
259
+ */
260
+ throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.USER_NOT_FOUND);
261
+ return ctx.json({ success: true });
262
+ });
263
+ const verifyEmailOTPBodySchema = z.object({
264
+ email: z.string({}).meta({ description: "Email address to verify" }),
265
+ otp: z.string().meta({
266
+ required: true,
267
+ description: "OTP to verify"
268
+ })
269
+ });
270
+ /**
271
+ * ### Endpoint
272
+ *
273
+ * POST `/email-otp/verify-email`
274
+ *
275
+ * ### API Methods
276
+ *
277
+ * **server:**
278
+ * `auth.api.verifyEmailOTP`
279
+ *
280
+ * **client:**
281
+ * `authClient.emailOtp.verifyEmail`
282
+ *
283
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-email-otp-verify-email)
284
+ */
285
+ const verifyEmailOTP = (opts) => createAuthEndpoint("/email-otp/verify-email", {
286
+ method: "POST",
287
+ body: verifyEmailOTPBodySchema,
288
+ metadata: { openapi: {
289
+ description: "Verify email with OTP",
290
+ responses: { 200: {
291
+ description: "Success",
292
+ content: { "application/json": { schema: {
293
+ type: "object",
294
+ properties: {
295
+ status: {
296
+ type: "boolean",
297
+ description: "Indicates if the verification was successful",
298
+ enum: [true]
299
+ },
300
+ token: {
301
+ type: "string",
302
+ nullable: true,
303
+ description: "Session token if autoSignInAfterVerification is enabled, otherwise null"
304
+ },
305
+ user: { $ref: "#/components/schemas/User" }
306
+ },
307
+ required: [
308
+ "status",
309
+ "token",
310
+ "user"
311
+ ]
312
+ } } }
313
+ } }
314
+ } }
315
+ }, async (ctx) => {
316
+ const email = ctx.body.email.toLowerCase();
317
+ if (!z.email().safeParse(email).success) throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_EMAIL);
318
+ await atomicVerifyOTP(ctx, opts, toOTPIdentifier("email-verification", email), ctx.body.otp);
319
+ const user = await ctx.context.internalAdapter.findUserByEmail(email);
320
+ if (!user)
321
+ /**
322
+ * safe to leak the existence of a user, given the user has already the OTP from the
323
+ * email
324
+ */
325
+ throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.USER_NOT_FOUND);
326
+ if (ctx.context.options.emailVerification?.beforeEmailVerification) await ctx.context.options.emailVerification.beforeEmailVerification(user.user, ctx.request);
327
+ const updatedUser = await ctx.context.internalAdapter.updateUser(user.user.id, {
328
+ email,
329
+ emailVerified: true
330
+ });
331
+ await ctx.context.options.emailVerification?.afterEmailVerification?.(updatedUser, ctx.request);
332
+ if (ctx.context.options.emailVerification?.autoSignInAfterVerification) {
333
+ const session = await ctx.context.internalAdapter.createSession(updatedUser.id);
334
+ await setSessionCookie(ctx, {
335
+ session,
336
+ user: updatedUser
337
+ });
338
+ return ctx.json({
339
+ status: true,
340
+ token: session.token,
341
+ user: parseUserOutput(ctx.context.options, updatedUser)
342
+ });
343
+ }
344
+ const currentSession = await getSessionFromCtx(ctx);
345
+ if (currentSession && updatedUser.emailVerified && currentSession.user.id === updatedUser.id) {
346
+ const dontRememberMeCookie = await ctx.getSignedCookie(ctx.context.authCookies.dontRememberToken.name, ctx.context.secret);
347
+ await setCookieCache(ctx, {
348
+ session: currentSession.session,
349
+ user: {
350
+ ...currentSession.user,
351
+ emailVerified: true
352
+ }
353
+ }, !!dontRememberMeCookie);
354
+ }
355
+ return ctx.json({
356
+ status: true,
357
+ token: null,
358
+ user: parseUserOutput(ctx.context.options, updatedUser)
359
+ });
360
+ });
361
+ const signInEmailOTPBodySchema = z.object({
362
+ email: z.string({}).meta({ description: "Email address to sign in" }),
363
+ otp: z.string().meta({
364
+ required: true,
365
+ description: "OTP sent to the email"
366
+ }),
367
+ name: z.string().meta({ description: "User display name. Only used if the user is registering for the first time. Eg: \"my-name\"" }).optional(),
368
+ image: z.string().meta({ description: "User profile image URL. Only used if the user is registering for the first time." }).optional()
369
+ }).and(z.record(z.string(), z.any()));
370
+ /**
371
+ * ### Endpoint
372
+ *
373
+ * POST `/sign-in/email-otp`
374
+ *
375
+ * ### API Methods
376
+ *
377
+ * **server:**
378
+ * `auth.api.signInEmailOTP`
379
+ *
380
+ * **client:**
381
+ * `authClient.signIn.emailOtp`
382
+ *
383
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-sign-in-email-otp)
384
+ */
385
+ const signInEmailOTP = (opts) => createAuthEndpoint("/sign-in/email-otp", {
386
+ method: "POST",
387
+ body: signInEmailOTPBodySchema,
388
+ metadata: { openapi: {
389
+ operationId: "signInWithEmailOTP",
390
+ description: "Sign in with email and OTP",
391
+ responses: { 200: {
392
+ description: "Success",
393
+ content: { "application/json": { schema: {
394
+ type: "object",
395
+ properties: {
396
+ token: {
397
+ type: "string",
398
+ description: "Session token for the authenticated session"
399
+ },
400
+ user: { $ref: "#/components/schemas/User" }
401
+ },
402
+ required: ["token", "user"]
403
+ } } }
404
+ } }
405
+ } }
406
+ }, async (ctx) => {
407
+ const { email: rawEmail, otp, name, image, ...rest } = ctx.body;
408
+ const email = rawEmail.toLowerCase();
409
+ await atomicVerifyOTP(ctx, opts, toOTPIdentifier("sign-in", email), otp);
410
+ const user = await ctx.context.internalAdapter.findUserByEmail(email);
411
+ if (!user) {
412
+ if (opts.disableSignUp) throw APIError$1.from("BAD_REQUEST", EMAIL_OTP_ERROR_CODES.INVALID_OTP);
413
+ const additionalFields = parseUserInput(ctx.context.options, rest, "create");
414
+ const newUser = await ctx.context.internalAdapter.createUser({
415
+ ...additionalFields,
416
+ email,
417
+ emailVerified: true,
418
+ name: name || "",
419
+ image
420
+ }, { method: "email-otp" });
421
+ const session = await ctx.context.internalAdapter.createSession(newUser.id);
422
+ await setSessionCookie(ctx, {
423
+ session,
424
+ user: newUser
425
+ });
426
+ return ctx.json({
427
+ token: session.token,
428
+ user: parseUserOutput(ctx.context.options, newUser)
429
+ });
430
+ }
431
+ let verifiedUser = user.user;
432
+ if (!verifiedUser.emailVerified) {
433
+ const promotedUser = await revokeUnprovenAccountAccess(ctx, verifiedUser.id);
434
+ if (!promotedUser) throw APIError$1.from("BAD_REQUEST", EMAIL_OTP_ERROR_CODES.INVALID_OTP);
435
+ verifiedUser = promotedUser;
436
+ }
437
+ const session = await ctx.context.internalAdapter.createSession(verifiedUser.id);
438
+ await setSessionCookie(ctx, {
439
+ session,
440
+ user: verifiedUser
441
+ });
442
+ return ctx.json({
443
+ token: session.token,
444
+ user: parseUserOutput(ctx.context.options, verifiedUser)
445
+ });
446
+ });
447
+ const requestPasswordResetEmailOTPBodySchema = z.object({ email: z.string().meta({ description: "Email address to send the OTP" }) });
448
+ /**
449
+ * ### Endpoint
450
+ *
451
+ * POST `/email-otp/request-password-reset`
452
+ *
453
+ * ### API Methods
454
+ *
455
+ * **server:**
456
+ * `auth.api.requestPasswordResetEmailOTP`
457
+ *
458
+ * **client:**
459
+ * `authClient.emailOtp.requestPasswordReset`
460
+ *
461
+ * @see [Read our docs to learn more.](https://www.better-auth.com/docs/plugins/email-otp#reset-password-with-otp)
462
+ */
463
+ const requestPasswordResetEmailOTP = (opts) => createAuthEndpoint("/email-otp/request-password-reset", {
464
+ method: "POST",
465
+ body: requestPasswordResetEmailOTPBodySchema,
466
+ metadata: { openapi: {
467
+ operationId: "requestPasswordResetWithEmailOTP",
468
+ description: "Request password reset with email and OTP",
469
+ responses: { 200: {
470
+ description: "Success",
471
+ content: { "application/json": { schema: {
472
+ type: "object",
473
+ properties: { success: {
474
+ type: "boolean",
475
+ description: "Indicates if the OTP was sent successfully"
476
+ } }
477
+ } } }
478
+ } }
479
+ } }
480
+ }, async (ctx) => {
481
+ const email = ctx.body.email.toLowerCase();
482
+ const identifier = toOTPIdentifier("forget-password", email);
483
+ const otp = await resolveOTP(ctx, opts, email, "forget-password");
484
+ if (!await ctx.context.internalAdapter.findUserByEmail(email)) {
485
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(identifier);
486
+ return ctx.json({ success: true });
487
+ }
488
+ await ctx.context.runInBackgroundOrAwait(opts.sendVerificationOTP({
489
+ email,
490
+ otp,
491
+ type: "forget-password"
492
+ }, ctx));
493
+ return ctx.json({ success: true });
494
+ });
495
+ const forgetPasswordEmailOTPBodySchema = z.object({ email: z.string().meta({ description: "Email address to send the OTP" }) });
496
+ /**
497
+ * ### Endpoint
498
+ *
499
+ * POST `/forget-password/email-otp`
500
+ *
501
+ * ### API Methods
502
+ *
503
+ * **server:**
504
+ * `auth.api.forgetPasswordEmailOTP`
505
+ *
506
+ * **client:**
507
+ * `authClient.forgetPassword.emailOtp`
508
+ *
509
+ * @deprecated Use `/email-otp/request-password-reset` instead.
510
+ * @see [Read our docs to learn more.](https://www.better-auth.com/docs/plugins/email-otp#reset-password-with-otp)
511
+ */
512
+ const forgetPasswordEmailOTP = (opts) => {
513
+ const warnDeprecation = deprecate(() => {}, "The \"/forget-password/email-otp\" endpoint is deprecated. Please use \"/email-otp/request-password-reset\" instead. This endpoint will be removed in the next major version.");
514
+ return createAuthEndpoint("/forget-password/email-otp", {
515
+ method: "POST",
516
+ body: forgetPasswordEmailOTPBodySchema,
517
+ metadata: { openapi: {
518
+ operationId: "forgetPasswordWithEmailOTP",
519
+ description: "Deprecated: Use /email-otp/request-password-reset instead.",
520
+ responses: { 200: {
521
+ description: "Success",
522
+ content: { "application/json": { schema: {
523
+ type: "object",
524
+ properties: { success: {
525
+ type: "boolean",
526
+ description: "Indicates if the OTP was sent successfully"
527
+ } }
528
+ } } }
529
+ } }
530
+ } }
531
+ }, async (ctx) => {
532
+ warnDeprecation();
533
+ const email = ctx.body.email.toLowerCase();
534
+ const identifier = toOTPIdentifier("forget-password", email);
535
+ const otp = await resolveOTP(ctx, opts, email, "forget-password");
536
+ if (!await ctx.context.internalAdapter.findUserByEmail(email)) {
537
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(identifier);
538
+ return ctx.json({ success: true });
539
+ }
540
+ await ctx.context.runInBackgroundOrAwait(opts.sendVerificationOTP({
541
+ email,
542
+ otp,
543
+ type: "forget-password"
544
+ }, ctx));
545
+ return ctx.json({ success: true });
546
+ });
547
+ };
548
+ const resetPasswordEmailOTPBodySchema = z.object({
549
+ email: z.string().meta({ description: "Email address to reset the password" }),
550
+ otp: z.string().meta({ description: "OTP sent to the email" }),
551
+ password: z.string().meta({ description: "New password" })
552
+ });
553
+ /**
554
+ * ### Endpoint
555
+ *
556
+ * POST `/email-otp/reset-password`
557
+ *
558
+ * ### API Methods
559
+ *
560
+ * **server:**
561
+ * `auth.api.resetPasswordEmailOTP`
562
+ *
563
+ * **client:**
564
+ * `authClient.emailOtp.resetPassword`
565
+ *
566
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#api-method-email-otp-reset-password)
567
+ */
568
+ const resetPasswordEmailOTP = (opts) => createAuthEndpoint("/email-otp/reset-password", {
569
+ method: "POST",
570
+ body: resetPasswordEmailOTPBodySchema,
571
+ metadata: { openapi: {
572
+ operationId: "resetPasswordWithEmailOTP",
573
+ description: "Reset password with email and OTP",
574
+ responses: { 200: {
575
+ description: "Success",
576
+ content: { "application/json": { schema: {
577
+ type: "object",
578
+ properties: { success: { type: "boolean" } }
579
+ } } }
580
+ } }
581
+ } }
582
+ }, async (ctx) => {
583
+ const email = ctx.body.email.toLowerCase();
584
+ const minPasswordLength = ctx.context.password.config.minPasswordLength;
585
+ if (ctx.body.password.length < minPasswordLength) throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);
586
+ const maxPasswordLength = ctx.context.password.config.maxPasswordLength;
587
+ if (ctx.body.password.length > maxPasswordLength) throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_LONG);
588
+ await atomicVerifyOTP(ctx, opts, toOTPIdentifier("forget-password", email), ctx.body.otp);
589
+ const user = await ctx.context.internalAdapter.findUserByEmail(email);
590
+ if (!user) throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.USER_NOT_FOUND);
591
+ const passwordHash = await ctx.context.password.hash(ctx.body.password);
592
+ if (!await ctx.context.internalAdapter.findCredentialAccount(user.user.id)) await ctx.context.internalAdapter.createAccount({
593
+ userId: user.user.id,
594
+ providerId: "credential",
595
+ accountId: user.user.id,
596
+ password: passwordHash
597
+ });
598
+ else await ctx.context.internalAdapter.updatePassword(user.user.id, passwordHash);
599
+ if (ctx.context.options.emailAndPassword?.onPasswordReset) await ctx.context.options.emailAndPassword.onPasswordReset({ user: user.user }, ctx.request);
600
+ if (!user.user.emailVerified) await ctx.context.internalAdapter.updateUser(user.user.id, { emailVerified: true });
601
+ if (ctx.context.options.emailAndPassword?.revokeSessionsOnPasswordReset) await ctx.context.internalAdapter.deleteUserSessions(user.user.id);
602
+ return ctx.json({ success: true });
603
+ });
604
+ const requestEmailChangeEmailOTPBodySchema = z.object({
605
+ newEmail: z.string().meta({ description: "New email address to send the OTP" }),
606
+ otp: z.string().optional().meta({ description: "OTP sent to the current email. This is required if changeEmail.verifyCurrentEmail option is set to true" })
607
+ });
608
+ /**
609
+ * ### Endpoint
610
+ *
611
+ * POST `/email-otp/request-email-change`
612
+ *
613
+ * ### API Methods
614
+ *
615
+ * **server:**
616
+ * `auth.api.requestEmailChangeEmailOTP`
617
+ *
618
+ * **client:**
619
+ * `authClient.emailOtp.requestEmailChange`
620
+ *
621
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#change-email-with-otp)
622
+ */
623
+ const requestEmailChangeEmailOTP = (opts) => createAuthEndpoint("/email-otp/request-email-change", {
624
+ method: "POST",
625
+ body: requestEmailChangeEmailOTPBodySchema,
626
+ use: [sensitiveSessionMiddleware],
627
+ metadata: { openapi: {
628
+ operationId: "requestEmailChangeWithEmailOTP",
629
+ description: "Request email change with verification OTP sent to the new email",
630
+ responses: { 200: {
631
+ description: "Success",
632
+ content: { "application/json": { schema: {
633
+ type: "object",
634
+ properties: { success: { type: "boolean" } }
635
+ } } }
636
+ } }
637
+ } }
638
+ }, async (ctx) => {
639
+ if (!opts.changeEmail?.enabled) {
640
+ ctx.context.logger.error("Change email with OTP is disabled.");
641
+ throw APIError$1.fromStatus("BAD_REQUEST", { message: "Change email with OTP is disabled" });
642
+ }
643
+ const email = ctx.context.session.user.email.toLowerCase();
644
+ const newEmail = ctx.body.newEmail.toLowerCase();
645
+ if (!z.email().safeParse(newEmail).success) throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_EMAIL);
646
+ if (newEmail === email) {
647
+ ctx.context.logger.error("Email is the same");
648
+ throw APIError$1.fromStatus("BAD_REQUEST", { message: "Email is the same" });
649
+ }
650
+ if (opts.changeEmail?.verifyCurrentEmail) {
651
+ if (!ctx.body.otp) throw APIError$1.fromStatus("BAD_REQUEST", { message: "OTP is required to verify current email" });
652
+ await atomicVerifyOTP(ctx, opts, toOTPIdentifier("email-verification", email), ctx.body.otp);
653
+ } else if (ctx.body.otp) ctx.context.logger.warn("OTP provided but not required for verifying current email. If you want to require OTP verification for current email, please set the changeEmail.verifyCurrentEmail option to true in the configuration");
654
+ const otp = opts.generateOTP({
655
+ email: newEmail,
656
+ type: "change-email"
657
+ }, ctx) || defaultOTPGenerator(opts);
658
+ const storedOTP = await storeOTP(ctx, opts, otp);
659
+ await ctx.context.internalAdapter.createVerificationValue({
660
+ value: `${storedOTP}:0`,
661
+ identifier: toOTPIdentifier("change-email", `${email}-${newEmail}`),
662
+ expiresAt: getDate(opts.expiresIn, "sec")
663
+ });
664
+ if (await ctx.context.internalAdapter.findUserByEmail(newEmail)) {
665
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(toOTPIdentifier("change-email", `${email}-${newEmail}`));
666
+ return ctx.json({ success: true });
667
+ }
668
+ await ctx.context.runInBackgroundOrAwait(opts.sendVerificationOTP({
669
+ email: newEmail,
670
+ otp,
671
+ type: "change-email"
672
+ }, ctx));
673
+ return ctx.json({ success: true });
674
+ });
675
+ const changeEmailEmailOTPBodySchema = z.object({
676
+ newEmail: z.string().meta({ description: "New email address to verify and change to" }),
677
+ otp: z.string().meta({ description: "OTP sent to the new email" })
678
+ });
679
+ /**
680
+ * ### Endpoint
681
+ *
682
+ * POST `/email-otp/change-email`
683
+ *
684
+ * ### API Methods
685
+ *
686
+ * **server:**
687
+ * `auth.api.changeEmailEmailOTP`
688
+ *
689
+ * **client:**
690
+ * `authClient.emailOtp.changeEmail`
691
+ *
692
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/email-otp#change-email-with-otp)
693
+ */
694
+ const changeEmailEmailOTP = (opts) => createAuthEndpoint("/email-otp/change-email", {
695
+ method: "POST",
696
+ body: changeEmailEmailOTPBodySchema,
697
+ use: [sensitiveSessionMiddleware],
698
+ metadata: { openapi: {
699
+ operationId: "changeEmailWithEmailOTP",
700
+ description: "Verify new email with OTP and change the email if verification is successful",
701
+ responses: { 200: {
702
+ description: "Success",
703
+ content: { "application/json": { schema: {
704
+ type: "object",
705
+ properties: { success: { type: "boolean" } }
706
+ } } }
707
+ } }
708
+ } }
709
+ }, async (ctx) => {
710
+ if (!opts.changeEmail?.enabled) {
711
+ ctx.context.logger.error("Change email with OTP is disabled.");
712
+ throw APIError$1.fromStatus("BAD_REQUEST", { message: "Change email with OTP is disabled" });
713
+ }
714
+ const session = ctx.context.session;
715
+ const email = session.user.email.toLowerCase();
716
+ const newEmail = ctx.body.newEmail.toLowerCase();
717
+ if (!z.email().safeParse(newEmail).success) throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_EMAIL);
718
+ if (newEmail === email) {
719
+ ctx.context.logger.error("Email is the same");
720
+ throw APIError$1.fromStatus("BAD_REQUEST", { message: "Email is the same" });
721
+ }
722
+ await atomicVerifyOTP(ctx, opts, toOTPIdentifier("change-email", `${email}-${newEmail}`), ctx.body.otp);
723
+ const currentUser = await ctx.context.internalAdapter.findUserByEmail(email);
724
+ if (!currentUser)
725
+ /**
726
+ * safe to leak the existence of a user as a valid OTP has been provided
727
+ */
728
+ throw APIError$1.from("BAD_REQUEST", BASE_ERROR_CODES.USER_NOT_FOUND);
729
+ if (await ctx.context.internalAdapter.findUserByEmail(newEmail))
730
+ /**
731
+ * safe to leak the existence of a user as a valid OTP has been provided
732
+ */
733
+ throw APIError$1.fromStatus("BAD_REQUEST", { message: "Email already in use" });
734
+ if (ctx.context.options.emailVerification?.beforeEmailVerification) await ctx.context.options.emailVerification.beforeEmailVerification(currentUser.user, ctx.request);
735
+ const updatedUser = await ctx.context.internalAdapter.updateUser(currentUser.user.id, {
736
+ email: newEmail,
737
+ emailVerified: true
738
+ });
739
+ if (ctx.context.options.emailVerification?.afterEmailVerification) await ctx.context.options.emailVerification.afterEmailVerification(updatedUser, ctx.request);
740
+ await setSessionCookie(ctx, {
741
+ session: session.session,
742
+ user: {
743
+ ...session.user,
744
+ email: newEmail,
745
+ emailVerified: true
746
+ }
747
+ });
748
+ return ctx.json({ success: true });
749
+ });
750
+ const defaultOTPGenerator = (options) => generateRandomString(options.otpLength ?? 6, "0-9");
751
+ /**
752
+ * Verifies a single-use OTP with race-condition protection.
753
+ *
754
+ * The atomic consume is the single gate: only the first concurrent caller
755
+ * receives the record, every later racer receives `null` and is rejected, so
756
+ * a correct OTP can only ever be accepted once. When the submitted code is
757
+ * wrong the record is recreated with the same value and expiry and an
758
+ * incremented attempt count so the next try can still find it; the budget is
759
+ * enforced before verification, and a record whose attempts are exhausted is
760
+ * left consumed (no recreate), locking the identifier out.
761
+ */
762
+ async function atomicVerifyOTP(ctx, opts, identifier, providedOTP) {
763
+ const existing = await ctx.context.internalAdapter.findVerificationValue(identifier);
764
+ if (existing && existing.expiresAt < /* @__PURE__ */ new Date()) {
765
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(identifier);
766
+ throw APIError$1.from("BAD_REQUEST", EMAIL_OTP_ERROR_CODES.OTP_EXPIRED);
767
+ }
768
+ const consumed = await ctx.context.internalAdapter.consumeVerificationValue(identifier);
769
+ if (!consumed) throw APIError$1.from("BAD_REQUEST", EMAIL_OTP_ERROR_CODES.INVALID_OTP);
770
+ const [otpValue, attempts] = splitAtLastColon(consumed.value);
771
+ const allowedAttempts = opts?.allowedAttempts || 3;
772
+ const usedAttempts = parseInt(attempts || "0");
773
+ if (usedAttempts >= allowedAttempts) throw APIError$1.from("FORBIDDEN", EMAIL_OTP_ERROR_CODES.TOO_MANY_ATTEMPTS);
774
+ if (!await verifyStoredOTP(ctx, opts, otpValue, providedOTP)) {
775
+ await ctx.context.internalAdapter.createVerificationValue({
776
+ value: `${otpValue}:${usedAttempts + 1}`,
777
+ identifier,
778
+ expiresAt: consumed.expiresAt
779
+ });
780
+ throw APIError$1.from("BAD_REQUEST", EMAIL_OTP_ERROR_CODES.INVALID_OTP);
781
+ }
782
+ }
783
+ //#endregion
784
+ export { changeEmailEmailOTP, checkVerificationOTP, createVerificationOTP, forgetPasswordEmailOTP, getVerificationOTP, requestEmailChangeEmailOTP, requestPasswordResetEmailOTP, resetPasswordEmailOTP, sendVerificationOTP, signInEmailOTP, verifyEmailOTP };