better-auth 1.7.0-beta.2 → 1.7.0-beta.4

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 (282) hide show
  1. package/README.md +14 -15
  2. package/dist/_virtual/_rolldown/runtime.mjs +10 -1
  3. package/dist/api/index.d.mts +18 -48
  4. package/dist/api/routes/account.d.mts +4 -23
  5. package/dist/api/routes/account.mjs +102 -75
  6. package/dist/api/routes/callback.mjs +42 -20
  7. package/dist/api/routes/email-verification.d.mts +1 -0
  8. package/dist/api/routes/email-verification.mjs +6 -5
  9. package/dist/api/routes/error.mjs +1 -1
  10. package/dist/api/routes/password.mjs +1 -1
  11. package/dist/api/routes/session.mjs +15 -10
  12. package/dist/api/routes/sign-in.d.mts +3 -1
  13. package/dist/api/routes/sign-in.mjs +13 -15
  14. package/dist/api/routes/sign-up.d.mts +1 -0
  15. package/dist/api/routes/sign-up.mjs +10 -8
  16. package/dist/api/routes/update-user.mjs +8 -8
  17. package/dist/api/to-auth-endpoints.mjs +7 -1
  18. package/dist/auth/base.mjs +30 -27
  19. package/dist/client/config.mjs +8 -1
  20. package/dist/client/fetch-plugins.mjs +2 -1
  21. package/dist/client/index.d.mts +2 -2
  22. package/dist/client/lynx/index.d.mts +13 -0
  23. package/dist/client/lynx/index.mjs +2 -1
  24. package/dist/client/parser.mjs +0 -1
  25. package/dist/client/plugins/index.d.mts +4 -17
  26. package/dist/client/plugins/index.mjs +1 -4
  27. package/dist/client/proxy.mjs +2 -1
  28. package/dist/client/react/index.d.mts +13 -0
  29. package/dist/client/react/index.mjs +2 -1
  30. package/dist/client/session-atom.mjs +12 -1
  31. package/dist/client/solid/index.d.mts +13 -0
  32. package/dist/client/solid/index.mjs +3 -2
  33. package/dist/client/svelte/index.d.mts +13 -0
  34. package/dist/client/svelte/index.mjs +2 -1
  35. package/dist/client/vanilla.d.mts +13 -0
  36. package/dist/client/vanilla.mjs +2 -1
  37. package/dist/client/vue/index.d.mts +13 -0
  38. package/dist/client/vue/index.mjs +2 -1
  39. package/dist/context/create-context.mjs +10 -14
  40. package/dist/context/helpers.mjs +3 -2
  41. package/dist/cookies/cookie-utils.d.mts +33 -1
  42. package/dist/cookies/cookie-utils.mjs +95 -14
  43. package/dist/cookies/index.d.mts +2 -3
  44. package/dist/cookies/index.mjs +39 -11
  45. package/dist/cookies/session-store.mjs +4 -23
  46. package/dist/db/get-migration.mjs +4 -4
  47. package/dist/db/index.d.mts +2 -2
  48. package/dist/db/index.mjs +3 -2
  49. package/dist/db/internal-adapter.mjs +129 -27
  50. package/dist/db/schema.d.mts +14 -1
  51. package/dist/db/schema.mjs +26 -1
  52. package/dist/db/with-hooks.d.mts +1 -0
  53. package/dist/db/with-hooks.mjs +58 -1
  54. package/dist/index.d.mts +2 -2
  55. package/dist/index.mjs +2 -2
  56. package/dist/integrations/cookie-plugin-guard.mjs +18 -0
  57. package/dist/integrations/next-js.mjs +6 -0
  58. package/dist/integrations/svelte-kit.mjs +6 -0
  59. package/dist/integrations/tanstack-start-solid.mjs +6 -0
  60. package/dist/integrations/tanstack-start.mjs +6 -0
  61. package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/index.mjs +32 -0
  62. package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/linux.mjs +55 -0
  63. package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/macos.mjs +26 -0
  64. package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/termux.mjs +39 -0
  65. package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/windows.mjs +19 -0
  66. package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/chunks/prompt.mjs +845 -0
  67. package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/core.mjs +386 -0
  68. package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/index.mjs +320 -0
  69. package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/shared/consola.DRwqZj3T.mjs +62 -0
  70. package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/shared/consola.DXBYu-KD.mjs +190 -0
  71. package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/utils.mjs +2 -0
  72. package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/index.mjs +29 -0
  73. package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.mjs +42 -0
  74. package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.mjs +67 -0
  75. package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.mjs +23 -0
  76. package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.mjs +22 -0
  77. package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.mjs +36 -0
  78. package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/adapters/node.d.mts +292 -0
  79. package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/adapters/node.mjs +127 -0
  80. package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/index.d.mts +145 -0
  81. package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.BQXMA5bH.d.mts +298 -0
  82. package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.By9qWDAI.mjs +9 -0
  83. package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.CipVM6lf.mjs +3549 -0
  84. package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.D9ehKjSh.mjs +66 -0
  85. package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.DfCzGthR.mjs +227 -0
  86. package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/index.mjs +224 -0
  87. package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/command.mjs +52 -0
  88. package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/error.mjs +54 -0
  89. package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/kill.mjs +62 -0
  90. package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/pipe.mjs +26 -0
  91. package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/promise.mjs +32 -0
  92. package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/stdio.mjs +19 -0
  93. package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/stream.mjs +98 -0
  94. package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/verbose.mjs +15 -0
  95. package/dist/node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.d.mts +15 -0
  96. package/dist/node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.mjs +220 -0
  97. package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/array-buffer.mjs +54 -0
  98. package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/array.mjs +2 -0
  99. package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/buffer.mjs +14 -0
  100. package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/contents.mjs +76 -0
  101. package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/index.mjs +6 -0
  102. package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/string.mjs +35 -0
  103. package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/utils.mjs +10 -0
  104. package/dist/node_modules/.pnpm/http-shutdown@1.2.2/node_modules/http-shutdown/index.mjs +76 -0
  105. package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/core.mjs +274 -0
  106. package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/main.mjs +44 -0
  107. package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/realtime.mjs +15 -0
  108. package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/signals.mjs +23 -0
  109. package/dist/node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.mjs +24 -0
  110. package/dist/node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.mjs +18 -0
  111. package/dist/node_modules/.pnpm/is-stream@3.0.0/node_modules/is-stream/index.mjs +9 -0
  112. package/dist/node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.mjs +20 -0
  113. package/dist/node_modules/.pnpm/is64bit@2.0.0/node_modules/is64bit/index.mjs +13 -0
  114. package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.mjs +47 -0
  115. package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.mjs +33 -0
  116. package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.mjs +33 -0
  117. package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/chunks/xdg-open.mjs +1070 -0
  118. package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/index.mjs +619 -0
  119. package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/shared/listhen.1c46e31d.d.mts +83 -0
  120. package/dist/node_modules/.pnpm/merge-stream@2.0.0/node_modules/merge-stream/index.mjs +38 -0
  121. package/dist/node_modules/.pnpm/mimic-fn@4.0.0/node_modules/mimic-fn/index.mjs +38 -0
  122. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/aes.mjs +597 -0
  123. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/aesCipherSuites.mjs +195 -0
  124. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/asn1-validator.mjs +76 -0
  125. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/asn1.mjs +967 -0
  126. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/baseN.mjs +137 -0
  127. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/cipher.mjs +186 -0
  128. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/cipherModes.mjs +597 -0
  129. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/des.mjs +1187 -0
  130. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/ed25519.mjs +1029 -0
  131. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/forge.mjs +15 -0
  132. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/hmac.mjs +107 -0
  133. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/index.mjs +66 -0
  134. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/jsbn.mjs +1334 -0
  135. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/kem.mjs +146 -0
  136. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/log.mjs +241 -0
  137. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md.all.mjs +24 -0
  138. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md.mjs +18 -0
  139. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md5.mjs +324 -0
  140. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/mgf.mjs +20 -0
  141. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/mgf1.mjs +44 -0
  142. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/oids.mjs +154 -0
  143. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pbe.mjs +815 -0
  144. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pbkdf2.mjs +125 -0
  145. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pem.mjs +175 -0
  146. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs1.mjs +200 -0
  147. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs12.mjs +724 -0
  148. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs7.mjs +642 -0
  149. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs7asn1.mjs +405 -0
  150. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pki.mjs +101 -0
  151. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/prime.mjs +193 -0
  152. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/prng.mjs +290 -0
  153. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pss.mjs +141 -0
  154. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/random.mjs +141 -0
  155. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/rc2.mjs +538 -0
  156. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/rsa.mjs +1309 -0
  157. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha1.mjs +230 -0
  158. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha256.mjs +267 -0
  159. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha512.mjs +413 -0
  160. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/ssh.mjs +194 -0
  161. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/tls.mjs +3655 -0
  162. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/util.mjs +2117 -0
  163. package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/x509.mjs +2168 -0
  164. package/dist/node_modules/.pnpm/npm-run-path@5.3.0/node_modules/npm-run-path/index.mjs +34 -0
  165. package/dist/node_modules/.pnpm/onetime@6.0.0/node_modules/onetime/index.mjs +26 -0
  166. package/dist/node_modules/.pnpm/path-key@3.1.1/node_modules/path-key/index.mjs +14 -0
  167. package/dist/node_modules/.pnpm/path-key@4.0.0/node_modules/path-key/index.mjs +8 -0
  168. package/dist/node_modules/.pnpm/pathe@1.1.2/node_modules/pathe/dist/shared/pathe.ff20891b.mjs +176 -0
  169. package/dist/node_modules/.pnpm/shebang-command@2.0.0/node_modules/shebang-command/index.mjs +17 -0
  170. package/dist/node_modules/.pnpm/shebang-regex@3.0.0/node_modules/shebang-regex/index.mjs +8 -0
  171. package/dist/node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.mjs +169 -0
  172. package/dist/node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.mjs +33 -0
  173. package/dist/node_modules/.pnpm/std-env@3.10.0/node_modules/std-env/dist/index.mjs +171 -0
  174. package/dist/node_modules/.pnpm/strip-final-newline@3.0.0/node_modules/strip-final-newline/index.mjs +10 -0
  175. package/dist/node_modules/.pnpm/system-architecture@0.1.0/node_modules/system-architecture/index.mjs +16 -0
  176. package/dist/node_modules/.pnpm/uncrypto@0.1.3/node_modules/uncrypto/dist/crypto.node.mjs +7 -0
  177. package/dist/node_modules/.pnpm/untun@0.1.3/node_modules/untun/dist/chunks/index.mjs +154 -0
  178. package/dist/node_modules/.pnpm/untun@0.1.3/node_modules/untun/dist/index.mjs +34 -0
  179. package/dist/node_modules/.pnpm/uqr@0.1.2/node_modules/uqr/dist/index.mjs +896 -0
  180. package/dist/node_modules/.pnpm/which@2.0.2/node_modules/which/which.mjs +76 -0
  181. package/dist/oauth2/errors.mjs +27 -0
  182. package/dist/oauth2/index.d.mts +2 -2
  183. package/dist/oauth2/index.mjs +3 -3
  184. package/dist/oauth2/link-account.d.mts +27 -1
  185. package/dist/oauth2/link-account.mjs +30 -5
  186. package/dist/oauth2/state.mjs +8 -2
  187. package/dist/{package.mjs → packages/better-auth/package.mjs} +1 -1
  188. package/dist/plugins/access/access.d.mts +3 -15
  189. package/dist/plugins/access/access.mjs +11 -6
  190. package/dist/plugins/access/index.d.mts +2 -2
  191. package/dist/plugins/access/types.d.mts +11 -4
  192. package/dist/plugins/admin/access/statement.d.mts +29 -93
  193. package/dist/plugins/admin/admin.mjs +0 -4
  194. package/dist/plugins/admin/client.d.mts +6 -1
  195. package/dist/plugins/admin/client.mjs +5 -0
  196. package/dist/plugins/admin/routes.mjs +3 -2
  197. package/dist/plugins/anonymous/client.d.mts +1 -0
  198. package/dist/plugins/anonymous/error-codes.d.mts +1 -0
  199. package/dist/plugins/anonymous/error-codes.mjs +1 -0
  200. package/dist/plugins/anonymous/index.d.mts +1 -0
  201. package/dist/plugins/anonymous/index.mjs +16 -2
  202. package/dist/plugins/bearer/index.mjs +5 -12
  203. package/dist/plugins/captcha/index.mjs +14 -1
  204. package/dist/plugins/device-authorization/error-codes.mjs +1 -0
  205. package/dist/plugins/device-authorization/index.d.mts +1 -0
  206. package/dist/plugins/device-authorization/routes.mjs +34 -3
  207. package/dist/plugins/email-otp/routes.mjs +4 -4
  208. package/dist/plugins/generic-oauth/error-codes.mjs +0 -1
  209. package/dist/plugins/generic-oauth/index.d.mts +2 -4
  210. package/dist/plugins/generic-oauth/index.mjs +23 -17
  211. package/dist/plugins/generic-oauth/providers/auth0.mjs +1 -0
  212. package/dist/plugins/generic-oauth/providers/gumroad.mjs +1 -0
  213. package/dist/plugins/generic-oauth/providers/hubspot.mjs +1 -0
  214. package/dist/plugins/generic-oauth/providers/keycloak.mjs +1 -0
  215. package/dist/plugins/generic-oauth/providers/line.mjs +1 -0
  216. package/dist/plugins/generic-oauth/providers/microsoft-entra-id.mjs +1 -0
  217. package/dist/plugins/generic-oauth/providers/okta.mjs +1 -0
  218. package/dist/plugins/generic-oauth/providers/patreon.mjs +1 -0
  219. package/dist/plugins/generic-oauth/providers/slack.mjs +1 -0
  220. package/dist/plugins/generic-oauth/types.d.mts +30 -8
  221. package/dist/plugins/index.d.mts +2 -2
  222. package/dist/plugins/jwt/utils.d.mts +1 -1
  223. package/dist/plugins/last-login-method/client.mjs +2 -2
  224. package/dist/plugins/magic-link/index.d.mts +8 -1
  225. package/dist/plugins/magic-link/index.mjs +4 -17
  226. package/dist/plugins/mcp/authorize.mjs +8 -2
  227. package/dist/plugins/mcp/index.mjs +75 -35
  228. package/dist/plugins/multi-session/index.mjs +2 -2
  229. package/dist/plugins/oauth-proxy/index.mjs +45 -32
  230. package/dist/plugins/oauth-proxy/utils.mjs +3 -10
  231. package/dist/plugins/oidc-provider/authorize.mjs +8 -2
  232. package/dist/plugins/oidc-provider/index.mjs +65 -38
  233. package/dist/plugins/one-tap/client.mjs +9 -2
  234. package/dist/plugins/one-tap/index.mjs +19 -36
  235. package/dist/plugins/open-api/generator.mjs +25 -5
  236. package/dist/plugins/organization/access/statement.d.mts +68 -201
  237. package/dist/plugins/organization/adapter.d.mts +1 -1
  238. package/dist/plugins/organization/adapter.mjs +65 -58
  239. package/dist/plugins/organization/client.d.mts +3 -1
  240. package/dist/plugins/organization/client.mjs +1 -1
  241. package/dist/plugins/organization/error-codes.d.mts +2 -0
  242. package/dist/plugins/organization/error-codes.mjs +3 -1
  243. package/dist/plugins/organization/routes/crud-access-control.d.mts +2 -2
  244. package/dist/plugins/organization/routes/crud-invites.d.mts +8 -1
  245. package/dist/plugins/organization/routes/crud-invites.mjs +8 -3
  246. package/dist/plugins/organization/routes/crud-org.d.mts +4 -4
  247. package/dist/plugins/organization/routes/crud-org.mjs +2 -2
  248. package/dist/plugins/organization/routes/crud-team.mjs +7 -2
  249. package/dist/plugins/organization/schema.d.mts +1 -1
  250. package/dist/plugins/organization/types.d.mts +15 -5
  251. package/dist/plugins/phone-number/routes.mjs +1 -1
  252. package/dist/plugins/siwe/client.d.mts +4 -0
  253. package/dist/plugins/siwe/client.mjs +5 -1
  254. package/dist/plugins/siwe/index.d.mts +13 -2
  255. package/dist/plugins/siwe/index.mjs +179 -165
  256. package/dist/plugins/two-factor/backup-codes/index.d.mts +4 -3
  257. package/dist/plugins/two-factor/client.mjs +2 -1
  258. package/dist/plugins/two-factor/index.mjs +3 -2
  259. package/dist/plugins/username/client.d.mts +1 -0
  260. package/dist/plugins/username/error-codes.d.mts +1 -0
  261. package/dist/plugins/username/error-codes.mjs +2 -1
  262. package/dist/plugins/username/index.d.mts +43 -2
  263. package/dist/plugins/username/index.mjs +73 -6
  264. package/dist/state.d.mts +2 -2
  265. package/dist/state.mjs +18 -4
  266. package/dist/test-utils/headers.mjs +2 -7
  267. package/dist/test-utils/http-test-instance.d.mts +397 -0
  268. package/dist/test-utils/http-test-instance.mjs +54 -0
  269. package/dist/test-utils/index.d.mts +2 -1
  270. package/dist/test-utils/index.mjs +2 -1
  271. package/dist/test-utils/test-instance.d.mts +4110 -224
  272. package/dist/test-utils/test-instance.mjs +11 -2
  273. package/dist/types/auth.d.mts +4 -0
  274. package/dist/utils/index.d.mts +1 -1
  275. package/dist/utils/url.d.mts +2 -1
  276. package/dist/utils/url.mjs +9 -3
  277. package/dist/version.mjs +1 -1
  278. package/package.json +14 -14
  279. package/dist/oauth2/error-codes.d.mts +0 -20
  280. package/dist/plugins/generic-oauth/client.d.mts +0 -32
  281. package/dist/plugins/generic-oauth/client.mjs +0 -19
  282. package/dist/plugins/generic-oauth/error-codes.d.mts +0 -10
