From c2e43a67769ab215c2ceb2c749377b0cd66e79b5 Mon Sep 17 00:00:00 2001 From: onmax Date: Tue, 24 Mar 2026 21:00:10 +0100 Subject: [PATCH 1/5] fix(auth): rebuild nuxthub postgres adapters per request --- src/module/templates.ts | 26 +++++++ src/runtime/server/utils/auth.ts | 16 ++-- ...xthub-hyperdrive-database-template.test.ts | 34 ++++++++ test/server-auth-database-cache.test.ts | 77 +++++++++++++++++++ 4 files changed, 147 insertions(+), 6 deletions(-) create mode 100644 test/nuxthub-hyperdrive-database-template.test.ts create mode 100644 test/server-auth-database-cache.test.ts diff --git a/src/module/templates.ts b/src/module/templates.ts index 4b68fbea..bba471a1 100644 --- a/src/module/templates.ts +++ b/src/module/templates.ts @@ -23,6 +23,32 @@ interface BuildDatabaseCodeInput { export function buildDatabaseCode(input: BuildDatabaseCodeInput): string { if (input.provider === 'nuxthub') { + if (input.hubDialect === 'postgresql') { + return `import { db } from '@nuxthub/db' +import * as schema from './schema.${input.hubDialect}.mjs' +import { drizzleAdapter } from 'better-auth/adapters/drizzle' +import { drizzle } from 'drizzle-orm/postgres-js' +import postgres from 'postgres' + +const dialect = 'pg' + +function resolveBetterAuthDb() { + const hyperdrive = process.env.POSTGRES || globalThis.__env__?.POSTGRES || globalThis.POSTGRES + if (!hyperdrive?.connectionString) + return db + + const client = postgres(hyperdrive.connectionString, { + prepare: false, + onnotice: () => {}, + }) + + return drizzle({ client, schema }) +} + +export function createDatabase() { return drizzleAdapter(resolveBetterAuthDb(), { provider: dialect, schema, usePlural: ${input.usePlural}, camelCase: ${input.camelCase} }) } +export { db }` + } + return `import { db } from '@nuxthub/db' import * as schema from './schema.${input.hubDialect}.mjs' import { drizzleAdapter } from 'better-auth/adapters/drizzle' diff --git a/src/runtime/server/utils/auth.ts b/src/runtime/server/utils/auth.ts index e98c29e5..4e05faf8 100644 --- a/src/runtime/server/utils/auth.ts +++ b/src/runtime/server/utils/auth.ts @@ -251,12 +251,8 @@ export function serverAuth(event?: H3Event): AuthInstance { const siteUrl = getBaseURL(event) const hasExplicitSiteUrl = runtimeConfig.public.siteUrl && typeof runtimeConfig.public.siteUrl === 'string' const cacheKey = hasExplicitSiteUrl ? '__explicit__' : siteUrl - - const cached = _authCache.get(cacheKey) - if (cached) - return cached - const database = createDatabase() + const userConfig = createServerAuth({ runtimeConfig, db }) as BetterAuthOptions & { secondaryStorage?: BetterAuthOptions['secondaryStorage'] } @@ -271,6 +267,12 @@ export function serverAuth(event?: H3Event): AuthInstance { console.warn(customSecondaryStorage.message) } + if (!database) { + const cached = _authCache.get(cacheKey) + if (cached) + return cached + } + const auth = betterAuth({ ...userConfig, ...(database && { database }), @@ -280,6 +282,8 @@ export function serverAuth(event?: H3Event): AuthInstance { trustedOrigins, }) - _authCache.set(cacheKey, auth) + if (!database) + _authCache.set(cacheKey, auth) + return auth } diff --git a/test/nuxthub-hyperdrive-database-template.test.ts b/test/nuxthub-hyperdrive-database-template.test.ts new file mode 100644 index 00000000..410b6f69 --- /dev/null +++ b/test/nuxthub-hyperdrive-database-template.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from 'vitest' +import { buildDatabaseCode } from '../src/module/templates' + +describe('buildDatabaseCode', () => { + it('uses a dedicated postgres-js client with prepare disabled for nuxthub postgresql', () => { + const code = buildDatabaseCode({ + provider: 'nuxthub', + hubDialect: 'postgresql', + usePlural: false, + camelCase: true, + }) + + expect(code).toContain('import postgres from \'postgres\'') + expect(code).toContain('hyperdrive.connectionString') + expect(code).toContain('prepare: false') + expect(code).toContain('return db') + expect(code).toContain('drizzleAdapter(resolveBetterAuthDb()') + expect(code).not.toContain('_betterAuthDb') + }) + + it('keeps the existing generated adapter path for non-postgresql nuxthub databases', () => { + const code = buildDatabaseCode({ + provider: 'nuxthub', + hubDialect: 'sqlite', + usePlural: false, + camelCase: true, + }) + + expect(code).toContain('import { db } from \'@nuxthub/db\'') + expect(code).toContain('drizzleAdapter(db, { provider: dialect') + expect(code).not.toContain('import postgres from \'postgres\'') + expect(code).not.toContain('prepare: false') + }) +}) diff --git a/test/server-auth-database-cache.test.ts b/test/server-auth-database-cache.test.ts new file mode 100644 index 00000000..8f4f91c2 --- /dev/null +++ b/test/server-auth-database-cache.test.ts @@ -0,0 +1,77 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' + +const betterAuthMock = vi.fn() +const createDatabaseMock = vi.fn() +const createServerAuthMock = vi.fn() +const useRuntimeConfigMock = vi.fn() + +vi.mock('#auth/database', () => ({ + createDatabase: createDatabaseMock, + db: { query: {} }, +})) + +vi.mock('#auth/secondary-storage', () => ({ + createSecondaryStorage: vi.fn(() => undefined), +})) + +vi.mock('#auth/server', () => ({ + default: createServerAuthMock, +})) + +vi.mock('better-auth', () => ({ + betterAuth: betterAuthMock, +})) + +vi.mock('nitropack/runtime', () => ({ + useRuntimeConfig: useRuntimeConfigMock, +})) + +describe('serverAuth database cache behavior', () => { + beforeEach(() => { + vi.resetModules() + vi.clearAllMocks() + + useRuntimeConfigMock.mockReturnValue({ + public: { + siteUrl: 'https://example.com', + }, + auth: {}, + betterAuthSecret: 'test-secret', + }) + + createServerAuthMock.mockReturnValue({ + trustedOrigins: undefined, + }) + + betterAuthMock.mockImplementation((options: Record) => ({ + options, + marker: Symbol('auth-instance'), + })) + }) + + it('creates a fresh auth instance on each call when a database adapter is active', async () => { + createDatabaseMock.mockReturnValue({ kind: 'database-adapter' }) + + const { serverAuth } = await import('../src/runtime/server/utils/auth') + + const first = serverAuth() + const second = serverAuth() + + expect(first).not.toBe(second) + expect(createDatabaseMock).toHaveBeenCalledTimes(2) + expect(betterAuthMock).toHaveBeenCalledTimes(2) + }) + + it('keeps caching auth instances when no database adapter is configured', async () => { + createDatabaseMock.mockReturnValue(undefined) + + const { serverAuth } = await import('../src/runtime/server/utils/auth') + + const first = serverAuth() + const second = serverAuth() + + expect(first).toBe(second) + expect(createDatabaseMock).toHaveBeenCalledTimes(2) + expect(betterAuthMock).toHaveBeenCalledTimes(1) + }) +}) From 44c751c96f9f8f496f07274e39e42f5e13e18936 Mon Sep 17 00:00:00 2001 From: onmax Date: Thu, 26 Mar 2026 08:00:46 +0100 Subject: [PATCH 2/5] fix(auth): scope hyperdrive adapters to the request --- src/module/templates.ts | 64 +++++++++++++++++-- src/module/type-templates.ts | 2 +- src/runtime/server/utils/auth.ts | 36 +++++++++-- ...xthub-hyperdrive-database-template.test.ts | 16 +++-- test/server-auth-database-cache.test.ts | 40 +++++++++++- 5 files changed, 140 insertions(+), 18 deletions(-) diff --git a/src/module/templates.ts b/src/module/templates.ts index bba471a1..1ec87a9c 100644 --- a/src/module/templates.ts +++ b/src/module/templates.ts @@ -28,24 +28,78 @@ export function buildDatabaseCode(input: BuildDatabaseCodeInput): string { import * as schema from './schema.${input.hubDialect}.mjs' import { drizzleAdapter } from 'better-auth/adapters/drizzle' import { drizzle } from 'drizzle-orm/postgres-js' +import { useNitroApp } from 'nitropack/runtime' import postgres from 'postgres' const dialect = 'pg' +const requestDatabaseKey = Symbol.for('nuxt-better-auth.requestDatabase') +const fallbackRequestDatabaseContext = new WeakMap() -function resolveBetterAuthDb() { +function getRequestDatabaseContext(event) { + const eventWithContext = event + if (eventWithContext?.context && typeof eventWithContext.context === 'object') + return eventWithContext.context + + let context = fallbackRequestDatabaseContext.get(event) + if (!context) { + context = {} + fallbackRequestDatabaseContext.set(event, context) + } + return context +} + +function createHyperdriveAdapter(client) { + return drizzleAdapter(drizzle({ client, schema }), { provider: dialect, schema, usePlural: ${input.usePlural}, camelCase: ${input.camelCase} }) +} + +function registerClientCleanup(event, client) { + const nitroApp = useNitroApp() + let unregister + unregister = nitroApp.hooks.hook('afterResponse', (responseEvent) => { + if (responseEvent !== event) + return + + unregister?.() + + const close = client.end({ timeout: 0 }).catch(() => {}) + if (responseEvent.waitUntil) + responseEvent.waitUntil(close) + else + void close + }) +} + +export function createDatabase(event) { const hyperdrive = process.env.POSTGRES || globalThis.__env__?.POSTGRES || globalThis.POSTGRES if (!hyperdrive?.connectionString) - return db + return drizzleAdapter(db, { provider: dialect, schema, usePlural: ${input.usePlural}, camelCase: ${input.camelCase} }) + + if (event) { + const context = getRequestDatabaseContext(event) + const cached = context[requestDatabaseKey] + if (cached) + return cached + + const client = postgres(hyperdrive.connectionString, { + prepare: false, + onnotice: () => {}, + max: 1, + }) + const database = createHyperdriveAdapter(client) + + context[requestDatabaseKey] = database + registerClientCleanup(event, client) + return database + } const client = postgres(hyperdrive.connectionString, { prepare: false, onnotice: () => {}, + max: 1, }) - return drizzle({ client, schema }) + return createHyperdriveAdapter(client) } - -export function createDatabase() { return drizzleAdapter(resolveBetterAuthDb(), { provider: dialect, schema, usePlural: ${input.usePlural}, camelCase: ${input.camelCase} }) } export { db }` } diff --git a/src/module/type-templates.ts b/src/module/type-templates.ts index 8baa84ec..57cfacee 100644 --- a/src/module/type-templates.ts +++ b/src/module/type-templates.ts @@ -28,7 +28,7 @@ declare module '#auth/secondary-storage' { getContents: () => ` declare module '#auth/database' { import type { BetterAuthOptions } from 'better-auth' - export function createDatabase(): BetterAuthOptions['database'] + export function createDatabase(event?: import('h3').H3Event): BetterAuthOptions['database'] export const db: ${hasHubDb ? `typeof import('@nuxthub/db')['db']` : 'undefined'} } `, diff --git a/src/runtime/server/utils/auth.ts b/src/runtime/server/utils/auth.ts index 4e05faf8..4f42a712 100644 --- a/src/runtime/server/utils/auth.ts +++ b/src/runtime/server/utils/auth.ts @@ -1,8 +1,6 @@ import type { BetterAuthOptions } from 'better-auth' import type { H3Event } from 'h3' -// @ts-expect-error Nuxt generates this virtual module in app builds. import { createDatabase, db } from '#auth/database' -// @ts-expect-error Nuxt generates this virtual module in app builds. import { createSecondaryStorage } from '#auth/secondary-storage' import createServerAuth from '#auth/server' import { betterAuth } from 'better-auth' @@ -15,9 +13,29 @@ type AuthOptions = ReturnType type AuthInstance = ReturnType> const _authCache = new Map() +const requestAuthKey = Symbol.for('nuxt-better-auth.requestAuth') let _baseURLInferenceLogged = false let _customSecondaryStorageMisconfigWarned = false +interface RequestAuthContext { + [requestAuthKey]?: AuthInstance +} + +const fallbackRequestAuthContext = new WeakMap() + +function getRequestAuthContext(event: H3Event): RequestAuthContext { + const eventWithContext = event as H3Event & { context?: unknown } + if (eventWithContext.context && typeof eventWithContext.context === 'object') + return eventWithContext.context as RequestAuthContext + + let context = fallbackRequestAuthContext.get(event as object) + if (!context) { + context = {} + fallbackRequestAuthContext.set(event as object, context) + } + return context +} + function normalizeLoopbackOrigin(origin: string): string { if (!import.meta.dev) return origin @@ -251,8 +269,12 @@ export function serverAuth(event?: H3Event): AuthInstance { const siteUrl = getBaseURL(event) const hasExplicitSiteUrl = runtimeConfig.public.siteUrl && typeof runtimeConfig.public.siteUrl === 'string' const cacheKey = hasExplicitSiteUrl ? '__explicit__' : siteUrl - const database = createDatabase() + const requestContext = event ? getRequestAuthContext(event) : undefined + + if (requestContext?.[requestAuthKey]) + return requestContext[requestAuthKey] + const database = createDatabase(event) const userConfig = createServerAuth({ runtimeConfig, db }) as BetterAuthOptions & { secondaryStorage?: BetterAuthOptions['secondaryStorage'] } @@ -269,8 +291,11 @@ export function serverAuth(event?: H3Event): AuthInstance { if (!database) { const cached = _authCache.get(cacheKey) - if (cached) + if (cached) { + if (requestContext) + requestContext[requestAuthKey] = cached return cached + } } const auth = betterAuth({ @@ -282,6 +307,9 @@ export function serverAuth(event?: H3Event): AuthInstance { trustedOrigins, }) + if (requestContext) + requestContext[requestAuthKey] = auth + if (!database) _authCache.set(cacheKey, auth) diff --git a/test/nuxthub-hyperdrive-database-template.test.ts b/test/nuxthub-hyperdrive-database-template.test.ts index 410b6f69..7fad84cf 100644 --- a/test/nuxthub-hyperdrive-database-template.test.ts +++ b/test/nuxthub-hyperdrive-database-template.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest' import { buildDatabaseCode } from '../src/module/templates' describe('buildDatabaseCode', () => { - it('uses a dedicated postgres-js client with prepare disabled for nuxthub postgresql', () => { + it('uses request-scoped hyperdrive clients with cleanup for nuxthub postgresql', () => { const code = buildDatabaseCode({ provider: 'nuxthub', hubDialect: 'postgresql', @@ -10,12 +10,14 @@ describe('buildDatabaseCode', () => { camelCase: true, }) - expect(code).toContain('import postgres from \'postgres\'') - expect(code).toContain('hyperdrive.connectionString') + expect(code).toContain('import { useNitroApp } from \'nitropack/runtime\'') + expect(code).toContain('const requestDatabaseKey = Symbol.for(\'nuxt-better-auth.requestDatabase\')') + expect(code).toContain('hook(\'afterResponse\'') + expect(code).toContain('client.end({ timeout: 0 })') expect(code).toContain('prepare: false') - expect(code).toContain('return db') - expect(code).toContain('drizzleAdapter(resolveBetterAuthDb()') - expect(code).not.toContain('_betterAuthDb') + expect(code).toContain('max: 1') + expect(code).toContain('export function createDatabase(event)') + expect(code).not.toContain('function resolveBetterAuthDb()') }) it('keeps the existing generated adapter path for non-postgresql nuxthub databases', () => { @@ -29,6 +31,6 @@ describe('buildDatabaseCode', () => { expect(code).toContain('import { db } from \'@nuxthub/db\'') expect(code).toContain('drizzleAdapter(db, { provider: dialect') expect(code).not.toContain('import postgres from \'postgres\'') - expect(code).not.toContain('prepare: false') + expect(code).not.toContain('hook(\'afterResponse\'') }) }) diff --git a/test/server-auth-database-cache.test.ts b/test/server-auth-database-cache.test.ts index 8f4f91c2..3894502f 100644 --- a/test/server-auth-database-cache.test.ts +++ b/test/server-auth-database-cache.test.ts @@ -1,3 +1,4 @@ +import type { H3Event } from 'h3' import { beforeEach, describe, expect, it, vi } from 'vitest' const betterAuthMock = vi.fn() @@ -26,6 +27,16 @@ vi.mock('nitropack/runtime', () => ({ useRuntimeConfig: useRuntimeConfigMock, })) +type MockEvent = H3Event & { + context: Record +} + +function createEvent(): MockEvent { + return { + context: {}, + } as MockEvent +} + describe('serverAuth database cache behavior', () => { beforeEach(() => { vi.resetModules() @@ -49,7 +60,34 @@ describe('serverAuth database cache behavior', () => { })) }) - it('creates a fresh auth instance on each call when a database adapter is active', async () => { + it('reuses the same auth instance within a request when a database adapter is active', async () => { + createDatabaseMock.mockReturnValue({ kind: 'database-adapter' }) + + const { serverAuth } = await import('../src/runtime/server/utils/auth') + const event = createEvent() + + const first = serverAuth(event) + const second = serverAuth(event) + + expect(first).toBe(second) + expect(createDatabaseMock).toHaveBeenCalledTimes(1) + expect(betterAuthMock).toHaveBeenCalledTimes(1) + }) + + it('creates a fresh auth instance for each request when a database adapter is active', async () => { + createDatabaseMock.mockReturnValue({ kind: 'database-adapter' }) + + const { serverAuth } = await import('../src/runtime/server/utils/auth') + + const first = serverAuth(createEvent()) + const second = serverAuth(createEvent()) + + expect(first).not.toBe(second) + expect(createDatabaseMock).toHaveBeenCalledTimes(2) + expect(betterAuthMock).toHaveBeenCalledTimes(2) + }) + + it('creates a fresh auth instance without request context when a database adapter is active', async () => { createDatabaseMock.mockReturnValue({ kind: 'database-adapter' }) const { serverAuth } = await import('../src/runtime/server/utils/auth') From e368bdc37b616642a63cea7cc84be5749f2b3551 Mon Sep 17 00:00:00 2001 From: onmax Date: Thu, 26 Mar 2026 10:11:38 +0100 Subject: [PATCH 3/5] fix(ci): restore plugin inference fixture --- src/runtime/server/utils/auth.ts | 27 +++++++++++++------ .../tsconfig.type-check.json | 1 + .../virtual-modules.d.ts | 8 ++++++ 3 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 test/cases/plugins-type-inference/virtual-modules.d.ts diff --git a/src/runtime/server/utils/auth.ts b/src/runtime/server/utils/auth.ts index 4f42a712..86b3dfaa 100644 --- a/src/runtime/server/utils/auth.ts +++ b/src/runtime/server/utils/auth.ts @@ -1,6 +1,8 @@ import type { BetterAuthOptions } from 'better-auth' import type { H3Event } from 'h3' +// @ts-ignore Nuxt generates this virtual module in app builds. import { createDatabase, db } from '#auth/database' +// @ts-ignore Nuxt generates this virtual module in app builds. import { createSecondaryStorage } from '#auth/secondary-storage' import createServerAuth from '#auth/server' import { betterAuth } from 'better-auth' @@ -10,7 +12,17 @@ import { withoutProtocol } from 'ufo' import { resolveCustomSecondaryStorageRequirement } from './custom-secondary-storage' type AuthOptions = ReturnType -type AuthInstance = ReturnType> +type UserAuthConfig = AuthOptions & { + trustedOrigins?: BetterAuthOptions['trustedOrigins'] + secondaryStorage?: BetterAuthOptions['secondaryStorage'] +} +type ResolvedAuthOptions = UserAuthConfig & { + secret: string + baseURL: string + trustedOrigins?: BetterAuthOptions['trustedOrigins'] + database?: BetterAuthOptions['database'] +} +type AuthInstance = ReturnType> const _authCache = new Map() const requestAuthKey = Symbol.for('nuxt-better-auth.requestAuth') @@ -275,9 +287,7 @@ export function serverAuth(event?: H3Event): AuthInstance { return requestContext[requestAuthKey] const database = createDatabase(event) - const userConfig = createServerAuth({ runtimeConfig, db }) as BetterAuthOptions & { - secondaryStorage?: BetterAuthOptions['secondaryStorage'] - } + const userConfig = createServerAuth({ runtimeConfig, db }) as UserAuthConfig const trustedOrigins = withDevTrustedOrigins(userConfig.trustedOrigins, Boolean(hasExplicitSiteUrl)) const hubSecondaryStorage = (runtimeConfig.auth as { hubSecondaryStorage?: boolean | 'custom' })?.hubSecondaryStorage @@ -298,14 +308,15 @@ export function serverAuth(event?: H3Event): AuthInstance { } } - const auth = betterAuth({ + const authOptions: ResolvedAuthOptions = { ...userConfig, - ...(database && { database }), - ...(hubSecondaryStorage === true && { secondaryStorage: createSecondaryStorage() }), + ...(database ? { database } : {}), + ...(hubSecondaryStorage === true ? { secondaryStorage: createSecondaryStorage() } : {}), secret: runtimeConfig.betterAuthSecret, baseURL: siteUrl, trustedOrigins, - }) + } + const auth = betterAuth(authOptions) if (requestContext) requestContext[requestAuthKey] = auth diff --git a/test/cases/plugins-type-inference/tsconfig.type-check.json b/test/cases/plugins-type-inference/tsconfig.type-check.json index 609d8fed..f839b036 100644 --- a/test/cases/plugins-type-inference/tsconfig.type-check.json +++ b/test/cases/plugins-type-inference/tsconfig.type-check.json @@ -19,6 +19,7 @@ "skipLibCheck": true }, "files": [ + "./virtual-modules.d.ts", "./.nuxt/types/nuxt-better-auth-infer.d.ts", "./.nuxt/types/nuxt-better-auth-nitro.d.ts", "./typecheck-target.ts" diff --git a/test/cases/plugins-type-inference/virtual-modules.d.ts b/test/cases/plugins-type-inference/virtual-modules.d.ts new file mode 100644 index 00000000..56091198 --- /dev/null +++ b/test/cases/plugins-type-inference/virtual-modules.d.ts @@ -0,0 +1,8 @@ +declare module '#auth/database' { + export const db: undefined + export function createDatabase(): undefined +} + +declare module '#auth/secondary-storage' { + export function createSecondaryStorage(): undefined +} From fb63ace1eeb8a79e933728f8d2c4099ee0800a19 Mon Sep 17 00:00:00 2001 From: onmax Date: Fri, 27 Mar 2026 08:21:45 +0100 Subject: [PATCH 4/5] fix(auth): use nuxt imports in server runtime --- .../server/api/_better-auth/config.get.ts | 2 +- src/runtime/server/middleware/route-access.ts | 2 +- src/runtime/server/utils/auth.ts | 2 +- .../tsconfig.type-check.json | 24 ++++--------------- test/server-auth-database-cache.test.ts | 2 +- 5 files changed, 8 insertions(+), 24 deletions(-) diff --git a/src/runtime/server/api/_better-auth/config.get.ts b/src/runtime/server/api/_better-auth/config.get.ts index 3eb43a2c..09c89ce0 100644 --- a/src/runtime/server/api/_better-auth/config.get.ts +++ b/src/runtime/server/api/_better-auth/config.get.ts @@ -1,5 +1,5 @@ +import { useRuntimeConfig } from '#imports' import { defineEventHandler } from 'h3' -import { useRuntimeConfig } from 'nitropack/runtime' import { serverAuth } from '../../utils/auth' export default defineEventHandler(async (event) => { diff --git a/src/runtime/server/middleware/route-access.ts b/src/runtime/server/middleware/route-access.ts index f914952f..e2b40159 100644 --- a/src/runtime/server/middleware/route-access.ts +++ b/src/runtime/server/middleware/route-access.ts @@ -1,6 +1,6 @@ import type { AuthMeta, AuthMode, AuthRouteRules } from '../../types' +import { getRouteRules } from '#imports' import { createError, defineEventHandler, getRequestURL } from 'h3' -import { getRouteRules } from 'nitropack/runtime' import { matchesUser } from '../../utils/match-user' import { getUserSession, requireUserSession } from '../utils/session' diff --git a/src/runtime/server/utils/auth.ts b/src/runtime/server/utils/auth.ts index 86b3dfaa..7be2a5a2 100644 --- a/src/runtime/server/utils/auth.ts +++ b/src/runtime/server/utils/auth.ts @@ -1,5 +1,6 @@ import type { BetterAuthOptions } from 'better-auth' import type { H3Event } from 'h3' +import { useRuntimeConfig } from '#imports' // @ts-ignore Nuxt generates this virtual module in app builds. import { createDatabase, db } from '#auth/database' // @ts-ignore Nuxt generates this virtual module in app builds. @@ -7,7 +8,6 @@ import { createSecondaryStorage } from '#auth/secondary-storage' import createServerAuth from '#auth/server' import { betterAuth } from 'better-auth' import { getRequestHost, getRequestProtocol } from 'h3' -import { useRuntimeConfig } from 'nitropack/runtime' import { withoutProtocol } from 'ufo' import { resolveCustomSecondaryStorageRequirement } from './custom-secondary-storage' diff --git a/test/cases/plugins-type-inference/tsconfig.type-check.json b/test/cases/plugins-type-inference/tsconfig.type-check.json index f839b036..8df84722 100644 --- a/test/cases/plugins-type-inference/tsconfig.type-check.json +++ b/test/cases/plugins-type-inference/tsconfig.type-check.json @@ -1,27 +1,11 @@ { + "extends": "./.nuxt/tsconfig.json", "compilerOptions": { - "target": "ESNext", - "lib": [ - "ESNext", - "DOM" - ], - "baseUrl": ".", - "module": "preserve", - "moduleResolution": "bundler", - "paths": { - "#auth/client": ["./app/auth.config"], - "#auth/server": ["./server/auth.config"], - "#nuxt-better-auth": ["../../../src/runtime/types/augment"] - }, - "types": [], - "strict": true, - "noEmit": true, - "skipLibCheck": true + "noEmit": true }, - "files": [ + "include": [ + "./.nuxt/nuxt.d.ts", "./virtual-modules.d.ts", - "./.nuxt/types/nuxt-better-auth-infer.d.ts", - "./.nuxt/types/nuxt-better-auth-nitro.d.ts", "./typecheck-target.ts" ] } diff --git a/test/server-auth-database-cache.test.ts b/test/server-auth-database-cache.test.ts index 3894502f..941bce07 100644 --- a/test/server-auth-database-cache.test.ts +++ b/test/server-auth-database-cache.test.ts @@ -23,7 +23,7 @@ vi.mock('better-auth', () => ({ betterAuth: betterAuthMock, })) -vi.mock('nitropack/runtime', () => ({ +vi.mock('#imports', () => ({ useRuntimeConfig: useRuntimeConfigMock, })) From 5ea1fddb031106666b7aea8f8976b1b78c8e9b7f Mon Sep 17 00:00:00 2001 From: onmax Date: Fri, 27 Mar 2026 08:24:22 +0100 Subject: [PATCH 5/5] fix(ci): align auth runtime typing stubs --- src/runtime/server/utils/auth.ts | 4 +--- test/cases/plugins-type-inference/virtual-modules.d.ts | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/runtime/server/utils/auth.ts b/src/runtime/server/utils/auth.ts index 7be2a5a2..c44cc43e 100644 --- a/src/runtime/server/utils/auth.ts +++ b/src/runtime/server/utils/auth.ts @@ -1,11 +1,9 @@ import type { BetterAuthOptions } from 'better-auth' import type { H3Event } from 'h3' -import { useRuntimeConfig } from '#imports' -// @ts-ignore Nuxt generates this virtual module in app builds. import { createDatabase, db } from '#auth/database' -// @ts-ignore Nuxt generates this virtual module in app builds. import { createSecondaryStorage } from '#auth/secondary-storage' import createServerAuth from '#auth/server' +import { useRuntimeConfig } from '#imports' import { betterAuth } from 'better-auth' import { getRequestHost, getRequestProtocol } from 'h3' import { withoutProtocol } from 'ufo' diff --git a/test/cases/plugins-type-inference/virtual-modules.d.ts b/test/cases/plugins-type-inference/virtual-modules.d.ts index 56091198..41096017 100644 --- a/test/cases/plugins-type-inference/virtual-modules.d.ts +++ b/test/cases/plugins-type-inference/virtual-modules.d.ts @@ -1,8 +1,8 @@ declare module '#auth/database' { export const db: undefined - export function createDatabase(): undefined + export function createDatabase(...args: any[]): undefined } declare module '#auth/secondary-storage' { - export function createSecondaryStorage(): undefined + export function createSecondaryStorage(...args: any[]): undefined }