Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions packages/core/src/node/__tests__/auth-handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import type { ResolvedConfig } from 'vite'
import process from 'node:process'
import { createInteractiveAuth } from 'devframe/recipes/interactive-auth'
import { describe, expect, it, vi } from 'vitest'
import { getAuthHandler, getBuildCapabilityToken, isBuildCapabilityAuth, isClientAuthDisabled } from '../auth-handler'
import { normalizeDevToolsConfig } from '../config'
import { createDevToolsContext } from '../context'
import '@vitejs/devtools-kit'

vi.mock('devframe/recipes/interactive-auth', async (importOriginal) => {
const actual = await importOriginal<typeof import('devframe/recipes/interactive-auth')>()
return { ...actual, createInteractiveAuth: vi.fn(actual.createInteractiveAuth) }
})

function createConfig(command: 'serve' | 'build' = 'serve'): ResolvedConfig {
return {
root: process.cwd(),
Expand Down Expand Up @@ -67,6 +73,34 @@ describe('getAuthHandler banner', () => {
})
})

describe('getAuthHandler onTrusted', () => {
it('forwards a configured onTrusted to the interactive auth handler', async () => {
const onTrusted = vi.fn()
const ctx = await createDevToolsContext(
createConfig(),
undefined,
normalizeDevToolsConfig({ onTrusted }, 'localhost'),
)

getAuthHandler(ctx)

expect(vi.mocked(createInteractiveAuth).mock.lastCall?.[1]).toMatchObject({ onTrusted })
})

it('skips onTrusted in implicit build mode (trust is token-based, no code exchange)', async () => {
const onTrusted = vi.fn()
const ctx = await createDevToolsContext(
createConfig('build'),
undefined,
normalizeDevToolsConfig({ onTrusted }, 'localhost'),
)

getAuthHandler(ctx)

expect(vi.mocked(createInteractiveAuth).mock.lastCall?.[1]?.onTrusted).toBeUndefined()
})
})

describe('build-mode capability token', () => {
it('flags implicit build mode as capability-token auth, not disabled', async () => {
const ctx = await createDevToolsContext(
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/node/auth-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ export function getAuthHandler(context: ViteDevToolsNodeContext): DevToolsAuthHa
handler = createInteractiveAuth(context, {
clientAuthTokens,
// Build mode trusts purely via the per-process capability token baked
// into the served connection meta, so silence the OTP console banner.
// into the served connection meta, so silence the OTP console banner
// and skip `onTrusted` — no code exchange ever happens to fire it.
banner: buildCapability ? () => {} : config.banner,
onTrusted: buildCapability ? undefined : config.onTrusted,
})
handlers.set(context, handler)
}
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/node/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { CreateInteractiveAuthOptions } from 'devframe/recipes/interactive-auth'
import type { McpSetting } from 'devframe/types'
import type { StartOptions } from './cli-commands'
import type { DevToolsUserOptions } from './plugin-options'
Expand Down Expand Up @@ -44,6 +45,12 @@ export interface DevToolsConfig extends Partial<StartOptions>, DevToolsUserOptio
* Supply this to surface the code in the host's own chrome instead.
*/
banner?: (info: { code: string, url: string }) => void
/**
* Called once a code exchange succeeds, so a host rendering its own
* `banner` can retract it. Not called for connect-time trust from a
* static `clientAuthTokens` entry, since no code exchange happens.
*/
onTrusted?: CreateInteractiveAuthOptions['onTrusted']
/**
* Origins allowed to open the DevTools WebSocket connection, in addition to the built-in
* loopback allowlist (`localhost`, `127.0.0.1`, etc).
Expand Down
Loading