@nuxtjs/better-auth 0.3.6 → 0.3.7

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/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxtjs/better-auth",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "configKey": "auth",
5
5
  "compatibility": {
6
6
  "nuxt": ">=4.0.0"
package/dist/module.mjs CHANGED
@@ -13,7 +13,7 @@ import { isCI, isTest } from 'std-env';
13
13
  import { isInternalAssetPath } from '../dist/runtime/internal/auth-route-rules.js';
14
14
  export { defineClientAuth, defineServerAuth } from '../dist/runtime/config.js';
15
15
 
16
- const version = "0.3.6";
16
+ const version = "0.3.7";
17
17
 
18
18
  const CONFIG_EXTENSIONS = [".ts", ".js", ".mts", ".cts", ".mjs", ".cjs"];
19
19
  const CONFIG_EXTENSION_RE = /\.[cm]?[jt]s$/;
@@ -607,6 +607,18 @@ async function setupBetterAuthSchema(nuxt, serverConfigPath, options, consola, h
607
607
  const hubCasing = getHubCasing(hub);
608
608
  const schemaOptions = { ...options.schema, useUuid: userConfig.advanced?.database?.generateId === "uuid", casing: options.schema?.casing ?? hubCasing };
609
609
  const schemaCode = await generateDrizzleSchema(authOptions, dialect, schemaOptions);
610
+ const { getAuthTables } = await import('better-auth/db');
611
+ const { initGetModelName } = await import('better-auth/adapters');
612
+ const authTables = getAuthTables(authOptions);
613
+ const getModelName = initGetModelName({
614
+ schema: authTables,
615
+ usePlural: schemaOptions.usePlural ?? false
616
+ });
617
+ const modelNames = {};
618
+ for (const name of ["user", "session", "account", "verification"]) {
619
+ if (authTables[name])
620
+ modelNames[name] = getModelName(name);
621
+ }
610
622
  const schemaDir = join(nuxt.options.buildDir, "better-auth");
611
623
  const schemaPathTs = join(schemaDir, `schema.${dialect}.ts`);
612
624
  const schemaPathMjs = join(schemaDir, `schema.${dialect}.mjs`);
@@ -622,6 +634,7 @@ async function setupBetterAuthSchema(nuxt, serverConfigPath, options, consola, h
622
634
  addTemplate({ filename: `better-auth/schema.${dialect}.ts`, getContents: () => schemaCode, write: true });
623
635
  addTemplate({ filename: `better-auth/schema.${dialect}.mjs`, getContents: () => schemaCode, write: true });
624
636
  consola.info(`Generated ${dialect} schema (.ts + .mjs)`);
637
+ return modelNames;
625
638
  } catch (error) {
626
639
  throw error instanceof Diagnostic ? error : diagnostics.NUXT_AUTH_SCHEMA_GENERATION_FAILED({ cause: error });
627
640
  }
@@ -755,7 +768,7 @@ function setupRuntimeConfig(input) {
755
768
  if (clientOnly) {
756
769
  const siteUrl = nuxt.options.runtimeConfig.public.siteUrl;
757
770
  if (!siteUrl)
758
- consola.warn("clientOnly mode: set runtimeConfig.public.siteUrl (or NUXT_PUBLIC_SITE_URL) to your frontend URL");
771
+ consola.warn("clientOnly mode: set runtimeConfig.public.siteUrl (or NUXT_PUBLIC_SITE_URL) to your auth backend URL, or set baseURL in defineClientAuth()");
759
772
  consola.info("clientOnly mode enabled - server utilities (serverAuth, getRequestSession, getUserSession, requireUserSession) are not available");
760
773
  return { secondaryStorageEnabled };
761
774
  }
@@ -914,7 +927,7 @@ export { db }`;
914
927
  return `export function createDatabase() { return undefined }
915
928
  export const db = undefined`;
916
929
  }
917
- function buildSchemaExportCode(hasHubDb, hubDialect) {
930
+ function buildSchemaExportCode(hasHubDb, hubDialect, modelNames = {}) {
918
931
  if (!hasHubDb) {
919
932
  return `export const user = undefined
920
933
  export const session = undefined
@@ -927,14 +940,14 @@ export const schema = undefined
927
940
  import * as generatedSchema from './schema.${hubDialect}.mjs'
928
941
 
929
942
  const getGeneratedTable = name => generatedSchema[name] ?? generatedSchema[\`\${name}s\`]
930
- export const user = getGeneratedTable('user')
931
- export const session = getGeneratedTable('session')
932
- export const account = getGeneratedTable('account')
933
- export const verification = getGeneratedTable('verification')
943
+ export const user = getGeneratedTable(${JSON.stringify(modelNames.user ?? "user")})
944
+ export const session = getGeneratedTable(${JSON.stringify(modelNames.session ?? "session")})
945
+ export const account = getGeneratedTable(${JSON.stringify(modelNames.account ?? "account")})
946
+ export const verification = getGeneratedTable(${JSON.stringify(modelNames.verification ?? "verification")})
934
947
  export const schema = { ...generatedSchema, user, session, account, verification }
935
948
  `;
936
949
  }
937
- function buildSchemaExportTypes(hasHubDb, hubDialect) {
950
+ function buildSchemaExportTypes(hasHubDb, hubDialect, modelNames = {}) {
938
951
  if (!hasHubDb) {
939
952
  return `export declare const user: undefined
940
953
  export declare const session: undefined
@@ -952,10 +965,10 @@ type GeneratedTable<Name extends string> = Name extends keyof GeneratedSchema
952
965
  ? GeneratedSchema[\`\${Name}s\`]
953
966
  : undefined
954
967
 
955
- export declare const user: GeneratedTable<'user'>
956
- export declare const session: GeneratedTable<'session'>
957
- export declare const account: GeneratedTable<'account'>
958
- export declare const verification: GeneratedTable<'verification'>
968
+ export declare const user: GeneratedTable<${JSON.stringify(modelNames.user ?? "user")}>
969
+ export declare const session: GeneratedTable<${JSON.stringify(modelNames.session ?? "session")}>
970
+ export declare const account: GeneratedTable<${JSON.stringify(modelNames.account ?? "account")}>
971
+ export declare const verification: GeneratedTable<${JSON.stringify(modelNames.verification ?? "verification")}>
959
972
  export declare const schema: GeneratedSchema & {
960
973
  user: typeof user
961
974
  session: typeof session
@@ -1657,6 +1670,7 @@ const module$1 = defineNuxtModule({
1657
1670
  });
1658
1671
  let serverConfigPath = setup.aliases["#auth/server"];
1659
1672
  let clientConfigPath = setup.aliases["#auth/client"];
1673
+ let schemaModelNames;
1660
1674
  if (serverConfigPath && setup.pluginSources.server.length) {
1661
1675
  const serverConfigCode = buildExtendedServerAuthCode(setup.configs.server.path, setup.pluginSources.server);
1662
1676
  serverConfigPath = addTemplate({
@@ -1686,13 +1700,13 @@ const module$1 = defineNuxtModule({
1686
1700
  nuxt.options.alias["#auth/database"] = databaseTemplate.dst;
1687
1701
  const schemaTemplate = addTemplate({
1688
1702
  filename: "better-auth/schema.mjs",
1689
- getContents: () => buildSchemaExportCode(setup.database.hasHubDb, setup.database.buildContext?.hubDialect ?? "sqlite"),
1703
+ getContents: () => buildSchemaExportCode(setup.database.hasHubDb, setup.database.buildContext?.hubDialect ?? "sqlite", schemaModelNames),
1690
1704
  write: true
1691
1705
  });
1692
1706
  nuxt.options.alias["#auth/schema"] = schemaTemplate.dst;
1693
1707
  addTemplate({
1694
1708
  filename: "better-auth/schema.d.ts",
1695
- getContents: () => buildSchemaExportTypes(setup.database.hasHubDb, setup.database.buildContext?.hubDialect ?? "sqlite"),
1709
+ getContents: () => buildSchemaExportTypes(setup.database.hasHubDb, setup.database.buildContext?.hubDialect ?? "sqlite", schemaModelNames),
1696
1710
  write: true
1697
1711
  });
1698
1712
  if (setup.schemaGeneration)
@@ -1733,7 +1747,7 @@ const module$1 = defineNuxtModule({
1733
1747
  if (setup.schemaGeneration) {
1734
1748
  if (setup.schemaGeneration.externalizeNuxtHubDatabase)
1735
1749
  registerNuxtHubDatabaseExternalHook(nuxt);
1736
- await setupBetterAuthSchema(
1750
+ schemaModelNames = await setupBetterAuthSchema(
1737
1751
  nuxt,
1738
1752
  serverConfigPath,
1739
1753
  options,
@@ -11,14 +11,30 @@ export function useAuthRequestFetch() {
11
11
  const clientOptions = createAppAuthClient.resolveOptions(siteUrl);
12
12
  const configuredBaseURL = clientOptions.baseURL ?? siteUrl;
13
13
  const baseURL = configuredBaseURL && new URL(configuredBaseURL).pathname.replace(/\/+$/, "") ? configuredBaseURL : joinURL(configuredBaseURL || "/", clientOptions.basePath ?? "/api/auth");
14
- const externalRequestFetch = requestFetch;
15
- return ((request, opts) => {
16
- if (typeof request !== "string" || !/^\/api\/auth(?=\/|$)/.test(request))
17
- return externalRequestFetch(request, opts);
18
- return externalRequestFetch(request.slice("/api/auth".length), {
19
- ...opts,
20
- baseURL,
21
- credentials: "include"
14
+ function wrapRequestFetch(fetch) {
15
+ const methods = /* @__PURE__ */ new Map();
16
+ return new Proxy(fetch, {
17
+ apply(target, thisArg, args) {
18
+ const [request, opts] = args;
19
+ if (typeof request !== "string" || !/^\/api\/auth(?=\/|$)/.test(request))
20
+ return Reflect.apply(target, thisArg, args);
21
+ return Reflect.apply(target, thisArg, [request.slice("/api/auth".length), {
22
+ ...opts,
23
+ baseURL,
24
+ credentials: "include"
25
+ }]);
26
+ },
27
+ get(target, prop, receiver) {
28
+ if (methods.has(prop))
29
+ return methods.get(prop);
30
+ const value = Reflect.get(target, prop, receiver);
31
+ if (typeof value !== "function" || prop !== "raw" && prop !== "create")
32
+ return value;
33
+ const method = prop === "raw" ? wrapRequestFetch(value) : (...args) => wrapRequestFetch(Reflect.apply(value, target, args));
34
+ methods.set(prop, method);
35
+ return method;
36
+ }
22
37
  });
23
- });
38
+ }
39
+ return wrapRequestFetch(requestFetch);
24
40
  }
@@ -74,6 +74,7 @@ export function useUserSession() {
74
74
  return;
75
75
  const previousUser = user.value;
76
76
  user.value = { ...user.value, ...updates };
77
+ const optimisticUser = user.value;
77
78
  if (!rawClient)
78
79
  return;
79
80
  try {
@@ -86,7 +87,8 @@ export function useUserSession() {
86
87
  throw new Error(normalizedError.message);
87
88
  }
88
89
  } catch (error) {
89
- user.value = previousUser;
90
+ if (user.value === optimisticUser)
91
+ user.value = previousUser;
90
92
  if (!(error instanceof Error)) {
91
93
  const normalizedError = normalizeAuthActionError(error);
92
94
  throw new Error(normalizedError.message);
@@ -1,5 +1,6 @@
1
1
  import { defu } from "defu";
2
2
  import { createRouter, toRouteMatcher } from "radix3";
3
+ import { parsePath, parseQuery } from "ufo";
3
4
  import { createError, defineNuxtRouteMiddleware, getRouteRules, navigateTo, useNuxtApp, useRequestHeaders, useRuntimeConfig } from "#imports";
4
5
  import { shouldSkipAuthRouteRules } from "../../internal/auth-route-rules.js";
5
6
  import { matchesUser } from "../../utils/match-user.js";
@@ -64,11 +65,11 @@ function resolveLoginRedirect(input) {
64
65
  return { to: loginTarget, external: false };
65
66
  if (!loginTarget.startsWith("/") || loginTarget.startsWith("//"))
66
67
  return { to: loginTarget, external: false };
67
- const [beforeHash, hash = ""] = loginTarget.split("#", 2);
68
- const [path, query = ""] = beforeHash.split("?", 2);
68
+ const { pathname: path, search, hash } = parsePath(loginTarget);
69
+ const query = search.slice(1);
69
70
  try {
70
- const params2 = new URLSearchParams(query);
71
- if (params2.has(redirectQueryKey))
71
+ const params = new URLSearchParams(query);
72
+ if (params.has(redirectQueryKey))
72
73
  return { to: loginTarget, external: false };
73
74
  } catch {
74
75
  return { to: loginTarget, external: false };
@@ -76,15 +77,13 @@ function resolveLoginRedirect(input) {
76
77
  if (import.meta.server) {
77
78
  const separator = query ? "&" : "";
78
79
  const encodedRedirect = encodeURIComponent(route.fullPath);
79
- const url = `${path}?${query}${separator}${redirectQueryKey}=${encodedRedirect}${hash ? `#${hash}` : ""}`;
80
+ const encodedKey = encodeURIComponent(redirectQueryKey);
81
+ const url = `${path}?${query}${separator}${encodedKey}=${encodedRedirect}${hash}`;
80
82
  return { to: url, external: true };
81
83
  }
82
- const params = new URLSearchParams(query);
83
- const queryObj = {};
84
- for (const [k, v] of params.entries())
85
- queryObj[k] = v;
84
+ const queryObj = parseQuery(query);
86
85
  queryObj[redirectQueryKey] = route.fullPath;
87
- return { to: { path, query: queryObj, ...hash ? { hash: `#${hash}` } : {} }, external: false };
86
+ return { to: { path, query: queryObj, ...hash ? { hash } : {} }, external: false };
88
87
  }
89
88
  async function getAuthRouteRules() {
90
89
  if (!authRouteRulesPromise) {
@@ -21,7 +21,14 @@ export default defineEventHandler(async (event) => {
21
21
  dbQuery.orderBy(desc(schema.account.createdAt)).limit(limit).offset(offset),
22
22
  countQuery
23
23
  ]);
24
- return { accounts, total: totalResult[0]?.count ?? 0, page, limit };
24
+ const safeAccounts = accounts.map((account) => ({
25
+ id: account.id,
26
+ userId: account.userId,
27
+ providerId: account.providerId,
28
+ accountId: account.accountId,
29
+ createdAt: account.createdAt
30
+ }));
31
+ return { accounts: safeAccounts, total: totalResult[0]?.count ?? 0, page, limit };
25
32
  } catch (error) {
26
33
  console.error("[DevTools] Fetch accounts failed:", error);
27
34
  return { accounts: [], total: 0, error: "Failed to fetch accounts" };
@@ -1,3 +1,4 @@
1
1
  import type { ServerEvent } from './nitro-compat.js';
2
2
  export declare function appendCookieHeader(event: ServerEvent, header: string): void;
3
+ export declare function getSetCookieHeaders(headers: Headers): string[];
3
4
  export declare function appendSetCookieHeaders(event: ServerEvent, headers: Headers): void;
@@ -14,7 +14,7 @@ export function appendCookieHeader(event, header) {
14
14
  const responseHeaders = eventWithResponse.res?.headers ?? eventWithResponse.response?.headers;
15
15
  responseHeaders?.append("set-cookie", header);
16
16
  }
17
- function getSetCookieHeaders(headers) {
17
+ export function getSetCookieHeaders(headers) {
18
18
  const cookieHeaders = headers;
19
19
  const getSetCookie = cookieHeaders.getSetCookie;
20
20
  if (getSetCookie)
@@ -1,5 +1,4 @@
1
1
  import { betterAuth, env } from "better-auth";
2
- import { withoutProtocol } from "ufo";
3
2
  import { createDatabase, db } from "#auth/database";
4
3
  import createServerAuth from "#auth/server";
5
4
  import { getRequestHost, getRequestProtocol, useRuntimeConfig } from "../internal/nitro-compat.js";
@@ -83,33 +82,25 @@ function getNitroOrigin() {
83
82
  let port;
84
83
  if (import.meta.dev)
85
84
  port = process.env.NITRO_PORT || process.env.PORT || "3000";
86
- let protocol = cert && key || !import.meta.dev ? "https" : "http";
85
+ const protocol = cert && key || !import.meta.dev ? "https" : "http";
87
86
  try {
88
87
  if ((import.meta.dev || import.meta.prerender) && process.env.__NUXT_DEV__) {
89
- const origin = JSON.parse(process.env.__NUXT_DEV__).proxy.url;
90
- host = withoutProtocol(origin);
91
- protocol = origin.includes("https") ? "https" : "http";
88
+ const url = new URL(JSON.parse(process.env.__NUXT_DEV__).proxy.url);
89
+ if (url.protocol === "http:" || url.protocol === "https:")
90
+ return url.origin;
92
91
  } else if ((import.meta.dev || import.meta.prerender) && process.env.NUXT_VITE_NODE_OPTIONS) {
93
- const origin = JSON.parse(process.env.NUXT_VITE_NODE_OPTIONS).baseURL.replace("/__nuxt_vite_node__", "");
94
- host = withoutProtocol(origin);
95
- protocol = origin.includes("https") ? "https" : "http";
92
+ const url = new URL(JSON.parse(process.env.NUXT_VITE_NODE_OPTIONS).baseURL);
93
+ if (url.protocol === "http:" || url.protocol === "https:")
94
+ return url.origin;
96
95
  }
97
96
  } catch {
98
97
  }
99
98
  if (!host)
100
99
  return void 0;
101
- if (host.startsWith("[") && host.includes("]:")) {
102
- const lastBracketColon = host.lastIndexOf("]:");
103
- const extractedPort = host.slice(lastBracketColon + 2);
104
- host = host.slice(0, lastBracketColon + 1);
105
- if (extractedPort)
106
- port = extractedPort;
107
- } else if (host.includes(":") && !host.startsWith("[")) {
108
- const hostParts = host.split(":");
109
- port = hostParts.pop();
110
- host = hostParts.join(":");
111
- }
112
- const portSuffix = port ? `:${port}` : "";
100
+ if (!host.startsWith("[") && host.indexOf(":") !== host.lastIndexOf(":"))
101
+ host = `[${host}]`;
102
+ const hasExplicitPort = host.startsWith("[") ? host.includes("]:") : host.includes(":");
103
+ const portSuffix = !hasExplicitPort && port ? `:${port}` : "";
113
104
  return `${protocol}://${host}${portSuffix}`;
114
105
  }
115
106
  function resolveEnvironmentOrigin() {
@@ -162,8 +153,7 @@ function getDevTrustedOrigins() {
162
153
  try {
163
154
  const url = new URL(nitroOrigin);
164
155
  const protocol = url.protocol === "https:" ? "https" : "http";
165
- const port = url.port || "3000";
166
- const localhostOrigin = `${protocol}://localhost:${port}`;
156
+ const localhostOrigin = `${protocol}://localhost${url.port ? `:${url.port}` : ""}`;
167
157
  return dedupeOrigins([localhostOrigin, url.origin]);
168
158
  } catch {
169
159
  return [fallbackOrigin];
@@ -1,6 +1,6 @@
1
1
  import { matchesUser } from "../../utils/match-user.js";
2
2
  import { createAuthError } from "../internal/nitro-compat.js";
3
- import { appendCookieHeader, appendSetCookieHeaders } from "../internal/cookie-headers.js";
3
+ import { appendCookieHeader, appendSetCookieHeaders, getSetCookieHeaders } from "../internal/cookie-headers.js";
4
4
  import { serverAuth } from "./auth.js";
5
5
  const requestSessionLoadKey = Symbol.for("nuxt-better-auth.requestSessionLoad");
6
6
  const requestSessionMutationKey = Symbol.for("nuxt-better-auth.requestSessionMutation");
@@ -162,6 +162,30 @@ function expireCookies(event, cookie) {
162
162
  for (const cookieName of getChunkedCookieNames(event, cookie.name))
163
163
  expireCookie(event, cookieName, cookie.attributes);
164
164
  }
165
+ function isCookieOrChunk(name, cookieName) {
166
+ if (name === cookieName)
167
+ return true;
168
+ if (!name.startsWith(`${cookieName}.`))
169
+ return false;
170
+ const suffix = name.slice(cookieName.length + 1);
171
+ const index = Number(suffix);
172
+ return Number.isSafeInteger(index) && index >= 0 && String(index) === suffix;
173
+ }
174
+ function expireUnrefreshedSessionCookieCache(event, headers, cookie) {
175
+ const cookieName = getCookieName(cookie.name, cookie.attributes.prefix);
176
+ if (!cookieName)
177
+ return;
178
+ const responseHandlesCache = getSetCookieHeaders(headers).some((header) => {
179
+ const name = header.slice(0, header.indexOf("="));
180
+ return isCookieOrChunk(name, cookieName);
181
+ });
182
+ if (responseHandlesCache)
183
+ return;
184
+ for (const name of parseRequestCookies(getRequestHeaders(event).get("cookie")).keys()) {
185
+ if (isCookieOrChunk(name, cookieName))
186
+ expireCookie(event, name, cookie.attributes);
187
+ }
188
+ }
165
189
  function updateRequestHeaders(event, sessionCookie, clearedCookieNames) {
166
190
  const requestContext = getRequestSessionContext(event);
167
191
  const incomingHeaders = getIncomingRequestHeaders(event);
@@ -227,10 +251,14 @@ export async function refreshSessionCookieCache(event) {
227
251
  if (context[requestSessionLoadKey] !== load)
228
252
  return context.requestSession ?? null;
229
253
  delete context.requestSession;
230
- const { headers, response } = await loadFreshSession(event);
254
+ const [{ headers, response }, authContext] = await Promise.all([
255
+ loadFreshSession(event),
256
+ getServerAuthContext(event)
257
+ ]);
231
258
  if (context[requestSessionLoadKey] !== load)
232
259
  return context.requestSession ?? null;
233
260
  appendSetCookieHeaders(event, headers);
261
+ expireUnrefreshedSessionCookieCache(event, headers, authContext.authCookies.sessionData);
234
262
  context.requestSession = response;
235
263
  return response;
236
264
  });
@@ -1,9 +1,10 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { fileURLToPath } from "node:url";
3
- import { url } from "@nuxt/test-utils/e2e";
3
+ import { url, useTestContext } from "@nuxt/test-utils/e2e";
4
4
  import { parseJSON } from "better-auth/client";
5
5
  import { getRandomPort } from "get-port-please";
6
6
  import { defu } from "defu";
7
+ import { joinURL } from "ufo";
7
8
  export async function createAuthTestContext(options = {}) {
8
9
  if (options.host || options.dev || options.build === false || options.server === false)
9
10
  throw new Error("[nuxt-better-auth] Auth E2E helpers require a local test build. Use setup() with build and server enabled, without dev or host.");
@@ -22,7 +23,8 @@ export async function createAuthTestContext(options = {}) {
22
23
  }
23
24
  }, options);
24
25
  async function call(action, data = {}) {
25
- const response = await fetch(url(endpoint), {
26
+ const baseURL = useTestContext().nuxt?.options.app.baseURL ?? "/";
27
+ const response = await fetch(url(joinURL(baseURL, endpoint)), {
26
28
  method: "POST",
27
29
  headers: { "content-type": "application/json", "x-nuxt-auth-test": token },
28
30
  body: JSON.stringify({ action, data })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nuxtjs/better-auth",
3
3
  "type": "module",
4
- "version": "0.3.6",
4
+ "version": "0.3.7",
5
5
  "description": "Nuxt module for Better Auth integration with NuxtHub, route protection, session management, and role-based access",
6
6
  "author": "onmax",
7
7
  "license": "MIT",
@@ -75,7 +75,7 @@
75
75
  "@nuxt/devtools-kit": "^3.4.1",
76
76
  "@nuxt/kit": "^4.5.2",
77
77
  "@types/node": "^24.13.3",
78
- "auth": "1.7.3",
78
+ "auth": "1.7.7",
79
79
  "consola": "^3.4.2",
80
80
  "cookie-es": "^3.1.1",
81
81
  "defu": "^6.1.7",
@@ -102,7 +102,7 @@
102
102
  "@pinia/nuxt": "^1.0.2",
103
103
  "@types/better-sqlite3": "^9.6.0",
104
104
  "@vue/test-utils": "^2.4.6",
105
- "better-auth": "1.7.3",
105
+ "better-auth": "1.7.7",
106
106
  "better-call": "1.4.0",
107
107
  "better-sqlite3": "^12.11.1",
108
108
  "drizzle-kit": "^0.31.10",