@tanstack/devtools-vite 0.5.3 → 0.5.5

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/bin/intent.js ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ // Auto-generated by @tanstack/intent setup
3
+ // Exposes the intent end-user CLI for consumers of this library.
4
+ // Commit this file, then add to your package.json:
5
+ // "bin": { "intent": "./bin/intent.js" }
6
+ try {
7
+ await import('@tanstack/intent/intent-library')
8
+ } catch (e) {
9
+ if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') {
10
+ console.error('@tanstack/intent is not installed.')
11
+ console.error('')
12
+ console.error('Install it as a dev dependency:')
13
+ console.error(' npm add -D @tanstack/intent')
14
+ console.error('')
15
+ console.error('Or run directly:')
16
+ console.error(' npx @tanstack/intent@latest list')
17
+ process.exit(1)
18
+ }
19
+ throw e
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/devtools-vite",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "TanStack Vite plugin used to enhance the core devtools with additional functionalities",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -29,13 +29,18 @@
29
29
  },
30
30
  "./package.json": "./package.json"
31
31
  },
32
+ "bin": {
33
+ "intent": "./bin/intent.js"
34
+ },
32
35
  "sideEffects": false,
33
36
  "engines": {
34
37
  "node": ">=18"
35
38
  },
36
39
  "files": [
37
40
  "dist/",
38
- "src"
41
+ "src",
42
+ "skills",
43
+ "bin"
39
44
  ],
