@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,529 @@
1
+ import { parseUserInput, parseUserOutput } from "../../db/schema.mjs";
2
+ import { getDate } from "../../utils/date.mjs";
3
+ import { generateRandomString } from "../../crypto/random.mjs";
4
+ import { setSessionCookie } from "../../cookies/index.mjs";
5
+ import { getSessionFromCtx } from "../../api/routes/session.mjs";
6
+ import { HIDE_METADATA } from "../../utils/hide-metadata.mjs";
7
+ import { PHONE_NUMBER_ERROR_CODES } from "./error-codes.mjs";
8
+ import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
9
+ import { createAuthEndpoint } from "@better-auth/core/api";
10
+ import * as z from "zod";
11
+ //#region src/plugins/phone-number/routes.ts
12
+ const signInPhoneNumberBodySchema = z.object({
13
+ phoneNumber: z.string().meta({ description: "Phone number to sign in. Eg: \"+1234567890\"" }),
14
+ password: z.string().meta({ description: "Password to use for sign in." }),
15
+ rememberMe: z.boolean().meta({ description: "Remember the session. Eg: true" }).optional()
16
+ });
17
+ /**
18
+ * ### Endpoint
19
+ *
20
+ * POST `/sign-in/phone-number`
21
+ *
22
+ * ### API Methods
23
+ *
24
+ * **server:**
25
+ * `auth.api.signInPhoneNumber`
26
+ *
27
+ * **client:**
28
+ * `authClient.signIn.phoneNumber`
29
+ *
30
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/phone-number#api-method-sign-in-phone-number)
31
+ */
32
+ const signInPhoneNumber = (opts) => createAuthEndpoint("/sign-in/phone-number", {
33
+ method: "POST",
34
+ body: signInPhoneNumberBodySchema,
35
+ metadata: { openapi: {
36
+ summary: "Sign in with phone number",
37
+ description: "Use this endpoint to sign in with phone number",
38
+ responses: {
39
+ 200: {
40
+ description: "Success",
41
+ content: { "application/json": { schema: {
42
+ type: "object",
43
+ properties: {
44
+ user: { $ref: "#/components/schemas/User" },
45
+ session: { $ref: "#/components/schemas/Session" }
46
+ }
47
+ } } }
48
+ },
49
+ 400: { description: "Invalid phone number or password" }
50
+ }
51
+ } }
52
+ }, async (ctx) => {
53
+ const { password, phoneNumber } = ctx.body;
54
+ if (opts.phoneNumberValidator) {
55
+ if (!await opts.phoneNumberValidator(ctx.body.phoneNumber)) throw APIError.from("BAD_REQUEST", PHONE_NUMBER_ERROR_CODES.INVALID_PHONE_NUMBER);
56
+ }
57
+ const user = await ctx.context.adapter.findOne({
58
+ model: "user",
59
+ where: [{
60
+ field: "phoneNumber",
61
+ value: phoneNumber
62
+ }]
63
+ });
64
+ if (!user) throw APIError.from("UNAUTHORIZED", PHONE_NUMBER_ERROR_CODES.INVALID_PHONE_NUMBER_OR_PASSWORD);
65
+ if (opts.requireVerification) {
66
+ if (!user.phoneNumberVerified) {
67
+ const otp = generateOTP(opts.otpLength);
68
+ await ctx.context.internalAdapter.createVerificationValue({
69
+ value: otp,
70
+ identifier: phoneNumber,
71
+ expiresAt: getDate(opts.expiresIn, "sec")
72
+ });
73
+ if (opts.sendOTP) await ctx.context.runInBackgroundOrAwait(opts.sendOTP({
74
+ phoneNumber,
75
+ code: otp
76
+ }, ctx));
77
+ throw APIError.from("UNAUTHORIZED", PHONE_NUMBER_ERROR_CODES.PHONE_NUMBER_NOT_VERIFIED);
78
+ }
79
+ }
80
+ const credentialAccount = await ctx.context.internalAdapter.findCredentialAccount(user.id);
81
+ if (!credentialAccount) {
82
+ ctx.context.logger.warn("Credential account not found");
83
+ throw APIError.from("UNAUTHORIZED", PHONE_NUMBER_ERROR_CODES.INVALID_PHONE_NUMBER_OR_PASSWORD);
84
+ }
85
+ const currentPassword = credentialAccount?.password;
86
+ if (!currentPassword) {
87
+ ctx.context.logger.warn("Password not found");
88
+ throw APIError.from("UNAUTHORIZED", PHONE_NUMBER_ERROR_CODES.UNEXPECTED_ERROR);
89
+ }
90
+ if (!await ctx.context.password.verify({
91
+ hash: currentPassword,
92
+ password
93
+ })) {
94
+ ctx.context.logger.warn("Invalid password");
95
+ throw APIError.from("UNAUTHORIZED", PHONE_NUMBER_ERROR_CODES.INVALID_PHONE_NUMBER_OR_PASSWORD);
96
+ }
97
+ const session = await ctx.context.internalAdapter.createSession(user.id, ctx.body.rememberMe === false);
98
+ if (!session) {
99
+ ctx.context.logger.error("Failed to create session");
100
+ throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION);
101
+ }
102
+ await setSessionCookie(ctx, {
103
+ session,
104
+ user
105
+ }, ctx.body.rememberMe === false);
106
+ return ctx.json({
107
+ token: session.token,
108
+ user: parseUserOutput(ctx.context.options, user)
109
+ });
110
+ });
111
+ const sendPhoneNumberOTPBodySchema = z.object({ phoneNumber: z.string().meta({ description: "Phone number to send OTP. Eg: \"+1234567890\"" }) });
112
+ const consumePhoneNumberOTPBodySchema = z.object({
113
+ phoneNumber: z.string().meta({ description: "Phone number to verify. Eg: \"+1234567890\"" }),
114
+ code: z.string().meta({ description: "OTP code. Eg: \"123456\"" })
115
+ });
116
+ /**
117
+ * ### Endpoint
118
+ *
119
+ * POST `/phone-number/send-otp`
120
+ *
121
+ * ### API Methods
122
+ *
123
+ * **server:**
124
+ * `auth.api.sendPhoneNumberOTP`
125
+ *
126
+ * **client:**
127
+ * `authClient.phoneNumber.sendOtp`
128
+ *
129
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/phone-number#api-method-phone-number-send-otp)
130
+ */
131
+ const sendPhoneNumberOTP = (opts) => createAuthEndpoint("/phone-number/send-otp", {
132
+ method: "POST",
133
+ body: sendPhoneNumberOTPBodySchema,
134
+ metadata: { openapi: {
135
+ summary: "Send OTP to phone number",
136
+ description: "Use this endpoint to send OTP to phone number",
137
+ responses: { 200: {
138
+ description: "Success",
139
+ content: { "application/json": { schema: {
140
+ type: "object",
141
+ properties: { message: { type: "string" } }
142
+ } } }
143
+ } }
144
+ } }
145
+ }, async (ctx) => {
146
+ if (!opts?.sendOTP) {
147
+ ctx.context.logger.warn("sendOTP not implemented");
148
+ throw APIError.from("NOT_IMPLEMENTED", PHONE_NUMBER_ERROR_CODES.SEND_OTP_NOT_IMPLEMENTED);
149
+ }
150
+ if (opts.phoneNumberValidator) {
151
+ if (!await opts.phoneNumberValidator(ctx.body.phoneNumber)) throw APIError.from("BAD_REQUEST", PHONE_NUMBER_ERROR_CODES.INVALID_PHONE_NUMBER);
152
+ }
153
+ const code = generateOTP(opts.otpLength);
154
+ await ctx.context.internalAdapter.createVerificationValue({
155
+ value: `${code}:0`,
156
+ identifier: ctx.body.phoneNumber,
157
+ expiresAt: getDate(opts.expiresIn, "sec")
158
+ });
159
+ const sendOTPResult = opts.sendOTP({
160
+ phoneNumber: ctx.body.phoneNumber,
161
+ code
162
+ }, ctx);
163
+ if (ctx.context.options.advanced?.backgroundTasks?.handler && sendOTPResult instanceof Promise) try {
164
+ ctx.context.runInBackground(sendOTPResult.catch((e) => {
165
+ ctx.context.logger.error("Failed to run background task:", e);
166
+ }));
167
+ } catch (e) {
168
+ ctx.context.logger.error("Failed to run background task:", e);
169
+ }
170
+ else await sendOTPResult;
171
+ return ctx.json({ message: "code sent" });
172
+ });
173
+ async function verifyAndConsumePhoneNumberOTP(ctx, opts, body) {
174
+ const { phoneNumber, code } = body;
175
+ if (opts.verifyOTP) {
176
+ if (!await opts.verifyOTP({
177
+ phoneNumber,
178
+ code
179
+ }, ctx)) throw APIError.from("BAD_REQUEST", PHONE_NUMBER_ERROR_CODES.INVALID_OTP);
180
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(phoneNumber);
181
+ return;
182
+ }
183
+ await verifyPhoneNumberOTP(ctx, opts, phoneNumber, code);
184
+ }
185
+ /**
186
+ * ### API Methods
187
+ *
188
+ * **server:**
189
+ * `auth.api.consumePhoneNumberOTP`
190
+ *
191
+ * Verifies and consumes an OTP without updating a user or creating a session.
192
+ */
193
+ const consumePhoneNumberOTP = (opts) => createAuthEndpoint({
194
+ method: "POST",
195
+ body: consumePhoneNumberOTPBodySchema,
196
+ metadata: HIDE_METADATA
197
+ }, async (ctx) => {
198
+ await verifyAndConsumePhoneNumberOTP(ctx, opts, ctx.body);
199
+ return ctx.json({ status: true });
200
+ });
201
+ const verifyPhoneNumberBodySchema = z.object({
202
+ /**
203
+ * Phone number
204
+ */
205
+ phoneNumber: z.string().meta({ description: "Phone number to verify. Eg: \"+1234567890\"" }),
206
+ /**
207
+ * OTP code
208
+ */
209
+ code: z.string().meta({ description: "OTP code. Eg: \"123456\"" }),
210
+ /**
211
+ * Disable session creation after verification
212
+ * @default false
213
+ */
214
+ disableSession: z.boolean().meta({ description: "Disable session creation after verification. Eg: false" }).optional(),
215
+ /**
216
+ * This checks if there is a session already
217
+ * and updates the phone number with the provided
218
+ * phone number
219
+ */
220
+ updatePhoneNumber: z.boolean().meta({ description: "Check if there is a session and update the phone number. Eg: true" }).optional()
221
+ }).and(z.record(z.string(), z.any()));
222
+ /**
223
+ * ### Endpoint
224
+ *
225
+ * POST `/phone-number/verify`
226
+ *
227
+ * ### API Methods
228
+ *
229
+ * **server:**
230
+ * `auth.api.verifyPhoneNumber`
231
+ *
232
+ * **client:**
233
+ * `authClient.phoneNumber.verify`
234
+ *
235
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/phone-number#api-method-phone-number-verify)
236
+ */
237
+ const verifyPhoneNumber = (opts) => createAuthEndpoint("/phone-number/verify", {
238
+ method: "POST",
239
+ body: verifyPhoneNumberBodySchema,
240
+ metadata: { openapi: {
241
+ summary: "Verify phone number",
242
+ description: "Use this endpoint to verify phone number",
243
+ responses: {
244
+ "200": {
245
+ description: "Phone number verified successfully",
246
+ content: { "application/json": { schema: {
247
+ type: "object",
248
+ properties: {
249
+ status: {
250
+ type: "boolean",
251
+ description: "Indicates if the verification was successful",
252
+ enum: [true]
253
+ },
254
+ token: {
255
+ type: "string",
256
+ nullable: true,
257
+ description: "Session token if session is created, null if disableSession is true or no session is created"
258
+ },
259
+ user: {
260
+ type: "object",
261
+ nullable: true,
262
+ properties: {
263
+ id: {
264
+ type: "string",
265
+ description: "Unique identifier of the user"
266
+ },
267
+ email: {
268
+ type: "string",
269
+ format: "email",
270
+ nullable: true,
271
+ description: "User's email address"
272
+ },
273
+ emailVerified: {
274
+ type: "boolean",
275
+ nullable: true,
276
+ description: "Whether the email is verified"
277
+ },
278
+ name: {
279
+ type: "string",
280
+ nullable: true,
281
+ description: "User's name"
282
+ },
283
+ image: {
284
+ type: "string",
285
+ format: "uri",
286
+ nullable: true,
287
+ description: "User's profile image URL"
288
+ },
289
+ phoneNumber: {
290
+ type: "string",
291
+ description: "User's phone number"
292
+ },
293
+ phoneNumberVerified: {
294
+ type: "boolean",
295
+ description: "Whether the phone number is verified"
296
+ },
297
+ createdAt: {
298
+ type: "string",
299
+ format: "date-time",
300
+ description: "Timestamp when the user was created"
301
+ },
302
+ updatedAt: {
303
+ type: "string",
304
+ format: "date-time",
305
+ description: "Timestamp when the user was last updated"
306
+ }
307
+ },
308
+ required: [
309
+ "id",
310
+ "phoneNumber",
311
+ "phoneNumberVerified",
312
+ "createdAt",
313
+ "updatedAt"
314
+ ],
315
+ description: "User object with phone number details, null if no user is created or found"
316
+ }
317
+ },
318
+ required: ["status"]
319
+ } } }
320
+ },
321
+ 400: { description: "Invalid OTP" }
322
+ }
323
+ } }
324
+ }, async (ctx) => {
325
+ await verifyAndConsumePhoneNumberOTP(ctx, opts, ctx.body);
326
+ if (ctx.body.updatePhoneNumber) {
327
+ const session = await getSessionFromCtx(ctx);
328
+ if (!session) throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.USER_NOT_FOUND);
329
+ if ((await ctx.context.adapter.findMany({
330
+ model: "user",
331
+ where: [{
332
+ field: "phoneNumber",
333
+ value: ctx.body.phoneNumber
334
+ }]
335
+ })).length) throw APIError.from("BAD_REQUEST", PHONE_NUMBER_ERROR_CODES.PHONE_NUMBER_EXIST);
336
+ const user = await ctx.context.internalAdapter.updateUser(session.user.id, {
337
+ [opts.phoneNumber]: ctx.body.phoneNumber,
338
+ [opts.phoneNumberVerified]: true
339
+ });
340
+ if (!user) throw APIError.from("INTERNAL_SERVER_ERROR", BASE_ERROR_CODES.FAILED_TO_UPDATE_USER);
341
+ await opts?.callbackOnVerification?.({
342
+ phoneNumber: ctx.body.phoneNumber,
343
+ user
344
+ }, ctx);
345
+ return ctx.json({
346
+ status: true,
347
+ token: session.session.token,
348
+ user: parseUserOutput(ctx.context.options, user)
349
+ });
350
+ }
351
+ let user = await ctx.context.adapter.findOne({
352
+ model: "user",
353
+ where: [{
354
+ value: ctx.body.phoneNumber,
355
+ field: opts.phoneNumber
356
+ }]
357
+ });
358
+ if (!user) {
359
+ if (opts?.signUpOnVerification) {
360
+ const { phoneNumber, code, disableSession, updatePhoneNumber, ...rest } = ctx.body;
361
+ const additionalFields = parseUserInput(ctx.context.options, rest, "create");
362
+ user = await ctx.context.internalAdapter.createUser({
363
+ ...additionalFields,
364
+ email: opts.signUpOnVerification.getTempEmail(ctx.body.phoneNumber),
365
+ name: opts.signUpOnVerification.getTempName ? opts.signUpOnVerification.getTempName(ctx.body.phoneNumber) : ctx.body.phoneNumber,
366
+ [opts.phoneNumber]: ctx.body.phoneNumber,
367
+ [opts.phoneNumberVerified]: true
368
+ }, { method: "phone-number" });
369
+ if (!user) throw APIError.from("INTERNAL_SERVER_ERROR", BASE_ERROR_CODES.FAILED_TO_CREATE_USER);
370
+ }
371
+ } else user = await ctx.context.internalAdapter.updateUser(user.id, { [opts.phoneNumberVerified]: true });
372
+ if (!user) throw APIError.from("INTERNAL_SERVER_ERROR", BASE_ERROR_CODES.FAILED_TO_UPDATE_USER);
373
+ await opts?.callbackOnVerification?.({
374
+ phoneNumber: ctx.body.phoneNumber,
375
+ user
376
+ }, ctx);
377
+ if (!ctx.body.disableSession) {
378
+ const session = await ctx.context.internalAdapter.createSession(user.id);
379
+ if (!session) throw APIError.from("INTERNAL_SERVER_ERROR", BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION);
380
+ await setSessionCookie(ctx, {
381
+ session,
382
+ user
383
+ });
384
+ return ctx.json({
385
+ status: true,
386
+ token: session.token,
387
+ user: parseUserOutput(ctx.context.options, user)
388
+ });
389
+ }
390
+ return ctx.json({
391
+ status: true,
392
+ token: null,
393
+ user: parseUserOutput(ctx.context.options, user)
394
+ });
395
+ });
396
+ const requestPasswordResetPhoneNumberBodySchema = z.object({ phoneNumber: z.string() });
397
+ const requestPasswordResetPhoneNumber = (opts) => createAuthEndpoint("/phone-number/request-password-reset", {
398
+ method: "POST",
399
+ body: requestPasswordResetPhoneNumberBodySchema,
400
+ metadata: { openapi: {
401
+ description: "Request OTP for password reset via phone number",
402
+ responses: { "200": {
403
+ description: "OTP sent successfully for password reset",
404
+ content: { "application/json": { schema: {
405
+ type: "object",
406
+ properties: { status: {
407
+ type: "boolean",
408
+ description: "Indicates if the OTP was sent successfully",
409
+ enum: [true]
410
+ } },
411
+ required: ["status"]
412
+ } } }
413
+ } }
414
+ } }
415
+ }, async (ctx) => {
416
+ const user = await ctx.context.adapter.findOne({
417
+ model: "user",
418
+ where: [{
419
+ value: ctx.body.phoneNumber,
420
+ field: opts.phoneNumber
421
+ }]
422
+ });
423
+ const code = generateOTP(opts.otpLength);
424
+ await ctx.context.internalAdapter.createVerificationValue({
425
+ value: `${code}:0`,
426
+ identifier: `${ctx.body.phoneNumber}-request-password-reset`,
427
+ expiresAt: getDate(opts.expiresIn, "sec")
428
+ });
429
+ if (!user) return ctx.json({ status: true });
430
+ if (opts.sendPasswordResetOTP) await ctx.context.runInBackgroundOrAwait(opts.sendPasswordResetOTP({
431
+ phoneNumber: ctx.body.phoneNumber,
432
+ code
433
+ }, ctx));
434
+ return ctx.json({ status: true });
435
+ });
436
+ const resetPasswordPhoneNumberBodySchema = z.object({
437
+ otp: z.string().meta({ description: "The one time password to reset the password. Eg: \"123456\"" }),
438
+ phoneNumber: z.string().meta({ description: "The phone number to the account which intends to reset the password for. Eg: \"+1234567890\"" }),
439
+ newPassword: z.string().meta({ description: `The new password. Eg: "new-and-secure-password"` })
440
+ });
441
+ const resetPasswordPhoneNumber = (opts) => createAuthEndpoint("/phone-number/reset-password", {
442
+ method: "POST",
443
+ body: resetPasswordPhoneNumberBodySchema,
444
+ metadata: { openapi: {
445
+ description: "Reset password using phone number OTP",
446
+ responses: { "200": {
447
+ description: "Password reset successfully",
448
+ content: { "application/json": { schema: {
449
+ type: "object",
450
+ properties: { status: {
451
+ type: "boolean",
452
+ description: "Indicates if the password was reset successfully",
453
+ enum: [true]
454
+ } },
455
+ required: ["status"]
456
+ } } }
457
+ } }
458
+ } }
459
+ }, async (ctx) => {
460
+ await verifyPhoneNumberOTP(ctx, opts, `${ctx.body.phoneNumber}-request-password-reset`, ctx.body.otp);
461
+ const user = await ctx.context.adapter.findOne({
462
+ model: "user",
463
+ where: [{
464
+ field: "phoneNumber",
465
+ value: ctx.body.phoneNumber
466
+ }]
467
+ });
468
+ if (!user) throw APIError.from("BAD_REQUEST", PHONE_NUMBER_ERROR_CODES.UNEXPECTED_ERROR);
469
+ const minLength = ctx.context.password.config.minPasswordLength;
470
+ const maxLength = ctx.context.password.config.maxPasswordLength;
471
+ if (ctx.body.newPassword.length < minLength) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);
472
+ if (ctx.body.newPassword.length > maxLength) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_LONG);
473
+ const hashedPassword = await ctx.context.password.hash(ctx.body.newPassword);
474
+ if (!await ctx.context.internalAdapter.findCredentialAccount(user.id)) await ctx.context.internalAdapter.createAccount({
475
+ userId: user.id,
476
+ providerId: "credential",
477
+ accountId: user.id,
478
+ password: hashedPassword
479
+ });
480
+ else await ctx.context.internalAdapter.updatePassword(user.id, hashedPassword);
481
+ if (ctx.context.options.emailAndPassword?.onPasswordReset) await ctx.context.options.emailAndPassword.onPasswordReset({ user }, ctx.request);
482
+ if (ctx.context.options.emailAndPassword?.revokeSessionsOnPasswordReset) await ctx.context.internalAdapter.deleteUserSessions(user.id);
483
+ return ctx.json({ status: true });
484
+ });
485
+ /**
486
+ * Atomically verifies a phone-number OTP against a stored verification value.
487
+ *
488
+ * Consuming the row is the race gate: the first concurrent caller wins the
489
+ * row, every racer behind it gets `null` and is rejected, so the same code can
490
+ * never satisfy two simultaneous verifications. On a wrong code that is still
491
+ * within the attempt budget, the row is recreated with the same value and
492
+ * expiry and an incremented attempt counter. Once the budget is exhausted the
493
+ * row is not recreated.
494
+ */
495
+ async function verifyPhoneNumberOTP(ctx, opts, identifier, providedCode) {
496
+ const existing = await ctx.context.internalAdapter.findVerificationValue(identifier);
497
+ if (!existing) throw APIError.from("BAD_REQUEST", PHONE_NUMBER_ERROR_CODES.OTP_NOT_FOUND);
498
+ if (existing.expiresAt < /* @__PURE__ */ new Date()) {
499
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(identifier);
500
+ throw APIError.from("BAD_REQUEST", PHONE_NUMBER_ERROR_CODES.OTP_EXPIRED);
501
+ }
502
+ const allowedAttempts = opts?.allowedAttempts ?? 3;
503
+ if (parseVerificationAttempts(existing.value.split(":")[1]) >= allowedAttempts) {
504
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(identifier);
505
+ throw APIError.from("FORBIDDEN", PHONE_NUMBER_ERROR_CODES.TOO_MANY_ATTEMPTS);
506
+ }
507
+ const consumed = await ctx.context.internalAdapter.consumeVerificationValue(identifier);
508
+ if (!consumed) throw APIError.from("BAD_REQUEST", PHONE_NUMBER_ERROR_CODES.INVALID_OTP);
509
+ const [otpValue, rawAttempts] = consumed.value.split(":");
510
+ const attempts = parseVerificationAttempts(rawAttempts);
511
+ if (attempts >= allowedAttempts) throw APIError.from("FORBIDDEN", PHONE_NUMBER_ERROR_CODES.TOO_MANY_ATTEMPTS);
512
+ if (otpValue !== providedCode) {
513
+ await ctx.context.internalAdapter.createVerificationValue({
514
+ value: `${otpValue}:${attempts + 1}`,
515
+ identifier,
516
+ expiresAt: consumed.expiresAt
517
+ });
518
+ throw APIError.from("BAD_REQUEST", PHONE_NUMBER_ERROR_CODES.INVALID_OTP);
519
+ }
520
+ }
521
+ function parseVerificationAttempts(value) {
522
+ const attempts = Number(value ?? 0);
523
+ return Number.isSafeInteger(attempts) && attempts > 0 ? attempts : 0;
524
+ }
525
+ function generateOTP(size) {
526
+ return generateRandomString(size, "0-9");
527
+ }
528
+ //#endregion
529
+ export { consumePhoneNumberOTP, requestPasswordResetPhoneNumber, resetPasswordPhoneNumber, sendPhoneNumberOTP, signInPhoneNumber, verifyPhoneNumber };
@@ -0,0 +1,22 @@
1
+ //#region src/plugins/phone-number/schema.d.ts
2
+ declare const schema: {
3
+ user: {
4
+ fields: {
5
+ phoneNumber: {
6
+ type: "string";
7
+ required: false;
8
+ unique: true;
9
+ sortable: true;
10
+ returned: true;
11
+ };
12
+ phoneNumberVerified: {
13
+ type: "boolean";
14
+ required: false;
15
+ returned: true;
16
+ input: false;
17
+ };
18
+ };
19
+ };
20
+ };
21
+ //#endregion
22
+ export { schema };
@@ -0,0 +1,18 @@
1
+ //#region src/plugins/phone-number/schema.ts
2
+ const schema = { user: { fields: {
3
+ phoneNumber: {
4
+ type: "string",
5
+ required: false,
6
+ unique: true,
7
+ sortable: true,
8
+ returned: true
9
+ },
10
+ phoneNumberVerified: {
11
+ type: "boolean",
12
+ required: false,
13
+ returned: true,
14
+ input: false
15
+ }
16
+ } } };
17
+ //#endregion
18
+ export { schema };
@@ -0,0 +1,116 @@
1
+ import { User } from "../../types/models.mjs";
2
+ import { InferOptionSchema } from "../../types/plugins.mjs";
3
+ import { schema } from "./schema.mjs";
4
+ import { Awaitable, GenericEndpointContext } from "@better-auth/core";
5
+
6
+ //#region src/plugins/phone-number/types.d.ts
7
+ interface UserWithPhoneNumber extends User {
8
+ phoneNumber: string;
9
+ phoneNumberVerified: boolean;
10
+ }
11
+ interface PhoneNumberOptions {
12
+ /**
13
+ * Length of the OTP code
14
+ * @default 6
15
+ */
16
+ otpLength?: number | undefined;
17
+ /**
18
+ * Send OTP code to the user
19
+ *
20
+ * @param phoneNumber
21
+ * @param code
22
+ * @returns
23
+ */
24
+ sendOTP: (data: {
25
+ phoneNumber: string;
26
+ code: string;
27
+ }, ctx?: GenericEndpointContext | undefined) => Awaitable<void>;
28
+ /**
29
+ * Custom OTP verification function
30
+ *
31
+ * If provided, this function will be called instead of the internal verification logic.
32
+ * This is useful when using SMS providers that handle their own OTP generation and verification.
33
+ *
34
+ * @param data - Contains phone number and OTP code
35
+ * @param request - The request object
36
+ * @returns true if OTP is valid, false otherwise
37
+ */
38
+ verifyOTP?: ((data: {
39
+ phoneNumber: string;
40
+ code: string;
41
+ }, ctx?: GenericEndpointContext) => Awaitable<boolean>) | undefined;
42
+ /**
43
+ * a callback to send otp on user requesting to reset their password
44
+ *
45
+ * @param data - contains phone number and code
46
+ * @param request - the request object
47
+ * @returns
48
+ */
49
+ sendPasswordResetOTP?: ((data: {
50
+ phoneNumber: string;
51
+ code: string;
52
+ }, ctx?: GenericEndpointContext) => Awaitable<void>) | undefined;
53
+ /**
54
+ * Expiry time of the OTP code in seconds
55
+ * @default 300
56
+ */
57
+ expiresIn?: number | undefined;
58
+ /**
59
+ * Function to validate phone number
60
+ *
61
+ * by default any string is accepted
62
+ */
63
+ phoneNumberValidator?: ((phoneNumber: string) => Awaitable<boolean>) | undefined;
64
+ /**
65
+ * Require a phone number verification before signing in
66
+ *
67
+ * @default false
68
+ */
69
+ requireVerification?: boolean | undefined;
70
+ /**
71
+ * Callback when phone number is verified
72
+ */
73
+ callbackOnVerification?: ((data: {
74
+ phoneNumber: string;
75
+ user: UserWithPhoneNumber;
76
+ }, ctx?: GenericEndpointContext) => Awaitable<void>) | undefined;
77
+ /**
78
+ * Sign up user after phone number verification
79
+ *
80
+ * the user will be signed up with the temporary email
81
+ * and the phone number will be updated after verification
82
+ */
83
+ signUpOnVerification?: {
84
+ /**
85
+ * When a user signs up, a temporary email will be need to be created
86
+ * to sign up the user. This function should return a temporary email
87
+ * for the user given the phone number
88
+ *
89
+ * @param phoneNumber
90
+ * @returns string (temporary email)
91
+ */
92
+ getTempEmail: (phoneNumber: string) => string;
93
+ /**
94
+ * When a user signs up, a temporary name will be need to be created
95
+ * to sign up the user. This function should return a temporary name
96
+ * for the user given the phone number
97
+ *
98
+ * @param phoneNumber
99
+ * @returns string (temporary name)
100
+ *
101
+ * @default phoneNumber - the phone number will be used as the name
102
+ */
103
+ getTempName?: (phoneNumber: string) => string;
104
+ } | undefined;
105
+ /**
106
+ * Custom schema for the admin plugin
107
+ */
108
+ schema?: InferOptionSchema<typeof schema> | undefined;
109
+ /**
110
+ * Allowed attempts for the OTP code
111
+ * @default 3
112
+ */
113
+ allowedAttempts?: number | undefined;
114
+ }
115
+ //#endregion
116
+ export { PhoneNumberOptions, UserWithPhoneNumber };
@@ -0,0 +1,14 @@
1
+ import { siwe } from "./index.mjs";
2
+
3
+ //#region src/plugins/siwe/client.d.ts
4
+ declare const siweClient: () => {
5
+ id: "siwe";
6
+ version: string;
7
+ $InferServerPlugin: ReturnType<typeof siwe>;
8
+ pathMethods: {
9
+ "/siwe/nonce": "POST";
10
+ "/siwe/get-nonce": "POST";
11
+ };
12
+ };
13
+ //#endregion
14
+ export { siweClient };