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
5 changes: 5 additions & 0 deletions .changeset/fix-eslint-unnecessary-condition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/devtools-vite': patch
---

Fix unnecessary condition ESLint error in console pipe log method lookup.
8 changes: 5 additions & 3 deletions packages/devtools-vite/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {

const originalConsole = Object.fromEntries(
consolePipingLevels.map((l) => [l, console[l].bind(console)]),
) as Record<ConsoleLevel, typeof console.log>
) as Partial<Record<ConsoleLevel, typeof console.log>>

// SSE clients for broadcasting server logs to browser
const sseClients: Array<{
Expand Down Expand Up @@ -253,8 +253,10 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
for (const entry of entries) {
const prefix = chalk.cyan('[Client]')
const logMethod =
originalConsole[entry.level as ConsoleLevel] ||
originalConsole.log
originalConsole[entry.level as ConsoleLevel] ??
// log exists in consolePipingLevels
originalConsole.log!

const cleanedArgs = stripEnhancedLogPrefix(
entry.args,
(loc) => chalk.gray(loc),
Expand Down
88 changes: 87 additions & 1 deletion packages/devtools-vite/tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { devtools } from '../src/plugin'
import type { Plugin } from 'vite'
import type * as Utils from '../src/utils'

let capturedOnConsolePipe: ((entries: Array<any>) => void) | undefined

vi.mock('../src/utils', async (importOriginal) => {
const actual = await importOriginal<typeof Utils>()
return {
...actual,
handleDevToolsViteRequest: vi.fn(
(_req: any, _res: any, _next: any, handlers: any) => {
if (typeof handlers === 'object' && handlers?.onConsolePipe) {
capturedOnConsolePipe = handlers.onConsolePipe
}
},
),
}
})

// Helper to find a plugin by name from the array returned by devtools()
function findPlugin(plugins: Array<Plugin>, name: string): Plugin | undefined {
Expand Down Expand Up @@ -313,6 +330,75 @@ describe('devtools plugin', () => {
})
})

describe('configureServer - onConsolePipe uses pre-wrap console methods', () => {
let originalLog: typeof console.log
let beforeWrapSpy: ReturnType<typeof vi.fn>
let afterWrapSpy: ReturnType<typeof vi.fn>

beforeEach(async () => {
capturedOnConsolePipe = undefined
originalLog = console.log
beforeWrapSpy = vi.fn()
afterWrapSpy = vi.fn()

console.log = beforeWrapSpy

const plugins = devtools({ eventBusConfig: { enabled: false } })
const customServerPlugin = findPlugin(
plugins,
'@tanstack/devtools:custom-server',
)!

const server = {
...createMockServer(),
middlewares: {
use: vi.fn((handler: any) => {
handler({ url: '/not-a-tsd-route', socket: {} }, {}, vi.fn())
}),
},
}

const configureServer = customServerPlugin.configureServer as (
server: any,
) => Promise<void>
await configureServer(server)

console.log = afterWrapSpy
})

afterEach(() => {
console.log = originalLog
capturedOnConsolePipe = undefined
})

it('uses the captured original method directly for a known level', () => {
expect(capturedOnConsolePipe).toBeDefined()
beforeWrapSpy.mockClear()
afterWrapSpy.mockClear()

capturedOnConsolePipe!([
{ level: 'log', args: ['test message'], timestamp: Date.now() },
])

expect(beforeWrapSpy).toHaveBeenCalledTimes(1)
expect(afterWrapSpy).not.toHaveBeenCalled()
})
it('falls back to captured originalConsole.log for an unknown level, not the live console.log', () => {
expect(capturedOnConsolePipe).toBeDefined()
beforeWrapSpy.mockClear()
afterWrapSpy.mockClear()

// 'trace' is not in consolePipingLevels so originalConsole['trace'] is
// undefined and the fallback branch is taken.
capturedOnConsolePipe!([
{ level: 'trace', args: ['test message'], timestamp: Date.now() },
])

expect(beforeWrapSpy).toHaveBeenCalledTimes(1)
expect(afterWrapSpy).not.toHaveBeenCalled()
})
})

describe('plugin array', () => {
it('should return an array of plugins', () => {
const plugins = devtools()
Expand Down
Loading