better-auth 1.7.3 → 1.7.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.
@@ -4,7 +4,7 @@ import { runWithEndpointContext } from "@better-auth/core/context";
4
4
  import { shouldPublishLog } from "@better-auth/core/env";
5
5
  import { APIError } from "@better-auth/core/error";
6
6
  import { createDefu } from "defu";
7
- import { ATTR_CONTEXT, ATTR_HOOK_TYPE, ATTR_HTTP_ROUTE, ATTR_OPERATION_ID, withSpan } from "@better-auth/core/instrumentation";
7
+ import { ATTR_CONTEXT, ATTR_HOOK_TYPE, ATTR_HTTP_ROUTE, ATTR_OPERATION_ID, createWithSpan } from "@better-auth/core/instrumentation";
8
8
  import { kAPIErrorHeaderSymbol, toResponse } from "better-call";
9
9
  //#region src/api/dispatch.ts
10
10
  const defuReplaceArrays = createDefu((obj, key, value) => {
@@ -62,6 +62,7 @@ function mergeAPIErrorHeaders(error) {
62
62
  return headers;
63
63
  }
64
64
  async function runBeforeHooks(context, hooks, endpoint, operationId) {
65
+ const withSpan = createWithSpan(context.context.options);
65
66
  let modifiedContext = {};
66
67
  for (const hook of hooks) {
67
68
  let matched = false;
@@ -105,6 +106,7 @@ async function runBeforeHooks(context, hooks, endpoint, operationId) {
105
106
  return { context: modifiedContext };
106
107
  }
107
108
  async function runAfterHooks(context, hooks, endpoint, operationId) {
109
+ const withSpan = createWithSpan(context.context.options);
108
110
  for (const hook of hooks) {
109
111
  if (!hook.matcher(context)) continue;
110
112
  const hookSource = hooksSourceWeakMap.get(hook.handler) ?? "unknown";
@@ -182,6 +184,7 @@ function getHooks(authContext) {
182
184
  * @param input Input context whose `context` is an already-resolved `AuthContext`.
183
185
  */
184
186
  async function dispatchAuthEndpoint(endpoint, input) {
187
+ const withSpan = createWithSpan(input.context.options);
185
188
  const operationId = input.operationId ?? getOperationId(endpoint);
186
189
  const route = endpoint.path ?? "/:virtual";
187
190
  const endpointMethod = endpoint.options?.method;
@@ -21,7 +21,7 @@ import { toAuthEndpoints } from "./to-auth-endpoints.mjs";
21
21
  import { logger } from "@better-auth/core/env";
22
22
  import { APIError } from "@better-auth/core/error";
23
23
  import { getIP } from "@better-auth/core/utils/ip";
24
- import { ATTR_CONTEXT, ATTR_HOOK_TYPE, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_HTTP_ROUTE, withSpan } from "@better-auth/core/instrumentation";
24
+ import { ATTR_CONTEXT, ATTR_HOOK_TYPE, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_HTTP_ROUTE, createWithSpan } from "@better-auth/core/instrumentation";
25
25
  import { normalizePathname } from "@better-auth/core/utils/url";
26
26
  import { createRouter } from "better-call";
27
27
  import { NO_STORE_HEADERS, createAuthEndpoint, createAuthMiddleware, optionsMiddleware } from "@better-auth/core/api";
@@ -82,6 +82,7 @@ To resolve this, you can:
82
82
  }
83
83
  }
84
84
  function getEndpoints(ctx, options) {
85
+ const withSpan = createWithSpan(options);
85
86
  const pluginEndpoints = options.plugins?.reduce((acc, plugin) => {
86
87
  return {
87
88
  ...acc,
@@ -148,6 +149,7 @@ function getEndpoints(ctx, options) {
148
149
  };
149
150
  }
150
151
  const router = (ctx, options) => {
152
+ const withSpan = createWithSpan(options);
151
153
  const { api, middlewares } = getEndpoints(ctx, options);
152
154
  const basePath = new URL(ctx.baseURL).pathname;
153
155
  return createRouter(api, {
@@ -1,7 +1,8 @@
1
1
  import { getCurrentAdapter, queueAfterTransactionHook, tryGetCurrentAuthEndpointContext } from "@better-auth/core/context";
2
- import { ATTR_CONTEXT, ATTR_DB_COLLECTION_NAME, ATTR_HOOK_TYPE, withSpan } from "@better-auth/core/instrumentation";
2
+ import { ATTR_CONTEXT, ATTR_DB_COLLECTION_NAME, ATTR_HOOK_TYPE, createWithSpan } from "@better-auth/core/instrumentation";
3
3
  //#region src/db/with-hooks.ts
4
4
  function getWithHooks(adapter, ctx) {
5
+ const withSpan = createWithSpan(ctx.options);
5
6
  const hooksEntries = ctx.hooks;
6
7
  async function createWithHooks(data, model, customCreateFn) {
7
8
  const context = tryGetCurrentAuthEndpointContext();
package/dist/package.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "1.7.3";
2
+ var version = "1.7.4";
3
3
  //#endregion
4
4
  export { version };
@@ -53,7 +53,7 @@ import { OpenAPIOptions, openAPI } from "./open-api/index.mjs";
53
53
  import { PhoneNumberOptions, UserWithPhoneNumber } from "./phone-number/types.mjs";
54
54
  import { phoneNumber } from "./phone-number/index.mjs";
55
55
  import { SIWEPluginOptions, siwe } from "./siwe/index.mjs";
56
- import { LoginResult, TestCookie, TestHelpers, TestUtilsOptions } from "./test-utils/types.mjs";
56
+ import { LoginResult, TestAuthOptions, TestCookie, TestHelpers, TestUtilsOptions } from "./test-utils/types.mjs";
57
57
  import { testUtils } from "./test-utils/index.mjs";
58
58
  import { BackupCodeOptions, backupCode2fa, encodeBackupCodes, generateBackupCodes, getBackupCodes, verifyBackupCode } from "./two-factor/backup-codes/index.mjs";
59
59
  import { OTPOptions, otp2fa } from "./two-factor/otp/index.mjs";
@@ -66,4 +66,4 @@ import { USERNAME_ERROR_CODES } from "./username/error-codes.mjs";
66
66
  import { UsernameOptions, UsernamePlugin, UsernamePluginWithoutDisplayUsername, username } from "./username/index.mjs";
67
67
  import { hasPermission } from "./organization/has-permission.mjs";
68
68
  import { DefaultOrganizationPlugin, DynamicAccessControlEndpoints, OrganizationCreator, OrganizationEndpoints, OrganizationPlugin, TeamEndpoints, organization, parseRoles } from "./organization/organization.mjs";
69
- export { AccessControl, AdminOptions, AnonymousOptions, AnonymousSession, ArrayElement, Auth0Options, AuthorizeResponse, BackupCodeOptions, BaseCaptchaOptions, BaseOAuthProviderOptions, BearerOptions, CaptchaFoxOptions, CaptchaOptions, CloudflareTurnstileOptions, CustomSessionPluginOptions, DefaultOrganizationPlugin, DeviceAuthorizationGrant, DeviceAuthorizationGrantAuthorization, DeviceAuthorizationOptions, DeviceAuthorizationPluginOptions, DeviceAuthorizationRequest, DeviceCode, DeviceCodeRedemptionAuthorization, DeviceCodeRedemptionResult, DynamicAccessControlEndpoints, MULTI_SESSION_ERROR_CODES as ERROR_CODES, EmailOTPOptions, ExactRoleStatements, FieldSchema, GenericOAuthConfig, GenericOAuthOptions, GenericOAuthUserInfo, GoogleRecaptchaOptions, GumroadOptions, HCaptchaOptions, HIDE_METADATA, HaveIBeenPwnedOptions, HubSpotOptions, InferAdminRolesFromOption, InferInvitation, InferMember, InferOptionSchema, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPluginContext, InferPluginErrorCodes, InferPluginIDs, InferTeam, Invitation, InvitationInput, InvitationStatus, JWKOptions, JWSAlgorithms, Jwk, JwtOptions, KeycloakOptions, LastLoginMethodOptions, LineOptions, LoginResult, MagicLinkOptions, Member, MemberInput, MicrosoftEntraIdOptions, MultiSessionConfig, OAUTH_POPUP_COMPLETE_SCRIPT, OAUTH_POPUP_DATA_ELEMENT_ID, OAUTH_POPUP_ERROR_CODES, OAUTH_POPUP_MESSAGE_TYPE, OAUTH_POPUP_SCRIPT_CSP_HASH, OAuthPopupData, OAuthPopupMessage, OAuthProxyOptions, OTPOptions, OktaOptions, OneTapOptions, OneTimeTokenOptions, OpenAPIModelSchema, OpenAPIOptions, OpenAPIParameter, OpenAPISchema, Organization, OrganizationCreator, OrganizationEndpoints, OrganizationInput, OrganizationOptions, OrganizationPlugin, OrganizationRole, OrganizationSchema, POPUP_MARKER_COOKIE, Path, PatreonOptions, PhoneNumberOptions, Provider, ResolvedSigningKey, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, SIWEPluginOptions, SessionWithImpersonatedBy, SlackOptions, Statements, SubArray, Subset, TOTPOptions, TWO_FACTOR_ERROR_CODES, Team, TeamEndpoints, TeamInput, TeamMember, TeamMemberInput, TestCookie, TestHelpers, TestUtilsOptions, TimeString, TwoFactorOptions, TwoFactorProvider, TwoFactorTable, USERNAME_ERROR_CODES, UserWithAnonymous, UserWithPhoneNumber, UserWithRole, UserWithTwoFactor, UsernameOptions, UsernamePlugin, UsernamePluginWithoutDisplayUsername, YandexOptions, admin, anonymous, auth0, backupCode2fa, bearer, captcha, createAccessControl, createJwk, customSession, defaultRolesSchema, deviceAuthorization, deviceAuthorizationOptionsSchema, emailOTP, encodeBackupCodes, generateBackupCodes, generateExportedKeyPair, generator, genericOAuth, getBackupCodes, getJwtToken, getOrgAdapter, gumroad, hasPermission, haveIBeenPwned, hubspot, invitationSchema, invitationStatus, isPasswordCompromised, jwt, keycloak, lastLoginMethod, line, magicLink, memberSchema, microsoftEntraId, ms, multiSession, oAuthProxy, oauthPopup, okta, oneTap, oneTimeToken, openAPI, organization, organizationRoleSchema, organizationSchema, otp2fa, parseRoles, patreon, phoneNumber, redeemDeviceCode, resolveSigningKey, role, roleSchema, sec, signJWT, siwe, slack, teamMemberSchema, teamSchema, testUtils, toExpJWT, totp2fa, twoFactor, twoFactorClient, username, verifyBackupCode, verifyJWT, yandex };
69
+ export { AccessControl, AdminOptions, AnonymousOptions, AnonymousSession, ArrayElement, Auth0Options, AuthorizeResponse, BackupCodeOptions, BaseCaptchaOptions, BaseOAuthProviderOptions, BearerOptions, CaptchaFoxOptions, CaptchaOptions, CloudflareTurnstileOptions, CustomSessionPluginOptions, DefaultOrganizationPlugin, DeviceAuthorizationGrant, DeviceAuthorizationGrantAuthorization, DeviceAuthorizationOptions, DeviceAuthorizationPluginOptions, DeviceAuthorizationRequest, DeviceCode, DeviceCodeRedemptionAuthorization, DeviceCodeRedemptionResult, DynamicAccessControlEndpoints, MULTI_SESSION_ERROR_CODES as ERROR_CODES, EmailOTPOptions, ExactRoleStatements, FieldSchema, GenericOAuthConfig, GenericOAuthOptions, GenericOAuthUserInfo, GoogleRecaptchaOptions, GumroadOptions, HCaptchaOptions, HIDE_METADATA, HaveIBeenPwnedOptions, HubSpotOptions, InferAdminRolesFromOption, InferInvitation, InferMember, InferOptionSchema, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPluginContext, InferPluginErrorCodes, InferPluginIDs, InferTeam, Invitation, InvitationInput, InvitationStatus, JWKOptions, JWSAlgorithms, Jwk, JwtOptions, KeycloakOptions, LastLoginMethodOptions, LineOptions, LoginResult, MagicLinkOptions, Member, MemberInput, MicrosoftEntraIdOptions, MultiSessionConfig, OAUTH_POPUP_COMPLETE_SCRIPT, OAUTH_POPUP_DATA_ELEMENT_ID, OAUTH_POPUP_ERROR_CODES, OAUTH_POPUP_MESSAGE_TYPE, OAUTH_POPUP_SCRIPT_CSP_HASH, OAuthPopupData, OAuthPopupMessage, OAuthProxyOptions, OTPOptions, OktaOptions, OneTapOptions, OneTimeTokenOptions, OpenAPIModelSchema, OpenAPIOptions, OpenAPIParameter, OpenAPISchema, Organization, OrganizationCreator, OrganizationEndpoints, OrganizationInput, OrganizationOptions, OrganizationPlugin, OrganizationRole, OrganizationSchema, POPUP_MARKER_COOKIE, Path, PatreonOptions, PhoneNumberOptions, Provider, ResolvedSigningKey, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, SIWEPluginOptions, SessionWithImpersonatedBy, SlackOptions, Statements, SubArray, Subset, TOTPOptions, TWO_FACTOR_ERROR_CODES, Team, TeamEndpoints, TeamInput, TeamMember, TeamMemberInput, TestAuthOptions, TestCookie, TestHelpers, TestUtilsOptions, TimeString, TwoFactorOptions, TwoFactorProvider, TwoFactorTable, USERNAME_ERROR_CODES, UserWithAnonymous, UserWithPhoneNumber, UserWithRole, UserWithTwoFactor, UsernameOptions, UsernamePlugin, UsernamePluginWithoutDisplayUsername, YandexOptions, admin, anonymous, auth0, backupCode2fa, bearer, captcha, createAccessControl, createJwk, customSession, defaultRolesSchema, deviceAuthorization, deviceAuthorizationOptionsSchema, emailOTP, encodeBackupCodes, generateBackupCodes, generateExportedKeyPair, generator, genericOAuth, getBackupCodes, getJwtToken, getOrgAdapter, gumroad, hasPermission, haveIBeenPwned, hubspot, invitationSchema, invitationStatus, isPasswordCompromised, jwt, keycloak, lastLoginMethod, line, magicLink, memberSchema, microsoftEntraId, ms, multiSession, oAuthProxy, oauthPopup, okta, oneTap, oneTimeToken, openAPI, organization, organizationRoleSchema, organizationSchema, otp2fa, parseRoles, patreon, phoneNumber, redeemDeviceCode, resolveSigningKey, role, roleSchema, sec, signJWT, siwe, slack, teamMemberSchema, teamSchema, testUtils, toExpJWT, totp2fa, twoFactor, twoFactorClient, username, verifyBackupCode, verifyJWT, yandex };
@@ -1,10 +1,15 @@
1
1
  import { createCookieHeaders, createTestCookie } from "./cookie-builder.mjs";
2
+ import { sessionSchema } from "@better-auth/core/db";
2
3
  //#region src/plugins/test-utils/auth-helpers.ts
4
+ function createSession(ctx, opts) {
5
+ const additionalFields = Object.fromEntries(Object.entries(opts.session ?? {}).filter(([key]) => !Object.hasOwn(sessionSchema.shape, key)));
6
+ return ctx.internalAdapter.createSession(opts.userId, false, additionalFields, true);
7
+ }
3
8
  function createLogin(ctx) {
4
9
  return async (opts) => {
5
10
  const user = await ctx.internalAdapter.findUserById(opts.userId);
6
11
  if (!user) throw new Error(`User not found: ${opts.userId}`);
7
- const session = await ctx.internalAdapter.createSession(opts.userId);
12
+ const session = await createSession(ctx, opts);
8
13
  return {
9
14
  session,
10
15
  user,
@@ -16,12 +21,12 @@ function createLogin(ctx) {
16
21
  }
17
22
  function createGetAuthHeaders(ctx) {
18
23
  return async (opts) => {
19
- return createCookieHeaders(ctx, (await ctx.internalAdapter.createSession(opts.userId)).token);
24
+ return createCookieHeaders(ctx, (await createSession(ctx, opts)).token);
20
25
  };
21
26
  }
22
27
  function createGetCookies(ctx) {
23
28
  return async (opts) => {
24
- return createTestCookie(ctx, (await ctx.internalAdapter.createSession(opts.userId)).token, opts.domain);
29
+ return createTestCookie(ctx, (await createSession(ctx, opts)).token, opts.domain);
25
30
  };
26
31
  }
27
32
  //#endregion
@@ -1,4 +1,4 @@
1
- import { LoginResult, TestCookie, TestHelpers, TestUtilsOptions } from "./types.mjs";
1
+ import { LoginResult, TestAuthOptions, TestCookie, TestHelpers, TestUtilsOptions } from "./types.mjs";
2
2
  import * as _$_better_auth_core0 from "@better-auth/core";
3
3
 
4
4
  //#region src/plugins/test-utils/index.d.ts
@@ -21,6 +21,12 @@ interface LoginResult {
21
21
  cookies: TestCookie[];
22
22
  token: string;
23
23
  }
24
+ /** Options for creating a session with the test auth helpers. */
25
+ interface TestAuthOptions {
26
+ userId: string;
27
+ /** Additional session fields. Standard session fields are ignored. */
28
+ session?: Record<string, unknown>;
29
+ }
24
30
  interface TestHelpers {
25
31
  createUser(overrides?: Partial<User> & Record<string, unknown>): User;
26
32
  createOrganization?(overrides?: Record<string, unknown>): Record<string, unknown>;
@@ -33,18 +39,13 @@ interface TestHelpers {
33
39
  }): Promise<Record<string, unknown>>;
34
40
  deleteUser(userId: string): Promise<void>;
35
41
  deleteOrganization?(orgId: string): Promise<void>;
36
- login(opts: {
37
- userId: string;
38
- }): Promise<LoginResult>;
39
- getAuthHeaders(opts: {
40
- userId: string;
41
- }): Promise<Headers>;
42
- getCookies(opts: {
43
- userId: string;
42
+ login(opts: TestAuthOptions): Promise<LoginResult>;
43
+ getAuthHeaders(opts: TestAuthOptions): Promise<Headers>;
44
+ getCookies(opts: TestAuthOptions & {
44
45
  domain?: string;
45
46
  }): Promise<TestCookie[]>;
46
47
  getOTP?(identifier: string): string | undefined;
47
48
  clearOTPs?(): void;
48
49
  }
49
50
  //#endregion
50
- export { LoginResult, TestCookie, TestHelpers, TestUtilsOptions };
51
+ export { LoginResult, TestAuthOptions, TestCookie, TestHelpers, TestUtilsOptions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-auth",
3
- "version": "1.7.3",
3
+ "version": "1.7.4",
4
4
  "description": "The most comprehensive authentication framework for TypeScript.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -473,13 +473,13 @@
473
473
  "kysely": "^0.28.17 || ^0.29.0",
474
474
  "nanostores": "^1.3.0",
475
475
  "zod": "^4.5.4",
476
- "@better-auth/core": "1.7.3",
477
- "@better-auth/drizzle-adapter": "1.7.3",
478
- "@better-auth/kysely-adapter": "1.7.3",
479
- "@better-auth/memory-adapter": "1.7.3",
480
- "@better-auth/mongo-adapter": "1.7.3",
481
- "@better-auth/prisma-adapter": "1.7.3",
482
- "@better-auth/telemetry": "1.7.3"
476
+ "@better-auth/core": "1.7.4",
477
+ "@better-auth/drizzle-adapter": "1.7.4",
478
+ "@better-auth/kysely-adapter": "1.7.4",
479
+ "@better-auth/memory-adapter": "1.7.4",
480
+ "@better-auth/mongo-adapter": "1.7.4",
481
+ "@better-auth/prisma-adapter": "1.7.4",
482
+ "@better-auth/telemetry": "1.7.4"
483
483
  },
484
484
  "devDependencies": {
485
485
  "@lynx-js/react": "^0.121.2",
@@ -496,7 +496,7 @@
496
496
  "@types/react-dom": "^19.2.3",
497
497
  "happy-dom": "^20.8.9",
498
498
  "msw": "^2.14.6",
499
- "next": "^16.2.11",
499
+ "next": "^16.3.4",
500
500
  "oauth2-mock-server": "^9.0.0",
501
501
  "react": "^19.2.7",
502
502
  "react-dom": "^19.2.7",
@@ -504,7 +504,7 @@
504
504
  "tsdown": "0.21.10",
505
505
  "type-fest": "^5.7.0",
506
506
  "typescript": "^6.0.3",
507
- "vitest": "^4.1.10",
507
+ "vitest": "^5.0.0",
508
508
  "vue": "^3.5.29"
509
509
  },
510
510
  "peerDependencies": {
@@ -525,7 +525,7 @@
525
525
  "react-dom": "^18.0.0 || ^19.0.0",
526
526
  "solid-js": "^1.0.0",
527
527
  "svelte": "^4.0.0 || ^5.0.0",
528
- "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0",
528
+ "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0",
529
529
  "vue": "^3.0.0"
530
530
  },
531
531
  "peerDependenciesMeta": {