40
45
  "peerDependencies": {
41
46
  "vite": "^6.0.0 || ^7.0.0"
@@ -0,0 +1,312 @@
1
+ ---
2
+ name: devtools-vite-plugin
3
+ description: >
4
+ Configure @tanstack/devtools-vite for source inspection (data-tsd-source,
5
+ inspectHotkey, ignore patterns), console piping (client-to-server,
6
+ server-to-client, levels), enhanced logging, server event bus (port, host,
7
+ HTTPS), production stripping (removeDevtoolsOnBuild), editor integration
8
+ (launch-editor, custom editor.open). Must be FIRST plugin in Vite config.
9
+ Vite ^6 || ^7 only.
10
+ type: core
11
+ library: tanstack-devtools
12
+ library_version: '0.10.12'
13
+ sources:
14
+ - 'TanStack/devtools:docs/vite-plugin.md'
15
+ - 'TanStack/devtools:docs/source-inspector.md'
16
+ - 'TanStack/devtools:packages/devtools-vite/src/plugin.ts'
17
+ ---
18
+
19
+ Configure @tanstack/devtools-vite -- the Vite plugin that enhances TanStack Devtools with source inspection, console piping, enhanced logging, a server event bus, production stripping, editor integration, and a plugin marketplace. The plugin returns an array of sub-plugins, all using `enforce: 'pre'`, so it must be the FIRST plugin in the Vite config.
20
+
21
+ ## Installation and Basic Setup
22
+
23
+ ```ts
24
+ // vite.config.ts
25
+ import { devtools } from '@tanstack/devtools-vite'
26
+
27
+ export default {
28
+ plugins: [
29
+ devtools(),
30
+ // ... other plugins AFTER devtools
31
+ ],
32
+ }
33
+ ```
34
+
35
+ Install as a dev dependency:
36
+
37
+ ```sh
38
+ pnpm add -D @tanstack/devtools-vite
39
+ ```
40
+
41
+ There is also a `defineDevtoolsConfig` helper for type-safe config objects:
42
+
43
+ ```ts
44
+ import { devtools, defineDevtoolsConfig } from '@tanstack/devtools-vite'
45
+
46
+ const config = defineDevtoolsConfig({
47
+ // fully typed options
48
+ })
49
+
50
+ export default {
51
+ plugins: [devtools(config)],
52
+ }
53
+ ```
54
+
55
+ ## Exports
56
+
57
+ From `packages/devtools-vite/src/index.ts`:
58
+
59
+ - `devtools` -- main plugin factory, returns `Array<Plugin>`
60
+ - `defineDevtoolsConfig` -- identity function for type-safe config
61
+ - `TanStackDevtoolsViteConfig` -- config type (re-exported)
62
+ - `ConsoleLevel` -- `'log' | 'warn' | 'error' | 'info' | 'debug'`
63
+
64
+ ## Architecture: Sub-Plugins
65
+
66
+ `devtools()` returns an array of Vite plugins. Each has `enforce: 'pre'` and only activates when its conditions are met (dev mode, serve command, etc.).
67
+
68
+ | Sub-plugin name | What it does | When active |
69
+ | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
70
+ | `@tanstack/devtools:inject-source` | Babel transform adding `data-tsd-source` attrs to JSX | dev mode + `injectSource.enabled` |
71
+ | `@tanstack/devtools:config` | Reserved for future config modifications | serve command only |
72
+ | `@tanstack/devtools:custom-server` | Starts ServerEventBus, registers middleware for open-source/console-pipe endpoints | dev mode |
73
+ | `@tanstack/devtools:remove-devtools-on-build` | Strips devtools imports/JSX from production bundles | build command or production mode + `removeDevtoolsOnBuild` |
74
+ | `@tanstack/devtools:event-client-setup` | Marketplace: listens for install/add-plugin events via devtoolsEventClient | dev mode + serve + not CI |
75
+ | `@tanstack/devtools:console-pipe-transform` | Injects runtime console-pipe code into entry files | dev mode + serve + `consolePiping.enabled` |
76
+ | `@tanstack/devtools:better-console-logs` | Babel transform prepending source location to `console.log`/`console.error` | dev mode + `enhancedLogs.enabled` |
77
+ | `@tanstack/devtools:inject-plugin` | Detects which file imports TanStackDevtools (for marketplace injection) | dev mode + serve |
78
+ | `@tanstack/devtools:connection-injection` | Replaces `__TANSTACK_DEVTOOLS_PORT__`, `__TANSTACK_DEVTOOLS_HOST__`, `__TANSTACK_DEVTOOLS_PROTOCOL__` placeholders | dev mode + serve |
79
+
80
+ ## Subsystem Details
81
+
82
+ ### Source Injection
83
+
84
+ Adds `data-tsd-source="<relative-path>:<line>:<column>"` attributes to every JSX opening element via Babel. This powers the "Go to Source" feature -- hold the inspect hotkey (default: Shift+Alt+Ctrl/Meta), hover over elements, click to open in editor.
85
+
86
+ **Key behaviors:**
87
+
88
+ - Skips `<Fragment>` and `<React.Fragment>`
89
+ - Skips elements where the component's props parameter is spread (`{...props}`) -- this is because injecting the attribute would be overwritten by the spread
90
+ - Skips files matching `injectSource.ignore.files` patterns
91
+ - Skips components matching `injectSource.ignore.components` patterns
92
+ - Patterns can be strings (matched via picomatch) or RegExp
93
+ - Transform filter excludes `node_modules`, `?raw` imports, `/dist/`, `/build/`
94
+
95
+ **Source files:** `packages/devtools-vite/src/inject-source.ts`, `packages/devtools-vite/src/matcher.ts`
96
+
97
+ ```ts
98
+ devtools({
99
+ injectSource: {
100
+ enabled: true,
101
+ ignore: {
102
+ files: ['node_modules', /.*\.test\.(js|ts|jsx|tsx)$/],
103
+ components: ['InternalComponent', /.*Provider$/],
104
+ },
105
+ },
106
+ })
107
+ ```
108
+
109
+ ### Console Piping
110
+
111
+ Bidirectional console piping between client and server. Injects runtime code (IIFE) into entry files that:
112
+
113
+ **Client side:**
114
+
115
+ 1. Wraps `console[level]` to batch and POST entries to `/__tsd/console-pipe`
116
+ 2. Opens an EventSource on `/__tsd/console-pipe/sse` to receive server logs
117
+ 3. Server logs appear in browser console with a purple `[Server]` prefix
118
+ 4. Client logs appear in terminal with a cyan `[Client]` prefix
119
+
120
+ **Server side (SSR/Nitro):**
121
+
122
+ 1. Wraps `console[level]` to batch and POST entries to `<viteServerUrl>/__tsd/console-pipe/server`
123
+ 2. These are then broadcast to all SSE clients
124
+
125
+ **Entry file detection:** looks for `<html` tag, `StartClient`, `hydrateRoot`, `createRoot`, or `solid-js/web` + `render(` in code.
126
+
127
+ **Source files:** `packages/devtools-vite/src/virtual-console.ts`, `packages/devtools-vite/src/utils.ts` (middleware handlers)
128
+
129
+ ```ts
130
+ devtools({
131
+ consolePiping: {
132
+ enabled: true,
133
+ levels: ['log', 'warn', 'error', 'info', 'debug'],
134
+ },
135
+ })
136
+ ```
137
+
138
+ ### Enhanced Logging
139
+
140
+ Babel transform that prepends source location info to `console.log()` and `console.error()` calls. In the browser, this renders as a clickable "Go to Source" link. On the server, it shows `LOG <path>:<line>:<column>` in chalk colors.
141
+
142
+ The transform inserts a spread of a conditional expression: `...(typeof window === 'undefined' ? serverLogMessage : browserLogMessage)` as the first argument of the console call.
143
+
144
+ **Source file:** `packages/devtools-vite/src/enhance-logs.ts`
145
+
146
+ ```ts
147
+ devtools({
148
+ enhancedLogs: {
149
+ enabled: true, // default
150
+ },
151
+ })
152
+ ```
153
+
154
+ ### Production Stripping
155
+
156
+ Removes all devtools code from production builds. The transform:
157
+
158
+ 1. Finds files importing from these packages: `@tanstack/react-devtools`, `@tanstack/preact-devtools`, `@tanstack/solid-devtools`, `@tanstack/vue-devtools`, `@tanstack/devtools`
159
+ 2. Removes the import declarations
160
+ 3. Removes the JSX elements that use the imported components
161
+ 4. Cleans up leftover imports that were only used inside the removed JSX (e.g., plugin panel components)
162
+
163
+ Active when: `command !== 'serve'` OR `config.mode === 'production'` (handles hosting providers like Cloudflare/Netlify that may not use `build` command but set mode to production).
164
+
165
+ **Source file:** `packages/devtools-vite/src/remove-devtools.ts`
166
+
167
+ ```ts
168
+ devtools({
169
+ removeDevtoolsOnBuild: true, // default
170
+ })
171
+ ```
172
+
173
+ ### Server Event Bus
174
+
175
+ A WebSocket + SSE server for devtools-to-client communication. Managed by `@tanstack/devtools-event-bus/server`.
176
+
177
+ **Key behaviors:**
178
+
179
+ - Default port: 4206
180
+ - On EADDRINUSE: falls back to OS-assigned port (port 0)
181
+ - When Vite uses HTTPS: piggybacks on Vite's httpServer instead of creating a standalone one (shares TLS certificate)
182
+ - Uses global variables (`__TANSTACK_DEVTOOLS_SERVER__`, etc.) to survive HMR without restarting
183
+ - The actual port is injected into client code via `__TANSTACK_DEVTOOLS_PORT__` placeholder replacement
184
+
185
+ **Source file:** `packages/event-bus/src/server/server.ts`
186
+
187
+ ```ts
188
+ devtools({
189
+ eventBusConfig: {
190
+ port: 4206, // default
191
+ enabled: true, // default; set false for storybook/vitest
192
+ debug: false, // default; logs internal bus activity
193
+ },
194
+ })
195
+ ```
196
+
197
+ ### Editor Integration
198
+
199
+ Uses `launch-editor` to open source files in the editor. Default editor is VS Code. The `editor.open` callback receives `(path, lineNumber, columnNumber)` as strings.
200
+
201
+ The open-source flow: browser requests `/__tsd/open-source?source=<encoded-path:line:col>` --> Vite middleware parses source param --> calls `editor.open`.
202
+
203
+ Supported editors via launch-editor: VS Code, WebStorm, Sublime Text, Atom, and more. For unsupported editors, provide a custom `editor.open` function.
204
+
205
+ **Source file:** `packages/devtools-vite/src/editor.ts`
206
+
207
+ ```ts
208
+ devtools({
209
+ editor: {
210
+ name: 'Cursor',
211
+ open: async (path, lineNumber, columnNumber) => {
212
+ // Custom editor open logic
213
+ // path is the absolute file path
214
+ // lineNumber and columnNumber are strings or undefined
215
+ },
216
+ },
217
+ })
218
+ ```
219
+
220
+ ### Plugin Marketplace
221
+
222
+ When the dev server is running, listens for events via `devtoolsEventClient`:
223
+
224
+ - `install-devtools` -- runs package manager install, then auto-injects plugin into devtools setup file
225
+ - `add-plugin-to-devtools` -- injects plugin import and JSX/function call into the file containing `<TanStackDevtools>`
226
+ - `bump-package-version` -- updates a package to a minimum version
227
+ - `mounted` -- sends package.json and outdated deps to the UI
228
+
229
+ Auto-detection of the devtools setup file: the `inject-plugin` sub-plugin scans transforms for files importing from `@tanstack/react-devtools`, `@tanstack/solid-devtools`, `@tanstack/vue-devtools`, etc., and stores the file ID.
230
+
231
+ **Source files:** `packages/devtools-vite/src/inject-plugin.ts`, `packages/devtools-vite/src/package-manager.ts`
232
+
233
+ ## Common Mistakes
234
+
235
+ ### 1. Not placing devtools() first in Vite plugins (HIGH)
236
+
237
+ All sub-plugins use `enforce: 'pre'`. They must transform code before framework plugins (React, Vue, Solid, etc.) process it. If devtools is not first, source injection and enhanced logs may silently fail because framework transforms remove the raw JSX before devtools can annotate it.
238
+
239
+ ```ts
240
+ // WRONG
241
+ export default {
242
+ plugins: [
243
+ react(),
244
+ devtools(), // too late -- react() already transformed JSX
245
+ ],
246
+ }
247
+
248
+ // CORRECT
249
+ export default {
250
+ plugins: [devtools(), react()],
251
+ }
252
+ ```
253
+
254
+ ### 2. Using devtools-vite with non-Vite bundlers (HIGH)
255
+
256
+ `@tanstack/devtools-vite` has a peer dependency on `vite ^6.0.0 || ^7.0.0`. It uses Vite-specific APIs (`configureServer`, `handleHotUpdate`, `transform` with filter objects, `Plugin` type). It will not work with webpack, rspack, esbuild, or other bundlers. For non-Vite setups, use `@tanstack/devtools-event-bus` client directly without the Vite plugin.
257
+
258
+ ### 3. Expecting Vite plugin features in production (MEDIUM)
259
+
260
+ Source injection, console piping, enhanced logging, the server event bus, and the marketplace only operate during development (`config.mode === 'development'` and `command === 'serve'`). In production builds, the only active sub-plugin is `remove-devtools-on-build` (which strips devtools code). Do not rely on any of these features being available at runtime in production.
261
+
262
+ ### 4. Source injection on spread-props elements (MEDIUM)
263
+
264
+ The Babel transform in `inject-source.ts` explicitly skips any JSX element that has a `{...props}` spread where `props` is the component's parameter name. This is intentional -- the spread would overwrite the injected `data-tsd-source` attribute. If source inspection doesn't work for a specific component, check if it spreads its props parameter.
265
+
266
+ ```tsx
267
+ // data-tsd-source will NOT be injected on <div> here
268
+ const MyComponent = (props) => {
269
+ return <div {...props}>content</div>
270
+ }
271
+ ```
272
+
273
+ ### 5. Event bus port conflict in multi-project setups (MEDIUM)
274
+
275
+ The default event bus port is 4206. When running multiple Vite dev servers concurrently (monorepo), the second server will hit EADDRINUSE. The event bus handles this by falling back to an OS-assigned port (port 0), and the actual port is injected via placeholder replacement. However, if you need predictable ports (e.g., for firewall rules), set different ports explicitly:
276
+
277
+ ```ts
278
+ // Project A
279
+ devtools({ eventBusConfig: { port: 4206 } })
280
+
281
+ // Project B
282
+ devtools({ eventBusConfig: { port: 4207 } })
283
+ ```
284
+
285
+ ## Internal Middleware Endpoints
286
+
287
+ These are registered on the Vite dev server (not the event bus server):
288
+
289
+ | Endpoint | Method | Purpose |
290
+ | ------------------------------------------- | ------ | --------------------------------------------------------- |
291
+ | `/__tsd/open-source?source=<path:line:col>` | GET | Opens file in editor, returns HTML that closes the window |
292
+ | `/__tsd/console-pipe` | POST | Receives client console entries (batched JSON) |
293
+ | `/__tsd/console-pipe/server` | POST | Receives server-side console entries |
294
+ | `/__tsd/console-pipe/sse` | GET | SSE stream for broadcasting server logs to browser |
295
+
296
+ ## Cross-References
297
+
298
+ - **devtools-app-setup** -- How to set up `<TanStackDevtools>` in your app (must be done before the Vite plugin provides value)
299
+ - **devtools-production** -- Details on production stripping configuration and keeping devtools in production builds
300
+
301
+ ## Key Source Files
302
+
303
+ - `packages/devtools-vite/src/plugin.ts` -- Main plugin factory with all sub-plugins and config type
304
+ - `packages/devtools-vite/src/inject-source.ts` -- Babel transform for data-tsd-source injection
305
+ - `packages/devtools-vite/src/enhance-logs.ts` -- Babel transform for enhanced console logs
306
+ - `packages/devtools-vite/src/remove-devtools.ts` -- Production stripping transform
307
+ - `packages/devtools-vite/src/virtual-console.ts` -- Console pipe runtime code generator
308
+ - `packages/devtools-vite/src/editor.ts` -- Editor config type and launch-editor integration
309
+ - `packages/devtools-vite/src/inject-plugin.ts` -- Marketplace plugin injection into devtools setup file
310
+ - `packages/devtools-vite/src/utils.ts` -- Middleware request handling and helpers
311
+ - `packages/devtools-vite/src/matcher.ts` -- Picomatch/RegExp pattern matcher
312
+ - `packages/event-bus/src/server/server.ts` -- ServerEventBus implementation (WebSocket + SSE + EADDRINUSE fallback)
@@ -0,0 +1,413 @@
1
+ # @tanstack/devtools-vite Options Reference
2
+
3
+ Complete configuration reference for the `devtools()` Vite plugin. All options are optional -- calling `devtools()` with no arguments uses sensible defaults.
4
+
5
+ **Source of truth:** `packages/devtools-vite/src/plugin.ts` (type `TanStackDevtoolsViteConfig`)
6
+
7
+ ## Top-Level Config Type
8
+
9
+ ```ts
10
+ import type { Plugin } from 'vite'
11
+
12
+ type ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug'
13
+
14
+ type TanStackDevtoolsViteConfig = {
15
+ editor?: EditorConfig
16
+ eventBusConfig?: ServerEventBusConfig & { enabled?: boolean }
17
+ enhancedLogs?: { enabled: boolean }
18
+ removeDevtoolsOnBuild?: boolean
19
+ logging?: boolean
20
+ injectSource?: {
21
+ enabled: boolean
22
+ ignore?: {
23
+ files?: Array<string | RegExp>
24
+ components?: Array<string | RegExp>
25
+ }
26
+ }
27
+ consolePiping?: {
28
+ enabled?: boolean
29
+ levels?: Array<ConsoleLevel>
30
+ }
31
+ }
32
+
33
+ // Returns Array<Plugin> (9 sub-plugins)
34
+ declare function devtools(args?: TanStackDevtoolsViteConfig): Array<Plugin>
35
+
36
+ // Identity function for type-safe config objects
37
+ declare function defineDevtoolsConfig(
38
+ config: TanStackDevtoolsViteConfig,
39
+ ): TanStackDevtoolsViteConfig
40
+ ```
41
+
42
+ ---
43
+
44
+ ## `injectSource`
45
+
46
+ Controls source injection -- the Babel transform that adds `data-tsd-source` attributes to JSX elements for the "Go to Source" feature.
47
+
48
+ | Field | Type | Default | Description |
49
+ | ------------------- | ------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
50
+ | `enabled` | `boolean` | `true` | Whether to inject `data-tsd-source` attributes into JSX elements during development. |
51
+ | `ignore` | `object` | `undefined` | Patterns to exclude from injection. |
52
+ | `ignore.files` | `Array<string \| RegExp>` | `[]` | File paths to skip. Strings are matched via picomatch glob syntax. RegExp patterns are tested directly. Matched against the file's path relative to `process.cwd()`. |
53
+ | `ignore.components` | `Array<string \| RegExp>` | `[]` | Component/element names to skip. Strings are matched via picomatch. RegExp patterns are tested directly. Matched against the JSX element name (e.g., `"div"`, `"MyComponent"`, `"Namespace.Component"`). |
54
+
55
+ **Built-in exclusions (hardcoded in transform filter, not configurable):**
56
+
57
+ - `node_modules`
58
+ - `?raw` imports
59
+ - `/dist/` paths
60
+ - `/build/` paths
61
+ - `<Fragment>` and `<React.Fragment>` elements
62
+ - Elements with `{...propsParam}` spread (where `propsParam` is the function's parameter name)
63
+
64
+ **Example:**
65
+
66
+ ```ts
67
+ devtools({
68
+ injectSource: {
69
+ enabled: true,
70
+ ignore: {
71
+ files: ['node_modules', /.*\.test\.(js|ts|jsx|tsx)$/, '**/generated/**'],
72
+ components: ['InternalComponent', /.*Provider$/, /^Styled/],
73
+ },
74
+ },
75
+ })
76
+ ```
77
+
78
+ ---
79
+
80
+ ## `consolePiping`
81
+
82
+ Controls bidirectional console log piping between client (browser) and server (terminal/SSR runtime).
83
+
84
+ | Field | Type | Default | Description |
85
+ | --------- | --------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
86
+ | `enabled` | `boolean` | `true` | Whether to enable console piping. When enabled, client `console.*` calls are forwarded to the terminal, and server `console.*` calls are forwarded to the browser console. |
87
+ | `levels` | `Array<ConsoleLevel>` | `['log', 'warn', 'error', 'info', 'debug']` | Which console methods to intercept and pipe. `ConsoleLevel` is `'log' \| 'warn' \| 'error' \| 'info' \| 'debug'`. |
88
+
89
+ **Runtime behavior:**
90
+
91
+ - Client batches entries (max 50, flush after 100ms) and POSTs to `/__tsd/console-pipe`
92
+ - Server batches entries (max 20, flush after 50ms) and POSTs to `<viteServerUrl>/__tsd/console-pipe/server`
93
+ - Browser subscribes to server logs via `EventSource` at `/__tsd/console-pipe/sse`
94
+ - Self-referential log messages (containing `[TSD Console Pipe]` or `[@tanstack/devtools`) are excluded to prevent recursion
95
+ - Flushes remaining batch on `beforeunload` (client only)
96
+
97
+ **Example:**
98
+
99
+ ```ts
100
+ // Only pipe errors and warnings
101
+ devtools({
102
+ consolePiping: {
103
+ enabled: true,
104
+ levels: ['error', 'warn'],
105
+ },
106
+ })
107
+
108
+ // Disable entirely
109
+ devtools({
110
+ consolePiping: {
111
+ enabled: false,
112
+ },
113
+ })
114
+ ```
115
+
116
+ ---
117
+
118
+ ## `enhancedLogs`
119
+
120
+ Controls the Babel transform that prepends source location information to `console.log()` and `console.error()` calls.
121
+
122
+ | Field | Type | Default | Description |
123
+ | --------- | --------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
124
+ | `enabled` | `boolean` | `true` | Whether to enhance console.log and console.error with source location. When enabled, each log call gets a clickable "Go to Source" link in the browser and a file:line:column prefix in the terminal. |
125
+
126
+ **What gets transformed:**
127
+
128
+ - Only `console.log(...)` and `console.error(...)` calls (not `warn`, `info`, `debug`)
129
+ - Skips `node_modules`, `?raw`, `/dist/`, `/build/`
130
+ - Skips files that don't contain the string `console.`
131
+
132
+ **Browser output format:**
133
+
134
+ ```
135
+ %cLOG%c %cGo to Source: http://localhost:5173/__tsd/open-source?source=...%c
136
+ -> <original args>
137
+ ```
138
+
139
+ **Server output format (chalk):**
140
+
141
+ ```
142
+ LOG /src/components/Header.tsx:26:13
143
+ -> <original args>
144
+ ```
145
+
146
+ **Example:**
147
+
148
+ ```ts
149
+ devtools({
150
+ enhancedLogs: {
151
+ enabled: false, // disable source-annotated logs
152
+ },
153
+ })
154
+ ```
155
+
156
+ ---
157
+
158
+ ## `removeDevtoolsOnBuild`
159
+
160
+ Controls whether devtools code is stripped from production builds.
161
+
162
+ | Field | Type | Default | Description |
163
+ | ----------------------- | --------- | ------- | ----------------------------------------------------------------------------- |
164
+ | `removeDevtoolsOnBuild` | `boolean` | `true` | When true, removes all devtools imports and JSX usage from production builds. |
165
+
166
+ **Packages stripped:**
167
+
168
+ - `@tanstack/react-devtools`
169
+ - `@tanstack/preact-devtools`
170
+ - `@tanstack/solid-devtools`
171
+ - `@tanstack/vue-devtools`
172
+ - `@tanstack/devtools`
173
+
174
+ **Activation condition:** Active when `command !== 'serve'` OR `config.mode === 'production'`. This dual check supports hosting providers (Cloudflare, Netlify, Heroku) that may not use the `build` command but always set mode to `production`.
175
+
176
+ **What gets removed:**
177
+
178
+ 1. Import declarations from the listed packages
179
+ 2. JSX elements using the imported component names
180
+ 3. Leftover imports that were only referenced inside the removed JSX (e.g., plugin panel components referenced in the `plugins` prop)
181
+
182
+ **Example:**
183
+
184
+ ```ts
185
+ // Keep devtools in production (for staging/QA environments)
186
+ devtools({
187
+ removeDevtoolsOnBuild: false,
188
+ })
189
+ ```
190
+
191
+ ---
192
+
193
+ ## `logging`
194
+
195
+ Controls the plugin's own console output.
196
+
197
+ | Field | Type | Default | Description |
198
+ | --------- | --------- | ------- | ----------------------------------------------------------------------------------------------------------- |
199
+ | `logging` | `boolean` | `true` | Whether the devtools plugin logs status messages to the terminal (e.g., "Removed devtools code from: ..."). |
200
+
201
+ **Example:**
202
+
203
+ ```ts
204
+ devtools({
205
+ logging: false, // suppress devtools plugin output
206
+ })
207
+ ```
208
+
209
+ ---
210
+
211
+ ## `eventBusConfig`
212
+
213
+ Configuration for the server event bus that handles devtools-to-client communication via WebSocket and SSE.
214
+
215
+ | Field | Type | Default | Description |
216
+ | ------------ | ---------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
217
+ | `enabled` | `boolean` | `true` | Whether to start the server event bus. Set to `false` when running devtools in environments that don't need it (e.g., Storybook, Vitest). This field is specific to the Vite plugin wrapper; it is not part of `ServerEventBusConfig` from `@tanstack/devtools-event-bus/server`. |
218
+ | `port` | `number` | `4206` | Preferred port for the event bus server. If the port is in use (EADDRINUSE), the bus falls back to an OS-assigned port (port 0). |
219
+ | `host` | `string` | Derived from `server.host` in Vite config, or `'localhost'` | Hostname to bind the event bus server to. |
220
+ | `debug` | `boolean` | `false` | When true, logs internal event bus activity (connections, dispatches, etc.) to the console. |
221
+ | `httpServer` | `HttpServerLike` | `undefined` | An external HTTP server to attach to instead of creating a standalone one. The Vite plugin automatically sets this when HTTPS is enabled (uses `server.httpServer` from Vite) so WebSocket/SSE connections share the same TLS certificate. You generally do not need to set this manually. |
222
+
223
+ **`HttpServerLike` interface:**
224
+
225
+ ```ts
226
+ interface HttpServerLike {
227
+ on: (event: string, listener: (...args: Array<any>) => void) => this
228
+ removeListener: (
229
+ event: string,
230
+ listener: (...args: Array<any>) => void,
231
+ ) => this
232
+ address: () =>
233
+ | { port: number; family: string; address: string }
234
+ | string
235
+ | null
236
+ }
237
+ ```
238
+
239
+ **`ServerEventBusConfig` type (from `@tanstack/devtools-event-bus/server`):**
240
+
241
+ ```ts
242
+ interface ServerEventBusConfig {
243
+ port?: number | undefined
244
+ host?: string | undefined
245
+ debug?: boolean | undefined
246
+ httpServer?: HttpServerLike | undefined
247
+ }
248
+ ```
249
+
250
+ **HTTPS behavior:** When `server.https` is configured in Vite, the plugin passes `server.httpServer` as `httpServer` to the event bus. This causes the bus to piggyback on Vite's server rather than creating a standalone HTTP server, ensuring WebSocket and SSE connections use the same TLS certificate.
251
+
252
+ **Port fallback:** The `ServerEventBus.start()` method tries the configured port first. On `EADDRINUSE`, it retries with port 0 (OS-assigned). The actual port is stored and injected into client code via `__TANSTACK_DEVTOOLS_PORT__` placeholder.
253
+
254
+ **Example:**
255
+
256
+ ```ts
257
+ devtools({
258
+ eventBusConfig: {
259
+ port: 4300,
260
+ enabled: true,
261
+ debug: true, // see all event bus activity
262
+ },
263
+ })
264
+
265
+ // Disable for Storybook
266
+ devtools({
267
+ eventBusConfig: {
268
+ enabled: false,
269
+ },
270
+ })
271
+ ```
272
+
273
+ ---
274
+
275
+ ## `editor`
276
+
277
+ Configuration for the "open in editor" functionality used by the source inspector.
278
+
279
+ | Field | Type | Default | Description |
280
+ | ------ | ----------------------------------------------------------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
281
+ | `name` | `string` | `'VSCode'` | Name of the editor, used for debugging/logging purposes. |
282
+ | `open` | `(path: string, lineNumber: string \| undefined, columnNumber?: string) => Promise<void>` | Uses `launch-editor` to open VS Code | Callback function that opens a file in the editor. The `path` is an absolute file path. `lineNumber` and `columnNumber` are strings (not numbers) or undefined. |
283
+
284
+ **`EditorConfig` type (from `packages/devtools-vite/src/editor.ts`):**
285
+
286
+ ```ts
287
+ type EditorConfig = {
288
+ name: string
289
+ open: (
290
+ path: string,
291
+ lineNumber: string | undefined,
292
+ columnNumber?: string,
293
+ ) => Promise<void>
294
+ }
295
+ ```
296
+
297
+ **Default implementation:**
298
+
299
+ ```ts
300
+ const DEFAULT_EDITOR_CONFIG: EditorConfig = {
301
+ name: 'VSCode',
302
+ open: async (path, lineNumber, columnNumber) => {
303
+ const launch = (await import('launch-editor')).default
304
+ launch(
305
+ `${path.replaceAll('$', '\\$')}${lineNumber ? `:${lineNumber}` : ''}${columnNumber ? `:${columnNumber}` : ''}`,
306
+ undefined,
307
+ (filename, err) => {
308
+ console.warn(`Failed to open ${filename} in editor: ${err}`)
309
+ },
310
+ )
311
+ },
312
+ }
313
+ ```
314
+
315
+ **Supported editors via launch-editor:** VS Code, WebStorm, IntelliJ IDEA, Sublime Text, Atom, Vim, Emacs, and more. Full list: https://github.com/yyx990803/launch-editor#supported-editors
316
+
317
+ **Example -- custom editor:**
318
+
319
+ ```ts
320
+ devtools({
321
+ editor: {
322
+ name: 'Neovim',
323
+ open: async (path, lineNumber, columnNumber) => {
324
+ const { execFile } = await import('node:child_process')
325
+ const lineArg = lineNumber ? `+${lineNumber}` : ''
326
+ execFile('nvim', [lineArg, path].filter(Boolean))
327
+ },
328
+ },
329
+ })
330
+ ```
331
+
332
+ ---
333
+
334
+ ## Connection Placeholders
335
+
336
+ These are not user-facing config options but are relevant if you work on `@tanstack/devtools` internals. The `connection-injection` sub-plugin replaces these string literals in `@tanstack/devtools*` and `@tanstack/event-bus` source code during dev:
337
+
338
+ | Placeholder | Replaced with | Fallback |
339
+ | -------------------------------- | ----------------------------------- | ------------- |
340
+ | `__TANSTACK_DEVTOOLS_PORT__` | Actual event bus port (number) | `4206` |
341
+ | `__TANSTACK_DEVTOOLS_HOST__` | Event bus hostname (JSON string) | `"localhost"` |
342
+ | `__TANSTACK_DEVTOOLS_PROTOCOL__` | `"http"` or `"https"` (JSON string) | `"http"` |
343
+
344
+ ---
345
+
346
+ ## Full Configuration Example
347
+
348
+ ```ts
349
+ import { devtools } from '@tanstack/devtools-vite'
350
+
351
+ export default {
352
+ plugins: [
353
+ devtools({
354
+ // Source injection for Go to Source feature
355
+ injectSource: {
356
+ enabled: true,
357
+ ignore: {
358
+ files: [/.*\.stories\.(js|ts|jsx|tsx)$/],
359
+ components: [/^Styled/, 'InternalWrapper'],
360
+ },
361
+ },
362
+
363
+ // Bidirectional console piping
364
+ consolePiping: {
365
+ enabled: true,
366
+ levels: ['log', 'warn', 'error'],
367
+ },
368
+
369
+ // Enhanced console.log/error with source locations
370
+ enhancedLogs: {
371
+ enabled: true,
372
+ },
373
+
374
+ // Strip devtools from production builds
375
+ removeDevtoolsOnBuild: true,
376
+
377
+ // Plugin console output
378
+ logging: true,
379
+
380
+ // Server event bus
381
+ eventBusConfig: {
382
+ port: 4206,
383
+ enabled: true,
384
+ debug: false,
385
+ },
386
+
387
+ // Editor integration (default: VS Code via launch-editor)
388
+ // editor: { name: 'VSCode', open: async (path, line, col) => { ... } },
389
+ }),
390
+ // ... framework plugin (react(), vue(), solid(), etc.)
391
+ ],
392
+ }
393
+ ```
394
+
395
+ ---
396
+
397
+ ## Defaults Summary
398
+
399
+ | Option | Default Value |
400
+ | ------------------------ | ------------------------------------------- |
401
+ | `injectSource.enabled` | `true` |
402
+ | `injectSource.ignore` | `undefined` (no ignores) |
403
+ | `consolePiping.enabled` | `true` |
404
+ | `consolePiping.levels` | `['log', 'warn', 'error', 'info', 'debug']` |
405
+ | `enhancedLogs.enabled` | `true` |
406
+ | `removeDevtoolsOnBuild` | `true` |
407
+ | `logging` | `true` |
408
+ | `eventBusConfig.enabled` | `true` |
409
+ | `eventBusConfig.port` | `4206` |
410
+ | `eventBusConfig.host` | Vite's `server.host` or `'localhost'` |
411
+ | `eventBusConfig.debug` | `false` |
412
+ | `editor.name` | `'VSCode'` |
413
+ | `editor.open` | Uses `launch-editor` |