@@ -0,0 +1,76 @@
1
+ import { __commonJSMin, __require } from "../../../../../_virtual/_rolldown/runtime.mjs";
2
+ import { require_isexe } from "../../../isexe@2.0.0/node_modules/isexe/index.mjs";
3
+ //#region ../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js
4
+ var require_which = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5
+ const isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
6
+ const path = __require("path");
7
+ const COLON = isWindows ? ";" : ":";
8
+ const isexe = require_isexe();
9
+ const getNotFoundError = (cmd) => Object.assign(/* @__PURE__ */ new Error(`not found: ${cmd}`), { code: "ENOENT" });
10
+ const getPathInfo = (cmd, opt) => {
11
+ const colon = opt.colon || COLON;
12
+ const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [...isWindows ? [process.cwd()] : [], ...(opt.path || process.env.PATH || "").split(colon)];
13
+ const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
14
+ const pathExt = isWindows ? pathExtExe.split(colon) : [""];
15
+ if (isWindows) {
16
+ if (cmd.indexOf(".") !== -1 && pathExt[0] !== "") pathExt.unshift("");
17
+ }
18
+ return {
19
+ pathEnv,
20
+ pathExt,
21
+ pathExtExe
22
+ };
23
+ };
24
+ const which = (cmd, opt, cb) => {
25
+ if (typeof opt === "function") {
26
+ cb = opt;
27
+ opt = {};
28
+ }
29
+ if (!opt) opt = {};
30
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
31
+ const found = [];
32
+ const step = (i) => new Promise((resolve, reject) => {
33
+ if (i === pathEnv.length) return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
34
+ const ppRaw = pathEnv[i];
35
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
36
+ const pCmd = path.join(pathPart, cmd);
37
+ resolve(subStep(!pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd, i, 0));
38
+ });
39
+ const subStep = (p, i, ii) => new Promise((resolve, reject) => {
40
+ if (ii === pathExt.length) return resolve(step(i + 1));
41
+ const ext = pathExt[ii];
42
+ isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
43
+ if (!er && is) if (opt.all) found.push(p + ext);
44
+ else return resolve(p + ext);
45
+ return resolve(subStep(p, i, ii + 1));
46
+ });
47
+ });
48
+ return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
49
+ };
50
+ const whichSync = (cmd, opt) => {
51
+ opt = opt || {};
52
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
53
+ const found = [];
54
+ for (let i = 0; i < pathEnv.length; i++) {
55
+ const ppRaw = pathEnv[i];
56
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
57
+ const pCmd = path.join(pathPart, cmd);
58
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
59
+ for (let j = 0; j < pathExt.length; j++) {
60
+ const cur = p + pathExt[j];
61
+ try {
62
+ if (isexe.sync(cur, { pathExt: pathExtExe })) if (opt.all) found.push(cur);
63
+ else return cur;
64
+ } catch (ex) {}
65
+ }
66
+ }
67
+ if (opt.all && found.length) return found;
68
+ if (opt.nothrow) return null;
69
+ throw getNotFoundError(cmd);
70
+ };
71
+ module.exports = which;
72
+ which.sync = whichSync;
73
+ }));
74
+ //#endregion
75
+ export default require_which();
76
+ export { require_which };
@@ -0,0 +1,27 @@
1
+ //#region src/oauth2/errors.ts
2
+ const HANDLING_DOCS_URL = "https://www.better-auth.com/docs/concepts/oauth#handling-providers-without-email";
3
+ /**
4
+ * Redirect the user to the OAuth error page with a machine-readable `error`
5
+ * code (and optional `error_description`).
6
+ *
7
+ * Every OAuth callback path routes its failures through this helper so the
8
+ * query parameter name, the `?`/`&` separator, and URL encoding are decided in
9
+ * one place. The error page reads the `error` query parameter, so callers must
10
+ * never hand-build the redirect with a different parameter name.
11
+ */
12
+ function redirectOnError(ctx, errorURL, error, description) {
13
+ const params = new URLSearchParams({ error });
14
+ if (description) params.set("error_description", description);
15
+ const sep = errorURL.includes("?") ? "&" : "?";
16
+ throw ctx.redirect(`${errorURL}${sep}${params.toString()}`);
17
+ }
18
+ /**
19
+ * Build the logger message shown when an OAuth provider does not return an
20
+ * email address. Kept in one place so every rejection site points users at
21
+ * the same workaround docs.
22
+ */
23
+ function missingEmailLogMessage(providerId, options) {
24
+ return `${options?.source === "generic" ? `Generic OAuth provider "${providerId}"` : `Provider "${providerId}"`} did not return an email${options?.source === "id_token" ? " in the id token" : ""}. Either request the provider's email scope, or synthesize one via \`mapProfileToUser\`. See ${HANDLING_DOCS_URL}`;
25
+ }
26
+ //#endregion
27
+ export { missingEmailLogMessage, redirectOnError };
@@ -1,5 +1,5 @@
1
1
  import { generateState, parseState } from "./state.mjs";
2
- import { handleOAuthUserInfo } from "./link-account.mjs";
2
+ import { applyUpdateUserInfoOnLink, handleOAuthUserInfo } from "./link-account.mjs";
3
3
  import { decryptOAuthToken, setTokenUtil } from "./utils.mjs";
4
4
  export * from "@better-auth/core/oauth2";
5
- export { decryptOAuthToken, generateState, handleOAuthUserInfo, parseState, setTokenUtil };
5
+ export { applyUpdateUserInfoOnLink, decryptOAuthToken, generateState, handleOAuthUserInfo, parseState, setTokenUtil };
@@ -1,5 +1,5 @@
1
- import { generateState, parseState } from "./state.mjs";
2
1
  import { decryptOAuthToken, setTokenUtil } from "./utils.mjs";
3
- import { handleOAuthUserInfo } from "./link-account.mjs";
2
+ import { applyUpdateUserInfoOnLink, handleOAuthUserInfo } from "./link-account.mjs";
3
+ import { generateState, parseState } from "./state.mjs";
4
4
  export * from "@better-auth/core/oauth2";
5
- export { decryptOAuthToken, generateState, handleOAuthUserInfo, parseState, setTokenUtil };
5
+ export { applyUpdateUserInfoOnLink, decryptOAuthToken, generateState, handleOAuthUserInfo, parseState, setTokenUtil };
@@ -42,5 +42,31 @@ declare function handleOAuthUserInfo(c: GenericEndpointContext, opts: {
42
42
  error: null;
43
43
  isRegister: boolean;
44
44
  }>;
45
+ /**
46
+ * Provider profile a freshly linked account may copy onto the local user.
47
+ * `id` is the provider's account id (never the local user id), and `email`/
48
+ * `emailVerified` are identity anchors; all three are stripped before the
49
+ * remaining fields are written.
50
+ */
51
+ type LinkedProviderProfile = {
52
+ id: string | number;
53
+ name?: string | undefined;
54
+ email?: string | null | undefined;
55
+ emailVerified?: boolean | undefined;
56
+ image?: string | null | undefined;
57
+ };
58
+ /**
59
+ * Apply the `account.accountLinking.updateUserInfoOnLink` policy: when enabled,
60
+ * copy the freshly linked provider's profile onto the local user, matching the
61
+ * field set persisted on sign-up. The local `email` and `emailVerified` are
62
+ * never changed, so a link can't rebind the account's identity, and
63
+ * `updateUser` drops `undefined` fields, so a provider that omits one leaves
64
+ * the existing column intact.
65
+ *
66
+ * Returns the updated user so a caller that issues a session can seed the
67
+ * cookie cache with the fresh row. Returns `undefined` when the policy is
68
+ * disabled or the update fails: a failed profile sync must not abort the link.
69
+ */
70
+ declare function applyUpdateUserInfoOnLink(c: GenericEndpointContext, userId: string, userInfo: LinkedProviderProfile): Promise<User | undefined>;
45
71
  //#endregion
46
- export { handleOAuthUserInfo };
72
+ export { applyUpdateUserInfoOnLink, handleOAuthUserInfo };
@@ -1,5 +1,6 @@
1
1
  import { isAPIError } from "../utils/is-api-error.mjs";
2
2
  import { setAccountCookie } from "../cookies/session-store.mjs";
3
+ import { redirectOnError } from "./errors.mjs";
3
4
  import { setTokenUtil } from "./utils.mjs";
4
5
  import { createEmailVerificationToken } from "../api/routes/email-verification.mjs";
5
6
  import { isDevelopment, logger } from "@better-auth/core/env";
@@ -8,8 +9,7 @@ async function handleOAuthUserInfo(c, opts) {
8
9
  const { userInfo, account, callbackURL, disableSignUp, overrideUserInfo } = opts;
9
10
  const dbUser = await c.context.internalAdapter.findOAuthUser(userInfo.email.toLowerCase(), account.accountId, account.providerId).catch((e) => {
10
11
  logger.error("Better auth was unable to query your database.\nError: ", e);
11
- const errorURL = c.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;
12
- throw c.redirect(`${errorURL}?error=internal_server_error`);
12
+ redirectOnError(c, c.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`, "internal_server_error");
13
13
  });
14
14
  let user = dbUser?.user;
15
15
  const isRegister = !user;
@@ -17,7 +17,9 @@ async function handleOAuthUserInfo(c, opts) {
17
17
  const linkedAccount = dbUser.linkedAccount ?? dbUser.accounts.find((acc) => acc.providerId === account.providerId && acc.accountId === account.accountId);
18
18
  if (!linkedAccount) {
19
19
  const accountLinking = c.context.options.account?.accountLinking;
20
- if (!(opts.isTrustedProvider || c.context.trustedProviders.includes(account.providerId)) && !userInfo.emailVerified || accountLinking?.enabled === false || accountLinking?.disableImplicitLinking === true) {
20
+ const isTrustedProvider = opts.isTrustedProvider || c.context.trustedProviders.includes(account.providerId);
21
+ const requireLocalEmailVerified = accountLinking?.requireLocalEmailVerified ?? true;
22
+ if (!isTrustedProvider && !userInfo.emailVerified || requireLocalEmailVerified && !dbUser.user.emailVerified || accountLinking?.enabled === false || accountLinking?.disableImplicitLinking === true) {
21
23
  if (isDevelopment()) logger.warn(`User already exist but account isn't linked to ${account.providerId}. To read more about how account linking works in Better Auth see https://www.better-auth.com/docs/concepts/users-accounts#account-linking.`);
22
24
  return {
23
25
  error: "account not linked",
@@ -44,6 +46,7 @@ async function handleOAuthUserInfo(c, opts) {
44
46
  };
45
47
  }
46
48
  if (userInfo.emailVerified && !dbUser.user.emailVerified && userInfo.email.toLowerCase() === dbUser.user.email) await c.context.internalAdapter.updateUser(dbUser.user.id, { emailVerified: true });
49
+ user = await applyUpdateUserInfoOnLink(c, dbUser.user.id, userInfo) ?? user;
47
50
  } else {
48
51
  const freshTokens = c.context.options.account?.updateAccountOnSignIn !== false ? Object.fromEntries(Object.entries({
49
52
  idToken: account.idToken,
@@ -94,7 +97,7 @@ async function handleOAuthUserInfo(c, opts) {
94
97
  if (c.context.options.account?.storeAccountCookie) await setAccountCookie(c, createdAccount);
95
98
  if (!userInfo.emailVerified && user && c.context.options.emailVerification?.sendOnSignUp && c.context.options.emailVerification?.sendVerificationEmail) {
96
99
  const token = await createEmailVerificationToken(c.context.secret, user.email, void 0, c.context.options.emailVerification?.expiresIn);
97
- const url = `${c.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;
100
+ const url = `${c.context.baseURL}/verify-email?token=${token}&callbackURL=${encodeURIComponent(callbackURL || "/")}`;
98
101
  await c.context.runInBackgroundOrAwait(c.context.options.emailVerification.sendVerificationEmail({
99
102
  user,
100
103
  url,
@@ -135,5 +138,27 @@ async function handleOAuthUserInfo(c, opts) {
135
138
  isRegister
136
139
  };
137
140
  }
141
+ /**
142
+ * Apply the `account.accountLinking.updateUserInfoOnLink` policy: when enabled,
143
+ * copy the freshly linked provider's profile onto the local user, matching the
144
+ * field set persisted on sign-up. The local `email` and `emailVerified` are
145
+ * never changed, so a link can't rebind the account's identity, and
146
+ * `updateUser` drops `undefined` fields, so a provider that omits one leaves
147
+ * the existing column intact.
148
+ *
149
+ * Returns the updated user so a caller that issues a session can seed the
150
+ * cookie cache with the fresh row. Returns `undefined` when the policy is
151
+ * disabled or the update fails: a failed profile sync must not abort the link.
152
+ */
153
+ async function applyUpdateUserInfoOnLink(c, userId, userInfo) {
154
+ if (c.context.options.account?.accountLinking?.updateUserInfoOnLink !== true) return;
155
+ const { id: _id, email: _email, emailVerified: _emailVerified, ...profile } = userInfo;
156
+ try {
157
+ return await c.context.internalAdapter.updateUser(userId, profile);
158
+ } catch (e) {
159
+ c.context.logger.warn("Could not update user info on account link", e);
160
+ return;
161
+ }
162
+ }
138
163
  //#endregion
139
- export { handleOAuthUserInfo };
164
+ export { applyUpdateUserInfoOnLink, handleOAuthUserInfo };
@@ -1,4 +1,5 @@
1
1
  import { generateRandomString } from "../crypto/random.mjs";
2
+ import { redirectOnError } from "./errors.mjs";
2
3
  import { setOAuthState } from "../api/state/oauth.mjs";
3
4
  import { StateError, generateGenericState, parseGenericState } from "../state.mjs";
4
5
  import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
@@ -36,8 +37,13 @@ async function parseState(c) {
36
37
  parsedData = await parseGenericState(c, state);
37
38
  } catch (error) {
38
39
  c.context.logger.error("Failed to parse state", error);
39
- if (error instanceof StateError && error.code === "state_security_mismatch") throw c.redirect(`${errorURL}?error=state_mismatch`);
40
- throw c.redirect(`${errorURL}?error=please_restart_the_process`);
40
+ let code = "internal_server_error";
41
+ let redirectErrorURL = errorURL;
42
+ if (error instanceof StateError) {
43
+ code = error.code === "state_security_mismatch" ? "state_mismatch" : error.code;
44
+ redirectErrorURL = error.errorURL ?? errorURL;
45
+ }
46
+ redirectOnError(c, redirectErrorURL, code);
41
47
  }
42
48
  if (!parsedData.errorURL) parsedData.errorURL = errorURL;
43
49
  if (parsedData) await setOAuthState(parsedData);
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "1.7.0-beta.2";
2
+ var version = "1.7.0-beta.4";
3
3
  //#endregion
4
4
  export { version };
@@ -1,4 +1,4 @@
1
- import { Statements, Subset } from "./types.mjs";
1
+ import { ExactRoleStatements, Role, RoleInput, Statements } from "./types.mjs";
2
2
 
3
3
  //#region src/plugins/access/access.d.ts
4
4
  type AuthorizeResponse = {
@@ -8,21 +8,9 @@ type AuthorizeResponse = {
8
8
  success: true;
9
9
  error?: never | undefined;
10
10
  };
11
- declare function role<TStatements extends Statements>(statements: TStatements): {
12
- authorize<K extends keyof TStatements>(request: { [key in K]?: TStatements[key] | {
13
- actions: TStatements[key];
14
- connector: "OR" | "AND";
15
- } }, connector?: "OR" | "AND"): AuthorizeResponse;
16
- statements: TStatements;
17
- };
11
+ declare function role<const TRoleStatements extends Statements, TAuthorizeStatements extends Statements = TRoleStatements>(statements: TRoleStatements): Role<ExactRoleStatements<TRoleStatements>, TAuthorizeStatements>;
18
12
  declare function createAccessControl<const TStatements extends Statements>(s: TStatements): {
19
- newRole<K extends keyof TStatements>(statements: Subset<K, TStatements>): {
20
- authorize<K_1 extends K>(request: K_1 extends infer T extends keyof Subset<K, TStatements> ? { [key in T]?: Subset<K, TStatements>[key] | {
21
- actions: Subset<K, TStatements>[key];
22
- connector: "OR" | "AND";
23
- } | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
24
- statements: Subset<K, TStatements>;
25
- };
13
+ newRole<const TRoleStatements extends Statements>(statements: RoleInput<TStatements, TRoleStatements>): Role<ExactRoleStatements<TRoleStatements>, TStatements>;
26
14
  statements: TStatements;
27
15
  };
28
16
  //#endregion
@@ -6,14 +6,19 @@ function role(statements) {
6
6
  let success = false;
7
7
  for (const [requestedResource, requestedActions] of Object.entries(request)) {
8
8
  const allowedActions = statements[requestedResource];
9
- if (!allowedActions) return {
10
- success: false,
11
- error: `You are not allowed to access resource: ${requestedResource}`
12
- };
13
- if (Array.isArray(requestedActions)) success = requestedActions.every((requestedAction) => allowedActions.includes(requestedAction));
9
+ if (!allowedActions) {
10
+ if (connector === "AND") return {
11
+ success: false,
12
+ error: `You are not allowed to access resource: ${requestedResource}`
13
+ };
14
+ success = false;
15
+ continue;
16
+ }
17
+ if (Array.isArray(requestedActions)) success = requestedActions.length > 0 && requestedActions.every((requestedAction) => allowedActions.includes(requestedAction));
14
18
  else if (typeof requestedActions === "object") {
15
19
  const actions = requestedActions;
16
- if (actions.connector === "OR") success = actions.actions.some((requestedAction) => allowedActions.includes(requestedAction));
20
+ if (!Array.isArray(actions.actions) || actions.actions.length === 0) success = false;
21
+ else if (actions.connector === "OR") success = actions.actions.some((requestedAction) => allowedActions.includes(requestedAction));
17
22
  else success = actions.actions.every((requestedAction) => allowedActions.includes(requestedAction));
18
23
  } else throw new BetterAuthError("Invalid access control request");
19
24
  if (success && connector === "OR") return { success };
@@ -1,3 +1,3 @@
1
- import { AccessControl, ArrayElement, Role, Statements, SubArray, Subset } from "./types.mjs";
1
+ import { AccessControl, ArrayElement, ExactRoleStatements, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, Statements, SubArray, Subset } from "./types.mjs";
2
2
  import { AuthorizeResponse, createAccessControl, role } from "./access.mjs";
3
- export { AccessControl, ArrayElement, AuthorizeResponse, Role, Statements, SubArray, Subset, createAccessControl, role };
3
+ export { AccessControl, ArrayElement, AuthorizeResponse, ExactRoleStatements, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, Statements, SubArray, Subset, createAccessControl, role };
@@ -8,10 +8,17 @@ type Subset<K extends keyof R, R extends Record<string | LiteralString, readonly
8
8
  type Statements = {
9
9
  readonly [resource: string]: readonly LiteralString[];
10
10
  };
11
+ type RoleStatements<TStatements extends Statements> = { readonly [P in keyof TStatements]?: SubArray<TStatements[P]> };
12
+ type RoleInput<TStatements extends Statements, TRoleStatements extends Statements> = TRoleStatements & (string extends keyof TRoleStatements ? {} : RoleStatements<TStatements> & Record<Exclude<keyof TRoleStatements, keyof TStatements>, never>);
13
+ type ExactRoleStatements<TStatements extends Statements> = { readonly [P in keyof TStatements]: readonly [...TStatements[P]] };
11
14
  type AccessControl<TStatements extends Statements = Statements> = ReturnType<typeof createAccessControl<TStatements>>;
12
- type Role<TStatements extends Statements = Record<string, any>> = {
13
- authorize: (request: any, connector?: ("OR" | "AND") | undefined) => AuthorizeResponse;
14
- statements: TStatements;
15
+ type RoleAuthorizeRequest<TStatements extends Statements> = { [P in keyof TStatements]?: SubArray<TStatements[P]> | {
16
+ actions: SubArray<TStatements[P]>;
17
+ connector: "OR" | "AND";
18
+ } };
19
+ type Role<TRoleStatements extends Statements = Record<string, any>, TAuthorizeStatements extends Statements = TRoleStatements> = {
20
+ authorize: (request: RoleAuthorizeRequest<TAuthorizeStatements>, connector?: ("OR" | "AND") | undefined) => AuthorizeResponse;
21
+ statements: TRoleStatements;
15
22
  };
16
23
  //#endregion
17
- export { AccessControl, ArrayElement, Role, Statements, SubArray, Subset };
24
+ export { AccessControl, ArrayElement, ExactRoleStatements, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, Statements, SubArray, Subset };
@@ -1,115 +1,51 @@
1
- import { Subset } from "../../access/types.mjs";
2
- import { AuthorizeResponse } from "../../access/access.mjs";
1
+ import { ExactRoleStatements, Role, RoleInput, Statements } from "../../access/types.mjs";
3
2
  //#region src/plugins/admin/access/statement.d.ts
4
3
  declare const defaultStatements: {
5
4
  readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
6
5
  readonly session: readonly ["list", "revoke", "delete"];
7
6
  };
8
7
  declare const defaultAc: {
9
- newRole<K extends "user" | "session">(statements: Subset<K, {
8
+ newRole<const TRoleStatements extends Statements>(statements: RoleInput<{
10
9
  readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
11
10
  readonly session: readonly ["list", "revoke", "delete"];
12
- }>): {
13
- authorize<K_1 extends K>(request: K_1 extends infer T extends keyof Subset<K, {
14
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
15
- readonly session: readonly ["list", "revoke", "delete"];
16
- }> ? { [key in T]?: Subset<K, {
17
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
18
- readonly session: readonly ["list", "revoke", "delete"];
19
- }>[key] | {
20
- actions: Subset<K, {
21
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
22
- readonly session: readonly ["list", "revoke", "delete"];
23
- }>[key];
24
- connector: "OR" | "AND";
25
- } | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
26
- statements: Subset<K, {
27
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
28
- readonly session: readonly ["list", "revoke", "delete"];
29
- }>;
30
- };
11
+ }, TRoleStatements>): Role<ExactRoleStatements<TRoleStatements>, {
12
+ readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
13
+ readonly session: readonly ["list", "revoke", "delete"];
14
+ }>;
31
15
  statements: {
32
16
  readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
33
17
  readonly session: readonly ["list", "revoke", "delete"];
34
18
  };
35
19
  };
36
- declare const adminAc: {
37
- authorize<K extends "user" | "session">(request: K extends infer T extends keyof Subset<"user" | "session", {
38
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
39
- readonly session: readonly ["list", "revoke", "delete"];
40
- }> ? { [key in T]?: Subset<"user" | "session", {
41
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
42
- readonly session: readonly ["list", "revoke", "delete"];
43
- }>[key] | {
44
- actions: Subset<"user" | "session", {
45
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
46
- readonly session: readonly ["list", "revoke", "delete"];
47
- }>[key];
48
- connector: "OR" | "AND";
49
- } | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
50
- statements: Subset<"user" | "session", {
20
+ declare const adminAc: Role<ExactRoleStatements<{
21
+ readonly user: ["create", "list", "set-role", "ban", "impersonate", "delete", "set-password", "get", "update"];
22
+ readonly session: ["list", "revoke", "delete"];
23
+ }>, {
24
+ readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
25
+ readonly session: readonly ["list", "revoke", "delete"];
26
+ }>;
27
+ declare const userAc: Role<ExactRoleStatements<{
28
+ readonly user: [];
29
+ readonly session: [];
30
+ }>, {
31
+ readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
32
+ readonly session: readonly ["list", "revoke", "delete"];
33
+ }>;
34
+ declare const defaultRoles: {
35
+ admin: Role<ExactRoleStatements<{
36
+ readonly user: ["create", "list", "set-role", "ban", "impersonate", "delete", "set-password", "get", "update"];
37
+ readonly session: ["list", "revoke", "delete"];
38
+ }>, {
51
39
  readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
52
40
  readonly session: readonly ["list", "revoke", "delete"];
53
41
  }>;
54
- };
55
- declare const userAc: {
56
- authorize<K extends "user" | "session">(request: K extends infer T extends keyof Subset<"user" | "session", {
57
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
58
- readonly session: readonly ["list", "revoke", "delete"];
59
- }> ? { [key in T]?: Subset<"user" | "session", {
60
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
61
- readonly session: readonly ["list", "revoke", "delete"];
62
- }>[key] | {
63
- actions: Subset<"user" | "session", {
64
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
65
- readonly session: readonly ["list", "revoke", "delete"];
66
- }>[key];
67
- connector: "OR" | "AND";
68
- } | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
69
- statements: Subset<"user" | "session", {
42
+ user: Role<ExactRoleStatements<{
43
+ readonly user: [];
44
+ readonly session: [];
45
+ }>, {
70
46
  readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
71
47
  readonly session: readonly ["list", "revoke", "delete"];
72
48
  }>;
73
49
  };
74
- declare const defaultRoles: {
75
- admin: {
76
- authorize<K extends "user" | "session">(request: K extends infer T extends keyof Subset<"user" | "session", {
77
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
78
- readonly session: readonly ["list", "revoke", "delete"];
79
- }> ? { [key in T]?: Subset<"user" | "session", {
80
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
81
- readonly session: readonly ["list", "revoke", "delete"];
82
- }>[key] | {
83
- actions: Subset<"user" | "session", {
84
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
85
- readonly session: readonly ["list", "revoke", "delete"];
86
- }>[key];
87
- connector: "OR" | "AND";
88
- } | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
89
- statements: Subset<"user" | "session", {
90
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
91
- readonly session: readonly ["list", "revoke", "delete"];
92
- }>;
93
- };
94
- user: {
95
- authorize<K extends "user" | "session">(request: K extends infer T extends keyof Subset<"user" | "session", {
96
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
97
- readonly session: readonly ["list", "revoke", "delete"];
98
- }> ? { [key in T]?: Subset<"user" | "session", {
99
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
100
- readonly session: readonly ["list", "revoke", "delete"];
101
- }>[key] | {
102
- actions: Subset<"user" | "session", {
103
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
104
- readonly session: readonly ["list", "revoke", "delete"];
105
- }>[key];
106
- connector: "OR" | "AND";
107
- } | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
108
- statements: Subset<"user" | "session", {
109
- readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
110
- readonly session: readonly ["list", "revoke", "delete"];
111
- }>;
112
- };
113
- };
114
50
  //#endregion
115
51
  export { adminAc, defaultAc, defaultRoles, defaultStatements, userAc };
@@ -42,10 +42,6 @@ const admin = (options) => {
42
42
  });
43
43
  return;
44
44
  }
45
- if (ctx.path.startsWith("/callback")) {
46
- const redirectURI = ctx.context.options.onAPIError?.errorURL || `${ctx.context.baseURL}/error`;
47
- throw ctx.redirect(`${redirectURI}?error=banned&error_description=${opts.bannedUserMessage}`);
48
- }
49
45
  throw APIError.from("FORBIDDEN", {
50
46
  message: opts.bannedUserMessage,
51
47
  code: "BANNED_USER"
@@ -44,8 +44,13 @@ declare const adminClient: <O extends AdminClientOptions>(options?: O | undefine
44
44
  };
45
45
  pathMethods: {
46
46
  "/admin/list-users": "GET";
47
+ "/admin/impersonate-user": "POST";
47
48
  "/admin/stop-impersonating": "POST";
48
49
  };
50
+ atomListeners: {
51
+ matcher: (path: string) => path is "/admin/impersonate-user" | "/admin/stop-impersonating";
52
+ signal: "$sessionSignal";
53
+ }[];
49
54
  $ERROR_CODES: {
50
55
  USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL: _better_auth_core_utils_error_codes0.RawError<"USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL">;
51
56
  FAILED_TO_CREATE_USER: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_CREATE_USER">;
@@ -71,4 +76,4 @@ declare const adminClient: <O extends AdminClientOptions>(options?: O | undefine
71
76
  };
72
77
  };
73
78
  //#endregion
74
- export { adminClient };
79
+ export { AdminClientOptions, adminClient };
@@ -25,8 +25,13 @@ const adminClient = (options) => {
25
25
  } } }),
26
26
  pathMethods: {
27
27
  "/admin/list-users": "GET",
28
+ "/admin/impersonate-user": "POST",
28
29
  "/admin/stop-impersonating": "POST"
29
30
  },
31
+ atomListeners: [{
32
+ matcher: (path) => path === "/admin/impersonate-user" || path === "/admin/stop-impersonating",
33
+ signal: "$sessionSignal"
34
+ }],
30
35
  $ERROR_CODES: ADMIN_ERROR_CODES
31
36
  };
32
37
  };
@@ -462,7 +462,7 @@ const banUser = (opts) => createAuthEndpoint("/admin/ban-user", {
462
462
  banExpires: ctx.body.banExpiresIn ? getDate(ctx.body.banExpiresIn, "sec") : opts?.defaultBanExpiresIn ? getDate(opts.defaultBanExpiresIn, "sec") : void 0,
463
463
  updatedAt: /* @__PURE__ */ new Date()
464
464
  });
465
- await ctx.context.internalAdapter.deleteSessions(ctx.body.userId);
465
+ await ctx.context.internalAdapter.deleteUserSessions(ctx.body.userId);
466
466
  return ctx.json({ user: parseUserOutput(ctx.context.options, user) });
467
467
  });
468
468
  const impersonateUserBodySchema = z.object({ userId: z.coerce.string().meta({ description: "The user id" }) });
@@ -658,7 +658,7 @@ const revokeUserSessions = (opts) => createAuthEndpoint("/admin/revoke-user-sess
658
658
  options: opts,
659
659
  permissions: { session: ["revoke"] }
660
660
  })) throw APIError.from("FORBIDDEN", ADMIN_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_REVOKE_USERS_SESSIONS);
661
- await ctx.context.internalAdapter.deleteSessions(ctx.body.userId);
661
+ await ctx.context.internalAdapter.deleteUserSessions(ctx.body.userId);
662
662
  return ctx.json({ success: true });
663
663
  });
664
664
  const removeUserBodySchema = z.object({ userId: z.coerce.string().meta({ description: "The user id" }) });
@@ -703,6 +703,7 @@ const removeUser = (opts) => createAuthEndpoint("/admin/remove-user", {
703
703
  })) throw APIError.from("FORBIDDEN", ADMIN_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_DELETE_USERS);
704
704
  if (ctx.body.userId === ctx.context.session.user.id) throw APIError.from("BAD_REQUEST", ADMIN_ERROR_CODES.YOU_CANNOT_REMOVE_YOURSELF);
705
705
  if (!await ctx.context.internalAdapter.findUserById(ctx.body.userId)) throw APIError.from("NOT_FOUND", BASE_ERROR_CODES.USER_NOT_FOUND);
706
+ await ctx.context.internalAdapter.deleteUserSessions(ctx.body.userId);
706
707
  await ctx.context.internalAdapter.deleteUser(ctx.body.userId);
707
708
  return ctx.json({ success: true });
708
709
  });
@@ -23,6 +23,7 @@ declare const anonymousClient: () => {
23
23
  COULD_NOT_CREATE_SESSION: _better_auth_core_utils_error_codes0.RawError<"COULD_NOT_CREATE_SESSION">;
24
24
  ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY: _better_auth_core_utils_error_codes0.RawError<"ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY">;
25
25
  FAILED_TO_DELETE_ANONYMOUS_USER: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER">;
26
+ FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS">;
26
27
  USER_IS_NOT_ANONYMOUS: _better_auth_core_utils_error_codes0.RawError<"USER_IS_NOT_ANONYMOUS">;
27
28
  DELETE_ANONYMOUS_USER_DISABLED: _better_auth_core_utils_error_codes0.RawError<"DELETE_ANONYMOUS_USER_DISABLED">;
28
29
  };
@@ -7,6 +7,7 @@ declare const ANONYMOUS_ERROR_CODES: {
7
7
  COULD_NOT_CREATE_SESSION: _better_auth_core_utils_error_codes0.RawError<"COULD_NOT_CREATE_SESSION">;
8
8
  ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY: _better_auth_core_utils_error_codes0.RawError<"ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY">;
9
9
  FAILED_TO_DELETE_ANONYMOUS_USER: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER">;
10
+ FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS">;
10
11
  USER_IS_NOT_ANONYMOUS: _better_auth_core_utils_error_codes0.RawError<"USER_IS_NOT_ANONYMOUS">;
11
12
  DELETE_ANONYMOUS_USER_DISABLED: _better_auth_core_utils_error_codes0.RawError<"DELETE_ANONYMOUS_USER_DISABLED">;
12
13
  };
@@ -6,6 +6,7 @@ const ANONYMOUS_ERROR_CODES = defineErrorCodes({
6
6
  COULD_NOT_CREATE_SESSION: "Could not create session",
7
7
  ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY: "Anonymous users cannot sign in again anonymously",
8
8
  FAILED_TO_DELETE_ANONYMOUS_USER: "Failed to delete anonymous user",
9
+ FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS: "Failed to delete anonymous user sessions",
9
10
  USER_IS_NOT_ANONYMOUS: "User is not anonymous",
10
11
  DELETE_ANONYMOUS_USER_DISABLED: "Deleting anonymous users is disabled"
11
12
  });
@@ -162,6 +162,7 @@ declare const anonymous: (options?: AnonymousOptions | undefined) => {
162
162
  COULD_NOT_CREATE_SESSION: _better_auth_core_utils_error_codes0.RawError<"COULD_NOT_CREATE_SESSION">;
163
163
  ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY: _better_auth_core_utils_error_codes0.RawError<"ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY">;
164
164
  FAILED_TO_DELETE_ANONYMOUS_USER: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER">;
165
+ FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS">;
165
166
  USER_IS_NOT_ANONYMOUS: _better_auth_core_utils_error_codes0.RawError<"USER_IS_NOT_ANONYMOUS">;
166
167
  DELETE_ANONYMOUS_USER_DISABLED: _better_auth_core_utils_error_codes0.RawError<"DELETE_ANONYMOUS_USER_DISABLED">;
167
168
  };