@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,685 @@
1
+ import { getSchema } from "./get-schema.mjs";
2
+ import { getAuthTables } from "@better-auth/core/db";
3
+ import { createLogger } from "@better-auth/core/env";
4
+ import { BetterAuthError } from "@better-auth/core/error";
5
+ import { createKyselyAdapter, getMssqlSchema, getPostgresSchema, toIntrospectedTables, toPhysicalSchema } from "@better-auth/kysely-adapter";
6
+ import { initGetFieldName, initGetModelName } from "@better-auth/core/db/adapter";
7
+ import { diffSchema, formatSchemaFinding, getDatabaseFieldIndexName, getDatabaseIndexStringLength, getPortableDatabaseIdentifierKey, invalidateSchemaChecks } from "@better-auth/core/db/internal";
8
+ import { sql } from "kysely";
9
+ //#region src/db/get-migration.ts
10
+ const map = {
11
+ postgres: {
12
+ string: [
13
+ "character varying",
14
+ "varchar",
15
+ "text",
16
+ "uuid"
17
+ ],
18
+ number: [
19
+ "int4",
20
+ "integer",
21
+ "bigint",
22
+ "smallint",
23
+ "numeric",
24
+ "real",
25
+ "double precision"
26
+ ],
27
+ boolean: ["bool", "boolean"],
28
+ date: [
29
+ "timestamptz",
30
+ "timestamp",
31
+ "date"
32
+ ],
33
+ json: ["json", "jsonb"]
34
+ },
35
+ mysql: {
36
+ string: [
37
+ "varchar",
38
+ "text",
39
+ "uuid"
40
+ ],
41
+ number: [
42
+ "integer",
43
+ "int",
44
+ "bigint",
45
+ "smallint",
46
+ "decimal",
47
+ "float",
48
+ "double"
49
+ ],
50
+ boolean: ["boolean", "tinyint"],
51
+ date: [
52
+ "timestamp",
53
+ "datetime",
54
+ "date"
55
+ ],
56
+ json: ["json"]
57
+ },
58
+ sqlite: {
59
+ string: ["TEXT"],
60
+ number: [
61
+ "INTEGER",
62
+ "REAL",
63
+ "BIGINT"
64
+ ],
65
+ boolean: ["INTEGER", "BOOLEAN"],
66
+ date: ["DATE", "INTEGER"],
67
+ json: ["TEXT"]
68
+ },
69
+ mssql: {
70
+ string: [
71
+ "varchar",
72
+ "nvarchar",
73
+ "uniqueidentifier"
74
+ ],
75
+ number: [
76
+ "int",
77
+ "bigint",
78
+ "smallint",
79
+ "decimal",
80
+ "float",
81
+ "double"
82
+ ],
83
+ boolean: ["bit", "smallint"],
84
+ date: [
85
+ "datetime2",
86
+ "date",
87
+ "datetime"
88
+ ],
89
+ json: ["varchar", "nvarchar"]
90
+ }
91
+ };
92
+ function createDatabaseIndexKey(tableName, indexName) {
93
+ return `${getPortableDatabaseIdentifierKey(tableName)}\u0000${getPortableDatabaseIdentifierKey(indexName)}`;
94
+ }
95
+ function createDatabaseColumnKey(tableName, columnName) {
96
+ return `${tableName}\u0000${columnName}`;
97
+ }
98
+ function databaseIndexMatches(existing, configured) {
99
+ return existing.unique === (configured.unique ?? false) && existing.validFullColumns && existing.columns.length === configured.columns.length && existing.columns.every((column, position) => column === configured.columns[position]);
100
+ }
101
+ function databaseValueIsTrue(value) {
102
+ if (typeof value === "boolean") return value;
103
+ if (typeof value === "number") return value !== 0;
104
+ return value === "1" || value?.toLowerCase() === "true" || value === "t";
105
+ }
106
+ function toDatabaseIndexMap(indexes) {
107
+ return new Map(indexes.map((index) => {
108
+ const columns = [...index.columns].sort((left, right) => left.position - right.position);
109
+ return [createDatabaseIndexKey(index.table, index.name), {
110
+ columns: columns.flatMap((column) => column.name === null ? [] : [column.name]),
111
+ name: index.name,
112
+ table: index.table,
113
+ unique: index.unique,
114
+ validFullColumns: index.valid && !index.partial && columns.length > 0 && columns.every((column) => column.name !== null && column.fullLength)
115
+ }];
116
+ }));
117
+ }
118
+ async function getDatabaseIndexMap(db, target, tableNames, introspectIndexes) {
119
+ if (introspectIndexes) return toDatabaseIndexMap(await introspectIndexes(tableNames));
120
+ let rows;
121
+ switch (target.type) {
122
+ case "sqlite":
123
+ rows = (await sql`
124
+ SELECT
125
+ tables.name AS "tableName",
126
+ index_list.name AS "indexName",
127
+ index_info.name AS "columnName",
128
+ index_list."unique" AS "isUnique",
129
+ index_list.partial AS "isPartial",
130
+ index_info.seqno AS "columnPosition"
131
+ FROM sqlite_master AS tables
132
+ INNER JOIN pragma_index_list(tables.name) AS index_list
133
+ INNER JOIN pragma_index_info(index_list.name) AS index_info
134
+ WHERE tables.type = 'table'
135
+ `.execute(db)).rows;
136
+ break;
137
+ case "postgres":
138
+ rows = (await sql`
139
+ SELECT
140
+ table_class.relname AS "tableName",
141
+ index_class.relname AS "indexName",
142
+ index_attribute.attname AS "columnName",
143
+ index_data.indisunique AS "isUnique",
144
+ index_data.indisvalid AS "isValid",
145
+ (index_data.indpred IS NOT NULL) AS "isPartial",
146
+ index_column.ordinality AS "columnPosition"
147
+ FROM pg_class AS table_class
148
+ INNER JOIN pg_namespace AS table_namespace
149
+ ON table_namespace.oid = table_class.relnamespace
150
+ INNER JOIN pg_index AS index_data
151
+ ON index_data.indrelid = table_class.oid
152
+ INNER JOIN pg_class AS index_class
153
+ ON index_class.oid = index_data.indexrelid
154
+ INNER JOIN LATERAL unnest(index_data.indkey)
155
+ WITH ORDINALITY AS index_column(attribute_number, ordinality)
156
+ ON TRUE
157
+ LEFT JOIN pg_attribute AS index_attribute
158
+ ON index_attribute.attrelid = table_class.oid
159
+ AND index_attribute.attnum = index_column.attribute_number
160
+ WHERE table_namespace.nspname = ${target.schema}
161
+ AND table_class.relkind = 'r'
162
+ AND index_column.ordinality <= index_data.indnkeyatts
163
+ `.execute(db)).rows;
164
+ break;
165
+ case "mysql":
166
+ rows = (await sql`
167
+ SELECT
168
+ table_name AS tableName,
169
+ index_name AS indexName,
170
+ column_name AS columnName,
171
+ non_unique AS nonUnique,
172
+ seq_in_index AS columnPosition,
173
+ sub_part AS prefixLength,
174
+ COALESCE(LOWER(comment) = 'disabled', FALSE) AS isDisabled
175
+ FROM information_schema.statistics
176
+ WHERE table_schema = DATABASE()
177
+ `.execute(db)).rows;
178
+ break;
179
+ case "mssql":
180
+ rows = (await sql`
181
+ SELECT
182
+ tables.name AS "tableName",
183
+ indexes.name AS "indexName",
184
+ columns.name AS "columnName",
185
+ indexes.is_unique AS "isUnique",
186
+ indexes.is_disabled AS "isDisabled",
187
+ indexes.is_hypothetical AS "isHypothetical",
188
+ indexes.has_filter AS "isPartial",
189
+ index_columns.key_ordinal AS "columnPosition"
190
+ FROM sys.indexes AS indexes
191
+ INNER JOIN sys.tables AS tables
192
+ ON indexes.object_id = tables.object_id
193
+ INNER JOIN sys.schemas AS table_schemas
194
+ ON table_schemas.schema_id = tables.schema_id
195
+ INNER JOIN sys.index_columns AS index_columns
196
+ ON index_columns.object_id = indexes.object_id
197
+ AND index_columns.index_id = indexes.index_id
198
+ INNER JOIN sys.columns AS columns
199
+ ON columns.object_id = index_columns.object_id
200
+ AND columns.column_id = index_columns.column_id
201
+ WHERE table_schemas.name = ${target.schema}
202
+ AND indexes.name IS NOT NULL
203
+ AND index_columns.key_ordinal > 0
204
+ `.execute(db)).rows;
205
+ break;
206
+ }
207
+ const indexMetadata = /* @__PURE__ */ new Map();
208
+ for (const row of rows) {
209
+ const table = row.tableName ?? row.table_name ?? row.TABLE_NAME ?? row.tablename ?? row.tbl_name;
210
+ const name = row.indexName ?? row.index_name ?? row.INDEX_NAME ?? row.name;
211
+ const column = row.columnName ?? row.column_name ?? row.COLUMN_NAME;
212
+ if (!table || !name) continue;
213
+ const key = createDatabaseIndexKey(table, name);
214
+ const nonUnique = row.nonUnique ?? row.non_unique ?? row.NON_UNIQUE;
215
+ const unique = nonUnique === void 0 ? databaseValueIsTrue(row.isUnique ?? row.is_unique) : !databaseValueIsTrue(nonUnique);
216
+ const position = Number(row.columnPosition ?? row.column_position ?? row.keyOrdinal ?? row.key_ordinal ?? row.ordinality ?? row.seqInIndex ?? row.seq_in_index ?? row.SEQ_IN_INDEX ?? row.seqno ?? 0);
217
+ const indexColumn = {
218
+ fullLength: column !== void 0 && column !== null && (row.prefixLength === void 0 || row.prefixLength === null),
219
+ name: column ?? null,
220
+ position
221
+ };
222
+ const partial = databaseValueIsTrue(row.isPartial);
223
+ const valid = !databaseValueIsTrue(row.isDisabled) && !databaseValueIsTrue(row.isHypothetical) && (row.isValid === void 0 || databaseValueIsTrue(row.isValid));
224
+ const existing = indexMetadata.get(key);
225
+ indexMetadata.set(key, existing ? {
226
+ ...existing,
227
+ columns: [...existing.columns, indexColumn],
228
+ partial: existing.partial || partial,
229
+ valid: existing.valid && valid
230
+ } : {
231
+ columns: [indexColumn],
232
+ name,
233
+ partial,
234
+ table,
235
+ unique,
236
+ valid
237
+ });
238
+ }
239
+ return toDatabaseIndexMap([...indexMetadata.values()]);
240
+ }
241
+ async function getDatabaseColumnBounds(db, target) {
242
+ let rows;
243
+ switch (target.type) {
244
+ case "postgres":
245
+ case "sqlite": return /* @__PURE__ */ new Map();
246
+ case "mysql":
247
+ rows = (await sql`
248
+ SELECT
249
+ table_name AS tableName,
250
+ column_name AS columnName,
251
+ character_octet_length AS maxIndexBytes
252
+ FROM information_schema.columns
253
+ WHERE table_schema = DATABASE()
254
+ `.execute(db)).rows;
255
+ break;
256
+ case "mssql":
257
+ rows = (await sql`
258
+ SELECT
259
+ tables.name AS "tableName",
260
+ columns.name AS "columnName",
261
+ columns.max_length AS "maxIndexBytes"
262
+ FROM sys.columns AS columns
263
+ INNER JOIN sys.tables AS tables
264
+ ON tables.object_id = columns.object_id
265
+ INNER JOIN sys.schemas AS table_schemas
266
+ ON table_schemas.schema_id = tables.schema_id
267
+ WHERE table_schemas.name = ${target.schema}
268
+ `.execute(db)).rows;
269
+ break;
270
+ }
271
+ const bounds = /* @__PURE__ */ new Map();
272
+ for (const row of rows) {
273
+ const table = row.tableName ?? row.TABLE_NAME;
274
+ const column = row.columnName ?? row.COLUMN_NAME;
275
+ if (!table || !column) continue;
276
+ const maxIndexBytes = Number(row.maxIndexBytes ?? row.MAX_INDEX_BYTES ?? -1);
277
+ bounds.set(createDatabaseColumnKey(table, column), { maxIndexBytes: maxIndexBytes < 0 ? null : maxIndexBytes });
278
+ }
279
+ return bounds;
280
+ }
281
+ function assertExistingTableIndexFits({ columnBounds, dbType, existingColumns, fields, indexes, index, table }) {
282
+ const byteBudget = dbType === "mysql" ? 3072 : 1700;
283
+ let requiredBytes = 0;
284
+ for (const column of index.columns) {
285
+ const field = fields[column];
286
+ if (!field) continue;
287
+ if (field.type === "string" || Array.isArray(field.type)) {
288
+ if (!existingColumns.has(column)) {
289
+ const generatedLength = getDatabaseIndexStringLength({
290
+ columnName: column,
291
+ dialect: dbType,
292
+ fields,
293
+ indexes
294
+ });
295
+ requiredBytes += (generatedLength ?? 0) * (dbType === "mysql" ? 4 : 1);
296
+ continue;
297
+ }
298
+ const bound = columnBounds.get(createDatabaseColumnKey(table, column));
299
+ if (!bound?.maxIndexBytes) throw new BetterAuthError(`Cannot create database index "${index.name}" on existing table "${table}" because column "${column}" is not bounded for ${dbType === "mysql" ? "MySQL" : "SQL Server"}. Change it to a bounded string column, resolve oversized values, then run the migration again.`);
300
+ requiredBytes += bound.maxIndexBytes;
301
+ } else requiredBytes += 16;
302
+ }
303
+ if (requiredBytes > byteBudget) throw new BetterAuthError(`Cannot create database index "${index.name}" on existing table "${table}" because its columns can exceed ${dbType === "mysql" ? "MySQL" : "SQL Server"}'s ${byteBudget}-byte index-key limit. Bound the indexed string columns to the generated schema lengths, resolve oversized values, then run the migration again.`);
304
+ }
305
+ /**
306
+ * Thrown when {@link getMigrations} refuses to add a required column with no
307
+ * default value to a populated table. Distinct from the plain
308
+ * {@link BetterAuthError} thrown for index-definition conflicts, so callers
309
+ * can tell the two apart without matching on message text.
310
+ */
311
+ var UnsafeMigrationError = class extends BetterAuthError {};
312
+ function hasTimestampColumnDefault(field, dbType) {
313
+ return field.type === "date" && typeof field.defaultValue === "function" && (dbType === "postgres" || dbType === "mysql" || dbType === "mssql");
314
+ }
315
+ function hasStaticColumnDefault(field) {
316
+ return !(field.unique && field.required === false) && (field.type === "string" || field.type === "number" || field.type === "boolean") && field.defaultValue !== void 0 && field.defaultValue !== null && typeof field.defaultValue !== "function";
317
+ }
318
+ async function tableHasRows(db, dbType, table) {
319
+ const probe = db.selectFrom(table).select(sql`1`.as("present"));
320
+ return (await (dbType === "mssql" ? probe.top(1) : probe.limit(1)).execute()).length > 0;
321
+ }
322
+ function matchType(columnDataType, fieldType, dbType) {
323
+ function normalize(type) {
324
+ return type.toLowerCase().split("(")[0].trim();
325
+ }
326
+ if (fieldType === "string[]" || fieldType === "number[]") return columnDataType.toLowerCase().includes("json");
327
+ const types = map[dbType];
328
+ return (Array.isArray(fieldType) ? types["string"].map((t) => t.toLowerCase()) : types[fieldType].map((t) => t.toLowerCase())).includes(normalize(columnDataType));
329
+ }
330
+ /**
331
+ * Build the migration plan that `auth migrate` executes and `auth generate`
332
+ * prints for the Kysely adapter.
333
+ *
334
+ * Adding a required column without a default to a populated table is refused:
335
+ * existing rows have no value to backfill. `throwOnUnsafe` picks how that
336
+ * refusal is delivered: executing callers get an {@link UnsafeMigrationError},
337
+ * read-only callers get the plan plus the same message in `unsafeChanges`.
338
+ *
339
+ * @throws {UnsafeMigrationError} when a required column cannot be migrated
340
+ * safely and `throwOnUnsafe` is left on.
341
+ * @throws {BetterAuthError} when an index definition conflicts with an
342
+ * existing or already-planned index.
343
+ */
344
+ async function getMigrations(config, { throwOnUnsafe = true } = {}) {
345
+ const betterAuthSchema = getSchema(config);
346
+ const authTables = getAuthTables(config);
347
+ const logger = createLogger(config.logger);
348
+ const unsafeChanges = [];
349
+ const reportUnsafeChange = (message) => {
350
+ if (throwOnUnsafe) throw new UnsafeMigrationError(message);
351
+ unsafeChanges.push(message);
352
+ };
353
+ let { kysely: db, databaseType: dbType, introspectIndexes, schemaName } = await createKyselyAdapter(config);
354
+ if (!dbType) {
355
+ logger.warn("Could not determine database type, defaulting to sqlite. Please provide a type in the database options to avoid this.");
356
+ dbType = "sqlite";
357
+ }
358
+ if (!db) {
359
+ logger.error("Only kysely adapter is supported for migrations. You can use `generate` command to generate the schema, if you're using a different adapter.");
360
+ process.exit(1);
361
+ }
362
+ const allTableMetadata = await db.introspection.getTables();
363
+ let target;
364
+ let tableMetadata = allTableMetadata;
365
+ switch (dbType) {
366
+ case "postgres": {
367
+ const schema = schemaName ?? await getPostgresSchema(db);
368
+ target = {
369
+ type: "postgres",
370
+ schema
371
+ };
372
+ logger.debug(`PostgreSQL migration: Using schema '${schema}' (${schemaName ? "from database.schemaName" : "from search_path"})`);
373
+ try {
374
+ if (!(await db.introspection.getSchemas()).some(({ name }) => name === schema)) if (schemaName) logger.debug(`Schema '${schema}' does not exist yet. The migration creates it before creating tables.`);
375
+ else logger.warn(`Schema '${schema}' does not exist. Create it before running migrations or check your database configuration.`);
376
+ } catch (error) {
377
+ logger.debug(`Could not verify schema existence: ${error instanceof Error ? error.message : String(error)}`);
378
+ }
379
+ /**
380
+ * Kysely 0.28 does not expose `isForeign`, while 0.29 adds foreign table metadata.
381
+ * @see https://github.com/kysely-org/kysely/pull/1494
382
+ */
383
+ tableMetadata = allTableMetadata.filter((table) => table.schema === schema && !table.isView && !("isForeign" in table && table.isForeign));
384
+ logger.debug(`Found ${tableMetadata.length} table(s) in schema '${schema}': ${tableMetadata.map((table) => table.name).join(", ") || "(none)"}`);
385
+ break;
386
+ }
387
+ case "mssql": {
388
+ const schema = await getMssqlSchema(db);
389
+ target = {
390
+ type: "mssql",
391
+ schema
392
+ };
393
+ logger.debug(`SQL Server migration: Using schema '${schema}' (from the current user's default schema)`);
394
+ tableMetadata = allTableMetadata.filter((table) => table.schema === schema);
395
+ break;
396
+ }
397
+ case "mysql":
398
+ target = { type: "mysql" };
399
+ break;
400
+ case "sqlite":
401
+ target = { type: "sqlite" };
402
+ break;
403
+ }
404
+ const databaseIndexMap = await getDatabaseIndexMap(db, target, allTableMetadata.map((table) => table.name), introspectIndexes);
405
+ const databaseColumnBounds = await getDatabaseColumnBounds(db, target);
406
+ const schemaProblems = diffSchema(toPhysicalSchema(db, betterAuthSchema), toIntrospectedTables(tableMetadata)).filter((finding) => finding.kind === "unexpected-required-column").map((finding) => formatSchemaFinding(finding, "database"));
407
+ const toBeCreated = [];
408
+ const toBeAdded = [];
409
+ const toBeAddedIndexes = [];
410
+ const plannedIndexes = /* @__PURE__ */ new Map();
411
+ for (const [key, value] of Object.entries(betterAuthSchema)) {
412
+ if (value.disableMigrations) continue;
413
+ const table = tableMetadata.find((table) => table.name === key);
414
+ for (const index of value.indexes ?? []) {
415
+ const name = index.name;
416
+ const indexKey = createDatabaseIndexKey(key, name);
417
+ const existingIndex = databaseIndexMap.get(indexKey);
418
+ if (existingIndex) {
419
+ if (!databaseIndexMatches(existingIndex, index)) throw new BetterAuthError(`Database index "${name}" on table "${key}" does not match the configured fields and uniqueness. Rename or replace the existing index, then run the migration again.`);
420
+ continue;
421
+ }
422
+ if (dbType === "sqlite" || dbType === "postgres") {
423
+ const indexOnAnotherTable = [...databaseIndexMap.values()].find((databaseIndex) => getPortableDatabaseIdentifierKey(databaseIndex.name) === getPortableDatabaseIdentifierKey(name) && getPortableDatabaseIdentifierKey(databaseIndex.table) !== getPortableDatabaseIdentifierKey(key));
424
+ if (indexOnAnotherTable) throw new BetterAuthError(`Database index name "${name}" is already used by table "${indexOnAnotherTable.table}". Index names must be unique across the schema.`);
425
+ }
426
+ const plannedIndex = plannedIndexes.get(indexKey);
427
+ if (plannedIndex) {
428
+ if (!databaseIndexMatches({
429
+ columns: plannedIndex.columns,
430
+ name: plannedIndex.name,
431
+ table: key,
432
+ unique: plannedIndex.unique ?? false,
433
+ validFullColumns: true
434
+ }, index)) throw new BetterAuthError(`Database index name "${name}" identifies more than one index on table "${key}".`);
435
+ continue;
436
+ }
437
+ if (table && (dbType === "mysql" || dbType === "mssql")) assertExistingTableIndexFits({
438
+ columnBounds: databaseColumnBounds,
439
+ dbType,
440
+ existingColumns: new Set(table.columns.map((column) => column.name)),
441
+ fields: value.fields,
442
+ index,
443
+ indexes: value.indexes ?? [],
444
+ table: key
445
+ });
446
+ plannedIndexes.set(indexKey, index);
447
+ toBeAddedIndexes.push({
448
+ table: key,
449
+ index,
450
+ name
451
+ });
452
+ }
453
+ if (!table) {
454
+ const tIndex = toBeCreated.findIndex((t) => t.table === key);
455
+ const tableData = {
456
+ table: key,
457
+ fields: value.fields,
458
+ order: value.order || Infinity
459
+ };
460
+ const insertIndex = toBeCreated.findIndex((t) => (t.order || Infinity) > tableData.order);
461
+ if (insertIndex === -1) if (tIndex === -1) toBeCreated.push(tableData);
462
+ else toBeCreated[tIndex].fields = {
463
+ ...toBeCreated[tIndex].fields,
464
+ ...value.fields
465
+ };
466
+ else toBeCreated.splice(insertIndex, 0, tableData);
467
+ continue;
468
+ }
469
+ const toBeAddedFields = {};
470
+ for (const [fieldName, field] of Object.entries(value.fields)) {
471
+ const column = table.columns.find((c) => c.name === fieldName);
472
+ if (!column) {
473
+ toBeAddedFields[fieldName] = field;
474
+ continue;
475
+ }
476
+ if (field.required !== false && column.isNullable) logger.warn(`Column "${fieldName}" on table "${key}" stays nullable while the schema declares the field required, so existing rows can still hold null. Backfill every row for this column and enforce NOT NULL to remove the drift.`);
477
+ if (matchType(column.dataType, field.type, dbType)) continue;
478
+ else logger.warn(`Field ${fieldName} in table ${key} has a different type in the database. Expected ${field.type} but got ${column.dataType}.`);
479
+ }
480
+ if (Object.keys(toBeAddedFields).length > 0) toBeAdded.push({
481
+ table: key,
482
+ fields: toBeAddedFields,
483
+ order: value.order || Infinity
484
+ });
485
+ }
486
+ const migrations = [];
487
+ if (schemaName && toBeCreated.length > 0) migrations.push(db.schema.createSchema(schemaName).ifNotExists());
488
+ const useUUIDs = config.advanced?.database?.generateId === "uuid";
489
+ const useNumberId = config.advanced?.database?.generateId === "serial";
490
+ function getType(field, fieldName, tableIndexStringLength) {
491
+ const type = field.type;
492
+ const provider = dbType || "sqlite";
493
+ const typeMap = {
494
+ string: {
495
+ sqlite: "text",
496
+ postgres: "text",
497
+ mysql: tableIndexStringLength ? `varchar(${tableIndexStringLength})` : field.unique ? "varchar(255)" : field.references ? "varchar(36)" : field.sortable ? "varchar(255)" : field.index ? "varchar(255)" : "text",
498
+ mssql: tableIndexStringLength ? `varchar(${tableIndexStringLength})` : field.unique || field.sortable ? "varchar(255)" : field.references ? "varchar(36)" : "varchar(8000)"
499
+ },
500
+ boolean: {
501
+ sqlite: "integer",
502
+ postgres: "boolean",
503
+ mysql: "boolean",
504
+ mssql: "smallint"
505
+ },
506
+ number: {
507
+ sqlite: field.bigint ? "bigint" : "integer",
508
+ postgres: field.bigint ? "bigint" : "integer",
509
+ mysql: field.bigint ? "bigint" : "integer",
510
+ mssql: field.bigint ? "bigint" : "integer"
511
+ },
512
+ date: {
513
+ sqlite: "date",
514
+ postgres: "timestamptz",
515
+ mysql: "timestamp(3)",
516
+ mssql: sql`datetime2(3)`
517
+ },
518
+ json: {
519
+ sqlite: "text",
520
+ postgres: "jsonb",
521
+ mysql: "json",
522
+ mssql: "varchar(8000)"
523
+ },
524
+ id: {
525
+ postgres: useNumberId ? sql`integer GENERATED BY DEFAULT AS IDENTITY` : useUUIDs ? "uuid" : "text",
526
+ mysql: useNumberId ? "integer" : useUUIDs ? "varchar(36)" : "varchar(36)",
527
+ mssql: useNumberId ? "integer" : useUUIDs ? "varchar(36)" : "varchar(36)",
528
+ sqlite: useNumberId ? "integer" : "text"
529
+ },
530
+ foreignKeyId: {
531
+ postgres: useNumberId ? "integer" : useUUIDs ? "uuid" : "text",
532
+ mysql: useNumberId ? "integer" : useUUIDs ? "varchar(36)" : "varchar(36)",
533
+ mssql: useNumberId ? "integer" : useUUIDs ? "varchar(36)" : "varchar(36)",
534
+ sqlite: useNumberId ? "integer" : "text"
535
+ },
536
+ "string[]": {
537
+ sqlite: "text",
538
+ postgres: "jsonb",
539
+ mysql: "json",
540
+ mssql: "varchar(8000)"
541
+ },
542
+ "number[]": {
543
+ sqlite: "text",
544
+ postgres: "jsonb",
545
+ mysql: "json",
546
+ mssql: "varchar(8000)"
547
+ }
548
+ };
549
+ if (fieldName === "id" || field.references?.field === "id") {
550
+ if (fieldName === "id") return typeMap.id[provider];
551
+ return typeMap.foreignKeyId[provider];
552
+ }
553
+ if (Array.isArray(type)) return "text";
554
+ if (!(type in typeMap)) throw new Error(`Unsupported field type '${String(type)}' for field '${fieldName}'. Allowed types are: string, number, boolean, date, string[], number[]. If you need to store structured data, store it as a JSON string (type: "string") or split it into primitive fields. See https://better-auth.com/docs/advanced/schema#additional-fields`);
555
+ return typeMap[type][provider];
556
+ }
557
+ const getModelName = initGetModelName({
558
+ schema: authTables,
559
+ usePlural: false
560
+ });
561
+ const getFieldName = initGetFieldName({
562
+ schema: authTables,
563
+ usePlural: false
564
+ });
565
+ function getReferencePath(model, field) {
566
+ try {
567
+ return `${getModelName(model)}.${getFieldName({
568
+ model,
569
+ field
570
+ })}`;
571
+ } catch {
572
+ return `${model}.${field}`;
573
+ }
574
+ }
575
+ const deferredIndexes = [];
576
+ const getTableIndexStringLength = (tableName, fieldName) => {
577
+ if (dbType !== "mysql" && dbType !== "mssql") return void 0;
578
+ const table = betterAuthSchema[tableName];
579
+ if (!table) return void 0;
580
+ return getDatabaseIndexStringLength({
581
+ columnName: fieldName,
582
+ dialect: dbType,
583
+ fields: table.fields,
584
+ indexes: table.indexes ?? []
585
+ });
586
+ };
587
+ if (toBeAdded.length) {
588
+ const populatedTables = /* @__PURE__ */ new Map();
589
+ for (const table of toBeAdded) for (const [fieldName, field] of Object.entries(table.fields)) {
590
+ const timestampDefault = hasTimestampColumnDefault(field, dbType);
591
+ const staticDefault = hasStaticColumnDefault(field);
592
+ if (field.required !== false && !timestampDefault && !staticDefault) {
593
+ let populated = populatedTables.get(table.table);
594
+ if (populated === void 0) {
595
+ populated = await tableHasRows(db, dbType, table.table);
596
+ populatedTables.set(table.table, populated);
597
+ }
598
+ if (populated) {
599
+ const textDetail = field.type === "string" ? " For a text column, every existing row ends up with the same empty string." : "";
600
+ reportUnsafeChange(`Cannot add required column "${fieldName}" to populated table "${table.table}": the schema declares no default value, so existing rows have no value to backfill. MySQL accepts this statement instead of rejecting it and fills every existing row with an implicit default for the column type, reporting a successful migration over corrupted data.${textDetail} Add the column as nullable, backfill a correct value for every row, then make it NOT NULL.`);
601
+ }
602
+ }
603
+ const type = getType(field, fieldName, getTableIndexStringLength(table.table, fieldName));
604
+ const builder = db.schema.alterTable(table.table);
605
+ if (field.index || field.unique) {
606
+ const indexName = getDatabaseFieldIndexName(table.table, fieldName, field.unique ?? false);
607
+ let indexBuilder = db.schema.createIndex(indexName).on(table.table).columns([fieldName]);
608
+ if (field.unique) {
609
+ indexBuilder = indexBuilder.unique();
610
+ if (field.required === false && dbType === "mssql") indexBuilder = indexBuilder.where(fieldName, "is not", null);
611
+ if (field.required !== false && field.defaultValue !== void 0 && field.defaultValue !== null && typeof field.defaultValue !== "function") logger.warn(`Adding unique column "${fieldName}" to existing table "${table.table}" backfills every existing row with its default value. If the table has more than one row, creating the unique index "${indexName}" will fail; backfill distinct values manually, then re-run the migration or create the index yourself.`);
612
+ }
613
+ deferredIndexes.push(indexBuilder);
614
+ }
615
+ const built = builder.addColumn(fieldName, type, (col) => {
616
+ col = field.required !== false ? col.notNull() : col;
617
+ if (field.references) col = col.references(getReferencePath(field.references.model, field.references.field)).onDelete(field.references.onDelete || "cascade");
618
+ if (timestampDefault) if (dbType === "mysql") col = col.defaultTo(sql`CURRENT_TIMESTAMP(3)`);
619
+ else col = col.defaultTo(sql`CURRENT_TIMESTAMP`);
620
+ else if (staticDefault) col = col.defaultTo(typeof field.defaultValue === "boolean" && (dbType === "sqlite" || dbType === "mssql") ? field.defaultValue ? 1 : 0 : field.defaultValue);
621
+ return col;
622
+ });
623
+ migrations.push(built);
624
+ }
625
+ }
626
+ if (toBeCreated.length) for (const table of toBeCreated) {
627
+ const idType = getType({ type: useNumberId ? "number" : "string" }, "id");
628
+ let dbT = db.schema.createTable(table.table).addColumn("id", idType, (col) => {
629
+ if (useNumberId) {
630
+ if (dbType === "postgres") return col.primaryKey().notNull();
631
+ else if (dbType === "sqlite") return col.primaryKey().notNull();
632
+ else if (dbType === "mssql") return col.identity().primaryKey().notNull();
633
+ return col.autoIncrement().primaryKey().notNull();
634
+ }
635
+ if (useUUIDs) {
636
+ if (dbType === "postgres") return col.primaryKey().defaultTo(sql`pg_catalog.gen_random_uuid()`).notNull();
637
+ return col.primaryKey().notNull();
638
+ }
639
+ return col.primaryKey().notNull();
640
+ });
641
+ for (const [fieldName, field] of Object.entries(table.fields)) {
642
+ const type = getType(field, fieldName, getTableIndexStringLength(table.table, fieldName));
643
+ dbT = dbT.addColumn(fieldName, type, (col) => {
644
+ col = field.required !== false ? col.notNull() : col;
645
+ if (field.references) col = col.references(getReferencePath(field.references.model, field.references.field)).onDelete(field.references.onDelete || "cascade");
646
+ if (field.unique) col = col.unique();
647
+ if (field.type === "date" && typeof field.defaultValue === "function" && (dbType === "postgres" || dbType === "mysql" || dbType === "mssql")) if (dbType === "mysql") col = col.defaultTo(sql`CURRENT_TIMESTAMP(3)`);
648
+ else col = col.defaultTo(sql`CURRENT_TIMESTAMP`);
649
+ return col;
650
+ });
651
+ if (field.index && !field.unique) {
652
+ const builder = db.schema.createIndex(getDatabaseFieldIndexName(table.table, fieldName, false)).on(table.table).columns([fieldName]);
653
+ deferredIndexes.push(builder);
654
+ }
655
+ }
656
+ migrations.push(dbT);
657
+ }
658
+ for (const { table, index, name } of toBeAddedIndexes) {
659
+ let builder = db.schema.createIndex(name).on(table).columns([...index.columns]);
660
+ if (index.unique) builder = builder.unique();
661
+ deferredIndexes.push(builder);
662
+ }
663
+ for (const index of deferredIndexes) migrations.push(index);
664
+ async function runMigrations() {
665
+ try {
666
+ for (const migration of migrations) await migration.execute();
667
+ } finally {
668
+ if (migrations.length && config.database) invalidateSchemaChecks(config.database);
669
+ }
670
+ }
671
+ async function compileMigrations() {
672
+ return migrations.map((m) => m.compile().sql).join(";\n\n") + ";";
673
+ }
674
+ return {
675
+ toBeCreated,
676
+ toBeAdded,
677
+ toBeAddedIndexes,
678
+ unsafeChanges,
679
+ schemaProblems,
680
+ runMigrations,
681
+ compileMigrations
682
+ };
683
+ }
684
+ //#endregion
685
+ export { UnsafeMigrationError, getMigrations, matchType };