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
@@ -1,9 +1,10 @@
1
+ import { isSafeUrlScheme } from "@better-auth/core/utils/url";
1
2
  //#region src/client/fetch-plugins.ts
2
3
  const redirectPlugin = {
3
4
  id: "redirect",
4
5
  name: "Redirect",
5
6
  hooks: { onSuccess(context) {
6
- if (context.data?.url && context.data?.redirect) {
7
+ if (context.data?.url && context.data?.redirect && isSafeUrlScheme(context.data.url)) {
7
8
  if (typeof window !== "undefined" && window.location) {
8
9
  if (window.location) try {
9
10
  window.location.href = context.data.url;
@@ -8,7 +8,7 @@ import { parseJSON } from "./parser.mjs";
8
8
  import { AuthQueryAtom, useAuthQuery } from "./query.mjs";
9
9
  import { SessionRefreshOptions, SessionResponse, createSessionRefreshManager } from "./session-refresh.mjs";
10
10
  import { AuthClient, createAuthClient } from "./vanilla.mjs";
11
- import { AccessControl, ArrayElement, Role, Statements, SubArray, Subset } from "../plugins/access/types.mjs";
11
+ import { AccessControl, ArrayElement, ExactRoleStatements, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, Statements, SubArray, Subset } from "../plugins/access/types.mjs";
12
12
  import { AuthorizeResponse, createAccessControl, role } from "../plugins/access/access.mjs";
13
13
  import { OrganizationOptions } from "../plugins/organization/types.mjs";
14
14
  import { InferInvitation, InferMember, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferTeam, Invitation, InvitationInput, InvitationStatus, Member, MemberInput, Organization, OrganizationInput, OrganizationRole, OrganizationSchema, Team, TeamInput, TeamMember, TeamMemberInput, defaultRolesSchema, invitationSchema, invitationStatus, memberSchema, organizationRoleSchema, organizationSchema, roleSchema, teamMemberSchema, teamSchema } from "../plugins/organization/schema.mjs";
@@ -31,4 +31,4 @@ declare function InferAuth<O extends {
31
31
  options: BetterAuthOptions;
32
32
  }>(): O["options"];
33
33
  //#endregion
34
- export { AccessControl, ArrayElement, AuthClient, AuthQueryAtom, AuthorizeResponse, BetterAuthClientOptions, BetterAuthClientPlugin, BroadcastChannel, BroadcastListener, BroadcastMessage, CamelCase, ClientAtomListener, ClientStore, type DBPrimitive, DefaultOrganizationPlugin, DynamicAccessControlEndpoints, ExtractPluginField, type FocusListener, type FocusManager, HasRequiredKeys, InferActions, InferAdditionalFromClient, InferAuth, InferClientAPI, InferCtx, InferErrorCodes, InferInvitation, InferMember, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPlugin, InferPluginFieldFromTuple, InferRoute, InferRoutes, InferSessionFromClient, InferSignUpEmailCtx, InferTeam, InferUserFromClient, InferUserUpdateCtx, Invitation, InvitationInput, InvitationStatus, IsAny, IsSignal, Member, MemberInput, MergeRoutes, type OnlineListener, type OnlineManager, Organization, OrganizationCreator, OrganizationEndpoints, OrganizationInput, OrganizationOptions, OrganizationPlugin, OrganizationRole, OrganizationSchema, OverrideMerge, PathToObject, Prettify, PrettifyDeep, ProxyRequest, RequiredKeysOf, Role, SessionQueryParams, SessionRefreshOptions, SessionResponse, Statements, StripEmptyObjects, SubArray, Subset, Team, TeamEndpoints, TeamInput, TeamMember, TeamMemberInput, type UnionToIntersection, createAccessControl, createAuthClient, createSessionRefreshManager, defaultRolesSchema, getGlobalBroadcastChannel, getOrgAdapter, hasPermission, invitationSchema, invitationStatus, kBroadcastChannel, kFocusManager, kOnlineManager, memberSchema, organization, organizationRoleSchema, organizationSchema, parseJSON, parseRoles, role, roleSchema, teamMemberSchema, teamSchema, useAuthQuery };
34
+ export { AccessControl, ArrayElement, AuthClient, AuthQueryAtom, AuthorizeResponse, BetterAuthClientOptions, BetterAuthClientPlugin, BroadcastChannel, BroadcastListener, BroadcastMessage, CamelCase, ClientAtomListener, ClientStore, type DBPrimitive, DefaultOrganizationPlugin, DynamicAccessControlEndpoints, ExactRoleStatements, ExtractPluginField, type FocusListener, type FocusManager, HasRequiredKeys, InferActions, InferAdditionalFromClient, InferAuth, InferClientAPI, InferCtx, InferErrorCodes, InferInvitation, InferMember, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPlugin, InferPluginFieldFromTuple, InferRoute, InferRoutes, InferSessionFromClient, InferSignUpEmailCtx, InferTeam, InferUserFromClient, InferUserUpdateCtx, Invitation, InvitationInput, InvitationStatus, IsAny, IsSignal, Member, MemberInput, MergeRoutes, type OnlineListener, type OnlineManager, Organization, OrganizationCreator, OrganizationEndpoints, OrganizationInput, OrganizationOptions, OrganizationPlugin, OrganizationRole, OrganizationSchema, OverrideMerge, PathToObject, Prettify, PrettifyDeep, ProxyRequest, RequiredKeysOf, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, SessionQueryParams, SessionRefreshOptions, SessionResponse, Statements, StripEmptyObjects, SubArray, Subset, Team, TeamEndpoints, TeamInput, TeamMember, TeamMemberInput, type UnionToIntersection, createAccessControl, createAuthClient, createSessionRefreshManager, defaultRolesSchema, getGlobalBroadcastChannel, getOrgAdapter, hasPermission, invitationSchema, invitationStatus, kBroadcastChannel, kFocusManager, kOnlineManager, memberSchema, organization, organizationRoleSchema, organizationSchema, parseJSON, parseRoles, role, roleSchema, teamMemberSchema, teamSchema, useAuthQuery };
@@ -14,6 +14,19 @@ type InferResolvedHooks<O extends BetterAuthClientOptions> = O extends {
14
14
  plugins: Array<infer Plugin>;
15
15
  } ? UnionToIntersection<Plugin extends BetterAuthClientPlugin ? Plugin["getAtoms"] extends ((fetch: any) => infer Atoms) ? Atoms extends Record<string, any> ? { [key in keyof Atoms as IsSignal<key> extends true ? never : key extends string ? `use${Capitalize<key>}` : never]: () => ReturnType<Atoms[key]["get"]> } : {} : {} : {}> : {};
16
16
  declare function createAuthClient<Option extends BetterAuthClientOptions>(options?: Option | undefined): UnionToIntersection<InferResolvedHooks<Option>> & InferClientAPI<Option> & InferActions<Option> & {
17
+ hydrateSession: (session: NonNullable<InferClientAPI<Option> extends {
18
+ getSession: () => Promise<infer Res>;
19
+ } ? Res extends {
20
+ data: null;
21
+ error: {
22
+ message?: string | undefined;
23
+ status: number;
24
+ statusText: string;
25
+ };
26
+ } | {
27
+ data: infer S;
28
+ error: null;
29
+ } ? S : Res : never> | null) => void;
17
30
  useSession: () => {
18
31
  data: InferClientAPI<Option> extends {
19
32
  getSession: () => Promise<infer Res>;
@@ -7,12 +7,13 @@ function getAtomKey(str) {
7
7
  return `use${capitalizeFirstLetter(str)}`;
8
8
  }
9
9
  function createAuthClient(options) {
10
- const { pluginPathMethods, pluginsActions, pluginsAtoms, $fetch, $store, atomListeners } = getClientConfig(options);
10
+ const { pluginPathMethods, pluginsActions, pluginsAtoms, hydrateSession, $fetch, $store, atomListeners } = getClientConfig(options);
11
11
  const resolvedHooks = {};
12
12
  for (const [key, value] of Object.entries(pluginsAtoms)) resolvedHooks[getAtomKey(key)] = () => useStore(value);
13
13
  return createDynamicPathProxy({
14
14
  ...pluginsActions,
15
15
  ...resolvedHooks,
16
+ hydrateSession,
16
17
  $fetch,
17
18
  $store
18
19
  }, $fetch, pluginPathMethods, pluginsAtoms, atomListeners);
@@ -34,7 +34,6 @@ function betterJSONParse(value, options = {}) {
34
34
  const { strict = false, warnings = false, reviver, parseDates = true } = options;
35
35
  if (typeof value !== "string") return value;
36
36
  const trimmed = value.trim();
37
- if (trimmed.length > 0 && trimmed[0] === "\"" && trimmed.endsWith("\"") && !trimmed.slice(1, -1).includes("\"")) return trimmed.slice(1, -1);
38
37
  const lowerValue = trimmed.toLowerCase();
39
38
  if (lowerValue.length <= 9 && lowerValue in SPECIAL_VALUES) return SPECIAL_VALUES[lowerValue];
40
39
  if (!JSON_SIGNATURE.test(trimmed)) {
@@ -1,19 +1,9 @@
1
+ import { FieldAttributeToObject, RemoveFieldsWithReturnedFalse } from "../../db/field.mjs";
1
2
  import { ExtractPluginField, HasRequiredKeys, InferPluginFieldFromTuple, IsAny, OverrideMerge, Prettify, PrettifyDeep, RequiredKeysOf, StripEmptyObjects, UnionToIntersection } from "../../types/helper.mjs";
2
3
  import { InferInvitation, InferMember, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferTeam, Invitation, InvitationInput, InvitationStatus, Member, MemberInput, Organization, OrganizationInput, OrganizationRole, OrganizationSchema, Team, TeamInput, TeamMember, TeamMemberInput, defaultRolesSchema, invitationSchema, invitationStatus, memberSchema, organizationRoleSchema, organizationSchema, roleSchema, teamMemberSchema, teamSchema } from "../../plugins/organization/schema.mjs";
3
4
  import { AdminOptions, InferAdminRolesFromOption, SessionWithImpersonatedBy, UserWithRole } from "../../plugins/admin/types.mjs";
4
5
  import { schema } from "../../plugins/anonymous/schema.mjs";
5
6
  import { AnonymousOptions, AnonymousSession, UserWithAnonymous } from "../../plugins/anonymous/types.mjs";
6
- import { GenericOAuthConfig, GenericOAuthOptions } from "../../plugins/generic-oauth/types.mjs";
7
- import { Auth0Options, auth0 } from "../../plugins/generic-oauth/providers/auth0.mjs";
8
- import { GumroadOptions, gumroad } from "../../plugins/generic-oauth/providers/gumroad.mjs";
9
- import { HubSpotOptions, hubspot } from "../../plugins/generic-oauth/providers/hubspot.mjs";
10
- import { KeycloakOptions, keycloak } from "../../plugins/generic-oauth/providers/keycloak.mjs";
11
- import { LineOptions, line } from "../../plugins/generic-oauth/providers/line.mjs";
12
- import { MicrosoftEntraIdOptions, microsoftEntraId } from "../../plugins/generic-oauth/providers/microsoft-entra-id.mjs";
13
- import { OktaOptions, okta } from "../../plugins/generic-oauth/providers/okta.mjs";
14
- import { PatreonOptions, patreon } from "../../plugins/generic-oauth/providers/patreon.mjs";
15
- import { SlackOptions, slack } from "../../plugins/generic-oauth/providers/slack.mjs";
16
- import { BaseOAuthProviderOptions } from "../../plugins/generic-oauth/index.mjs";
17
7
  import { JWKOptions, JWSAlgorithms, Jwk, JwtOptions, ResolvedSigningKey } from "../../plugins/jwt/types.mjs";
18
8
  import { AuthorizationQuery, Client, CodeVerificationValue, OAuthAccessToken, OIDCMetadata, OIDCOptions, TokenBody } from "../../plugins/oidc-provider/types.mjs";
19
9
  import { MULTI_SESSION_ERROR_CODES } from "../../plugins/multi-session/error-codes.mjs";
@@ -30,16 +20,13 @@ import { USERNAME_ERROR_CODES } from "../../plugins/username/error-codes.mjs";
30
20
  import { ORGANIZATION_ERROR_CODES } from "../../plugins/organization/error-codes.mjs";
31
21
  import { inferAdditionalFields } from "../../plugins/additional-fields/client.mjs";
32
22
  import { ADMIN_ERROR_CODES } from "../../plugins/admin/error-codes.mjs";
33
- import { adminClient } from "../../plugins/admin/client.mjs";
23
+ import { AdminClientOptions, adminClient } from "../../plugins/admin/client.mjs";
34
24
  import { ANONYMOUS_ERROR_CODES } from "../../plugins/anonymous/error-codes.mjs";
35
25
  import { anonymousClient } from "../../plugins/anonymous/client.mjs";
36
26
  import { customSessionClient } from "../../plugins/custom-session/client.mjs";
37
27
  import { deviceAuthorizationClient } from "../../plugins/device-authorization/client.mjs";
38
28
  import { EMAIL_OTP_ERROR_CODES } from "../../plugins/email-otp/error-codes.mjs";
39
29
  import { emailOTPClient } from "../../plugins/email-otp/client.mjs";
40
- import { OAUTH_CALLBACK_ERROR_CODES } from "../../oauth2/error-codes.mjs";
41
- import { GENERIC_OAUTH_ERROR_CODES } from "../../plugins/generic-oauth/error-codes.mjs";
42
- import { genericOAuthClient } from "../../plugins/generic-oauth/client.mjs";
43
30
  import { jwtClient } from "../../plugins/jwt/client.mjs";
44
31
  import { LastLoginMethodClientConfig, lastLoginMethodClient } from "../../plugins/last-login-method/client.mjs";
45
32
  import { magicLinkClient } from "../../plugins/magic-link/client.mjs";
@@ -47,10 +34,10 @@ import { multiSessionClient } from "../../plugins/multi-session/client.mjs";
47
34
  import { OidcClientPlugin, oidcClient } from "../../plugins/oidc-provider/client.mjs";
48
35
  import { GoogleOneTapActionOptions, GoogleOneTapOptions, GsiButtonConfiguration, oneTapClient } from "../../plugins/one-tap/client.mjs";
49
36
  import { oneTimeTokenClient } from "../../plugins/one-time-token/client.mjs";
50
- import { clientSideHasPermission, inferOrgAdditionalFields, organizationClient } from "../../plugins/organization/client.mjs";
37
+ import { OrganizationClientOptions, clientSideHasPermission, inferOrgAdditionalFields, organizationClient } from "../../plugins/organization/client.mjs";
51
38
  import { PHONE_NUMBER_ERROR_CODES } from "../../plugins/phone-number/error-codes.mjs";
52
39
  import { phoneNumberClient } from "../../plugins/phone-number/client.mjs";
53
40
  import { siweClient } from "../../plugins/siwe/client.mjs";
54
41
  import { usernameClient } from "../../plugins/username/client.mjs";
55
42
  import { InferServerPlugin } from "./infer-plugin.mjs";
56
- export { ADMIN_ERROR_CODES, ANONYMOUS_ERROR_CODES, AdminOptions, AnonymousOptions, AnonymousSession, Auth0Options, AuthorizationQuery, BackupCodeOptions, BaseOAuthProviderOptions, Client, CodeVerificationValue, EMAIL_OTP_ERROR_CODES, ExtractPluginField, GENERIC_OAUTH_ERROR_CODES, GenericOAuthConfig, GenericOAuthOptions, GoogleOneTapActionOptions, GoogleOneTapOptions, GsiButtonConfiguration, GumroadOptions, HasRequiredKeys, HubSpotOptions, InferAdminRolesFromOption, InferInvitation, InferMember, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPluginFieldFromTuple, InferServerPlugin, InferTeam, Invitation, InvitationInput, InvitationStatus, IsAny, JWKOptions, JWSAlgorithms, Jwk, JwtOptions, KeycloakOptions, LastLoginMethodClientConfig, LineOptions, MULTI_SESSION_ERROR_CODES, Member, MemberInput, MicrosoftEntraIdOptions, MultiSessionConfig, OAUTH_CALLBACK_ERROR_CODES, OAuthAccessToken, OIDCMetadata, OIDCOptions, ORGANIZATION_ERROR_CODES, OTPOptions, OidcClientPlugin, OktaOptions, OneTimeTokenOptions, Organization, OrganizationInput, OrganizationRole, OrganizationSchema, OverrideMerge, PHONE_NUMBER_ERROR_CODES, PatreonOptions, PhoneNumberOptions, Prettify, PrettifyDeep, RequiredKeysOf, ResolvedSigningKey, SessionWithImpersonatedBy, SlackOptions, StripEmptyObjects, TOTPOptions, TWO_FACTOR_ERROR_CODES, Team, TeamInput, TeamMember, TeamMemberInput, TokenBody, TwoFactorOptions, TwoFactorProvider, TwoFactorTable, USERNAME_ERROR_CODES, UnionToIntersection, UserWithAnonymous, UserWithPhoneNumber, UserWithRole, UserWithTwoFactor, adminClient, anonymousClient, auth0, backupCode2fa, clientSideHasPermission, customSessionClient, defaultRolesSchema, deviceAuthorizationClient, emailOTPClient, encodeBackupCodes, generateBackupCodes, genericOAuthClient, getBackupCodes, gumroad, hubspot, inferAdditionalFields, inferOrgAdditionalFields, invitationSchema, invitationStatus, jwtClient, keycloak, lastLoginMethodClient, line, magicLinkClient, memberSchema, microsoftEntraId, multiSessionClient, oidcClient, okta, oneTapClient, oneTimeTokenClient, organizationClient, organizationRoleSchema, organizationSchema, otp2fa, patreon, phoneNumberClient, roleSchema, schema, siweClient, slack, teamMemberSchema, teamSchema, totp2fa, twoFactorClient, usernameClient, verifyBackupCode };
43
+ export { ADMIN_ERROR_CODES, ANONYMOUS_ERROR_CODES, AdminClientOptions, AdminOptions, AnonymousOptions, AnonymousSession, AuthorizationQuery, BackupCodeOptions, Client, CodeVerificationValue, EMAIL_OTP_ERROR_CODES, ExtractPluginField, type FieldAttributeToObject, GoogleOneTapActionOptions, GoogleOneTapOptions, GsiButtonConfiguration, HasRequiredKeys, InferAdminRolesFromOption, InferInvitation, InferMember, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPluginFieldFromTuple, InferServerPlugin, InferTeam, Invitation, InvitationInput, InvitationStatus, IsAny, JWKOptions, JWSAlgorithms, Jwk, JwtOptions, LastLoginMethodClientConfig, MULTI_SESSION_ERROR_CODES, Member, MemberInput, MultiSessionConfig, OAuthAccessToken, OIDCMetadata, OIDCOptions, ORGANIZATION_ERROR_CODES, OTPOptions, OidcClientPlugin, OneTimeTokenOptions, Organization, OrganizationClientOptions, OrganizationInput, OrganizationRole, OrganizationSchema, OverrideMerge, PHONE_NUMBER_ERROR_CODES, PhoneNumberOptions, Prettify, PrettifyDeep, type RemoveFieldsWithReturnedFalse, RequiredKeysOf, ResolvedSigningKey, SessionWithImpersonatedBy, StripEmptyObjects, TOTPOptions, TWO_FACTOR_ERROR_CODES, Team, TeamInput, TeamMember, TeamMemberInput, TokenBody, TwoFactorOptions, TwoFactorProvider, TwoFactorTable, USERNAME_ERROR_CODES, UnionToIntersection, UserWithAnonymous, UserWithPhoneNumber, UserWithRole, UserWithTwoFactor, adminClient, anonymousClient, backupCode2fa, clientSideHasPermission, customSessionClient, defaultRolesSchema, deviceAuthorizationClient, emailOTPClient, encodeBackupCodes, generateBackupCodes, getBackupCodes, inferAdditionalFields, inferOrgAdditionalFields, invitationSchema, invitationStatus, jwtClient, lastLoginMethodClient, magicLinkClient, memberSchema, multiSessionClient, oidcClient, oneTapClient, oneTimeTokenClient, organizationClient, organizationRoleSchema, organizationSchema, otp2fa, phoneNumberClient, roleSchema, schema, siweClient, teamMemberSchema, teamSchema, totp2fa, twoFactorClient, usernameClient, verifyBackupCode };
@@ -1,4 +1,3 @@
1
- import { OAUTH_CALLBACK_ERROR_CODES } from "../../oauth2/error-codes.mjs";
2
1
  import { inferAdditionalFields } from "../../plugins/additional-fields/client.mjs";
3
2
  import { ADMIN_ERROR_CODES } from "../../plugins/admin/error-codes.mjs";
4
3
  import { adminClient } from "../../plugins/admin/client.mjs";
@@ -8,8 +7,6 @@ import { customSessionClient } from "../../plugins/custom-session/client.mjs";
8
7
  import { deviceAuthorizationClient } from "../../plugins/device-authorization/client.mjs";
9
8
  import { EMAIL_OTP_ERROR_CODES } from "../../plugins/email-otp/error-codes.mjs";
10
9
  import { emailOTPClient } from "../../plugins/email-otp/client.mjs";
11
- import { GENERIC_OAUTH_ERROR_CODES } from "../../plugins/generic-oauth/error-codes.mjs";
12
- import { genericOAuthClient } from "../../plugins/generic-oauth/client.mjs";
13
10
  import { jwtClient } from "../../plugins/jwt/client.mjs";
14
11
  import { lastLoginMethodClient } from "../../plugins/last-login-method/client.mjs";
15
12
  import { magicLinkClient } from "../../plugins/magic-link/client.mjs";
@@ -28,4 +25,4 @@ import { twoFactorClient } from "../../plugins/two-factor/client.mjs";
28
25
  import { USERNAME_ERROR_CODES } from "../../plugins/username/error-codes.mjs";
29
26
  import { usernameClient } from "../../plugins/username/client.mjs";
30
27
  import { InferServerPlugin } from "./infer-plugin.mjs";
31
- export { ADMIN_ERROR_CODES, ANONYMOUS_ERROR_CODES, EMAIL_OTP_ERROR_CODES, GENERIC_OAUTH_ERROR_CODES, InferServerPlugin, MULTI_SESSION_ERROR_CODES, OAUTH_CALLBACK_ERROR_CODES, ORGANIZATION_ERROR_CODES, PHONE_NUMBER_ERROR_CODES, TWO_FACTOR_ERROR_CODES, USERNAME_ERROR_CODES, adminClient, anonymousClient, clientSideHasPermission, customSessionClient, deviceAuthorizationClient, emailOTPClient, genericOAuthClient, inferAdditionalFields, inferOrgAdditionalFields, jwtClient, lastLoginMethodClient, magicLinkClient, multiSessionClient, oidcClient, oneTapClient, oneTimeTokenClient, organizationClient, phoneNumberClient, siweClient, twoFactorClient, usernameClient };
28
+ export { ADMIN_ERROR_CODES, ANONYMOUS_ERROR_CODES, EMAIL_OTP_ERROR_CODES, InferServerPlugin, MULTI_SESSION_ERROR_CODES, ORGANIZATION_ERROR_CODES, PHONE_NUMBER_ERROR_CODES, TWO_FACTOR_ERROR_CODES, USERNAME_ERROR_CODES, adminClient, anonymousClient, clientSideHasPermission, customSessionClient, deviceAuthorizationClient, emailOTPClient, inferAdditionalFields, inferOrgAdditionalFields, jwtClient, lastLoginMethodClient, magicLinkClient, multiSessionClient, oidcClient, oneTapClient, oneTimeTokenClient, organizationClient, phoneNumberClient, siweClient, twoFactorClient, usernameClient };
@@ -1,4 +1,5 @@
1
1
  import { isAtom } from "../utils/is-atom.mjs";
2
+ import { toKebabCase } from "@better-auth/core/utils/string";
2
3
  //#region src/client/proxy.ts
3
4
  function getMethod(path, knownPathMethods, args) {
4
5
  const method = knownPathMethods[path];
@@ -26,7 +27,7 @@ function createDynamicPathProxy(routes, client, knownPathMethods, atoms, atomLis
26
27
  return createProxy(fullPath);
27
28
  },
28
29
  apply: async (_, __, args) => {
29
- const routePath = "/" + path.map((segment) => segment.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)).join("/");
30
+ const routePath = "/" + path.map(toKebabCase).join("/");
30
31
  const arg = args[0] || {};
31
32
  const fetchOptions = args[1] || {};
32
33
  const { query, fetchOptions: argFetchOptions, ...body } = arg;
@@ -14,6 +14,19 @@ type InferResolvedHooks<O extends BetterAuthClientOptions> = O extends {
14
14
  plugins: Array<infer Plugin>;
15
15
  } ? UnionToIntersection<Plugin extends BetterAuthClientPlugin ? Plugin["getAtoms"] extends ((fetch: any) => infer Atoms) ? Atoms extends Record<string, any> ? { [key in keyof Atoms as IsSignal<key> extends true ? never : key extends string ? `use${Capitalize<key>}` : never]: () => ReturnType<Atoms[key]["get"]> } : {} : {} : {}> : {};
16
16
  declare function createAuthClient<Option extends BetterAuthClientOptions>(options?: Option | undefined): UnionToIntersection<InferResolvedHooks<Option>> & InferClientAPI<Option> & InferActions<Option> & {
17
+ hydrateSession: (session: NonNullable<InferClientAPI<Option> extends {
18
+ getSession: () => Promise<infer Res>;
19
+ } ? Res extends {
20
+ data: null;
21
+ error: {
22
+ message?: string | undefined;
23
+ status: number;
24
+ statusText: string;
25
+ };
26
+ } | {
27
+ data: infer S;
28
+ error: null;
29
+ } ? S : Res : never> | null) => void;
17
30
  useSession: () => {
18
31
  data: InferClientAPI<Option> extends {
19
32
  getSession: () => Promise<infer Res>;
@@ -7,12 +7,13 @@ function getAtomKey(str) {
7
7
  return `use${capitalizeFirstLetter(str)}`;
8
8
  }
9
9
  function createAuthClient(options) {
10
- const { pluginPathMethods, pluginsActions, pluginsAtoms, $fetch, $store, atomListeners } = getClientConfig(options);
10
+ const { pluginPathMethods, pluginsActions, pluginsAtoms, hydrateSession, $fetch, $store, atomListeners } = getClientConfig(options);
11
11
  const resolvedHooks = {};
12
12
  for (const [key, value] of Object.entries(pluginsAtoms)) resolvedHooks[getAtomKey(key)] = () => useStore(value);
13
13
  return createDynamicPathProxy({
14
14
  ...pluginsActions,
15
15
  ...resolvedHooks,
16
+ hydrateSession,
16
17
  $fetch,
17
18
  $store
18
19
  }, $fetch, pluginPathMethods, pluginsAtoms, atomListeners);
@@ -2,6 +2,17 @@ import { useAuthQuery } from "./query.mjs";
2
2
  import { createSessionRefreshManager } from "./session-refresh.mjs";
3
3
  import { atom, onMount } from "nanostores";
4
4
  //#region src/client/session-atom.ts
5
+ function hydrateSessionAtom(sessionAtom, session) {
6
+ if (typeof window === "undefined") return;
7
+ const currentSession = sessionAtom.get();
8
+ if (currentSession.data !== null || session === null) return;
9
+ sessionAtom.set({
10
+ ...currentSession,
11
+ data: session,
12
+ error: null,
13
+ isPending: false
14
+ });
15
+ }
5
16
  function getSessionAtom($fetch, options) {
6
17
  const $signal = atom(false);
7
18
  const session = useAuthQuery($signal, "/get-session", $fetch, { method: "GET" });
@@ -26,4 +37,4 @@ function getSessionAtom($fetch, options) {
26
37
  };
27
38
  }
28
39
  //#endregion
29
- export { getSessionAtom };
40
+ export { getSessionAtom, hydrateSessionAtom };
@@ -13,6 +13,19 @@ type InferResolvedHooks<O extends BetterAuthClientOptions> = O extends {
13
13
  plugins: Array<infer Plugin>;
14
14
  } ? UnionToIntersection<Plugin extends BetterAuthClientPlugin ? Plugin["getAtoms"] extends ((fetch: any) => infer Atoms) ? Atoms extends Record<string, any> ? { [key in keyof Atoms as IsSignal<key> extends true ? never : key extends string ? `use${Capitalize<key>}` : never]: () => Accessor<ReturnType<Atoms[key]["get"]>> } : {} : {} : {}> : {};
15
15
  declare function createAuthClient<Option extends BetterAuthClientOptions>(options?: Option | undefined): UnionToIntersection<InferResolvedHooks<Option>> & InferClientAPI<Option> & InferActions<Option> & {
16
+ hydrateSession: (session: NonNullable<InferClientAPI<Option> extends {
17
+ getSession: () => Promise<infer Res>;
18
+ } ? Res extends {
19
+ data: null;
20
+ error: {
21
+ message?: string | undefined;
22
+ status: number;
23
+ statusText: string;
24
+ };
25
+ } | {
26
+ data: infer S;
27
+ error: null;
28
+ } ? S : Res extends Record<string, any> ? Res : never : never> | null) => void;
16
29
  useSession: () => Accessor<{
17
30
  data: InferClientAPI<Option> extends {
18
31
  getSession: () => Promise<infer Res>;
@@ -7,12 +7,13 @@ function getAtomKey(str) {
7
7
  return `use${capitalizeFirstLetter(str)}`;
8
8
  }
9
9
  function createAuthClient(options) {
10
- const { pluginPathMethods, pluginsActions, pluginsAtoms, $fetch, atomListeners } = getClientConfig(options);
10
+ const { pluginPathMethods, pluginsActions, pluginsAtoms, hydrateSession, $fetch, atomListeners } = getClientConfig(options);
11
11
  const resolvedHooks = {};
12
12
  for (const [key, value] of Object.entries(pluginsAtoms)) resolvedHooks[getAtomKey(key)] = () => useStore(value);
13
13
  return createDynamicPathProxy({
14
14
  ...pluginsActions,
15
- ...resolvedHooks
15
+ ...resolvedHooks,
16
+ hydrateSession
16
17
  }, $fetch, pluginPathMethods, pluginsAtoms, atomListeners);
17
18
  }
18
19
  //#endregion
@@ -14,6 +14,19 @@ type InferResolvedHooks<O extends BetterAuthClientOptions> = O extends {
14
14
  plugins: Array<infer Plugin>;
15
15
  } ? UnionToIntersection<Plugin extends BetterAuthClientPlugin ? Plugin["getAtoms"] extends ((fetch: any) => infer Atoms) ? Atoms extends Record<string, any> ? { [key in keyof Atoms as IsSignal<key> extends true ? never : key extends string ? `use${Capitalize<key>}` : never]: () => Atoms[key] } : {} : {} : {}> : {};
16
16
  declare function createAuthClient<Option extends BetterAuthClientOptions>(options?: Option | undefined): UnionToIntersection<InferResolvedHooks<Option>> & InferClientAPI<Option> & InferActions<Option> & {
17
+ hydrateSession: (session: NonNullable<InferClientAPI<Option> extends {
18
+ getSession: () => Promise<infer Res>;
19
+ } ? Res extends {
20
+ data: null;
21
+ error: {
22
+ message?: string | undefined;
23
+ status: number;
24
+ statusText: string;
25
+ };
26
+ } | {
27
+ data: infer S;
28
+ error: null;
29
+ } ? S : Res extends Record<string, any> ? Res : never : never> | null) => void;
17
30
  useSession: () => Atom<{
18
31
  data: InferClientAPI<Option> extends {
19
32
  getSession: () => Promise<infer Res>;
@@ -3,12 +3,13 @@ import { createDynamicPathProxy } from "../proxy.mjs";
3
3
  import { capitalizeFirstLetter } from "@better-auth/core/utils/string";
4
4
  //#region src/client/svelte/index.ts
5
5
  function createAuthClient(options) {
6
- const { pluginPathMethods, pluginsActions, pluginsAtoms, $fetch, atomListeners, $store } = getClientConfig(options);
6
+ const { pluginPathMethods, pluginsActions, pluginsAtoms, hydrateSession, $fetch, atomListeners, $store } = getClientConfig(options);
7
7
  const resolvedHooks = {};
8
8
  for (const [key, value] of Object.entries(pluginsAtoms)) resolvedHooks[`use${capitalizeFirstLetter(key)}`] = () => value;
9
9
  return createDynamicPathProxy({
10
10
  ...pluginsActions,
11
11
  ...resolvedHooks,
12
+ hydrateSession,
12
13
  $fetch,
13
14
  $store
14
15
  }, $fetch, pluginPathMethods, pluginsAtoms, atomListeners);
@@ -12,6 +12,19 @@ type InferResolvedHooks<O extends BetterAuthClientOptions> = O extends {
12
12
  plugins: Array<infer Plugin>;
13
13
  } ? UnionToIntersection<Plugin extends BetterAuthClientPlugin ? Plugin["getAtoms"] extends ((fetch: any) => infer Atoms) ? Atoms extends Record<string, any> ? { [key in keyof Atoms as IsSignal<key> extends true ? never : key extends string ? `use${Capitalize<key>}` : never]: Atoms[key] } : {} : {} : {}> : {};
14
14
  declare function createAuthClient<Option extends BetterAuthClientOptions>(options?: Option | undefined): UnionToIntersection<InferResolvedHooks<Option>> & InferClientAPI<Option> & InferActions<Option> & {
15
+ hydrateSession: (session: NonNullable<InferClientAPI<Option> extends {
16
+ getSession: () => Promise<infer Res>;
17
+ } ? Res extends {
18
+ data: null;
19
+ error: {
20
+ message?: string | undefined;
21
+ status: number;
22
+ statusText: string;
23
+ };
24
+ } | {
25
+ data: infer S;
26
+ error: null;
27
+ } ? S : Res extends Record<string, any> ? Res : never : never> | null) => void;
15
28
  useSession: Atom<{
16
29
  data: InferClientAPI<Option> extends {
17
30
  getSession: () => Promise<infer Res>;
@@ -3,12 +3,13 @@ import { createDynamicPathProxy } from "./proxy.mjs";
3
3
  import { capitalizeFirstLetter } from "@better-auth/core/utils/string";
4
4
  //#region src/client/vanilla.ts
5
5
  function createAuthClient(options) {
6
- const { pluginPathMethods, pluginsActions, pluginsAtoms, $fetch, atomListeners, $store } = getClientConfig(options);
6
+ const { pluginPathMethods, pluginsActions, pluginsAtoms, hydrateSession, $fetch, atomListeners, $store } = getClientConfig(options);
7
7
  const resolvedHooks = {};
8
8
  for (const [key, value] of Object.entries(pluginsAtoms)) resolvedHooks[`use${capitalizeFirstLetter(key)}`] = value;
9
9
  return createDynamicPathProxy({
10
10
  ...pluginsActions,
11
11
  ...resolvedHooks,
12
+ hydrateSession,
12
13
  $fetch,
13
14
  $store
14
15
  }, $fetch, pluginPathMethods, pluginsAtoms, atomListeners);
@@ -14,6 +14,19 @@ type InferResolvedHooks<O extends BetterAuthClientOptions> = O extends {
14
14
  plugins: Array<infer Plugin>;
15
15
  } ? UnionToIntersection<Plugin extends BetterAuthClientPlugin ? Plugin["getAtoms"] extends ((fetch: any) => infer Atoms) ? Atoms extends Record<string, any> ? { [key in keyof Atoms as IsSignal<key> extends true ? never : key extends string ? `use${Capitalize<key>}` : never]: () => DeepReadonly<Ref<ReturnType<Atoms[key]["get"]>>> } : {} : {} : {}> : {};
16
16
  declare function createAuthClient<Option extends BetterAuthClientOptions>(options?: Option | undefined): UnionToIntersection<InferResolvedHooks<Option>> & InferClientAPI<Option> & InferActions<Option> & {
17
+ hydrateSession: (session: NonNullable<InferClientAPI<Option> extends {
18
+ getSession: () => Promise<infer Res>;
19
+ } ? Res extends {
20
+ data: null;
21
+ error: {
22
+ message?: string | undefined;
23
+ status: number;
24
+ statusText: string;
25
+ };
26
+ } | {
27
+ data: infer S;
28
+ error: null;
29
+ } ? S : Res extends Record<string, any> ? Res : never : never> | null) => void;
17
30
  useSession: {
18
31
  (): DeepReadonly<Ref<{
19
32
  data: InferClientAPI<Option> extends {
@@ -7,7 +7,7 @@ function getAtomKey(str) {
7
7
  return `use${capitalizeFirstLetter(str)}`;
8
8
  }
9
9
  function createAuthClient(options) {
10
- const { baseURL, pluginPathMethods, pluginsActions, pluginsAtoms, $fetch, $store, atomListeners } = getClientConfig(options, false);
10
+ const { baseURL, pluginPathMethods, pluginsActions, pluginsAtoms, hydrateSession, $fetch, $store, atomListeners } = getClientConfig(options, false);
11
11
  const resolvedHooks = {};
12
12
  for (const [key, value] of Object.entries(pluginsAtoms)) resolvedHooks[getAtomKey(key)] = () => useStore(value);
13
13
  function useSession(useFetch) {
@@ -26,6 +26,7 @@ function createAuthClient(options) {
26
26
  return createDynamicPathProxy({
27
27
  ...pluginsActions,
28
28
  ...resolvedHooks,
29
+ hydrateSession,
29
30
  useSession,
30
31
  $fetch,
31
32
  $store
@@ -42,18 +42,14 @@ function validateSecret(secret, logger) {
42
42
  if (estimateEntropy(secret) < 120) logger.warn("[better-auth] Warning: your BETTER_AUTH_SECRET appears low-entropy. Use a randomly generated secret for production.");
43
43
  }
44
44
  async function createAuthContext(adapter, options, getDatabaseType) {
45
- if (!options.database) options = defu$1(options, {
46
- session: { cookieCache: {
47
- enabled: true,
48
- strategy: "jwe",
49
- refreshCache: true,
50
- maxAge: options.session?.expiresIn || 3600 * 24 * 7
51
- } },
52
- account: {
53
- storeStateStrategy: "cookie",
54
- storeAccountCookie: true
55
- }
56
- });
45
+ const isStateful = !!options.database || !!options.secondaryStorage;
46
+ if (!isStateful) options = defu$1(options, { session: { cookieCache: {
47
+ enabled: true,
48
+ strategy: "jwe",
49
+ refreshCache: true,
50
+ maxAge: options.session?.expiresIn || 3600 * 24 * 7
51
+ } } });
52
+ if (!options.database) options = defu$1(options, { account: { storeAccountCookie: true } });
57
53
  const plugins = options.plugins || [];
58
54
  const internalPlugins = getInternalPlugins(options);
59
55
  const logger = createLogger(options.logger);
@@ -130,7 +126,7 @@ Most of the features of Better Auth will not work correctly.`);
130
126
  socialProviders: providers,
131
127
  options,
132
128
  oauthConfig: {
133
- storeStateStrategy: options.account?.storeStateStrategy || (options.database ? "database" : "cookie"),
129
+ storeStateStrategy: options.account?.storeStateStrategy || (isStateful ? "database" : "cookie"),
134
130
  skipStateCookieCheck: !!options.account?.skipStateCookieCheck
135
131
  },
136
132
  tables,
@@ -146,7 +142,7 @@ Most of the features of Better Auth will not work correctly.`);
146
142
  cookieRefreshCache: (() => {
147
143
  const refreshCache = options.session?.cookieCache?.refreshCache;
148
144
  const maxAge = options.session?.cookieCache?.maxAge || 300;
149
- if ((!!options.database || !!options.secondaryStorage) && refreshCache) {
145
+ if (isStateful && refreshCache) {
150
146
  logger.warn("[better-auth] `session.cookieCache.refreshCache` is enabled while `database` or `secondaryStorage` is configured. `refreshCache` is meant for stateless (DB-less) setups. Disabling `refreshCache` — remove it from your config to silence this warning.");
151
147
  return false;
152
148
  }
@@ -61,9 +61,10 @@ async function getTrustedOrigins(options, request) {
61
61
  const trustedOrigins = [];
62
62
  if (isDynamicBaseURLConfig(options.baseURL)) {
63
63
  const allowedHosts = options.baseURL.allowedHosts;
64
+ const proto = options.baseURL.protocol;
64
65
  for (const host of allowedHosts) if (!host.includes("://")) {
65
- trustedOrigins.push(`https://${host}`);
66
- if (isLoopbackHost(host)) trustedOrigins.push(`http://${host}`);
66
+ if (!proto || proto === "https" || proto === "auto") trustedOrigins.push(`https://${host}`);
67
+ if (proto === "http" || proto === "auto" || isLoopbackHost(host)) trustedOrigins.push(`http://${host}`);
67
68
  } else trustedOrigins.push(host);
68
69
  if (options.baseURL.fallback) try {
69
70
  trustedOrigins.push(new URL(options.baseURL.fallback).origin);
@@ -33,8 +33,40 @@ declare function stripSecureCookiePrefix(cookieName: string): string;
33
33
  declare function splitSetCookieHeader(setCookie: string): string[];
34
34
  declare function parseSetCookieHeader(setCookie: string): Map<string, CookieAttributes>;
35
35
  declare function toCookieOptions(attributes: CookieAttributes): ParsedCookieOptions;
36
+ /**
37
+ * Cookie-name token char set per RFC 7230 §3.2.6.
38
+ *
39
+ * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6
40
+ */
41
+ declare const cookieNameRegex: RegExp;
42
+ /**
43
+ * Tolerates `;` separators without the SP that RFC 6265 §4.2.1 mandates,
44
+ * since proxies and runtimes commonly strip it. Silently drops entries
45
+ * whose name violates RFC 7230 token or whose value violates RFC 6265
46
+ * cookie-octet (plus space and comma). Strips optional surrounding
47
+ * double-quotes per RFC 6265 §4.1.1.
48
+ */
49
+ declare function parseCookies(cookie: string): Map<string, string>;
50
+ /**
51
+ * Add or replace a cookie in the request `Cookie` header.
52
+ *
53
+ * Cookie pairs are joined with `; `, but `headers.append("cookie", ...)`
54
+ * joins with `, ` in some runtimes (e.g. Deno, Cloudflare Workers) and
55
+ * breaks downstream cookie parsing. This builds the header value via
56
+ * parse-mutate-serialize.
57
+ */
58
+ declare function setRequestCookie(headers: Headers, name: string, value: string): void;
59
+ /**
60
+ * Merge `Set-Cookie` header values into the target's `Cookie` header.
61
+ * Mutates `target`.
62
+ *
63
+ * Name/value-level merge only. RFC 6265 §5 user-agent semantics
64
+ * (expiration, domain/path scoping, ordering) are out of scope. Suitable
65
+ * for single-request proxy, middleware, and test contexts.
66
+ */
67
+ declare function applySetCookies(target: Headers, setCookieValues: Iterable<string>): void;
36
68
  declare function setCookieToHeader(headers: Headers): (context: {
37
69
  response: Response;
38
70
  }) => void;
39
71
  //#endregion
40
- export { CookieAttributes, HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, parseSetCookieHeader, setCookieToHeader, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions };
72
+ export { CookieAttributes, HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, applySetCookies, cookieNameRegex, parseCookies, parseSetCookieHeader, setCookieToHeader, setRequestCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions };
@@ -1,5 +1,6 @@
1
1
  //#region src/cookies/cookie-utils.ts
2
2
  function tryDecode(str) {
3
+ if (str.indexOf("%") === -1) return str;
3
4
  try {
4
5
  return decodeURIComponent(str);
5
6
  } catch {
@@ -49,9 +50,9 @@ function parseSetCookieHeader(setCookie) {
49
50
  splitSetCookieHeader(setCookie).forEach((cookieString) => {
50
51
  const [nameValue, ...attributes] = cookieString.split(";").map((part) => part.trim());
51
52
  const [name, ...valueParts] = (nameValue || "").split("=");
52
- const value = valueParts.join("=");
53
- if (!name || value === void 0) return;
54
- const attrObj = { value: value.includes("%") ? tryDecode(value) : value };
53
+ const value = unquoteCookieValue(valueParts.join("="));
54
+ if (!name) return;
55
+ const attrObj = { value: tryDecode(value) };
55
56
  attributes.forEach((attribute) => {
56
57
  const [attrName, ...attrValueParts] = attribute.split("=");
57
58
  const attrValue = attrValueParts.join("=");
@@ -102,21 +103,101 @@ function toCookieOptions(attributes) {
102
103
  partitioned: attributes.partitioned
103
104
  };
104
105
  }
106
+ /**
107
+ * Cookie-name token char set per RFC 7230 §3.2.6.
108
+ *
109
+ * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6
110
+ */
111
+ const cookieNameRegex = /^[\w!#$%&'*.^`|~+-]+$/;
112
+ /**
113
+ * Cookie-value char set per RFC 6265 §4.1.1, plus space and comma.
114
+ *
115
+ * @see https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1
116
+ * @see https://github.com/golang/go/issues/7243
117
+ */
118
+ const cookieValueRegex = /^[ !#-:<-[\]-~]*$/;
119
+ /**
120
+ * Strip surrounding double-quotes per RFC 6265 §4.1.1 quoted-string form.
121
+ *
122
+ * @see https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1
123
+ */
124
+ function unquoteCookieValue(value) {
125
+ if (value.length < 2 || !value.startsWith("\"") || !value.endsWith("\"")) return value;
126
+ return value.slice(1, -1);
127
+ }
128
+ /**
129
+ * Trim leading/trailing OWS (space / horizontal tab) per RFC 7230 §3.2.3.
130
+ * Narrower than `String.prototype.trim()`, which strips CR/LF and other
131
+ * whitespace and would let CTLs escape `cookieValueRegex`.
132
+ *
133
+ * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.3
134
+ */
135
+ function trimOWS(s) {
136
+ let start = 0;
137
+ let end = s.length;
138
+ while (start < end) {
139
+ const c = s.charCodeAt(start);
140
+ if (c !== 32 && c !== 9) break;
141
+ start++;
142
+ }
143
+ while (end > start) {
144
+ const c = s.charCodeAt(end - 1);
145
+ if (c !== 32 && c !== 9) break;
146
+ end--;
147
+ }
148
+ return start === 0 && end === s.length ? s : s.slice(start, end);
149
+ }
150
+ /**
151
+ * Tolerates `;` separators without the SP that RFC 6265 §4.2.1 mandates,
152
+ * since proxies and runtimes commonly strip it. Silently drops entries
153
+ * whose name violates RFC 7230 token or whose value violates RFC 6265
154
+ * cookie-octet (plus space and comma). Strips optional surrounding
155
+ * double-quotes per RFC 6265 §4.1.1.
156
+ */
157
+ function parseCookies(cookie) {
158
+ const cookieMap = /* @__PURE__ */ new Map();
159
+ if (cookie.length < 2) return cookieMap;
160
+ for (const chunk of cookie.split(";")) {
161
+ const eq = chunk.indexOf("=");
162
+ if (eq === -1) continue;
163
+ const key = trimOWS(chunk.slice(0, eq));
164
+ const val = unquoteCookieValue(trimOWS(chunk.slice(eq + 1)));
165
+ if (cookieNameRegex.test(key) && cookieValueRegex.test(val)) cookieMap.set(key, tryDecode(val));
166
+ }
167
+ return cookieMap;
168
+ }
169
+ /**
170
+ * Add or replace a cookie in the request `Cookie` header.
171
+ *
172
+ * Cookie pairs are joined with `; `, but `headers.append("cookie", ...)`
173
+ * joins with `, ` in some runtimes (e.g. Deno, Cloudflare Workers) and
174
+ * breaks downstream cookie parsing. This builds the header value via
175
+ * parse-mutate-serialize.
176
+ */
177
+ function setRequestCookie(headers, name, value) {
178
+ const cookieMap = parseCookies(headers.get("cookie") || "");
179
+ if (cookieNameRegex.test(name)) cookieMap.set(name, value);
180
+ headers.set("cookie", Array.from(cookieMap, ([k, v]) => `${k}=${encodeURIComponent(v)}`).join("; "));
181
+ }
182
+ /**
183
+ * Merge `Set-Cookie` header values into the target's `Cookie` header.
184
+ * Mutates `target`.
185
+ *
186
+ * Name/value-level merge only. RFC 6265 §5 user-agent semantics
187
+ * (expiration, domain/path scoping, ordering) are out of scope. Suitable
188
+ * for single-request proxy, middleware, and test contexts.
189
+ */
190
+ function applySetCookies(target, setCookieValues) {
191
+ const cookieMap = parseCookies(target.get("cookie") || "");
192
+ for (const setCookie of setCookieValues) for (const [name, attr] of parseSetCookieHeader(setCookie)) if (cookieNameRegex.test(name)) cookieMap.set(name, attr.value);
193
+ target.set("cookie", Array.from(cookieMap, ([k, v]) => `${k}=${encodeURIComponent(v)}`).join("; "));
194
+ }
105
195
  function setCookieToHeader(headers) {
106
196
  return (context) => {
107
197
  const setCookieHeader = context.response.headers.get("set-cookie");
108
198
  if (!setCookieHeader) return;
109
- const cookieMap = /* @__PURE__ */ new Map();
110
- (headers.get("cookie") || "").split(";").forEach((cookie) => {
111
- const [name, ...rest] = cookie.trim().split("=");
112
- if (name && rest.length > 0) cookieMap.set(name, rest.join("="));
113
- });
114
- parseSetCookieHeader(setCookieHeader).forEach((value, name) => {
115
- cookieMap.set(name, value.value);
116
- });
117
- const updatedCookies = Array.from(cookieMap.entries()).map(([name, value]) => `${name}=${value}`).join("; ");
118
- headers.set("cookie", updatedCookies);
199
+ applySetCookies(headers, [setCookieHeader]);
119
200
  };
120
201
  }
121
202
  //#endregion
122
- export { HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, parseSetCookieHeader, setCookieToHeader, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions };
203
+ export { HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, applySetCookies, cookieNameRegex, parseCookies, parseSetCookieHeader, setCookieToHeader, setRequestCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions };