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.
- package/README.md +14 -15
- package/dist/_virtual/_rolldown/runtime.mjs +10 -1
- package/dist/api/index.d.mts +18 -48
- package/dist/api/routes/account.d.mts +4 -23
- package/dist/api/routes/account.mjs +102 -75
- package/dist/api/routes/callback.mjs +42 -20
- package/dist/api/routes/email-verification.d.mts +1 -0
- package/dist/api/routes/email-verification.mjs +6 -5
- package/dist/api/routes/error.mjs +1 -1
- package/dist/api/routes/password.mjs +1 -1
- package/dist/api/routes/session.mjs +15 -10
- package/dist/api/routes/sign-in.d.mts +3 -1
- package/dist/api/routes/sign-in.mjs +13 -15
- package/dist/api/routes/sign-up.d.mts +1 -0
- package/dist/api/routes/sign-up.mjs +10 -8
- package/dist/api/routes/update-user.mjs +8 -8
- package/dist/api/to-auth-endpoints.mjs +7 -1
- package/dist/auth/base.mjs +30 -27
- package/dist/client/config.mjs +8 -1
- package/dist/client/fetch-plugins.mjs +2 -1
- package/dist/client/index.d.mts +2 -2
- package/dist/client/lynx/index.d.mts +13 -0
- package/dist/client/lynx/index.mjs +2 -1
- package/dist/client/parser.mjs +0 -1
- package/dist/client/plugins/index.d.mts +4 -17
- package/dist/client/plugins/index.mjs +1 -4
- package/dist/client/proxy.mjs +2 -1
- package/dist/client/react/index.d.mts +13 -0
- package/dist/client/react/index.mjs +2 -1
- package/dist/client/session-atom.mjs +12 -1
- package/dist/client/solid/index.d.mts +13 -0
- package/dist/client/solid/index.mjs +3 -2
- package/dist/client/svelte/index.d.mts +13 -0
- package/dist/client/svelte/index.mjs +2 -1
- package/dist/client/vanilla.d.mts +13 -0
- package/dist/client/vanilla.mjs +2 -1
- package/dist/client/vue/index.d.mts +13 -0
- package/dist/client/vue/index.mjs +2 -1
- package/dist/context/create-context.mjs +10 -14
- package/dist/context/helpers.mjs +3 -2
- package/dist/cookies/cookie-utils.d.mts +33 -1
- package/dist/cookies/cookie-utils.mjs +95 -14
- package/dist/cookies/index.d.mts +2 -3
- package/dist/cookies/index.mjs +39 -11
- package/dist/cookies/session-store.mjs +4 -23
- package/dist/db/get-migration.mjs +4 -4
- package/dist/db/index.d.mts +2 -2
- package/dist/db/index.mjs +3 -2
- package/dist/db/internal-adapter.mjs +129 -27
- package/dist/db/schema.d.mts +14 -1
- package/dist/db/schema.mjs +26 -1
- package/dist/db/with-hooks.d.mts +1 -0
- package/dist/db/with-hooks.mjs +58 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/integrations/cookie-plugin-guard.mjs +18 -0
- package/dist/integrations/next-js.mjs +6 -0
- package/dist/integrations/svelte-kit.mjs +6 -0
- package/dist/integrations/tanstack-start-solid.mjs +6 -0
- package/dist/integrations/tanstack-start.mjs +6 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/index.mjs +32 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/linux.mjs +55 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/macos.mjs +26 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/termux.mjs +39 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/windows.mjs +19 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/chunks/prompt.mjs +845 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/core.mjs +386 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/index.mjs +320 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/shared/consola.DRwqZj3T.mjs +62 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/shared/consola.DXBYu-KD.mjs +190 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/utils.mjs +2 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/index.mjs +29 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.mjs +42 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.mjs +67 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.mjs +23 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.mjs +22 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.mjs +36 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/adapters/node.d.mts +292 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/adapters/node.mjs +127 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/index.d.mts +145 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.BQXMA5bH.d.mts +298 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.By9qWDAI.mjs +9 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.CipVM6lf.mjs +3549 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.D9ehKjSh.mjs +66 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.DfCzGthR.mjs +227 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/index.mjs +224 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/command.mjs +52 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/error.mjs +54 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/kill.mjs +62 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/pipe.mjs +26 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/promise.mjs +32 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/stdio.mjs +19 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/stream.mjs +98 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/verbose.mjs +15 -0
- package/dist/node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.d.mts +15 -0
- package/dist/node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.mjs +220 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/array-buffer.mjs +54 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/array.mjs +2 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/buffer.mjs +14 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/contents.mjs +76 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/index.mjs +6 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/string.mjs +35 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/utils.mjs +10 -0
- package/dist/node_modules/.pnpm/http-shutdown@1.2.2/node_modules/http-shutdown/index.mjs +76 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/core.mjs +274 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/main.mjs +44 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/realtime.mjs +15 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/signals.mjs +23 -0
- package/dist/node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.mjs +24 -0
- package/dist/node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.mjs +18 -0
- package/dist/node_modules/.pnpm/is-stream@3.0.0/node_modules/is-stream/index.mjs +9 -0
- package/dist/node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.mjs +20 -0
- package/dist/node_modules/.pnpm/is64bit@2.0.0/node_modules/is64bit/index.mjs +13 -0
- package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.mjs +47 -0
- package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.mjs +33 -0
- package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.mjs +33 -0
- package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/chunks/xdg-open.mjs +1070 -0
- package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/index.mjs +619 -0
- package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/shared/listhen.1c46e31d.d.mts +83 -0
- package/dist/node_modules/.pnpm/merge-stream@2.0.0/node_modules/merge-stream/index.mjs +38 -0
- package/dist/node_modules/.pnpm/mimic-fn@4.0.0/node_modules/mimic-fn/index.mjs +38 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/aes.mjs +597 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/aesCipherSuites.mjs +195 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/asn1-validator.mjs +76 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/asn1.mjs +967 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/baseN.mjs +137 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/cipher.mjs +186 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/cipherModes.mjs +597 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/des.mjs +1187 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/ed25519.mjs +1029 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/forge.mjs +15 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/hmac.mjs +107 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/index.mjs +66 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/jsbn.mjs +1334 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/kem.mjs +146 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/log.mjs +241 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md.all.mjs +24 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md.mjs +18 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md5.mjs +324 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/mgf.mjs +20 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/mgf1.mjs +44 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/oids.mjs +154 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pbe.mjs +815 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pbkdf2.mjs +125 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pem.mjs +175 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs1.mjs +200 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs12.mjs +724 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs7.mjs +642 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs7asn1.mjs +405 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pki.mjs +101 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/prime.mjs +193 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/prng.mjs +290 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pss.mjs +141 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/random.mjs +141 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/rc2.mjs +538 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/rsa.mjs +1309 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha1.mjs +230 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha256.mjs +267 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha512.mjs +413 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/ssh.mjs +194 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/tls.mjs +3655 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/util.mjs +2117 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/x509.mjs +2168 -0
- package/dist/node_modules/.pnpm/npm-run-path@5.3.0/node_modules/npm-run-path/index.mjs +34 -0
- package/dist/node_modules/.pnpm/onetime@6.0.0/node_modules/onetime/index.mjs +26 -0
- package/dist/node_modules/.pnpm/path-key@3.1.1/node_modules/path-key/index.mjs +14 -0
- package/dist/node_modules/.pnpm/path-key@4.0.0/node_modules/path-key/index.mjs +8 -0
- package/dist/node_modules/.pnpm/pathe@1.1.2/node_modules/pathe/dist/shared/pathe.ff20891b.mjs +176 -0
- package/dist/node_modules/.pnpm/shebang-command@2.0.0/node_modules/shebang-command/index.mjs +17 -0
- package/dist/node_modules/.pnpm/shebang-regex@3.0.0/node_modules/shebang-regex/index.mjs +8 -0
- package/dist/node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.mjs +169 -0
- package/dist/node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.mjs +33 -0
- package/dist/node_modules/.pnpm/std-env@3.10.0/node_modules/std-env/dist/index.mjs +171 -0
- package/dist/node_modules/.pnpm/strip-final-newline@3.0.0/node_modules/strip-final-newline/index.mjs +10 -0
- package/dist/node_modules/.pnpm/system-architecture@0.1.0/node_modules/system-architecture/index.mjs +16 -0
- package/dist/node_modules/.pnpm/uncrypto@0.1.3/node_modules/uncrypto/dist/crypto.node.mjs +7 -0
- package/dist/node_modules/.pnpm/untun@0.1.3/node_modules/untun/dist/chunks/index.mjs +154 -0
- package/dist/node_modules/.pnpm/untun@0.1.3/node_modules/untun/dist/index.mjs +34 -0
- package/dist/node_modules/.pnpm/uqr@0.1.2/node_modules/uqr/dist/index.mjs +896 -0
- package/dist/node_modules/.pnpm/which@2.0.2/node_modules/which/which.mjs +76 -0
- package/dist/oauth2/errors.mjs +27 -0
- package/dist/oauth2/index.d.mts +2 -2
- package/dist/oauth2/index.mjs +3 -3
- package/dist/oauth2/link-account.d.mts +27 -1
- package/dist/oauth2/link-account.mjs +30 -5
- package/dist/oauth2/state.mjs +8 -2
- package/dist/{package.mjs → packages/better-auth/package.mjs} +1 -1
- package/dist/plugins/access/access.d.mts +3 -15
- package/dist/plugins/access/access.mjs +11 -6
- package/dist/plugins/access/index.d.mts +2 -2
- package/dist/plugins/access/types.d.mts +11 -4
- package/dist/plugins/admin/access/statement.d.mts +29 -93
- package/dist/plugins/admin/admin.mjs +0 -4
- package/dist/plugins/admin/client.d.mts +6 -1
- package/dist/plugins/admin/client.mjs +5 -0
- package/dist/plugins/admin/routes.mjs +3 -2
- package/dist/plugins/anonymous/client.d.mts +1 -0
- package/dist/plugins/anonymous/error-codes.d.mts +1 -0
- package/dist/plugins/anonymous/error-codes.mjs +1 -0
- package/dist/plugins/anonymous/index.d.mts +1 -0
- package/dist/plugins/anonymous/index.mjs +16 -2
- package/dist/plugins/bearer/index.mjs +5 -12
- package/dist/plugins/captcha/index.mjs +14 -1
- package/dist/plugins/device-authorization/error-codes.mjs +1 -0
- package/dist/plugins/device-authorization/index.d.mts +1 -0
- package/dist/plugins/device-authorization/routes.mjs +34 -3
- package/dist/plugins/email-otp/routes.mjs +4 -4
- package/dist/plugins/generic-oauth/error-codes.mjs +0 -1
- package/dist/plugins/generic-oauth/index.d.mts +2 -4
- package/dist/plugins/generic-oauth/index.mjs +23 -17
- package/dist/plugins/generic-oauth/providers/auth0.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/gumroad.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/hubspot.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/keycloak.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/line.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/microsoft-entra-id.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/okta.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/patreon.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/slack.mjs +1 -0
- package/dist/plugins/generic-oauth/types.d.mts +30 -8
- package/dist/plugins/index.d.mts +2 -2
- package/dist/plugins/jwt/utils.d.mts +1 -1
- package/dist/plugins/last-login-method/client.mjs +2 -2
- package/dist/plugins/magic-link/index.d.mts +8 -1
- package/dist/plugins/magic-link/index.mjs +4 -17
- package/dist/plugins/mcp/authorize.mjs +8 -2
- package/dist/plugins/mcp/index.mjs +75 -35
- package/dist/plugins/multi-session/index.mjs +2 -2
- package/dist/plugins/oauth-proxy/index.mjs +45 -32
- package/dist/plugins/oauth-proxy/utils.mjs +3 -10
- package/dist/plugins/oidc-provider/authorize.mjs +8 -2
- package/dist/plugins/oidc-provider/index.mjs +65 -38
- package/dist/plugins/one-tap/client.mjs +9 -2
- package/dist/plugins/one-tap/index.mjs +19 -36
- package/dist/plugins/open-api/generator.mjs +25 -5
- package/dist/plugins/organization/access/statement.d.mts +68 -201
- package/dist/plugins/organization/adapter.d.mts +1 -1
- package/dist/plugins/organization/adapter.mjs +65 -58
- package/dist/plugins/organization/client.d.mts +3 -1
- package/dist/plugins/organization/client.mjs +1 -1
- package/dist/plugins/organization/error-codes.d.mts +2 -0
- package/dist/plugins/organization/error-codes.mjs +3 -1
- package/dist/plugins/organization/routes/crud-access-control.d.mts +2 -2
- package/dist/plugins/organization/routes/crud-invites.d.mts +8 -1
- package/dist/plugins/organization/routes/crud-invites.mjs +8 -3
- package/dist/plugins/organization/routes/crud-org.d.mts +4 -4
- package/dist/plugins/organization/routes/crud-org.mjs +2 -2
- package/dist/plugins/organization/routes/crud-team.mjs +7 -2
- package/dist/plugins/organization/schema.d.mts +1 -1
- package/dist/plugins/organization/types.d.mts +15 -5
- package/dist/plugins/phone-number/routes.mjs +1 -1
- package/dist/plugins/siwe/client.d.mts +4 -0
- package/dist/plugins/siwe/client.mjs +5 -1
- package/dist/plugins/siwe/index.d.mts +13 -2
- package/dist/plugins/siwe/index.mjs +179 -165
- package/dist/plugins/two-factor/backup-codes/index.d.mts +4 -3
- package/dist/plugins/two-factor/client.mjs +2 -1
- package/dist/plugins/two-factor/index.mjs +3 -2
- package/dist/plugins/username/client.d.mts +1 -0
- package/dist/plugins/username/error-codes.d.mts +1 -0
- package/dist/plugins/username/error-codes.mjs +2 -1
- package/dist/plugins/username/index.d.mts +43 -2
- package/dist/plugins/username/index.mjs +73 -6
- package/dist/state.d.mts +2 -2
- package/dist/state.mjs +18 -4
- package/dist/test-utils/headers.mjs +2 -7
- package/dist/test-utils/http-test-instance.d.mts +397 -0
- package/dist/test-utils/http-test-instance.mjs +54 -0
- package/dist/test-utils/index.d.mts +2 -1
- package/dist/test-utils/index.mjs +2 -1
- package/dist/test-utils/test-instance.d.mts +4110 -224
- package/dist/test-utils/test-instance.mjs +11 -2
- package/dist/types/auth.d.mts +4 -0
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/url.d.mts +2 -1
- package/dist/utils/url.mjs +9 -3
- package/dist/version.mjs +1 -1
- package/package.json +14 -14
- package/dist/oauth2/error-codes.d.mts +0 -20
- package/dist/plugins/generic-oauth/client.d.mts +0 -32
- package/dist/plugins/generic-oauth/client.mjs +0 -19
- package/dist/plugins/generic-oauth/error-codes.d.mts +0 -10
package/dist/cookies/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Session, User } from "../types/models.mjs";
|
|
2
|
-
import { CookieAttributes, HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, parseSetCookieHeader, setCookieToHeader, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions } from "./cookie-utils.mjs";
|
|
2
|
+
import { CookieAttributes, HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, applySetCookies, cookieNameRegex, parseCookies, parseSetCookieHeader, setCookieToHeader, setRequestCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions } from "./cookie-utils.mjs";
|
|
3
3
|
import { createSessionStore, getAccountCookie, getChunkedCookie } from "./session-store.mjs";
|
|
4
4
|
import { BetterAuthCookie, BetterAuthCookies, BetterAuthOptions, GenericEndpointContext } from "@better-auth/core";
|
|
5
5
|
import * as better_call0 from "better-call";
|
|
@@ -95,7 +95,6 @@ declare function setSessionCookie(ctx: GenericEndpointContext, session: {
|
|
|
95
95
|
*/
|
|
96
96
|
declare function expireCookie(ctx: GenericEndpointContext, cookie: BetterAuthCookie): void;
|
|
97
97
|
declare function deleteSessionCookie(ctx: GenericEndpointContext, skipDontRememberMe?: boolean | undefined): void;
|
|
98
|
-
declare function parseCookies(cookieHeader: string): Map<string, string>;
|
|
99
98
|
type EligibleCookies = (string & {}) | (keyof BetterAuthCookies & {});
|
|
100
99
|
declare const getSessionCookie: (request: Request | Headers, config?: {
|
|
101
100
|
cookiePrefix?: string;
|
|
@@ -116,4 +115,4 @@ declare const getCookieCache: <S extends {
|
|
|
116
115
|
version?: string | ((session: Session & Record<string, any>, user: User & Record<string, any>) => string) | ((session: Session & Record<string, any>, user: User & Record<string, any>) => Promise<string>);
|
|
117
116
|
} | undefined) => Promise<S | null>;
|
|
118
117
|
//#endregion
|
|
119
|
-
export { CookieAttributes, EligibleCookies, HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, createCookieGetter, createSessionStore, deleteSessionCookie, expireCookie, getAccountCookie, getChunkedCookie, getCookieCache, getCookies, getSessionCookie, parseCookies, parseSetCookieHeader, setCookieCache, setCookieToHeader, setSessionCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions };
|
|
118
|
+
export { CookieAttributes, EligibleCookies, HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, applySetCookies, cookieNameRegex, createCookieGetter, createSessionStore, deleteSessionCookie, expireCookie, getAccountCookie, getChunkedCookie, getCookieCache, getCookies, getSessionCookie, parseCookies, parseSetCookieHeader, setCookieCache, setCookieToHeader, setRequestCookie, setSessionCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions };
|
package/dist/cookies/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { parseUserOutput } from "../db/schema.mjs";
|
|
|
4
4
|
import { getDate } from "../utils/date.mjs";
|
|
5
5
|
import { isPromise } from "../utils/is-promise.mjs";
|
|
6
6
|
import { sec } from "../utils/time.mjs";
|
|
7
|
-
import { HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, parseSetCookieHeader, setCookieToHeader, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions } from "./cookie-utils.mjs";
|
|
7
|
+
import { HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, applySetCookies, cookieNameRegex, parseCookies, parseSetCookieHeader, setCookieToHeader, setRequestCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions } from "./cookie-utils.mjs";
|
|
8
8
|
import { createAccountStore, createSessionStore, getAccountCookie, getChunkedCookie, setAccountCookie } from "./session-store.mjs";
|
|
9
9
|
import { env, isProduction } from "@better-auth/core/env";
|
|
10
10
|
import { BetterAuthError } from "@better-auth/core/error";
|
|
@@ -134,9 +134,46 @@ async function setSessionCookie(ctx, session, dontRememberMe, overrides) {
|
|
|
134
134
|
ctx.context.setNewSession(session);
|
|
135
135
|
}
|
|
136
136
|
/**
|
|
137
|
+
* Remove any prior `Set-Cookie` entries on the current response whose cookie
|
|
138
|
+
* name matches `cookieName` or any chunked variant (`${cookieName}.0`, etc.).
|
|
139
|
+
*
|
|
140
|
+
* Prevents a valid cookie value from leaking on the wire when the same cookie
|
|
141
|
+
* is set and then expired within a single request (e.g. `/sign-in/email`
|
|
142
|
+
* writes credential session cookies and the 2FA after-hook expires them).
|
|
143
|
+
* Browsers honor the expiring entry, but anything reading the raw response
|
|
144
|
+
* headers — proxy/LB logs, server-side SDK consumers, observability tools —
|
|
145
|
+
* sees the earlier valid value and could replay it (bypassing the 2FA gate
|
|
146
|
+
* when the cookie cache is enabled).
|
|
147
|
+
*
|
|
148
|
+
* Scrubs both the local middleware scope's `responseHeaders` and the outer
|
|
149
|
+
* endpoint scope's `ctx.context.responseHeaders`, because plugin after-hooks
|
|
150
|
+
* run in a fresh local scope while accumulated response headers live on the
|
|
151
|
+
* outer one. `scoped.context` is required by {@link GenericEndpointContext}
|
|
152
|
+
* but unit-test mocks pass a minimal object via `as any`, so we use optional
|
|
153
|
+
* chaining defensively. The `Set` collapses the case where both scopes
|
|
154
|
+
* reference the same `Headers`.
|
|
155
|
+
*/
|
|
156
|
+
function removeSetCookieEntries(ctx, cookieName) {
|
|
157
|
+
const scoped = ctx;
|
|
158
|
+
const targets = /* @__PURE__ */ new Set();
|
|
159
|
+
if (scoped.responseHeaders) targets.add(scoped.responseHeaders);
|
|
160
|
+
if (scoped.context?.responseHeaders) targets.add(scoped.context.responseHeaders);
|
|
161
|
+
const exact = `${cookieName}=`;
|
|
162
|
+
const chunk = `${cookieName}.`;
|
|
163
|
+
for (const headers of targets) {
|
|
164
|
+
const existing = typeof headers.getSetCookie === "function" ? headers.getSetCookie() : splitSetCookieHeader(headers.get("set-cookie") || "");
|
|
165
|
+
if (!existing.length) continue;
|
|
166
|
+
const survivors = existing.filter((entry) => !entry.startsWith(exact) && !entry.startsWith(chunk));
|
|
167
|
+
if (survivors.length === existing.length) continue;
|
|
168
|
+
headers.delete("set-cookie");
|
|
169
|
+
for (const entry of survivors) headers.append("set-cookie", entry);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
137
173
|
* Expires a cookie by setting `maxAge: 0` while preserving its attributes
|
|
138
174
|
*/
|
|
139
175
|
function expireCookie(ctx, cookie) {
|
|
176
|
+
removeSetCookieEntries(ctx, cookie.name);
|
|
140
177
|
ctx.setCookie(cookie.name, "", {
|
|
141
178
|
...cookie.attributes,
|
|
142
179
|
maxAge: 0
|
|
@@ -157,15 +194,6 @@ function deleteSessionCookie(ctx, skipDontRememberMe) {
|
|
|
157
194
|
sessionStore.setCookies(cleanCookies);
|
|
158
195
|
if (!skipDontRememberMe) expireCookie(ctx, ctx.context.authCookies.dontRememberToken);
|
|
159
196
|
}
|
|
160
|
-
function parseCookies(cookieHeader) {
|
|
161
|
-
const cookies = cookieHeader.split("; ");
|
|
162
|
-
const cookieMap = /* @__PURE__ */ new Map();
|
|
163
|
-
cookies.forEach((cookie) => {
|
|
164
|
-
const [name, value] = cookie.split(/=(.*)/s);
|
|
165
|
-
cookieMap.set(name, value);
|
|
166
|
-
});
|
|
167
|
-
return cookieMap;
|
|
168
|
-
}
|
|
169
197
|
const getSessionCookie = (request, config) => {
|
|
170
198
|
const cookies = (request instanceof Headers || !("headers" in request) ? request : request.headers).get("cookie");
|
|
171
199
|
if (!cookies) return null;
|
|
@@ -258,4 +286,4 @@ const getCookieCache = async (request, config) => {
|
|
|
258
286
|
return null;
|
|
259
287
|
};
|
|
260
288
|
//#endregion
|
|
261
|
-
export { HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, createCookieGetter, createSessionStore, deleteSessionCookie, expireCookie, getAccountCookie, getChunkedCookie, getCookieCache, getCookies, getSessionCookie, parseCookies, parseSetCookieHeader, setCookieCache, setCookieToHeader, setSessionCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions };
|
|
289
|
+
export { HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, applySetCookies, cookieNameRegex, createCookieGetter, createSessionStore, deleteSessionCookie, expireCookie, getAccountCookie, getChunkedCookie, getCookieCache, getCookies, getSessionCookie, parseCookies, parseSetCookieHeader, setCookieCache, setCookieToHeader, setRequestCookie, setSessionCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { symmetricDecodeJWT, symmetricEncodeJWT } from "../crypto/jwt.mjs";
|
|
2
|
+
import { parseCookies } from "./cookie-utils.mjs";
|
|
2
3
|
import { safeJSONParse } from "@better-auth/core/utils/json";
|
|
3
4
|
import * as z from "zod";
|
|
4
5
|
//#region src/cookies/session-store.ts
|
|
@@ -6,20 +7,6 @@ const ALLOWED_COOKIE_SIZE = 4096;
|
|
|
6
7
|
const ESTIMATED_EMPTY_COOKIE_SIZE = 200;
|
|
7
8
|
const CHUNK_SIZE = ALLOWED_COOKIE_SIZE - ESTIMATED_EMPTY_COOKIE_SIZE;
|
|
8
9
|
/**
|
|
9
|
-
* Parse cookies from the request headers
|
|
10
|
-
*/
|
|
11
|
-
function parseCookiesFromContext(ctx) {
|
|
12
|
-
const cookieHeader = ctx.headers?.get("cookie");
|
|
13
|
-
if (!cookieHeader) return {};
|
|
14
|
-
const cookies = {};
|
|
15
|
-
const pairs = cookieHeader.split("; ");
|
|
16
|
-
for (const pair of pairs) {
|
|
17
|
-
const [name, ...valueParts] = pair.split("=");
|
|
18
|
-
if (name && valueParts.length > 0) cookies[name] = valueParts.join("=");
|
|
19
|
-
}
|
|
20
|
-
return cookies;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
10
|
* Extract the chunk index from a cookie name
|
|
24
11
|
*/
|
|
25
12
|
function getChunkIndex(cookieName) {
|
|
@@ -33,8 +20,8 @@ function getChunkIndex(cookieName) {
|
|
|
33
20
|
*/
|
|
34
21
|
function readExistingChunks(cookieName, ctx) {
|
|
35
22
|
const chunks = {};
|
|
36
|
-
const cookies =
|
|
37
|
-
for (const [name, value] of
|
|
23
|
+
const cookies = parseCookies(ctx.headers?.get("cookie") || "");
|
|
24
|
+
for (const [name, value] of cookies) if (name.startsWith(cookieName)) chunks[name] = value;
|
|
38
25
|
return chunks;
|
|
39
26
|
}
|
|
40
27
|
/**
|
|
@@ -140,13 +127,7 @@ function getChunkedCookie(ctx, cookieName) {
|
|
|
140
127
|
const chunks = [];
|
|
141
128
|
const cookieHeader = ctx.headers?.get("cookie");
|
|
142
129
|
if (!cookieHeader) return null;
|
|
143
|
-
const
|
|
144
|
-
const pairs = cookieHeader.split("; ");
|
|
145
|
-
for (const pair of pairs) {
|
|
146
|
-
const [name, ...valueParts] = pair.split("=");
|
|
147
|
-
if (name && valueParts.length > 0) cookies[name] = valueParts.join("=");
|
|
148
|
-
}
|
|
149
|
-
for (const [name, val] of Object.entries(cookies)) if (name.startsWith(cookieName + ".")) {
|
|
130
|
+
for (const [name, val] of parseCookies(cookieHeader)) if (name.startsWith(cookieName + ".")) {
|
|
150
131
|
const indexStr = name.split(".").at(-1);
|
|
151
132
|
const index = parseInt(indexStr || "0", 10);
|
|
152
133
|
if (!isNaN(index)) chunks.push({
|
|
@@ -269,13 +269,14 @@ async function getMigrations(config) {
|
|
|
269
269
|
return `${model}.${field}`;
|
|
270
270
|
}
|
|
271
271
|
}
|
|
272
|
+
const deferredIndexes = [];
|
|
272
273
|
if (toBeAdded.length) for (const table of toBeAdded) for (const [fieldName, field] of Object.entries(table.fields)) {
|
|
273
274
|
const type = getType(field, fieldName);
|
|
274
275
|
const builder = db.schema.alterTable(table.table);
|
|
275
276
|
if (field.index) {
|
|
276
277
|
const indexName = `${table.table}_${fieldName}_${field.unique ? "uidx" : "idx"}`;
|
|
277
278
|
const indexBuilder = db.schema.createIndex(indexName).on(table.table).columns([fieldName]);
|
|
278
|
-
|
|
279
|
+
deferredIndexes.push(field.unique ? indexBuilder.unique() : indexBuilder);
|
|
279
280
|
}
|
|
280
281
|
const built = builder.addColumn(fieldName, type, (col) => {
|
|
281
282
|
col = field.required !== false ? col.notNull() : col;
|
|
@@ -287,7 +288,6 @@ async function getMigrations(config) {
|
|
|
287
288
|
});
|
|
288
289
|
migrations.push(built);
|
|
289
290
|
}
|
|
290
|
-
const toBeIndexed = [];
|
|
291
291
|
if (toBeCreated.length) for (const table of toBeCreated) {
|
|
292
292
|
const idType = getType({ type: useNumberId ? "number" : "string" }, "id");
|
|
293
293
|
let dbT = db.schema.createTable(table.table).addColumn("id", idType, (col) => {
|
|
@@ -315,12 +315,12 @@ async function getMigrations(config) {
|
|
|
315
315
|
});
|
|
316
316
|
if (field.index) {
|
|
317
317
|
const builder = db.schema.createIndex(`${table.table}_${fieldName}_${field.unique ? "uidx" : "idx"}`).on(table.table).columns([fieldName]);
|
|
318
|
-
|
|
318
|
+
deferredIndexes.push(field.unique ? builder.unique() : builder);
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
321
|
migrations.push(dbT);
|
|
322
322
|
}
|
|
323
|
-
|
|
323
|
+
for (const index of deferredIndexes) migrations.push(index);
|
|
324
324
|
async function runMigrations() {
|
|
325
325
|
for (const migration of migrations) await migration.execute();
|
|
326
326
|
}
|
package/dist/db/index.d.mts
CHANGED
|
@@ -3,7 +3,7 @@ import { convertFromDB, convertToDB } from "./field-converter.mjs";
|
|
|
3
3
|
import { getSchema } from "./get-schema.mjs";
|
|
4
4
|
import { DatabaseHooksEntry, getWithHooks } from "./with-hooks.mjs";
|
|
5
5
|
import { createInternalAdapter } from "./internal-adapter.mjs";
|
|
6
|
-
import { getSessionDefaultFields, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput } from "./schema.mjs";
|
|
6
|
+
import { buildSyntheticUserOutput, getSessionDefaultFields, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput } from "./schema.mjs";
|
|
7
7
|
import { FieldAttributeToSchema, toZodSchema } from "./to-zod.mjs";
|
|
8
8
|
export * from "@better-auth/core/db";
|
|
9
|
-
export { DatabaseHooksEntry, FieldAttributeToObject, FieldAttributeToSchema, InferAdditionalFieldsFromPluginOptions, InferFieldsInputClient, InferFieldsOutput, RemoveFieldsWithReturnedFalse, convertFromDB, convertToDB, createInternalAdapter, getSchema, getSessionDefaultFields, getWithHooks, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput, toZodSchema };
|
|
9
|
+
export { DatabaseHooksEntry, FieldAttributeToObject, FieldAttributeToSchema, InferAdditionalFieldsFromPluginOptions, InferFieldsInputClient, InferFieldsOutput, RemoveFieldsWithReturnedFalse, buildSyntheticUserOutput, convertFromDB, convertToDB, createInternalAdapter, getSchema, getSessionDefaultFields, getWithHooks, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput, toZodSchema };
|
package/dist/db/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __exportAll, __reExport } from "../_virtual/_rolldown/runtime.mjs";
|
|
2
2
|
import { getSchema } from "./get-schema.mjs";
|
|
3
|
-
import { getSessionDefaultFields, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput } from "./schema.mjs";
|
|
3
|
+
import { buildSyntheticUserOutput, getSessionDefaultFields, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput } from "./schema.mjs";
|
|
4
4
|
import { convertFromDB, convertToDB } from "./field-converter.mjs";
|
|
5
5
|
import { getWithHooks } from "./with-hooks.mjs";
|
|
6
6
|
import { createInternalAdapter } from "./internal-adapter.mjs";
|
|
@@ -8,6 +8,7 @@ import { toZodSchema } from "./to-zod.mjs";
|
|
|
8
8
|
export * from "@better-auth/core/db";
|
|
9
9
|
//#region src/db/index.ts
|
|
10
10
|
var db_exports = /* @__PURE__ */ __exportAll({
|
|
11
|
+
buildSyntheticUserOutput: () => buildSyntheticUserOutput,
|
|
11
12
|
convertFromDB: () => convertFromDB,
|
|
12
13
|
convertToDB: () => convertToDB,
|
|
13
14
|
createInternalAdapter: () => createInternalAdapter,
|
|
@@ -28,4 +29,4 @@ var db_exports = /* @__PURE__ */ __exportAll({
|
|
|
28
29
|
import * as import__better_auth_core_db from "@better-auth/core/db";
|
|
29
30
|
__reExport(db_exports, import__better_auth_core_db);
|
|
30
31
|
//#endregion
|
|
31
|
-
export { convertFromDB, convertToDB, createInternalAdapter, db_exports, getSchema, getSessionDefaultFields, getWithHooks, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput, toZodSchema };
|
|
32
|
+
export { buildSyntheticUserOutput, convertFromDB, convertToDB, createInternalAdapter, db_exports, getSchema, getSessionDefaultFields, getWithHooks, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput, toZodSchema };
|
|
@@ -15,8 +15,9 @@ const createInternalAdapter = (adapter, ctx) => {
|
|
|
15
15
|
const logger = ctx.logger;
|
|
16
16
|
const options = ctx.options;
|
|
17
17
|
const secondaryStorage = options.secondaryStorage;
|
|
18
|
+
const verificationConsumeLocks = /* @__PURE__ */ new Map();
|
|
18
19
|
const sessionExpiration = options.session?.expiresIn || 3600 * 24 * 7;
|
|
19
|
-
const { createWithHooks, updateWithHooks, updateManyWithHooks, deleteWithHooks, deleteManyWithHooks } = getWithHooks(adapter, ctx);
|
|
20
|
+
const { createWithHooks, updateWithHooks, updateManyWithHooks, deleteWithHooks, deleteManyWithHooks, consumeOneWithHooks } = getWithHooks(adapter, ctx);
|
|
20
21
|
async function refreshUserSessions(user) {
|
|
21
22
|
if (!secondaryStorage) return;
|
|
22
23
|
const listRaw = await secondaryStorage.get(`active-sessions-${user.id}`);
|
|
@@ -35,13 +36,30 @@ const createInternalAdapter = (adapter, ctx) => {
|
|
|
35
36
|
}), Math.floor(sessionTTL));
|
|
36
37
|
}));
|
|
37
38
|
}
|
|
39
|
+
async function withVerificationConsumeLock(key, fn) {
|
|
40
|
+
const previous = verificationConsumeLocks.get(key) ?? Promise.resolve();
|
|
41
|
+
let release;
|
|
42
|
+
const current = new Promise((resolve) => {
|
|
43
|
+
release = resolve;
|
|
44
|
+
});
|
|
45
|
+
const next = previous.catch(() => {}).then(() => current);
|
|
46
|
+
verificationConsumeLocks.set(key, next);
|
|
47
|
+
await previous.catch(() => {});
|
|
48
|
+
try {
|
|
49
|
+
return await fn();
|
|
50
|
+
} finally {
|
|
51
|
+
release();
|
|
52
|
+
if (verificationConsumeLocks.get(key) === next) verificationConsumeLocks.delete(key);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
38
55
|
return {
|
|
39
56
|
createOAuthUser: async (user, account) => {
|
|
40
57
|
return runWithTransaction(adapter, async () => {
|
|
41
58
|
const createdUser = await createWithHooks({
|
|
42
59
|
createdAt: /* @__PURE__ */ new Date(),
|
|
43
60
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
44
|
-
...user
|
|
61
|
+
...user,
|
|
62
|
+
email: user.email?.toLowerCase()
|
|
45
63
|
}, "user", void 0);
|
|
46
64
|
return {
|
|
47
65
|
user: createdUser,
|
|
@@ -364,27 +382,35 @@ const createInternalAdapter = (adapter, ctx) => {
|
|
|
364
382
|
value: userId
|
|
365
383
|
}], "account", void 0);
|
|
366
384
|
},
|
|
367
|
-
deleteAccount: async (
|
|
385
|
+
deleteAccount: async (id) => {
|
|
368
386
|
await deleteWithHooks([{
|
|
369
387
|
field: "id",
|
|
370
|
-
value:
|
|
388
|
+
value: id
|
|
371
389
|
}], "account", void 0);
|
|
372
390
|
},
|
|
373
|
-
|
|
391
|
+
deleteUserSessions: async (userId) => {
|
|
374
392
|
if (secondaryStorage) {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
await secondaryStorage.delete(`active-sessions-${userIdOrSessionTokens}`);
|
|
381
|
-
} else for (const sessionToken of userIdOrSessionTokens) if (await secondaryStorage.get(sessionToken)) await secondaryStorage.delete(sessionToken);
|
|
393
|
+
const activeSession = await secondaryStorage.get(`active-sessions-${userId}`);
|
|
394
|
+
const sessions = activeSession ? safeJSONParse(activeSession) : [];
|
|
395
|
+
if (!sessions) return;
|
|
396
|
+
for (const session of sessions) await secondaryStorage.delete(session.token);
|
|
397
|
+
await secondaryStorage.delete(`active-sessions-${userId}`);
|
|
382
398
|
if (!options.session?.storeSessionInDatabase || ctx.options.session?.preserveSessionInDatabase) return;
|
|
383
399
|
}
|
|
384
400
|
await deleteManyWithHooks([{
|
|
385
|
-
field:
|
|
386
|
-
value:
|
|
387
|
-
|
|
401
|
+
field: "userId",
|
|
402
|
+
value: userId
|
|
403
|
+
}], "session", void 0);
|
|
404
|
+
},
|
|
405
|
+
deleteSessions: async (sessionTokens) => {
|
|
406
|
+
if (secondaryStorage) {
|
|
407
|
+
for (const sessionToken of sessionTokens) if (await secondaryStorage.get(sessionToken)) await secondaryStorage.delete(sessionToken);
|
|
408
|
+
if (!options.session?.storeSessionInDatabase || ctx.options.session?.preserveSessionInDatabase) return;
|
|
409
|
+
}
|
|
410
|
+
await deleteManyWithHooks([{
|
|
411
|
+
field: "token",
|
|
412
|
+
value: sessionTokens,
|
|
413
|
+
operator: "in"
|
|
388
414
|
}], "session", void 0);
|
|
389
415
|
},
|
|
390
416
|
findOAuthUser: async (email, accountId, providerId) => {
|
|
@@ -475,7 +501,10 @@ const createInternalAdapter = (adapter, ctx) => {
|
|
|
475
501
|
}, "account", void 0);
|
|
476
502
|
},
|
|
477
503
|
updateUser: async (userId, data) => {
|
|
478
|
-
const user = await updateWithHooks(
|
|
504
|
+
const user = await updateWithHooks({
|
|
505
|
+
...data,
|
|
506
|
+
...data.email ? { email: data.email.toLowerCase() } : {}
|
|
507
|
+
}, [{
|
|
479
508
|
field: "id",
|
|
480
509
|
value: userId
|
|
481
510
|
}], "user", void 0);
|
|
@@ -483,7 +512,10 @@ const createInternalAdapter = (adapter, ctx) => {
|
|
|
483
512
|
return user;
|
|
484
513
|
},
|
|
485
514
|
updateUserByEmail: async (email, data) => {
|
|
486
|
-
const user = await updateWithHooks(
|
|
515
|
+
const user = await updateWithHooks({
|
|
516
|
+
...data,
|
|
517
|
+
...data.email ? { email: data.email.toLowerCase() } : {}
|
|
518
|
+
}, [{
|
|
487
519
|
field: "email",
|
|
488
520
|
value: email.toLowerCase()
|
|
489
521
|
}], "user", void 0);
|
|
@@ -508,15 +540,6 @@ const createInternalAdapter = (adapter, ctx) => {
|
|
|
508
540
|
}]
|
|
509
541
|
});
|
|
510
542
|
},
|
|
511
|
-
findAccount: async (accountId) => {
|
|
512
|
-
return await (await getCurrentAdapter(adapter)).findOne({
|
|
513
|
-
model: "account",
|
|
514
|
-
where: [{
|
|
515
|
-
field: "accountId",
|
|
516
|
-
value: accountId
|
|
517
|
-
}]
|
|
518
|
-
});
|
|
519
|
-
},
|
|
520
543
|
findAccountByProviderId: async (accountId, providerId) => {
|
|
521
544
|
return await (await getCurrentAdapter(adapter)).findOne({
|
|
522
545
|
model: "account",
|
|
@@ -611,6 +634,84 @@ const createInternalAdapter = (adapter, ctx) => {
|
|
|
611
634
|
value: storedIdentifier
|
|
612
635
|
}], "verification", void 0);
|
|
613
636
|
},
|
|
637
|
+
consumeVerificationValue: async (identifier) => {
|
|
638
|
+
const storageOption = getStorageOption(identifier, options.verification?.storeIdentifier);
|
|
639
|
+
const storedIdentifier = await processIdentifier(identifier, storageOption);
|
|
640
|
+
const identifiersToTry = storageOption && storageOption !== "plain" ? [storedIdentifier, identifier] : [storedIdentifier];
|
|
641
|
+
const hydrateCachedVerification = (raw) => {
|
|
642
|
+
if (!raw) return null;
|
|
643
|
+
const candidate = typeof raw === "string" ? safeJSONParse(raw) : typeof raw === "object" ? raw : null;
|
|
644
|
+
if (!candidate) return null;
|
|
645
|
+
const expiresAt = new Date(candidate.expiresAt);
|
|
646
|
+
if (!Number.isFinite(expiresAt.getTime())) return null;
|
|
647
|
+
return {
|
|
648
|
+
...candidate,
|
|
649
|
+
expiresAt
|
|
650
|
+
};
|
|
651
|
+
};
|
|
652
|
+
let consumed = null;
|
|
653
|
+
if (secondaryStorage && !options.verification?.storeInDatabase) {
|
|
654
|
+
const consumeCacheKey = async (key) => {
|
|
655
|
+
if (secondaryStorage.getAndDelete) return hydrateCachedVerification(await secondaryStorage.getAndDelete(key));
|
|
656
|
+
return withVerificationConsumeLock(key, async () => {
|
|
657
|
+
const parsed = hydrateCachedVerification(await secondaryStorage.get(key));
|
|
658
|
+
if (!parsed) return null;
|
|
659
|
+
await secondaryStorage.delete(key);
|
|
660
|
+
return parsed;
|
|
661
|
+
});
|
|
662
|
+
};
|
|
663
|
+
for (const stored of identifiersToTry) {
|
|
664
|
+
const cached = await consumeCacheKey(`verification:${stored}`);
|
|
665
|
+
if (!cached) continue;
|
|
666
|
+
await Promise.all(identifiersToTry.filter((candidate) => candidate !== stored).map((candidate) => secondaryStorage.delete(`verification:${candidate}`)));
|
|
667
|
+
consumed = cached;
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
} else {
|
|
671
|
+
const consumeByIdentifier = async (id) => withVerificationConsumeLock(`verification:${id}`, () => runWithTransaction(adapter, async () => {
|
|
672
|
+
const txAdapter = await getCurrentAdapter(adapter);
|
|
673
|
+
const where = [{
|
|
674
|
+
field: "identifier",
|
|
675
|
+
value: id
|
|
676
|
+
}];
|
|
677
|
+
const latest = (await txAdapter.findMany({
|
|
678
|
+
model: "verification",
|
|
679
|
+
where,
|
|
680
|
+
sortBy: {
|
|
681
|
+
field: "createdAt",
|
|
682
|
+
direction: "desc"
|
|
683
|
+
},
|
|
684
|
+
limit: 1
|
|
685
|
+
}))[0] ?? null;
|
|
686
|
+
if (!latest) return null;
|
|
687
|
+
return consumeOneWithHooks("verification", [{
|
|
688
|
+
field: "id",
|
|
689
|
+
value: latest.id
|
|
690
|
+
}], async () => {
|
|
691
|
+
const row = await txAdapter.consumeOne({
|
|
692
|
+
model: "verification",
|
|
693
|
+
where: [{
|
|
694
|
+
field: "id",
|
|
695
|
+
value: latest.id
|
|
696
|
+
}]
|
|
697
|
+
});
|
|
698
|
+
if (!row) return null;
|
|
699
|
+
await txAdapter.deleteMany({
|
|
700
|
+
model: "verification",
|
|
701
|
+
where
|
|
702
|
+
});
|
|
703
|
+
return row;
|
|
704
|
+
}, latest);
|
|
705
|
+
}));
|
|
706
|
+
for (const stored of identifiersToTry) {
|
|
707
|
+
consumed = await consumeByIdentifier(stored);
|
|
708
|
+
if (consumed) break;
|
|
709
|
+
}
|
|
710
|
+
if (consumed && secondaryStorage) await Promise.all(identifiersToTry.map((stored) => secondaryStorage.delete(`verification:${stored}`)));
|
|
711
|
+
}
|
|
712
|
+
if (!consumed || consumed.expiresAt < /* @__PURE__ */ new Date()) return null;
|
|
713
|
+
return consumed;
|
|
714
|
+
},
|
|
614
715
|
updateVerificationByIdentifier: async (identifier, data) => {
|
|
615
716
|
const storedIdentifier = await processIdentifier(identifier, getStorageOption(identifier, options.verification?.storeIdentifier));
|
|
616
717
|
if (secondaryStorage) {
|
|
@@ -634,7 +735,8 @@ const createInternalAdapter = (adapter, ctx) => {
|
|
|
634
735
|
value: storedIdentifier
|
|
635
736
|
}], "verification", void 0);
|
|
636
737
|
return data;
|
|
637
|
-
}
|
|
738
|
+
},
|
|
739
|
+
refreshUserSessions
|
|
638
740
|
};
|
|
639
741
|
};
|
|
640
742
|
//#endregion
|
package/dist/db/schema.d.mts
CHANGED
|
@@ -4,6 +4,19 @@ import { BetterAuthPluginDBSchema, DBFieldAttribute } from "@better-auth/core/db
|
|
|
4
4
|
|
|
5
5
|
//#region src/db/schema.d.ts
|
|
6
6
|
declare function parseUserOutput<T extends User$1>(options: BetterAuthOptions, user: T): T;
|
|
7
|
+
/**
|
|
8
|
+
* Builds a synthetic user object that matches the shape of a real user
|
|
9
|
+
* returned from the database. This ensures enumeration protection works
|
|
10
|
+
* correctly by making synthetic and real user responses indistinguishable.
|
|
11
|
+
*
|
|
12
|
+
* The function iterates over the user output schema and:
|
|
13
|
+
* - Includes all fields that should be returned (returned !== false)
|
|
14
|
+
* - Uses provided values when available
|
|
15
|
+
* - Sets optional fields to null when no value is provided
|
|
16
|
+
* - Applies default values where defined
|
|
17
|
+
* - Always includes the 'id' field (not part of schema but always present)
|
|
18
|
+
*/
|
|
19
|
+
declare function buildSyntheticUserOutput(options: BetterAuthOptions, data: Record<string, unknown>): Record<string, unknown>;
|
|
7
20
|
declare function parseSessionOutput<T extends Session$1>(options: BetterAuthOptions, session: T): T;
|
|
8
21
|
declare function parseAccountOutput<T extends Account>(options: BetterAuthOptions, account: T): Omit<T, "idToken" | "accessToken" | "refreshToken" | "accessTokenExpiresAt" | "refreshTokenExpiresAt" | "password">;
|
|
9
22
|
declare function parseInputData<T extends Record<string, any>>(data: T, schema: {
|
|
@@ -45,4 +58,4 @@ declare function mergeSchema<S extends BetterAuthPluginDBSchema>(schema: S, newS
|
|
|
45
58
|
} | undefined;
|
|
46
59
|
} | undefined } | undefined): S;
|
|
47
60
|
//#endregion
|
|
48
|
-
export { getSessionDefaultFields, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput };
|
|
61
|
+
export { buildSyntheticUserOutput, getSessionDefaultFields, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput };
|
package/dist/db/schema.mjs
CHANGED
|
@@ -24,6 +24,31 @@ function getFields(options, modelName, mode) {
|
|
|
24
24
|
function parseUserOutput(options, user) {
|
|
25
25
|
return filterOutputFields(user, getFields(options, "user", "output"));
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Builds a synthetic user object that matches the shape of a real user
|
|
29
|
+
* returned from the database. This ensures enumeration protection works
|
|
30
|
+
* correctly by making synthetic and real user responses indistinguishable.
|
|
31
|
+
*
|
|
32
|
+
* The function iterates over the user output schema and:
|
|
33
|
+
* - Includes all fields that should be returned (returned !== false)
|
|
34
|
+
* - Uses provided values when available
|
|
35
|
+
* - Sets optional fields to null when no value is provided
|
|
36
|
+
* - Applies default values where defined
|
|
37
|
+
* - Always includes the 'id' field (not part of schema but always present)
|
|
38
|
+
*/
|
|
39
|
+
function buildSyntheticUserOutput(options, data) {
|
|
40
|
+
const schema = getFields(options, "user", "output");
|
|
41
|
+
const result = {};
|
|
42
|
+
for (const key in schema) {
|
|
43
|
+
const fieldAttr = schema[key];
|
|
44
|
+
if (fieldAttr.returned === false) continue;
|
|
45
|
+
if (key in data && data[key] !== void 0) result[key] = data[key];
|
|
46
|
+
else if (fieldAttr.defaultValue !== void 0) result[key] = typeof fieldAttr.defaultValue === "function" ? fieldAttr.defaultValue() : fieldAttr.defaultValue;
|
|
47
|
+
else if (!fieldAttr.required) result[key] = null;
|
|
48
|
+
}
|
|
49
|
+
if ("id" in data) result.id = data.id;
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
27
52
|
function parseSessionOutput(options, session) {
|
|
28
53
|
return filterOutputFields(session, getFields(options, "session", "output"));
|
|
29
54
|
}
|
|
@@ -121,4 +146,4 @@ function mergeSchema(schema, newSchema) {
|
|
|
121
146
|
return schema;
|
|
122
147
|
}
|
|
123
148
|
//#endregion
|
|
124
|
-
export { getSessionDefaultFields, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput };
|
|
149
|
+
export { buildSyntheticUserOutput, getSessionDefaultFields, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput };
|
package/dist/db/with-hooks.d.mts
CHANGED
|
@@ -31,6 +31,7 @@ declare function getWithHooks(adapter: DBAdapter<BetterAuthOptions>, ctx: {
|
|
|
31
31
|
fn: (where: Where[]) => void | Promise<any>;
|
|
32
32
|
executeMainFn?: boolean;
|
|
33
33
|
} | undefined) => Promise<any>;
|
|
34
|
+
consumeOneWithHooks: <T extends Record<string, any>>(model: BaseModelNames, hookWhere: Where[], consumeFn: () => Promise<T | null>, preSnapshot?: T | null) => Promise<T | null>;
|
|
34
35
|
};
|
|
35
36
|
//#endregion
|
|
36
37
|
export { DatabaseHooksEntry, getWithHooks };
|
package/dist/db/with-hooks.mjs
CHANGED
|
@@ -185,12 +185,69 @@ function getWithHooks(adapter, ctx) {
|
|
|
185
185
|
}
|
|
186
186
|
return deleted;
|
|
187
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Wraps an atomic consume operation in the plugin `delete.before` and
|
|
190
|
+
* `delete.after` hook lifecycle. The caller supplies a `consumeFn` that
|
|
191
|
+
* performs the actual single-row delete-and-return (typically the
|
|
192
|
+
* adapter's `consumeOne`). The first concurrent caller wins, subsequent
|
|
193
|
+
* racers resolve to `null` without firing `delete.after` hooks.
|
|
194
|
+
*
|
|
195
|
+
* `preSnapshot` lets the caller hand in a row it already fetched so
|
|
196
|
+
* `delete.before` hooks don't trigger a second read. Without it, the
|
|
197
|
+
* helper falls back to a best-effort `findMany` against `hookWhere`.
|
|
198
|
+
* The snapshot only feeds `delete.before`; the `consumeFn` return value
|
|
199
|
+
* is the race gate.
|
|
200
|
+
*
|
|
201
|
+
* Returning `false` from a `delete.before` hook aborts the consume and
|
|
202
|
+
* the helper resolves to `null` (no `consumeFn` call, no after hooks).
|
|
203
|
+
*/
|
|
204
|
+
async function consumeOneWithHooks(model, hookWhere, consumeFn, preSnapshot) {
|
|
205
|
+
const context = await getCurrentAuthContext().catch(() => null);
|
|
206
|
+
const beforeHooks = hooksEntries.flatMap(({ source, hooks }) => {
|
|
207
|
+
const fn = hooks[model]?.delete?.before;
|
|
208
|
+
return fn ? [{
|
|
209
|
+
source,
|
|
210
|
+
fn
|
|
211
|
+
}] : [];
|
|
212
|
+
});
|
|
213
|
+
let snapshot = preSnapshot ?? null;
|
|
214
|
+
if (beforeHooks.length) {
|
|
215
|
+
if (!snapshot) try {
|
|
216
|
+
snapshot = (await (await getCurrentAdapter(adapter)).findMany({
|
|
217
|
+
model,
|
|
218
|
+
where: hookWhere,
|
|
219
|
+
limit: 1
|
|
220
|
+
}))[0] || null;
|
|
221
|
+
} catch {}
|
|
222
|
+
if (snapshot) {
|
|
223
|
+
for (const { source, fn } of beforeHooks) if (await withSpan(`db delete.before ${model}`, {
|
|
224
|
+
[ATTR_HOOK_TYPE]: "delete.before",
|
|
225
|
+
[ATTR_DB_COLLECTION_NAME]: model,
|
|
226
|
+
[ATTR_CONTEXT]: source
|
|
227
|
+
}, () => fn(snapshot, context)) === false) return null;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const consumed = await consumeFn();
|
|
231
|
+
if (!consumed) return null;
|
|
232
|
+
for (const { source, hooks } of hooksEntries) {
|
|
233
|
+
const toRun = hooks[model]?.delete?.after;
|
|
234
|
+
if (toRun) await queueAfterTransactionHook(async () => {
|
|
235
|
+
await withSpan(`db delete.after ${model}`, {
|
|
236
|
+
[ATTR_HOOK_TYPE]: "delete.after",
|
|
237
|
+
[ATTR_DB_COLLECTION_NAME]: model,
|
|
238
|
+
[ATTR_CONTEXT]: source
|
|
239
|
+
}, () => toRun(consumed, context));
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
return consumed;
|
|
243
|
+
}
|
|
188
244
|
return {
|
|
189
245
|
createWithHooks,
|
|
190
246
|
updateWithHooks,
|
|
191
247
|
updateManyWithHooks,
|
|
192
248
|
deleteWithHooks,
|
|
193
|
-
deleteManyWithHooks
|
|
249
|
+
deleteManyWithHooks,
|
|
250
|
+
consumeOneWithHooks
|
|
194
251
|
};
|
|
195
252
|
}
|
|
196
253
|
//#endregion
|
package/dist/index.d.mts
CHANGED
|
@@ -10,7 +10,7 @@ import { betterAuth } from "./auth/full.mjs";
|
|
|
10
10
|
import { generateState, parseState } from "./oauth2/state.mjs";
|
|
11
11
|
import { StateData, generateGenericState, parseGenericState } from "./state.mjs";
|
|
12
12
|
import { HIDE_METADATA } from "./utils/hide-metadata.mjs";
|
|
13
|
-
import { getBaseURL, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, resolveBaseURL, resolveDynamicBaseURL } from "./utils/url.mjs";
|
|
13
|
+
import { getBaseURL, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, resolveBaseURL, resolveDynamicBaseURL, trimTrailingSlashes } from "./utils/url.mjs";
|
|
14
14
|
import { APIError } from "./api/index.mjs";
|
|
15
15
|
import { StandardSchemaV1 } from "@better-auth/core";
|
|
16
16
|
import { getCurrentAdapter } from "@better-auth/core/context";
|
|
@@ -27,4 +27,4 @@ export * from "@better-auth/core/utils/json";
|
|
|
27
27
|
export * from "@better-auth/core/social-providers";
|
|
28
28
|
export * from "better-call";
|
|
29
29
|
export * from "zod";
|
|
30
|
-
export { APIError, Account, AdditionalSessionFieldsInput, AdditionalUserFieldsInput, Auth, BetterAuthAdvancedOptions, BetterAuthClientOptions, BetterAuthClientPlugin, BetterAuthCookies, BetterAuthOptions, BetterAuthPlugin, BetterAuthRateLimitOptions, ClientAtomListener, ClientStore, DBAdapter, DBAdapterInstance, DBAdapterSchemaCreation, DBTransactionAdapter, ExtractPluginField, FilteredAPI, HIDE_METADATA, HasRequiredKeys, InferAPI, InferActions, InferAdditionalFromClient, InferClientAPI, InferErrorCodes, InferOptionSchema, InferPluginContext, InferPluginErrorCodes, InferPluginFieldFromTuple, InferPluginIDs, InferPluginTypes, InferSessionAPI, InferSessionFromClient, InferUserFromClient, IsAny, IsSignal, type JSONWebKeySet, type JWTPayload, JoinConfig, JoinOption, OverrideMerge, Prettify, PrettifyDeep, RateLimit, RequiredKeysOf, Session, SessionQueryParams, type StandardSchemaV1, StateData, StoreIdentifierOption, StripEmptyObjects, type TelemetryEvent, UnionToIntersection, User, Verification, Where, betterAuth, createTelemetry, generateGenericState, generateState, getBaseURL, getCurrentAdapter, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, getTelemetryAuthConfig, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, parseGenericState, parseState, resolveBaseURL, resolveDynamicBaseURL };
|
|
30
|
+
export { APIError, Account, AdditionalSessionFieldsInput, AdditionalUserFieldsInput, Auth, BetterAuthAdvancedOptions, BetterAuthClientOptions, BetterAuthClientPlugin, BetterAuthCookies, BetterAuthOptions, BetterAuthPlugin, BetterAuthRateLimitOptions, ClientAtomListener, ClientStore, DBAdapter, DBAdapterInstance, DBAdapterSchemaCreation, DBTransactionAdapter, ExtractPluginField, FilteredAPI, HIDE_METADATA, HasRequiredKeys, InferAPI, InferActions, InferAdditionalFromClient, InferClientAPI, InferErrorCodes, InferOptionSchema, InferPluginContext, InferPluginErrorCodes, InferPluginFieldFromTuple, InferPluginIDs, InferPluginTypes, InferSessionAPI, InferSessionFromClient, InferUserFromClient, IsAny, IsSignal, type JSONWebKeySet, type JWTPayload, JoinConfig, JoinOption, OverrideMerge, Prettify, PrettifyDeep, RateLimit, RequiredKeysOf, Session, SessionQueryParams, type StandardSchemaV1, StateData, StoreIdentifierOption, StripEmptyObjects, type TelemetryEvent, UnionToIntersection, User, Verification, Where, betterAuth, createTelemetry, generateGenericState, generateState, getBaseURL, getCurrentAdapter, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, getTelemetryAuthConfig, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, parseGenericState, parseState, resolveBaseURL, resolveDynamicBaseURL, trimTrailingSlashes };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getBaseURL, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, resolveBaseURL, resolveDynamicBaseURL } from "./utils/url.mjs";
|
|
1
|
+
import { getBaseURL, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, resolveBaseURL, resolveDynamicBaseURL, trimTrailingSlashes } from "./utils/url.mjs";
|
|
2
2
|
import { generateGenericState, parseGenericState } from "./state.mjs";
|
|
3
3
|
import { generateState, parseState } from "./oauth2/state.mjs";
|
|
4
4
|
import { HIDE_METADATA } from "./utils/hide-metadata.mjs";
|
|
@@ -14,4 +14,4 @@ export * from "@better-auth/core/oauth2";
|
|
|
14
14
|
export * from "@better-auth/core/utils/error-codes";
|
|
15
15
|
export * from "@better-auth/core/utils/id";
|
|
16
16
|
export * from "@better-auth/core/utils/json";
|
|
17
|
-
export { APIError, HIDE_METADATA, betterAuth, createTelemetry, generateGenericState, generateState, getBaseURL, getCurrentAdapter, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, getTelemetryAuthConfig, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, parseGenericState, parseState, resolveBaseURL, resolveDynamicBaseURL };
|
|
17
|
+
export { APIError, HIDE_METADATA, betterAuth, createTelemetry, generateGenericState, generateState, getBaseURL, getCurrentAdapter, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, getTelemetryAuthConfig, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, parseGenericState, parseState, resolveBaseURL, resolveDynamicBaseURL, trimTrailingSlashes };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/integrations/cookie-plugin-guard.ts
|
|
2
|
+
/**
|
|
3
|
+
* Warns when a cookie integration plugin is not effectively last.
|
|
4
|
+
*
|
|
5
|
+
* A plugin is considered misordered when there is at least one other plugin
|
|
6
|
+
* after it in the `plugins` array that declares `hooks.after`, since those
|
|
7
|
+
* hooks can set cookies that this integration will not see.
|
|
8
|
+
*/
|
|
9
|
+
function warnIfCookiePluginNotLast(ctx, pluginId) {
|
|
10
|
+
const plugins = ctx.options.plugins || [];
|
|
11
|
+
if (plugins.length === 0) return;
|
|
12
|
+
const index = plugins.findIndex((p) => p.id === pluginId);
|
|
13
|
+
if (index === -1) return;
|
|
14
|
+
if (!plugins.slice(index + 1).some((p) => p.hooks && Array.isArray(p.hooks.after) && p.hooks.after.length > 0)) return;
|
|
15
|
+
ctx.logger.warn(`[better-auth] Cookie integration plugin "${pluginId}" should be placed last in the plugins array. Plugins with \`hooks.after\` running after it may set cookies that are not forwarded to the framework cookie store. Move your cookie integration plugin to the end of the \`plugins\` array to avoid missing \`Set-Cookie\` headers.`);
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { warnIfCookiePluginNotLast };
|