diff --git a/.changeset/fix-eslint-unnecessary-condition.md b/.changeset/fix-eslint-unnecessary-condition.md new file mode 100644 index 00000000..f37e24dc --- /dev/null +++ b/.changeset/fix-eslint-unnecessary-condition.md @@ -0,0 +1,5 @@ +--- +'@tanstack/devtools-vite': patch +--- + +Fix unnecessary condition ESLint error in console pipe log method lookup. diff --git a/packages/devtools-vite/src/plugin.ts b/packages/devtools-vite/src/plugin.ts index 8e1caf5f..47740560 100644 --- a/packages/devtools-vite/src/plugin.ts +++ b/packages/devtools-vite/src/plugin.ts @@ -225,7 +225,7 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array => { const originalConsole = Object.fromEntries( consolePipingLevels.map((l) => [l, console[l].bind(console)]), - ) as Record + ) as Partial> // SSE clients for broadcasting server logs to browser const sseClients: Array<{ @@ -253,8 +253,10 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array => { 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), diff --git a/packages/devtools-vite/tests/index.test.ts b/packages/devtools-vite/tests/index.test.ts index ba13a33e..b014875f 100644 --- a/packages/devtools-vite/tests/index.test.ts +++ b/packages/devtools-vite/tests/index.test.ts @@ -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) => void) | undefined + +vi.mock('../src/utils', async (importOriginal) => { + const actual = await importOriginal() + 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, name: string): Plugin | undefined { @@ -313,6 +330,75 @@ describe('devtools plugin', () => { }) }) + describe('configureServer - onConsolePipe uses pre-wrap console methods', () => { + let originalLog: typeof console.log + let beforeWrapSpy: ReturnType + let afterWrapSpy: ReturnType + + 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 + 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()