@tanstack/devtools-vite 0.5.0 → 0.5.2
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/dist/esm/plugin.js +73 -28
- package/dist/esm/plugin.js.map +1 -1
- package/dist/esm/utils.js +1 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/plugin.ts +98 -63
- package/src/utils.ts +1 -0
package/dist/esm/plugin.js
CHANGED
|
@@ -22,6 +22,8 @@ const devtools = (args) => {
|
|
|
22
22
|
const consolePipingLevels = consolePipingConfig.levels ?? ["log", "warn", "error", "info", "debug"];
|
|
23
23
|
let devtoolsFileId = null;
|
|
24
24
|
let devtoolsPort = null;
|
|
25
|
+
let devtoolsHost = null;
|
|
26
|
+
let devtoolsProtocol = null;
|
|
25
27
|
return [
|
|
26
28
|
{
|
|
27
29
|
enforce: "pre",
|
|
@@ -29,10 +31,15 @@ const devtools = (args) => {
|
|
|
29
31
|
apply(config) {
|
|
30
32
|
return config.mode === "development" && injectSourceConfig.enabled;
|
|
31
33
|
},
|
|
32
|
-
transform
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
transform: {
|
|
35
|
+
filter: {
|
|
36
|
+
id: {
|
|
37
|
+
exclude: [/node_modules/, /\?raw/, /\/dist\//, /\/build\//]
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
handler(code, id) {
|
|
41
|
+
return addSourceToJsx(code, id, args?.injectSource?.ignore);
|
|
42
|
+
}
|
|
36
43
|
}
|
|
37
44
|
},
|
|
38
45
|
{
|
|
@@ -53,9 +60,17 @@ const devtools = (args) => {
|
|
|
53
60
|
async configureServer(server) {
|
|
54
61
|
if (serverBusEnabled) {
|
|
55
62
|
const preferredPort = args?.eventBusConfig?.port ?? 4206;
|
|
63
|
+
const isHttps = !!server.config.server.https;
|
|
64
|
+
const serverHost = typeof server.config.server.host === "string" ? server.config.server.host : "localhost";
|
|
65
|
+
devtoolsProtocol = isHttps ? "https" : "http";
|
|
66
|
+
devtoolsHost = serverHost;
|
|
56
67
|
const bus = new ServerEventBus({
|
|
57
68
|
...args?.eventBusConfig,
|
|
58
|
-
port: preferredPort
|
|
69
|
+
port: preferredPort,
|
|
70
|
+
host: serverHost,
|
|
71
|
+
// When HTTPS is enabled, piggyback on Vite's server
|
|
72
|
+
// so WebSocket/SSE connections share the same TLS certificate
|
|
73
|
+
...isHttps && server.httpServer ? { httpServer: server.httpServer } : {}
|
|
59
74
|
});
|
|
60
75
|
devtoolsPort = await bus.start();
|
|
61
76
|
}
|
|
@@ -342,24 +357,30 @@ ${chalk.greenBright(`[@tanstack/devtools-vite]`)} Removed devtools code from: ${
|
|
|
342
357
|
apply(config, { command }) {
|
|
343
358
|
return config.mode === "development" && command === "serve" && (consolePipingConfig.enabled ?? true);
|
|
344
359
|
},
|
|
345
|
-
transform
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
)
|
|
359
|
-
|
|
360
|
+
transform: {
|
|
361
|
+
filter: {
|
|
362
|
+
id: {
|
|
363
|
+
include: /\.(tsx?|jsx?)$/,
|
|
364
|
+
exclude: [/node_modules/, /\/dist\//, /\?/]
|
|
365
|
+
},
|
|
366
|
+
code: {
|
|
367
|
+
exclude: /__tsdConsolePipe/
|
|
368
|
+
// avoid transforming files that already contain the console pipe code
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
handler(code) {
|
|
372
|
+
const isRootEntry = /<html[\s>]/i.test(code) || code.includes("StartClient") || code.includes("hydrateRoot") || code.includes("createRoot") || code.includes("solid-js/web") && code.includes("render(");
|
|
373
|
+
if (isRootEntry) {
|
|
374
|
+
const viteServerUrl = `http://localhost:${port}`;
|
|
375
|
+
const inlineCode = generateConsolePipeCode(
|
|
376
|
+
consolePipingLevels,
|
|
377
|
+
viteServerUrl
|
|
378
|
+
);
|
|
379
|
+
return `${inlineCode}
|
|
360
380
|
${code}`;
|
|
381
|
+
}
|
|
382
|
+
return void 0;
|
|
361
383
|
}
|
|
362
|
-
return void 0;
|
|
363
384
|
}
|
|
364
385
|
},
|
|
365
386
|
{
|
|
@@ -368,10 +389,18 @@ ${code}`;
|
|
|
368
389
|
apply(config) {
|
|
369
390
|
return config.mode === "development" && enhancedLogsConfig.enabled;
|
|
370
391
|
},
|
|
371
|
-
transform
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
392
|
+
transform: {
|
|
393
|
+
filter: {
|
|
394
|
+
id: {
|
|
395
|
+
exclude: [/node_modules/, /\?raw/, /\/dist\//, /\/build\//]
|
|
396
|
+
},
|
|
397
|
+
code: {
|
|
398
|
+
include: "console."
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
handler(code, id) {
|
|
402
|
+
return enhanceConsoleLog(code, id, port);
|
|
403
|
+
}
|
|
375
404
|
}
|
|
376
405
|
},
|
|
377
406
|
{
|
|
@@ -390,16 +419,32 @@ ${code}`;
|
|
|
390
419
|
}
|
|
391
420
|
},
|
|
392
421
|
{
|
|
393
|
-
name: "@tanstack/devtools:
|
|
422
|
+
name: "@tanstack/devtools:connection-injection",
|
|
394
423
|
apply(config, { command }) {
|
|
395
424
|
return config.mode === "development" && command === "serve";
|
|
396
425
|
},
|
|
397
426
|
transform(code, id) {
|
|
398
|
-
|
|
427
|
+
const hasPlaceholder = code.includes("__TANSTACK_DEVTOOLS_PORT__") || code.includes("__TANSTACK_DEVTOOLS_HOST__") || code.includes("__TANSTACK_DEVTOOLS_PROTOCOL__");
|
|
428
|
+
if (!hasPlaceholder) return;
|
|
399
429
|
if (!id.includes("@tanstack/devtools") && !id.includes("@tanstack/event-bus"))
|
|
400
430
|
return;
|
|
401
431
|
const portValue = devtoolsPort ?? 4206;
|
|
402
|
-
|
|
432
|
+
const hostValue = devtoolsHost ?? "localhost";
|
|
433
|
+
const protocolValue = devtoolsProtocol ?? "http";
|
|
434
|
+
let result = code;
|
|
435
|
+
result = result.replace(
|
|
436
|
+
/__TANSTACK_DEVTOOLS_PORT__/g,
|
|
437
|
+
String(portValue)
|
|
438
|
+
);
|
|
439
|
+
result = result.replace(
|
|
440
|
+
/__TANSTACK_DEVTOOLS_HOST__/g,
|
|
441
|
+
JSON.stringify(hostValue)
|
|
442
|
+
);
|
|
443
|
+
result = result.replace(
|
|
444
|
+
/__TANSTACK_DEVTOOLS_PROTOCOL__/g,
|
|
445
|
+
JSON.stringify(protocolValue)
|
|
446
|
+
);
|
|
447
|
+
return result;
|
|
403
448
|
}
|
|
404
449
|
}
|
|
405
450
|
];
|
package/dist/esm/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["../../src/plugin.ts"],"sourcesContent":["import { devtoolsEventClient } from '@tanstack/devtools-client'\nimport { ServerEventBus } from '@tanstack/devtools-event-bus/server'\nimport { normalizePath } from 'vite'\nimport chalk from 'chalk'\nimport {\n handleDevToolsViteRequest,\n readPackageJson,\n stripEnhancedLogPrefix,\n} from './utils'\nimport { DEFAULT_EDITOR_CONFIG, handleOpenSource } from './editor'\nimport { removeDevtools } from './remove-devtools'\nimport { addSourceToJsx } from './inject-source'\nimport { enhanceConsoleLog } from './enhance-logs'\nimport { detectDevtoolsFile, injectPluginIntoFile } from './inject-plugin'\nimport {\n addPluginToDevtools,\n emitOutdatedDeps,\n installPackage,\n} from './package-manager'\nimport { generateConsolePipeCode } from './virtual-console'\nimport type { ServerResponse } from 'node:http'\nimport type { Plugin } from 'vite'\nimport type { EditorConfig } from './editor'\nimport type { ServerEventBusConfig } from '@tanstack/devtools-event-bus/server'\n\nexport type ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug'\n\nexport type TanStackDevtoolsViteConfig = {\n /**\n * Configuration for the editor integration. Defaults to opening in VS code\n */\n editor?: EditorConfig\n /**\n * The configuration options for the server event bus\n */\n eventBusConfig?: ServerEventBusConfig & {\n /**\n * Should the server event bus be enabled or not\n * @default true\n */\n enabled?: boolean // defaults to true\n }\n /**\n * Configuration for enhanced logging.\n */\n enhancedLogs?: {\n /**\n * Whether to enable enhanced logging.\n * @default true\n */\n enabled: boolean\n }\n /**\n * Whether to remove devtools from the production build.\n * @default true\n */\n removeDevtoolsOnBuild?: boolean\n\n /**\n * Whether to log information to the console.\n * @default true\n */\n logging?: boolean\n /**\n * Configuration for source injection.\n */\n injectSource?: {\n /**\n * Whether to enable source injection via data-tsd-source.\n * @default true\n */\n enabled: boolean\n /**\n * List of files or patterns to ignore for source injection.\n */\n ignore?: {\n files?: Array<string | RegExp>\n components?: Array<string | RegExp>\n }\n }\n /**\n * Configuration for console piping between client and server.\n * When enabled, console logs from the client will appear in the terminal,\n * and server logs will appear in the browser console.\n */\n consolePiping?: {\n /**\n * Whether to enable console piping.\n * @default true\n */\n enabled?: boolean\n /**\n * Which console methods to pipe.\n * @default ['log', 'warn', 'error', 'info', 'debug']\n */\n levels?: Array<ConsoleLevel>\n }\n}\n\nexport const defineDevtoolsConfig = (config: TanStackDevtoolsViteConfig) =>\n config\n\nexport const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {\n let port = 5173\n const logging = args?.logging ?? true\n const enhancedLogsConfig = args?.enhancedLogs ?? { enabled: true }\n const injectSourceConfig = args?.injectSource ?? { enabled: true }\n const removeDevtoolsOnBuild = args?.removeDevtoolsOnBuild ?? true\n const serverBusEnabled = args?.eventBusConfig?.enabled ?? true\n const consolePipingConfig = args?.consolePiping ?? { enabled: true }\n const consolePipingLevels: Array<ConsoleLevel> =\n consolePipingConfig.levels ?? ['log', 'warn', 'error', 'info', 'debug']\n\n let devtoolsFileId: string | null = null\n let devtoolsPort: number | null = null\n\n return [\n {\n enforce: 'pre',\n name: '@tanstack/devtools:inject-source',\n apply(config) {\n return config.mode === 'development' && injectSourceConfig.enabled\n },\n transform(code, id) {\n if (\n id.includes('node_modules') ||\n id.includes('?raw') ||\n id.includes('dist') ||\n id.includes('build')\n )\n return\n\n return addSourceToJsx(code, id, args?.injectSource?.ignore)\n },\n },\n {\n name: '@tanstack/devtools:config',\n enforce: 'pre',\n config(_, { command }) {\n // we do not apply any config changes for build\n if (command !== 'serve') {\n return\n }\n\n /* const solidDedupeDeps = [\n 'solid-js',\n 'solid-js/web',\n 'solid-js/store',\n 'solid-js/html',\n 'solid-js/h',\n ]\n\n return {\n resolve: {\n dedupe: solidDedupeDeps,\n },\n optimizeDeps: {\n include: solidDedupeDeps,\n },\n } */\n },\n },\n {\n enforce: 'pre',\n name: '@tanstack/devtools:custom-server',\n apply(config) {\n // Custom server is only needed in development for piping events to the client\n return config.mode === 'development'\n },\n async configureServer(server) {\n if (serverBusEnabled) {\n const preferredPort = args?.eventBusConfig?.port ?? 4206\n const bus = new ServerEventBus({\n ...args?.eventBusConfig,\n port: preferredPort,\n })\n // start() now handles EADDRINUSE and returns the actual port\n devtoolsPort = await bus.start()\n }\n\n server.middlewares.use((req, _res, next) => {\n if (req.socket.localPort && req.socket.localPort !== port) {\n port = req.socket.localPort\n }\n next()\n })\n if (server.config.server.port) {\n port = server.config.server.port\n }\n\n server.httpServer?.on('listening', () => {\n port = server.config.server.port\n })\n\n const editor = args?.editor ?? DEFAULT_EDITOR_CONFIG\n const openInEditor: EditorConfig['open'] = async (\n path,\n lineNum,\n columnNum,\n ) => {\n if (!path) {\n return\n }\n await editor.open(path, lineNum, columnNum)\n }\n\n // SSE clients for broadcasting server logs to browser\n const sseClients: Array<{\n res: ServerResponse\n id: number\n }> = []\n let sseClientId = 0\n const consolePipingEnabled = consolePipingConfig.enabled ?? true\n\n server.middlewares.use((req, res, next) =>\n handleDevToolsViteRequest(req, res, next, {\n onOpenSource: (parsedData) => {\n const { data, routine } = parsedData\n if (routine === 'open-source') {\n return handleOpenSource({\n data: { type: data.type, data },\n openInEditor,\n })\n }\n return\n },\n ...(consolePipingEnabled\n ? {\n onConsolePipe: (entries) => {\n for (const entry of entries) {\n const prefix = chalk.cyan('[Client]')\n const logMethod = console[entry.level as ConsoleLevel]\n const cleanedArgs = stripEnhancedLogPrefix(\n entry.args,\n (loc) => chalk.gray(loc),\n )\n logMethod(prefix, ...cleanedArgs)\n }\n },\n onConsolePipeSSE: (res, req) => {\n res.setHeader('Content-Type', 'text/event-stream')\n res.setHeader('Cache-Control', 'no-cache')\n res.setHeader('Connection', 'keep-alive')\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.flushHeaders()\n\n const clientId = ++sseClientId\n sseClients.push({ res, id: clientId })\n\n req.on('close', () => {\n const index = sseClients.findIndex(\n (c) => c.id === clientId,\n )\n if (index !== -1) {\n sseClients.splice(index, 1)\n }\n })\n },\n onServerConsolePipe: (entries) => {\n try {\n const data = JSON.stringify({\n entries: entries.map((e) => ({\n level: e.level,\n args: e.args,\n source: 'server',\n timestamp: e.timestamp || Date.now(),\n })),\n })\n\n for (const client of sseClients) {\n client.res.write(`data: ${data}\\n\\n`)\n }\n } catch {}\n },\n }\n : {}),\n }),\n )\n },\n },\n {\n name: '@tanstack/devtools:remove-devtools-on-build',\n apply(config, { command }) {\n // Check both command and mode to support various hosting providers\n // Some providers (Cloudflare, Netlify, Heroku) might not use 'build' command\n // but will always set mode to 'production' for production builds\n return (\n (command !== 'serve' || config.mode === 'production') &&\n removeDevtoolsOnBuild\n )\n },\n enforce: 'pre',\n transform(code, id) {\n const devtoolPackages = [\n '@tanstack/react-devtools',\n '@tanstack/preact-devtools',\n '@tanstack/solid-devtools',\n '@tanstack/vue-devtools',\n '@tanstack/devtools',\n ]\n if (\n id.includes('node_modules') ||\n id.includes('?raw') ||\n !devtoolPackages.some((pkg) => code.includes(pkg))\n )\n return\n const transform = removeDevtools(code, id)\n if (!transform) return\n if (logging) {\n console.log(\n `\\n${chalk.greenBright(`[@tanstack/devtools-vite]`)} Removed devtools code from: ${id.replace(normalizePath(process.cwd()), '')}\\n`,\n )\n }\n return transform\n },\n },\n {\n name: '@tanstack/devtools:event-client-setup',\n apply(config, { command }) {\n if (\n process.env.CI ||\n process.env.NODE_ENV !== 'development' ||\n command !== 'serve'\n )\n return false\n return config.mode === 'development'\n },\n async configureServer() {\n const packageJson = await readPackageJson()\n const outdatedDeps = emitOutdatedDeps().then((deps) => deps)\n\n // Listen for package installation requests\n devtoolsEventClient.on('install-devtools', async (event) => {\n const result = await installPackage(event.payload.packageName)\n devtoolsEventClient.emit('devtools-installed', {\n packageName: event.payload.packageName,\n success: result.success,\n error: result.error,\n })\n\n // If installation was successful, automatically add the plugin to devtools\n if (result.success) {\n const { packageName, pluginName, pluginImport } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Auto-adding ${packageName} to devtools...`,\n ),\n )\n\n const injectResult = addPluginToDevtools(\n devtoolsFileId,\n packageName,\n pluginName,\n pluginImport,\n )\n\n if (injectResult.success) {\n // Emit plugin-added event so the UI updates\n devtoolsEventClient.emit('plugin-added', {\n packageName,\n success: true,\n })\n\n // Also re-read package.json to update the UI with the newly installed package\n const updatedPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: updatedPackageJson,\n })\n }\n }\n })\n\n // Listen for add plugin to devtools requests\n devtoolsEventClient.on('add-plugin-to-devtools', (event) => {\n const { packageName, pluginName, pluginImport } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Adding ${packageName} to devtools...`,\n ),\n )\n\n const result = addPluginToDevtools(\n devtoolsFileId,\n packageName,\n pluginName,\n pluginImport,\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName,\n success: result.success,\n error: result.error,\n })\n })\n\n // Handle bump-package-version event\n devtoolsEventClient.on('bump-package-version', async (event) => {\n const {\n packageName,\n devtoolsPackage,\n pluginName,\n minVersion,\n pluginImport,\n } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Bumping ${packageName} to version ${minVersion}...`,\n ),\n )\n\n // Install the package with the minimum version\n const packageWithVersion = minVersion\n ? `${packageName}@^${minVersion}`\n : packageName\n\n const result = await installPackage(packageWithVersion)\n\n if (!result.success) {\n console.log(\n chalk.redBright(\n `[@tanstack/devtools-vite] Failed to bump ${packageName}: ${result.error}`,\n ),\n )\n devtoolsEventClient.emit('devtools-installed', {\n packageName: devtoolsPackage,\n success: false,\n error: result.error,\n })\n return\n }\n\n console.log(\n chalk.greenBright(\n `[@tanstack/devtools-vite] Successfully bumped ${packageName} to ${minVersion}!`,\n ),\n )\n\n // Check if we found the devtools file\n if (!devtoolsFileId) {\n console.log(\n chalk.yellowBright(\n `[@tanstack/devtools-vite] Devtools file not found. Skipping auto-injection.`,\n ),\n )\n devtoolsEventClient.emit('devtools-installed', {\n packageName: devtoolsPackage,\n success: true,\n })\n return\n }\n\n // Now inject the devtools plugin\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Adding ${devtoolsPackage} to devtools...`,\n ),\n )\n\n const injectResult = injectPluginIntoFile(devtoolsFileId, {\n packageName: devtoolsPackage,\n pluginName,\n pluginImport,\n })\n\n if (injectResult.success) {\n console.log(\n chalk.greenBright(\n `[@tanstack/devtools-vite] Successfully added ${devtoolsPackage} to devtools!`,\n ),\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName: devtoolsPackage,\n success: true,\n })\n\n // Re-read package.json to update the UI\n const updatedPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: updatedPackageJson,\n })\n } else {\n console.log(\n chalk.redBright(\n `[@tanstack/devtools-vite] Failed to add ${devtoolsPackage} to devtools: ${injectResult.error}`,\n ),\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName: devtoolsPackage,\n success: false,\n error: injectResult.error,\n })\n }\n })\n\n // whenever a client mounts we send all the current info to the subscribers\n devtoolsEventClient.on('mounted', async () => {\n devtoolsEventClient.emit('outdated-deps-read', {\n outdatedDeps: await outdatedDeps,\n })\n devtoolsEventClient.emit('package-json-read', {\n packageJson,\n })\n })\n\n // Console piping is now handled via HTTP endpoints in the custom-server plugin\n },\n async handleHotUpdate({ file }) {\n if (file.endsWith('package.json')) {\n const newPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: newPackageJson,\n })\n emitOutdatedDeps()\n }\n },\n },\n // Inject console piping code into entry files (both client and server)\n {\n name: '@tanstack/devtools:console-pipe-transform',\n enforce: 'pre',\n apply(config, { command }) {\n return (\n config.mode === 'development' &&\n command === 'serve' &&\n (consolePipingConfig.enabled ?? true)\n )\n },\n transform(code, id) {\n // Inject the console pipe code into entry files\n if (\n id.includes('node_modules') ||\n id.includes('dist') ||\n id.includes('?') ||\n !id.match(/\\.(tsx?|jsx?)$/)\n ) {\n return\n }\n\n // Only inject once - check if already injected\n if (code.includes('__tsdConsolePipe')) {\n return\n }\n\n // Check if this is a root entry file (with <html> JSX or client entry points)\n // In SSR frameworks, this file runs on BOTH server (SSR) and client (hydration)\n // so our runtime check (typeof window === 'undefined') handles both environments\n const isRootEntry =\n /<html[\\s>]/i.test(code) ||\n code.includes('StartClient') ||\n code.includes('hydrateRoot') ||\n code.includes('createRoot') ||\n (code.includes('solid-js/web') && code.includes('render('))\n\n if (isRootEntry) {\n const viteServerUrl = `http://localhost:${port}`\n const inlineCode = generateConsolePipeCode(\n consolePipingLevels,\n viteServerUrl,\n )\n\n return `${inlineCode}\\n${code}`\n }\n\n return undefined\n },\n },\n {\n name: '@tanstack/devtools:better-console-logs',\n enforce: 'pre',\n apply(config) {\n return config.mode === 'development' && enhancedLogsConfig.enabled\n },\n transform(code, id) {\n // Ignore anything external\n if (\n id.includes('node_modules') ||\n id.includes('?raw') ||\n id.includes('dist') ||\n id.includes('build') ||\n !code.includes('console.')\n )\n return\n\n return enhanceConsoleLog(code, id, port)\n },\n },\n {\n name: '@tanstack/devtools:inject-plugin',\n apply(config, { command }) {\n return config.mode === 'development' && command === 'serve'\n },\n transform(code, id) {\n // First pass: find where TanStackDevtools is imported\n if (!devtoolsFileId && detectDevtoolsFile(code)) {\n // Extract actual file path (remove query params)\n const [filePath] = id.split('?')\n if (filePath) {\n devtoolsFileId = filePath\n }\n }\n\n return undefined\n },\n },\n {\n name: '@tanstack/devtools:port-injection',\n apply(config, { command }) {\n return config.mode === 'development' && command === 'serve'\n },\n transform(code, id) {\n // Only transform @tanstack packages that contain the port placeholder\n if (!code.includes('__TANSTACK_DEVTOOLS_PORT__')) return\n if (\n !id.includes('@tanstack/devtools') &&\n !id.includes('@tanstack/event-bus')\n )\n return\n\n // Replace placeholder with actual port (or fallback to 4206 if not resolved yet)\n const portValue = devtoolsPort ?? 4206\n return code.replace(/__TANSTACK_DEVTOOLS_PORT__/g, String(portValue))\n },\n },\n ]\n}\n"],"names":["res","req"],"mappings":";;;;;;;;;;;;AAmGO,MAAM,uBAAuB,CAAC,WACnC;AAEK,MAAM,WAAW,CAAC,SAAqD;AAC5E,MAAI,OAAO;AACX,QAAM,UAAU,MAAM,WAAW;AACjC,QAAM,qBAAqB,MAAM,gBAAgB,EAAE,SAAS,KAAA;AAC5D,QAAM,qBAAqB,MAAM,gBAAgB,EAAE,SAAS,KAAA;AAC5D,QAAM,wBAAwB,MAAM,yBAAyB;AAC7D,QAAM,mBAAmB,MAAM,gBAAgB,WAAW;AAC1D,QAAM,sBAAsB,MAAM,iBAAiB,EAAE,SAAS,KAAA;AAC9D,QAAM,sBACJ,oBAAoB,UAAU,CAAC,OAAO,QAAQ,SAAS,QAAQ,OAAO;AAExE,MAAI,iBAAgC;AACpC,MAAI,eAA8B;AAElC,SAAO;AAAA,IACL;AAAA,MACE,SAAS;AAAA,MACT,MAAM;AAAA,MACN,MAAM,QAAQ;AACZ,eAAO,OAAO,SAAS,iBAAiB,mBAAmB;AAAA,MAC7D;AAAA,MACA,UAAU,MAAM,IAAI;AAClB,YACE,GAAG,SAAS,cAAc,KAC1B,GAAG,SAAS,MAAM,KAClB,GAAG,SAAS,MAAM,KAClB,GAAG,SAAS,OAAO;AAEnB;AAEF,eAAO,eAAe,MAAM,IAAI,MAAM,cAAc,MAAM;AAAA,MAC5D;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO,GAAG,EAAE,WAAW;AAErB,YAAI,YAAY,SAAS;AACvB;AAAA,QACF;AAAA,MAkBF;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,SAAS;AAAA,MACT,MAAM;AAAA,MACN,MAAM,QAAQ;AAEZ,eAAO,OAAO,SAAS;AAAA,MACzB;AAAA,MACA,MAAM,gBAAgB,QAAQ;AAC5B,YAAI,kBAAkB;AACpB,gBAAM,gBAAgB,MAAM,gBAAgB,QAAQ;AACpD,gBAAM,MAAM,IAAI,eAAe;AAAA,YAC7B,GAAG,MAAM;AAAA,YACT,MAAM;AAAA,UAAA,CACP;AAED,yBAAe,MAAM,IAAI,MAAA;AAAA,QAC3B;AAEA,eAAO,YAAY,IAAI,CAAC,KAAK,MAAM,SAAS;AAC1C,cAAI,IAAI,OAAO,aAAa,IAAI,OAAO,cAAc,MAAM;AACzD,mBAAO,IAAI,OAAO;AAAA,UACpB;AACA,eAAA;AAAA,QACF,CAAC;AACD,YAAI,OAAO,OAAO,OAAO,MAAM;AAC7B,iBAAO,OAAO,OAAO,OAAO;AAAA,QAC9B;AAEA,eAAO,YAAY,GAAG,aAAa,MAAM;AACvC,iBAAO,OAAO,OAAO,OAAO;AAAA,QAC9B,CAAC;AAED,cAAM,SAAS,MAAM,UAAU;AAC/B,cAAM,eAAqC,OACzC,MACA,SACA,cACG;AACH,cAAI,CAAC,MAAM;AACT;AAAA,UACF;AACA,gBAAM,OAAO,KAAK,MAAM,SAAS,SAAS;AAAA,QAC5C;AAGA,cAAM,aAGD,CAAA;AACL,YAAI,cAAc;AAClB,cAAM,uBAAuB,oBAAoB,WAAW;AAE5D,eAAO,YAAY;AAAA,UAAI,CAAC,KAAK,KAAK,SAChC,0BAA0B,KAAK,KAAK,MAAM;AAAA,YACxC,cAAc,CAAC,eAAe;AAC5B,oBAAM,EAAE,MAAM,QAAA,IAAY;AAC1B,kBAAI,YAAY,eAAe;AAC7B,uBAAO,iBAAiB;AAAA,kBACtB,MAAM,EAAE,MAAM,KAAK,MAAM,KAAA;AAAA,kBACzB;AAAA,gBAAA,CACD;AAAA,cACH;AACA;AAAA,YACF;AAAA,YACA,GAAI,uBACA;AAAA,cACE,eAAe,CAAC,YAAY;AAC1B,2BAAW,SAAS,SAAS;AAC3B,wBAAM,SAAS,MAAM,KAAK,UAAU;AACpC,wBAAM,YAAY,QAAQ,MAAM,KAAqB;AACrD,wBAAM,cAAc;AAAA,oBAClB,MAAM;AAAA,oBACN,CAAC,QAAQ,MAAM,KAAK,GAAG;AAAA,kBAAA;AAEzB,4BAAU,QAAQ,GAAG,WAAW;AAAA,gBAClC;AAAA,cACF;AAAA,cACA,kBAAkB,CAACA,MAAKC,SAAQ;AAC9BD,qBAAI,UAAU,gBAAgB,mBAAmB;AACjDA,qBAAI,UAAU,iBAAiB,UAAU;AACzCA,qBAAI,UAAU,cAAc,YAAY;AACxCA,qBAAI,UAAU,+BAA+B,GAAG;AAChDA,qBAAI,aAAA;AAEJ,sBAAM,WAAW,EAAE;AACnB,2BAAW,KAAK,EAAE,KAAAA,MAAK,IAAI,UAAU;AAErCC,qBAAI,GAAG,SAAS,MAAM;AACpB,wBAAM,QAAQ,WAAW;AAAA,oBACvB,CAAC,MAAM,EAAE,OAAO;AAAA,kBAAA;AAElB,sBAAI,UAAU,IAAI;AAChB,+BAAW,OAAO,OAAO,CAAC;AAAA,kBAC5B;AAAA,gBACF,CAAC;AAAA,cACH;AAAA,cACA,qBAAqB,CAAC,YAAY;AAChC,oBAAI;AACF,wBAAM,OAAO,KAAK,UAAU;AAAA,oBAC1B,SAAS,QAAQ,IAAI,CAAC,OAAO;AAAA,sBAC3B,OAAO,EAAE;AAAA,sBACT,MAAM,EAAE;AAAA,sBACR,QAAQ;AAAA,sBACR,WAAW,EAAE,aAAa,KAAK,IAAA;AAAA,oBAAI,EACnC;AAAA,kBAAA,CACH;AAED,6BAAW,UAAU,YAAY;AAC/B,2BAAO,IAAI,MAAM,SAAS,IAAI;AAAA;AAAA,CAAM;AAAA,kBACtC;AAAA,gBACF,QAAQ;AAAA,gBAAC;AAAA,cACX;AAAA,YAAA,IAEF,CAAA;AAAA,UAAC,CACN;AAAA,QAAA;AAAA,MAEL;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,MAAM;AAAA,MACN,MAAM,QAAQ,EAAE,WAAW;AAIzB,gBACG,YAAY,WAAW,OAAO,SAAS,iBACxC;AAAA,MAEJ;AAAA,MACA,SAAS;AAAA,MACT,UAAU,MAAM,IAAI;AAClB,cAAM,kBAAkB;AAAA,UACtB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAEF,YACE,GAAG,SAAS,cAAc,KAC1B,GAAG,SAAS,MAAM,KAClB,CAAC,gBAAgB,KAAK,CAAC,QAAQ,KAAK,SAAS,GAAG,CAAC;AAEjD;AACF,cAAM,YAAY,eAAe,MAAM,EAAE;AACzC,YAAI,CAAC,UAAW;AAChB,YAAI,SAAS;AACX,kBAAQ;AAAA,YACN;AAAA,EAAK,MAAM,YAAY,2BAA2B,CAAC,gCAAgC,GAAG,QAAQ,cAAc,QAAQ,IAAA,CAAK,GAAG,EAAE,CAAC;AAAA;AAAA,UAAA;AAAA,QAEnI;AACA,eAAO;AAAA,MACT;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,MAAM;AAAA,MACN,MAAM,QAAQ,EAAE,WAAW;AACzB,YACE,QAAQ,IAAI,MACZ,QAAQ,IAAI,aAAa,iBACzB,YAAY;AAEZ,iBAAO;AACT,eAAO,OAAO,SAAS;AAAA,MACzB;AAAA,MACA,MAAM,kBAAkB;AACtB,cAAM,cAAc,MAAM,gBAAA;AAC1B,cAAM,eAAe,iBAAA,EAAmB,KAAK,CAAC,SAAS,IAAI;AAG3D,4BAAoB,GAAG,oBAAoB,OAAO,UAAU;AAC1D,gBAAM,SAAS,MAAM,eAAe,MAAM,QAAQ,WAAW;AAC7D,8BAAoB,KAAK,sBAAsB;AAAA,YAC7C,aAAa,MAAM,QAAQ;AAAA,YAC3B,SAAS,OAAO;AAAA,YAChB,OAAO,OAAO;AAAA,UAAA,CACf;AAGD,cAAI,OAAO,SAAS;AAClB,kBAAM,EAAE,aAAa,YAAY,aAAA,IAAiB,MAAM;AAExD,oBAAQ;AAAA,cACN,MAAM;AAAA,gBACJ,yCAAyC,WAAW;AAAA,cAAA;AAAA,YACtD;AAGF,kBAAM,eAAe;AAAA,cACnB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAGF,gBAAI,aAAa,SAAS;AAExB,kCAAoB,KAAK,gBAAgB;AAAA,gBACvC;AAAA,gBACA,SAAS;AAAA,cAAA,CACV;AAGD,oBAAM,qBAAqB,MAAM,gBAAA;AACjC,kCAAoB,KAAK,qBAAqB;AAAA,gBAC5C,aAAa;AAAA,cAAA,CACd;AAAA,YACH;AAAA,UACF;AAAA,QACF,CAAC;AAGD,4BAAoB,GAAG,0BAA0B,CAAC,UAAU;AAC1D,gBAAM,EAAE,aAAa,YAAY,aAAA,IAAiB,MAAM;AAExD,kBAAQ;AAAA,YACN,MAAM;AAAA,cACJ,oCAAoC,WAAW;AAAA,YAAA;AAAA,UACjD;AAGF,gBAAM,SAAS;AAAA,YACb;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAGF,8BAAoB,KAAK,gBAAgB;AAAA,YACvC;AAAA,YACA,SAAS,OAAO;AAAA,YAChB,OAAO,OAAO;AAAA,UAAA,CACf;AAAA,QACH,CAAC;AAGD,4BAAoB,GAAG,wBAAwB,OAAO,UAAU;AAC9D,gBAAM;AAAA,YACJ;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA,IACE,MAAM;AAEV,kBAAQ;AAAA,YACN,MAAM;AAAA,cACJ,qCAAqC,WAAW,eAAe,UAAU;AAAA,YAAA;AAAA,UAC3E;AAIF,gBAAM,qBAAqB,aACvB,GAAG,WAAW,KAAK,UAAU,KAC7B;AAEJ,gBAAM,SAAS,MAAM,eAAe,kBAAkB;AAEtD,cAAI,CAAC,OAAO,SAAS;AACnB,oBAAQ;AAAA,cACN,MAAM;AAAA,gBACJ,4CAA4C,WAAW,KAAK,OAAO,KAAK;AAAA,cAAA;AAAA,YAC1E;AAEF,gCAAoB,KAAK,sBAAsB;AAAA,cAC7C,aAAa;AAAA,cACb,SAAS;AAAA,cACT,OAAO,OAAO;AAAA,YAAA,CACf;AACD;AAAA,UACF;AAEA,kBAAQ;AAAA,YACN,MAAM;AAAA,cACJ,iDAAiD,WAAW,OAAO,UAAU;AAAA,YAAA;AAAA,UAC/E;AAIF,cAAI,CAAC,gBAAgB;AACnB,oBAAQ;AAAA,cACN,MAAM;AAAA,gBACJ;AAAA,cAAA;AAAA,YACF;AAEF,gCAAoB,KAAK,sBAAsB;AAAA,cAC7C,aAAa;AAAA,cACb,SAAS;AAAA,YAAA,CACV;AACD;AAAA,UACF;AAGA,kBAAQ;AAAA,YACN,MAAM;AAAA,cACJ,oCAAoC,eAAe;AAAA,YAAA;AAAA,UACrD;AAGF,gBAAM,eAAe,qBAAqB,gBAAgB;AAAA,YACxD,aAAa;AAAA,YACb;AAAA,YACA;AAAA,UAAA,CACD;AAED,cAAI,aAAa,SAAS;AACxB,oBAAQ;AAAA,cACN,MAAM;AAAA,gBACJ,gDAAgD,eAAe;AAAA,cAAA;AAAA,YACjE;AAGF,gCAAoB,KAAK,gBAAgB;AAAA,cACvC,aAAa;AAAA,cACb,SAAS;AAAA,YAAA,CACV;AAGD,kBAAM,qBAAqB,MAAM,gBAAA;AACjC,gCAAoB,KAAK,qBAAqB;AAAA,cAC5C,aAAa;AAAA,YAAA,CACd;AAAA,UACH,OAAO;AACL,oBAAQ;AAAA,cACN,MAAM;AAAA,gBACJ,2CAA2C,eAAe,iBAAiB,aAAa,KAAK;AAAA,cAAA;AAAA,YAC/F;AAGF,gCAAoB,KAAK,gBAAgB;AAAA,cACvC,aAAa;AAAA,cACb,SAAS;AAAA,cACT,OAAO,aAAa;AAAA,YAAA,CACrB;AAAA,UACH;AAAA,QACF,CAAC;AAGD,4BAAoB,GAAG,WAAW,YAAY;AAC5C,8BAAoB,KAAK,sBAAsB;AAAA,YAC7C,cAAc,MAAM;AAAA,UAAA,CACrB;AACD,8BAAoB,KAAK,qBAAqB;AAAA,YAC5C;AAAA,UAAA,CACD;AAAA,QACH,CAAC;AAAA,MAGH;AAAA,MACA,MAAM,gBAAgB,EAAE,QAAQ;AAC9B,YAAI,KAAK,SAAS,cAAc,GAAG;AACjC,gBAAM,iBAAiB,MAAM,gBAAA;AAC7B,8BAAoB,KAAK,qBAAqB;AAAA,YAC5C,aAAa;AAAA,UAAA,CACd;AACD,2BAAA;AAAA,QACF;AAAA,MACF;AAAA,IAAA;AAAA;AAAA,IAGF;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM,QAAQ,EAAE,WAAW;AACzB,eACE,OAAO,SAAS,iBAChB,YAAY,YACX,oBAAoB,WAAW;AAAA,MAEpC;AAAA,MACA,UAAU,MAAM,IAAI;AAElB,YACE,GAAG,SAAS,cAAc,KAC1B,GAAG,SAAS,MAAM,KAClB,GAAG,SAAS,GAAG,KACf,CAAC,GAAG,MAAM,gBAAgB,GAC1B;AACA;AAAA,QACF;AAGA,YAAI,KAAK,SAAS,kBAAkB,GAAG;AACrC;AAAA,QACF;AAKA,cAAM,cACJ,cAAc,KAAK,IAAI,KACvB,KAAK,SAAS,aAAa,KAC3B,KAAK,SAAS,aAAa,KAC3B,KAAK,SAAS,YAAY,KACzB,KAAK,SAAS,cAAc,KAAK,KAAK,SAAS,SAAS;AAE3D,YAAI,aAAa;AACf,gBAAM,gBAAgB,oBAAoB,IAAI;AAC9C,gBAAM,aAAa;AAAA,YACjB;AAAA,YACA;AAAA,UAAA;AAGF,iBAAO,GAAG,UAAU;AAAA,EAAK,IAAI;AAAA,QAC/B;AAEA,eAAO;AAAA,MACT;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM,QAAQ;AACZ,eAAO,OAAO,SAAS,iBAAiB,mBAAmB;AAAA,MAC7D;AAAA,MACA,UAAU,MAAM,IAAI;AAElB,YACE,GAAG,SAAS,cAAc,KAC1B,GAAG,SAAS,MAAM,KAClB,GAAG,SAAS,MAAM,KAClB,GAAG,SAAS,OAAO,KACnB,CAAC,KAAK,SAAS,UAAU;AAEzB;AAEF,eAAO,kBAAkB,MAAM,IAAI,IAAI;AAAA,MACzC;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,MAAM;AAAA,MACN,MAAM,QAAQ,EAAE,WAAW;AACzB,eAAO,OAAO,SAAS,iBAAiB,YAAY;AAAA,MACtD;AAAA,MACA,UAAU,MAAM,IAAI;AAElB,YAAI,CAAC,kBAAkB,mBAAmB,IAAI,GAAG;AAE/C,gBAAM,CAAC,QAAQ,IAAI,GAAG,MAAM,GAAG;AAC/B,cAAI,UAAU;AACZ,6BAAiB;AAAA,UACnB;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,MAAM;AAAA,MACN,MAAM,QAAQ,EAAE,WAAW;AACzB,eAAO,OAAO,SAAS,iBAAiB,YAAY;AAAA,MACtD;AAAA,MACA,UAAU,MAAM,IAAI;AAElB,YAAI,CAAC,KAAK,SAAS,4BAA4B,EAAG;AAClD,YACE,CAAC,GAAG,SAAS,oBAAoB,KACjC,CAAC,GAAG,SAAS,qBAAqB;AAElC;AAGF,cAAM,YAAY,gBAAgB;AAClC,eAAO,KAAK,QAAQ,+BAA+B,OAAO,SAAS,CAAC;AAAA,MACtE;AAAA,IAAA;AAAA,EACF;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["../../src/plugin.ts"],"sourcesContent":["import { devtoolsEventClient } from '@tanstack/devtools-client'\nimport { ServerEventBus } from '@tanstack/devtools-event-bus/server'\nimport { normalizePath } from 'vite'\nimport chalk from 'chalk'\nimport {\n handleDevToolsViteRequest,\n readPackageJson,\n stripEnhancedLogPrefix,\n} from './utils'\nimport { DEFAULT_EDITOR_CONFIG, handleOpenSource } from './editor'\nimport { removeDevtools } from './remove-devtools'\nimport { addSourceToJsx } from './inject-source'\nimport { enhanceConsoleLog } from './enhance-logs'\nimport { detectDevtoolsFile, injectPluginIntoFile } from './inject-plugin'\nimport {\n addPluginToDevtools,\n emitOutdatedDeps,\n installPackage,\n} from './package-manager'\nimport { generateConsolePipeCode } from './virtual-console'\nimport type { ServerResponse } from 'node:http'\nimport type { Plugin } from 'vite'\nimport type { EditorConfig } from './editor'\nimport type {\n HttpServerLike,\n ServerEventBusConfig,\n} from '@tanstack/devtools-event-bus/server'\n\nexport type ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug'\n\nexport type TanStackDevtoolsViteConfig = {\n /**\n * Configuration for the editor integration. Defaults to opening in VS code\n */\n editor?: EditorConfig\n /**\n * The configuration options for the server event bus\n */\n eventBusConfig?: ServerEventBusConfig & {\n /**\n * Should the server event bus be enabled or not\n * @default true\n */\n enabled?: boolean // defaults to true\n }\n /**\n * Configuration for enhanced logging.\n */\n enhancedLogs?: {\n /**\n * Whether to enable enhanced logging.\n * @default true\n */\n enabled: boolean\n }\n /**\n * Whether to remove devtools from the production build.\n * @default true\n */\n removeDevtoolsOnBuild?: boolean\n\n /**\n * Whether to log information to the console.\n * @default true\n */\n logging?: boolean\n /**\n * Configuration for source injection.\n */\n injectSource?: {\n /**\n * Whether to enable source injection via data-tsd-source.\n * @default true\n */\n enabled: boolean\n /**\n * List of files or patterns to ignore for source injection.\n */\n ignore?: {\n files?: Array<string | RegExp>\n components?: Array<string | RegExp>\n }\n }\n /**\n * Configuration for console piping between client and server.\n * When enabled, console logs from the client will appear in the terminal,\n * and server logs will appear in the browser console.\n */\n consolePiping?: {\n /**\n * Whether to enable console piping.\n * @default true\n */\n enabled?: boolean\n /**\n * Which console methods to pipe.\n * @default ['log', 'warn', 'error', 'info', 'debug']\n */\n levels?: Array<ConsoleLevel>\n }\n}\n\nexport const defineDevtoolsConfig = (config: TanStackDevtoolsViteConfig) =>\n config\n\nexport const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {\n let port = 5173\n const logging = args?.logging ?? true\n const enhancedLogsConfig = args?.enhancedLogs ?? { enabled: true }\n const injectSourceConfig = args?.injectSource ?? { enabled: true }\n const removeDevtoolsOnBuild = args?.removeDevtoolsOnBuild ?? true\n const serverBusEnabled = args?.eventBusConfig?.enabled ?? true\n const consolePipingConfig = args?.consolePiping ?? { enabled: true }\n const consolePipingLevels: Array<ConsoleLevel> =\n consolePipingConfig.levels ?? ['log', 'warn', 'error', 'info', 'debug']\n\n let devtoolsFileId: string | null = null\n let devtoolsPort: number | null = null\n let devtoolsHost: string | null = null\n let devtoolsProtocol: 'http' | 'https' | null = null\n\n return [\n {\n enforce: 'pre',\n name: '@tanstack/devtools:inject-source',\n apply(config) {\n return config.mode === 'development' && injectSourceConfig.enabled\n },\n transform: {\n filter: {\n id: {\n exclude: [/node_modules/, /\\?raw/, /\\/dist\\//, /\\/build\\//],\n },\n },\n handler(code, id) {\n return addSourceToJsx(code, id, args?.injectSource?.ignore)\n },\n },\n },\n {\n name: '@tanstack/devtools:config',\n enforce: 'pre',\n config(_, { command }) {\n // we do not apply any config changes for build\n if (command !== 'serve') {\n return\n }\n\n /* const solidDedupeDeps = [\n 'solid-js',\n 'solid-js/web',\n 'solid-js/store',\n 'solid-js/html',\n 'solid-js/h',\n ]\n\n return {\n resolve: {\n dedupe: solidDedupeDeps,\n },\n optimizeDeps: {\n include: solidDedupeDeps,\n },\n } */\n },\n },\n {\n enforce: 'pre',\n name: '@tanstack/devtools:custom-server',\n apply(config) {\n // Custom server is only needed in development for piping events to the client\n return config.mode === 'development'\n },\n async configureServer(server) {\n if (serverBusEnabled) {\n const preferredPort = args?.eventBusConfig?.port ?? 4206\n const isHttps = !!server.config.server.https\n const serverHost =\n typeof server.config.server.host === 'string'\n ? server.config.server.host\n : 'localhost'\n\n devtoolsProtocol = isHttps ? 'https' : 'http'\n devtoolsHost = serverHost\n\n const bus = new ServerEventBus({\n ...args?.eventBusConfig,\n port: preferredPort,\n host: serverHost,\n // When HTTPS is enabled, piggyback on Vite's server\n // so WebSocket/SSE connections share the same TLS certificate\n ...(isHttps && server.httpServer\n ? { httpServer: server.httpServer as HttpServerLike }\n : {}),\n })\n // start() now handles EADDRINUSE and returns the actual port\n devtoolsPort = await bus.start()\n }\n\n server.middlewares.use((req, _res, next) => {\n if (req.socket.localPort && req.socket.localPort !== port) {\n port = req.socket.localPort\n }\n next()\n })\n if (server.config.server.port) {\n port = server.config.server.port\n }\n\n server.httpServer?.on('listening', () => {\n port = server.config.server.port\n })\n\n const editor = args?.editor ?? DEFAULT_EDITOR_CONFIG\n const openInEditor: EditorConfig['open'] = async (\n path,\n lineNum,\n columnNum,\n ) => {\n if (!path) {\n return\n }\n await editor.open(path, lineNum, columnNum)\n }\n\n // SSE clients for broadcasting server logs to browser\n const sseClients: Array<{\n res: ServerResponse\n id: number\n }> = []\n let sseClientId = 0\n const consolePipingEnabled = consolePipingConfig.enabled ?? true\n\n server.middlewares.use((req, res, next) =>\n handleDevToolsViteRequest(req, res, next, {\n onOpenSource: (parsedData) => {\n const { data, routine } = parsedData\n if (routine === 'open-source') {\n return handleOpenSource({\n data: { type: data.type, data },\n openInEditor,\n })\n }\n return\n },\n ...(consolePipingEnabled\n ? {\n onConsolePipe: (entries) => {\n for (const entry of entries) {\n const prefix = chalk.cyan('[Client]')\n const logMethod = console[entry.level as ConsoleLevel]\n const cleanedArgs = stripEnhancedLogPrefix(\n entry.args,\n (loc) => chalk.gray(loc),\n )\n logMethod(prefix, ...cleanedArgs)\n }\n },\n onConsolePipeSSE: (res, req) => {\n res.setHeader('Content-Type', 'text/event-stream')\n res.setHeader('Cache-Control', 'no-cache')\n res.setHeader('Connection', 'keep-alive')\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.flushHeaders()\n\n const clientId = ++sseClientId\n sseClients.push({ res, id: clientId })\n\n req.on('close', () => {\n const index = sseClients.findIndex(\n (c) => c.id === clientId,\n )\n if (index !== -1) {\n sseClients.splice(index, 1)\n }\n })\n },\n onServerConsolePipe: (entries) => {\n try {\n const data = JSON.stringify({\n entries: entries.map((e) => ({\n level: e.level,\n args: e.args,\n source: 'server',\n timestamp: e.timestamp || Date.now(),\n })),\n })\n\n for (const client of sseClients) {\n client.res.write(`data: ${data}\\n\\n`)\n }\n } catch {}\n },\n }\n : {}),\n }),\n )\n },\n },\n {\n name: '@tanstack/devtools:remove-devtools-on-build',\n apply(config, { command }) {\n // Check both command and mode to support various hosting providers\n // Some providers (Cloudflare, Netlify, Heroku) might not use 'build' command\n // but will always set mode to 'production' for production builds\n return (\n (command !== 'serve' || config.mode === 'production') &&\n removeDevtoolsOnBuild\n )\n },\n enforce: 'pre',\n transform(code, id) {\n const devtoolPackages = [\n '@tanstack/react-devtools',\n '@tanstack/preact-devtools',\n '@tanstack/solid-devtools',\n '@tanstack/vue-devtools',\n '@tanstack/devtools',\n ]\n if (\n id.includes('node_modules') ||\n id.includes('?raw') ||\n !devtoolPackages.some((pkg) => code.includes(pkg))\n )\n return\n const transform = removeDevtools(code, id)\n if (!transform) return\n if (logging) {\n console.log(\n `\\n${chalk.greenBright(`[@tanstack/devtools-vite]`)} Removed devtools code from: ${id.replace(normalizePath(process.cwd()), '')}\\n`,\n )\n }\n return transform\n },\n },\n {\n name: '@tanstack/devtools:event-client-setup',\n apply(config, { command }) {\n if (\n process.env.CI ||\n process.env.NODE_ENV !== 'development' ||\n command !== 'serve'\n )\n return false\n return config.mode === 'development'\n },\n async configureServer() {\n const packageJson = await readPackageJson()\n const outdatedDeps = emitOutdatedDeps().then((deps) => deps)\n\n // Listen for package installation requests\n devtoolsEventClient.on('install-devtools', async (event) => {\n const result = await installPackage(event.payload.packageName)\n devtoolsEventClient.emit('devtools-installed', {\n packageName: event.payload.packageName,\n success: result.success,\n error: result.error,\n })\n\n // If installation was successful, automatically add the plugin to devtools\n if (result.success) {\n const { packageName, pluginName, pluginImport } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Auto-adding ${packageName} to devtools...`,\n ),\n )\n\n const injectResult = addPluginToDevtools(\n devtoolsFileId,\n packageName,\n pluginName,\n pluginImport,\n )\n\n if (injectResult.success) {\n // Emit plugin-added event so the UI updates\n devtoolsEventClient.emit('plugin-added', {\n packageName,\n success: true,\n })\n\n // Also re-read package.json to update the UI with the newly installed package\n const updatedPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: updatedPackageJson,\n })\n }\n }\n })\n\n // Listen for add plugin to devtools requests\n devtoolsEventClient.on('add-plugin-to-devtools', (event) => {\n const { packageName, pluginName, pluginImport } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Adding ${packageName} to devtools...`,\n ),\n )\n\n const result = addPluginToDevtools(\n devtoolsFileId,\n packageName,\n pluginName,\n pluginImport,\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName,\n success: result.success,\n error: result.error,\n })\n })\n\n // Handle bump-package-version event\n devtoolsEventClient.on('bump-package-version', async (event) => {\n const {\n packageName,\n devtoolsPackage,\n pluginName,\n minVersion,\n pluginImport,\n } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Bumping ${packageName} to version ${minVersion}...`,\n ),\n )\n\n // Install the package with the minimum version\n const packageWithVersion = minVersion\n ? `${packageName}@^${minVersion}`\n : packageName\n\n const result = await installPackage(packageWithVersion)\n\n if (!result.success) {\n console.log(\n chalk.redBright(\n `[@tanstack/devtools-vite] Failed to bump ${packageName}: ${result.error}`,\n ),\n )\n devtoolsEventClient.emit('devtools-installed', {\n packageName: devtoolsPackage,\n success: false,\n error: result.error,\n })\n return\n }\n\n console.log(\n chalk.greenBright(\n `[@tanstack/devtools-vite] Successfully bumped ${packageName} to ${minVersion}!`,\n ),\n )\n\n // Check if we found the devtools file\n if (!devtoolsFileId) {\n console.log(\n chalk.yellowBright(\n `[@tanstack/devtools-vite] Devtools file not found. Skipping auto-injection.`,\n ),\n )\n devtoolsEventClient.emit('devtools-installed', {\n packageName: devtoolsPackage,\n success: true,\n })\n return\n }\n\n // Now inject the devtools plugin\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Adding ${devtoolsPackage} to devtools...`,\n ),\n )\n\n const injectResult = injectPluginIntoFile(devtoolsFileId, {\n packageName: devtoolsPackage,\n pluginName,\n pluginImport,\n })\n\n if (injectResult.success) {\n console.log(\n chalk.greenBright(\n `[@tanstack/devtools-vite] Successfully added ${devtoolsPackage} to devtools!`,\n ),\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName: devtoolsPackage,\n success: true,\n })\n\n // Re-read package.json to update the UI\n const updatedPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: updatedPackageJson,\n })\n } else {\n console.log(\n chalk.redBright(\n `[@tanstack/devtools-vite] Failed to add ${devtoolsPackage} to devtools: ${injectResult.error}`,\n ),\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName: devtoolsPackage,\n success: false,\n error: injectResult.error,\n })\n }\n })\n\n // whenever a client mounts we send all the current info to the subscribers\n devtoolsEventClient.on('mounted', async () => {\n devtoolsEventClient.emit('outdated-deps-read', {\n outdatedDeps: await outdatedDeps,\n })\n devtoolsEventClient.emit('package-json-read', {\n packageJson,\n })\n })\n\n // Console piping is now handled via HTTP endpoints in the custom-server plugin\n },\n async handleHotUpdate({ file }) {\n if (file.endsWith('package.json')) {\n const newPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: newPackageJson,\n })\n emitOutdatedDeps()\n }\n },\n },\n // Inject console piping code into entry files (both client and server)\n {\n name: '@tanstack/devtools:console-pipe-transform',\n enforce: 'pre',\n apply(config, { command }) {\n return (\n config.mode === 'development' &&\n command === 'serve' &&\n (consolePipingConfig.enabled ?? true)\n )\n },\n transform: {\n filter: {\n id: {\n include: /\\.(tsx?|jsx?)$/,\n exclude: [/node_modules/, /\\/dist\\//, /\\?/],\n },\n code: {\n exclude: /__tsdConsolePipe/, // avoid transforming files that already contain the console pipe code\n },\n },\n handler(code) {\n // Check if this is a root entry file (with <html> JSX or client entry points)\n // In SSR frameworks, this file runs on BOTH server (SSR) and client (hydration)\n // so our runtime check (typeof window === 'undefined') handles both environments\n const isRootEntry =\n /<html[\\s>]/i.test(code) ||\n code.includes('StartClient') ||\n code.includes('hydrateRoot') ||\n code.includes('createRoot') ||\n (code.includes('solid-js/web') && code.includes('render('))\n\n if (isRootEntry) {\n const viteServerUrl = `http://localhost:${port}`\n const inlineCode = generateConsolePipeCode(\n consolePipingLevels,\n viteServerUrl,\n )\n\n return `${inlineCode}\\n${code}`\n }\n\n return undefined\n },\n },\n },\n {\n name: '@tanstack/devtools:better-console-logs',\n enforce: 'pre',\n apply(config) {\n return config.mode === 'development' && enhancedLogsConfig.enabled\n },\n transform: {\n filter: {\n id: {\n exclude: [/node_modules/, /\\?raw/, /\\/dist\\//, /\\/build\\//],\n },\n code: {\n include: 'console.',\n },\n },\n handler(code, id) {\n return enhanceConsoleLog(code, id, port)\n },\n },\n },\n {\n name: '@tanstack/devtools:inject-plugin',\n apply(config, { command }) {\n return config.mode === 'development' && command === 'serve'\n },\n transform(code, id) {\n // First pass: find where TanStackDevtools is imported\n if (!devtoolsFileId && detectDevtoolsFile(code)) {\n // Extract actual file path (remove query params)\n const [filePath] = id.split('?')\n if (filePath) {\n devtoolsFileId = filePath\n }\n }\n\n return undefined\n },\n },\n {\n name: '@tanstack/devtools:connection-injection',\n apply(config, { command }) {\n return config.mode === 'development' && command === 'serve'\n },\n transform(code, id) {\n // Only transform @tanstack packages that contain the connection placeholders\n const hasPlaceholder =\n code.includes('__TANSTACK_DEVTOOLS_PORT__') ||\n code.includes('__TANSTACK_DEVTOOLS_HOST__') ||\n code.includes('__TANSTACK_DEVTOOLS_PROTOCOL__')\n if (!hasPlaceholder) return\n if (\n !id.includes('@tanstack/devtools') &&\n !id.includes('@tanstack/event-bus')\n )\n return\n\n // Replace placeholders with actual values (or fallback defaults)\n const portValue = devtoolsPort ?? 4206\n const hostValue = devtoolsHost ?? 'localhost'\n const protocolValue = devtoolsProtocol ?? 'http'\n\n let result = code\n result = result.replace(\n /__TANSTACK_DEVTOOLS_PORT__/g,\n String(portValue),\n )\n result = result.replace(\n /__TANSTACK_DEVTOOLS_HOST__/g,\n JSON.stringify(hostValue),\n )\n result = result.replace(\n /__TANSTACK_DEVTOOLS_PROTOCOL__/g,\n JSON.stringify(protocolValue),\n )\n return result\n },\n },\n ]\n}\n"],"names":["res","req"],"mappings":"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"}
|
package/dist/esm/utils.js
CHANGED
package/dist/esm/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport { normalizePath } from 'vite'\nimport type { Connect } from 'vite'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { PackageJson } from '@tanstack/devtools-client'\n\ntype DevToolsRequestHandler = (data: any) => void\n\ntype DevToolsViteRequestOptions = {\n onOpenSource?: DevToolsRequestHandler\n onConsolePipe?: (entries: Array<any>) => void\n onServerConsolePipe?: (entries: Array<any>) => void\n onConsolePipeSSE?: (\n res: ServerResponse<IncomingMessage>,\n req: Connect.IncomingMessage,\n ) => void\n}\n\nexport const handleDevToolsViteRequest = (\n req: Connect.IncomingMessage,\n res: ServerResponse<IncomingMessage>,\n next: Connect.NextFunction,\n cbOrOptions: DevToolsRequestHandler | DevToolsViteRequestOptions,\n) => {\n // Normalize to options object for backward compatibility\n const options: DevToolsViteRequestOptions =\n typeof cbOrOptions === 'function'\n ? { onOpenSource: cbOrOptions }\n : cbOrOptions\n\n // Handle open-source requests\n if (req.url?.includes('__tsd/open-source')) {\n const searchParams = new URLSearchParams(req.url.split('?')[1])\n\n const source = searchParams.get('source')\n if (!source) {\n return\n }\n\n const parsed = parseOpenSourceParam(source)\n if (!parsed) {\n return\n }\n const { file, line, column } = parsed\n\n options.onOpenSource?.({\n type: 'open-source',\n routine: 'open-source',\n data: {\n source: file ? normalizePath(`${process.cwd()}/${file}`) : undefined,\n line,\n column,\n },\n })\n res.setHeader('Content-Type', 'text/html')\n res.write(`<script> window.close(); </script>`)\n res.end()\n return\n }\n\n // Handle console-pipe SSE endpoint (browser subscribes to server logs)\n if (req.url?.includes('__tsd/console-pipe/sse') && req.method === 'GET') {\n if (options.onConsolePipeSSE) {\n options.onConsolePipeSSE(res, req)\n return\n }\n return next()\n }\n\n // Handle server console-pipe POST endpoint (from app server runtime)\n if (req.url?.includes('__tsd/console-pipe/server') && req.method === 'POST') {\n if (options.onServerConsolePipe) {\n let body = ''\n req.on('data', (chunk: Buffer) => {\n body += chunk.toString()\n })\n req.on('end', () => {\n try {\n const { entries } = JSON.parse(body)\n options.onServerConsolePipe!(entries)\n res.statusCode = 200\n res.end('OK')\n } catch {\n res.statusCode = 400\n res.end('Bad Request')\n }\n })\n return\n }\n return next()\n }\n\n // Handle console-pipe POST endpoint (from client)\n if (req.url?.includes('__tsd/console-pipe') && req.method === 'POST') {\n if (options.onConsolePipe) {\n let body = ''\n req.on('data', (chunk: Buffer) => {\n body += chunk.toString()\n })\n req.on('end', () => {\n try {\n const { entries } = JSON.parse(body)\n options.onConsolePipe!(entries)\n res.statusCode = 200\n res.end('OK')\n } catch {\n res.statusCode = 400\n res.end('Bad Request')\n }\n })\n return\n }\n return next()\n }\n\n if (!req.url?.includes('__tsd')) {\n return next()\n }\n\n const chunks: Array<any> = []\n req.on('data', (chunk) => {\n chunks.push(chunk)\n })\n req.on('end', () => {\n const dataToParse = Buffer.concat(chunks)\n try {\n const parsedData = JSON.parse(dataToParse.toString())\n options.onOpenSource?.(parsedData)\n } catch (e) {}\n res.write('OK')\n })\n}\n\nexport const parseOpenSourceParam = (source: string) => {\n // Capture everything up to the last two colon-separated numeric parts as the file.\n // This supports filenames that may themselves contain colons.\n const parts = source.match(/^(.+):(\\d+):(\\d+)$/)\n\n if (!parts) return null\n\n const [, file, line, column] = parts\n return { file, line, column }\n}\n\nconst tryReadFile = async (filePath: string) => {\n try {\n const data = await fs.readFile(filePath, 'utf-8')\n return data\n } catch (error) {\n return null\n }\n}\n\nexport const tryParseJson = <T extends any>(\n jsonString: string | null | undefined,\n) => {\n if (!jsonString) {\n return null\n }\n try {\n const result = JSON.parse(jsonString)\n return result as T\n } catch (error) {\n return null\n }\n}\n\nexport const readPackageJson = async () =>\n tryParseJson<PackageJson>(await tryReadFile(process.cwd() + '/package.json'))\n\n/**\n * Extracts and formats the source location from enhanced client console logs.\n * Instead of stripping the prefix entirely, we extract the file:line:column\n * from the \"Go to Source\" URL and use that as a prefix.\n *\n * Enhanced logs format (two variants):\n * 1. ['%cLOG%c %cGo to Source: http://...?source=%2Fsrc%2F...%c \\n → ', 'color:...', 'color:...', 'color:...', 'color:...', 'message']\n * 2. ['\\x1b[...]%s\\x1b[...]', '%cLOG%c %cGo to Source: ...%c \\n → ', 'color:...', 'color:...', 'color:...', 'color:...', 'message']\n *\n * Output: ['src/components/Header.tsx:26:13', 'message']\n */\nexport const stripEnhancedLogPrefix = (\n args: Array<unknown>,\n formatSourceLocation?: (location: string) => unknown,\n): Array<unknown> => {\n if (args.length === 0) return args\n\n // Find the arg that contains the Go to Source URL\n let sourceArgIndex = -1\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n if (typeof arg === 'string' && arg.includes('__tsd/open-source?source=')) {\n sourceArgIndex = i\n break\n }\n }\n\n // If no source URL found, return args as-is (not an enhanced log)\n if (sourceArgIndex === -1) {\n return args\n }\n\n const sourceArg = args[sourceArgIndex] as string\n\n // Extract the source from the \"Go to Source\" URL\n // URL format: http://localhost:3000/__tsd/open-source?source=%2Fsrc%2Ffile.tsx%3A26%3A13%c\n // Note: The URL ends with %c which is a console format specifier, not URL encoding\n let sourceLocation = ''\n const sourceMatch = sourceArg.match(/source=([^&\\s]+?)%c/)\n if (sourceMatch?.[1]) {\n try {\n sourceLocation = decodeURIComponent(sourceMatch[1])\n // Remove leading slash if present\n if (sourceLocation.startsWith('/')) {\n sourceLocation = sourceLocation.slice(1)\n }\n } catch {\n // If decoding fails, leave it empty\n }\n }\n\n // Count %c markers in the source arg to know how many style args follow it\n const styleCount = (sourceArg.match(/%c/g) || []).length\n\n // The actual user args start after the source arg and all its style args\n const userArgsStart = sourceArgIndex + 1 + styleCount\n\n // Build the result: source location prefix + remaining args (the actual user data)\n const result: Array<unknown> = []\n\n // Add source location as prefix if we found one\n if (sourceLocation) {\n result.push(\n formatSourceLocation\n ? formatSourceLocation(sourceLocation)\n : sourceLocation,\n )\n }\n\n // Add remaining args (the actual user data)\n for (let i = userArgsStart; i < args.length; i++) {\n result.push(args[i])\n }\n\n return result.length > 0 ? result : args\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport { normalizePath } from 'vite'\nimport type { Connect } from 'vite'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { PackageJson } from '@tanstack/devtools-client'\n\ntype DevToolsRequestHandler = (data: any) => void\n\ntype DevToolsViteRequestOptions = {\n onOpenSource?: DevToolsRequestHandler\n onConsolePipe?: (entries: Array<any>) => void\n onServerConsolePipe?: (entries: Array<any>) => void\n onConsolePipeSSE?: (\n res: ServerResponse<IncomingMessage>,\n req: Connect.IncomingMessage,\n ) => void\n}\n\nexport const handleDevToolsViteRequest = (\n req: Connect.IncomingMessage,\n res: ServerResponse<IncomingMessage>,\n next: Connect.NextFunction,\n cbOrOptions: DevToolsRequestHandler | DevToolsViteRequestOptions,\n) => {\n // Normalize to options object for backward compatibility\n const options: DevToolsViteRequestOptions =\n typeof cbOrOptions === 'function'\n ? { onOpenSource: cbOrOptions }\n : cbOrOptions\n\n // Handle open-source requests\n if (req.url?.includes('__tsd/open-source')) {\n const searchParams = new URLSearchParams(req.url.split('?')[1])\n\n const source = searchParams.get('source')\n if (!source) {\n return\n }\n\n const parsed = parseOpenSourceParam(source)\n if (!parsed) {\n return\n }\n const { file, line, column } = parsed\n\n options.onOpenSource?.({\n type: 'open-source',\n routine: 'open-source',\n data: {\n source: file ? normalizePath(`${process.cwd()}/${file}`) : undefined,\n line,\n column,\n },\n })\n res.setHeader('Content-Type', 'text/html')\n res.write(`<script> window.close(); </script>`)\n res.end()\n return\n }\n\n // Handle console-pipe SSE endpoint (browser subscribes to server logs)\n if (req.url?.includes('__tsd/console-pipe/sse') && req.method === 'GET') {\n if (options.onConsolePipeSSE) {\n options.onConsolePipeSSE(res, req)\n return\n }\n return next()\n }\n\n // Handle server console-pipe POST endpoint (from app server runtime)\n if (req.url?.includes('__tsd/console-pipe/server') && req.method === 'POST') {\n if (options.onServerConsolePipe) {\n let body = ''\n req.on('data', (chunk: Buffer) => {\n body += chunk.toString()\n })\n req.on('end', () => {\n try {\n const { entries } = JSON.parse(body)\n options.onServerConsolePipe!(entries)\n res.statusCode = 200\n res.end('OK')\n } catch {\n res.statusCode = 400\n res.end('Bad Request')\n }\n })\n return\n }\n return next()\n }\n\n // Handle console-pipe POST endpoint (from client)\n if (req.url?.includes('__tsd/console-pipe') && req.method === 'POST') {\n if (options.onConsolePipe) {\n let body = ''\n req.on('data', (chunk: Buffer) => {\n body += chunk.toString()\n })\n req.on('end', () => {\n try {\n const { entries } = JSON.parse(body)\n options.onConsolePipe!(entries)\n res.statusCode = 200\n res.end('OK')\n } catch {\n res.statusCode = 400\n res.end('Bad Request')\n }\n })\n return\n }\n return next()\n }\n\n if (!req.url?.includes('__tsd')) {\n return next()\n }\n\n const chunks: Array<any> = []\n req.on('data', (chunk) => {\n chunks.push(chunk)\n })\n req.on('end', () => {\n const dataToParse = Buffer.concat(chunks)\n try {\n const parsedData = JSON.parse(dataToParse.toString())\n options.onOpenSource?.(parsedData)\n } catch (e) {}\n res.write('OK')\n res.end()\n })\n}\n\nexport const parseOpenSourceParam = (source: string) => {\n // Capture everything up to the last two colon-separated numeric parts as the file.\n // This supports filenames that may themselves contain colons.\n const parts = source.match(/^(.+):(\\d+):(\\d+)$/)\n\n if (!parts) return null\n\n const [, file, line, column] = parts\n return { file, line, column }\n}\n\nconst tryReadFile = async (filePath: string) => {\n try {\n const data = await fs.readFile(filePath, 'utf-8')\n return data\n } catch (error) {\n return null\n }\n}\n\nexport const tryParseJson = <T extends any>(\n jsonString: string | null | undefined,\n) => {\n if (!jsonString) {\n return null\n }\n try {\n const result = JSON.parse(jsonString)\n return result as T\n } catch (error) {\n return null\n }\n}\n\nexport const readPackageJson = async () =>\n tryParseJson<PackageJson>(await tryReadFile(process.cwd() + '/package.json'))\n\n/**\n * Extracts and formats the source location from enhanced client console logs.\n * Instead of stripping the prefix entirely, we extract the file:line:column\n * from the \"Go to Source\" URL and use that as a prefix.\n *\n * Enhanced logs format (two variants):\n * 1. ['%cLOG%c %cGo to Source: http://...?source=%2Fsrc%2F...%c \\n → ', 'color:...', 'color:...', 'color:...', 'color:...', 'message']\n * 2. ['\\x1b[...]%s\\x1b[...]', '%cLOG%c %cGo to Source: ...%c \\n → ', 'color:...', 'color:...', 'color:...', 'color:...', 'message']\n *\n * Output: ['src/components/Header.tsx:26:13', 'message']\n */\nexport const stripEnhancedLogPrefix = (\n args: Array<unknown>,\n formatSourceLocation?: (location: string) => unknown,\n): Array<unknown> => {\n if (args.length === 0) return args\n\n // Find the arg that contains the Go to Source URL\n let sourceArgIndex = -1\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n if (typeof arg === 'string' && arg.includes('__tsd/open-source?source=')) {\n sourceArgIndex = i\n break\n }\n }\n\n // If no source URL found, return args as-is (not an enhanced log)\n if (sourceArgIndex === -1) {\n return args\n }\n\n const sourceArg = args[sourceArgIndex] as string\n\n // Extract the source from the \"Go to Source\" URL\n // URL format: http://localhost:3000/__tsd/open-source?source=%2Fsrc%2Ffile.tsx%3A26%3A13%c\n // Note: The URL ends with %c which is a console format specifier, not URL encoding\n let sourceLocation = ''\n const sourceMatch = sourceArg.match(/source=([^&\\s]+?)%c/)\n if (sourceMatch?.[1]) {\n try {\n sourceLocation = decodeURIComponent(sourceMatch[1])\n // Remove leading slash if present\n if (sourceLocation.startsWith('/')) {\n sourceLocation = sourceLocation.slice(1)\n }\n } catch {\n // If decoding fails, leave it empty\n }\n }\n\n // Count %c markers in the source arg to know how many style args follow it\n const styleCount = (sourceArg.match(/%c/g) || []).length\n\n // The actual user args start after the source arg and all its style args\n const userArgsStart = sourceArgIndex + 1 + styleCount\n\n // Build the result: source location prefix + remaining args (the actual user data)\n const result: Array<unknown> = []\n\n // Add source location as prefix if we found one\n if (sourceLocation) {\n result.push(\n formatSourceLocation\n ? formatSourceLocation(sourceLocation)\n : sourceLocation,\n )\n }\n\n // Add remaining args (the actual user data)\n for (let i = userArgsStart; i < args.length; i++) {\n result.push(args[i])\n }\n\n return result.length > 0 ? result : args\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/devtools-vite",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "TanStack Vite plugin used to enhance the core devtools with additional functionalities",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"launch-editor": "^2.11.1",
|
|
51
51
|
"picomatch": "^4.0.3",
|
|
52
52
|
"@tanstack/devtools-client": "0.0.5",
|
|
53
|
-
"@tanstack/devtools-event-bus": "0.4.
|
|
53
|
+
"@tanstack/devtools-event-bus": "0.4.1"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/babel__core": "^7.20.5",
|
package/src/plugin.ts
CHANGED
|
@@ -21,7 +21,10 @@ import { generateConsolePipeCode } from './virtual-console'
|
|
|
21
21
|
import type { ServerResponse } from 'node:http'
|
|
22
22
|
import type { Plugin } from 'vite'
|
|
23
23
|
import type { EditorConfig } from './editor'
|
|
24
|
-
import type {
|
|
24
|
+
import type {
|
|
25
|
+
HttpServerLike,
|
|
26
|
+
ServerEventBusConfig,
|
|
27
|
+
} from '@tanstack/devtools-event-bus/server'
|
|
25
28
|
|
|
26
29
|
export type ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug'
|
|
27
30
|
|
|
@@ -113,6 +116,8 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
|
|
|
113
116
|
|
|
114
117
|
let devtoolsFileId: string | null = null
|
|
115
118
|
let devtoolsPort: number | null = null
|
|
119
|
+
let devtoolsHost: string | null = null
|
|
120
|
+
let devtoolsProtocol: 'http' | 'https' | null = null
|
|
116
121
|
|
|
117
122
|
return [
|
|
118
123
|
{
|
|
@@ -121,16 +126,15 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
|
|
|
121
126
|
apply(config) {
|
|
122
127
|
return config.mode === 'development' && injectSourceConfig.enabled
|
|
123
128
|
},
|
|
124
|
-
transform
|
|
125
|
-
|
|
126
|
-
id
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
)
|
|
131
|
-
return
|
|
132
|
-
|
|
133
|
-
return addSourceToJsx(code, id, args?.injectSource?.ignore)
|
|
129
|
+
transform: {
|
|
130
|
+
filter: {
|
|
131
|
+
id: {
|
|
132
|
+
exclude: [/node_modules/, /\?raw/, /\/dist\//, /\/build\//],
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
handler(code, id) {
|
|
136
|
+
return addSourceToJsx(code, id, args?.injectSource?.ignore)
|
|
137
|
+
},
|
|
134
138
|
},
|
|
135
139
|
},
|
|
136
140
|
{
|
|
@@ -170,9 +174,24 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
|
|
|
170
174
|
async configureServer(server) {
|
|
171
175
|
if (serverBusEnabled) {
|
|
172
176
|
const preferredPort = args?.eventBusConfig?.port ?? 4206
|
|
177
|
+
const isHttps = !!server.config.server.https
|
|
178
|
+
const serverHost =
|
|
179
|
+
typeof server.config.server.host === 'string'
|
|
180
|
+
? server.config.server.host
|
|
181
|
+
: 'localhost'
|
|
182
|
+
|
|
183
|
+
devtoolsProtocol = isHttps ? 'https' : 'http'
|
|
184
|
+
devtoolsHost = serverHost
|
|
185
|
+
|
|
173
186
|
const bus = new ServerEventBus({
|
|
174
187
|
...args?.eventBusConfig,
|
|
175
188
|
port: preferredPort,
|
|
189
|
+
host: serverHost,
|
|
190
|
+
// When HTTPS is enabled, piggyback on Vite's server
|
|
191
|
+
// so WebSocket/SSE connections share the same TLS certificate
|
|
192
|
+
...(isHttps && server.httpServer
|
|
193
|
+
? { httpServer: server.httpServer as HttpServerLike }
|
|
194
|
+
: {}),
|
|
176
195
|
})
|
|
177
196
|
// start() now handles EADDRINUSE and returns the actual port
|
|
178
197
|
devtoolsPort = await bus.start()
|
|
@@ -530,43 +549,39 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
|
|
|
530
549
|
(consolePipingConfig.enabled ?? true)
|
|
531
550
|
)
|
|
532
551
|
},
|
|
533
|
-
transform
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
const viteServerUrl = `http://localhost:${port}`
|
|
561
|
-
const inlineCode = generateConsolePipeCode(
|
|
562
|
-
consolePipingLevels,
|
|
563
|
-
viteServerUrl,
|
|
564
|
-
)
|
|
552
|
+
transform: {
|
|
553
|
+
filter: {
|
|
554
|
+
id: {
|
|
555
|
+
include: /\.(tsx?|jsx?)$/,
|
|
556
|
+
exclude: [/node_modules/, /\/dist\//, /\?/],
|
|
557
|
+
},
|
|
558
|
+
code: {
|
|
559
|
+
exclude: /__tsdConsolePipe/, // avoid transforming files that already contain the console pipe code
|
|
560
|
+
},
|
|
561
|
+
},
|
|
562
|
+
handler(code) {
|
|
563
|
+
// Check if this is a root entry file (with <html> JSX or client entry points)
|
|
564
|
+
// In SSR frameworks, this file runs on BOTH server (SSR) and client (hydration)
|
|
565
|
+
// so our runtime check (typeof window === 'undefined') handles both environments
|
|
566
|
+
const isRootEntry =
|
|
567
|
+
/<html[\s>]/i.test(code) ||
|
|
568
|
+
code.includes('StartClient') ||
|
|
569
|
+
code.includes('hydrateRoot') ||
|
|
570
|
+
code.includes('createRoot') ||
|
|
571
|
+
(code.includes('solid-js/web') && code.includes('render('))
|
|
572
|
+
|
|
573
|
+
if (isRootEntry) {
|
|
574
|
+
const viteServerUrl = `http://localhost:${port}`
|
|
575
|
+
const inlineCode = generateConsolePipeCode(
|
|
576
|
+
consolePipingLevels,
|
|
577
|
+
viteServerUrl,
|
|
578
|
+
)
|
|
565
579
|
|
|
566
|
-
|
|
567
|
-
|
|
580
|
+
return `${inlineCode}\n${code}`
|
|
581
|
+
}
|
|
568
582
|
|
|
569
|
-
|
|
583
|
+
return undefined
|
|
584
|
+
},
|
|
570
585
|
},
|
|
571
586
|
},
|
|
572
587
|
{
|
|
@@ -575,18 +590,18 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
|
|
|
575
590
|
apply(config) {
|
|
576
591
|
return config.mode === 'development' && enhancedLogsConfig.enabled
|
|
577
592
|
},
|
|
578
|
-
transform
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
593
|
+
transform: {
|
|
594
|
+
filter: {
|
|
595
|
+
id: {
|
|
596
|
+
exclude: [/node_modules/, /\?raw/, /\/dist\//, /\/build\//],
|
|
597
|
+
},
|
|
598
|
+
code: {
|
|
599
|
+
include: 'console.',
|
|
600
|
+
},
|
|
601
|
+
},
|
|
602
|
+
handler(code, id) {
|
|
603
|
+
return enhanceConsoleLog(code, id, port)
|
|
604
|
+
},
|
|
590
605
|
},
|
|
591
606
|
},
|
|
592
607
|
{
|
|
@@ -608,22 +623,42 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
|
|
|
608
623
|
},
|
|
609
624
|
},
|
|
610
625
|
{
|
|
611
|
-
name: '@tanstack/devtools:
|
|
626
|
+
name: '@tanstack/devtools:connection-injection',
|
|
612
627
|
apply(config, { command }) {
|
|
613
628
|
return config.mode === 'development' && command === 'serve'
|
|
614
629
|
},
|
|
615
630
|
transform(code, id) {
|
|
616
|
-
// Only transform @tanstack packages that contain the
|
|
617
|
-
|
|
631
|
+
// Only transform @tanstack packages that contain the connection placeholders
|
|
632
|
+
const hasPlaceholder =
|
|
633
|
+
code.includes('__TANSTACK_DEVTOOLS_PORT__') ||
|
|
634
|
+
code.includes('__TANSTACK_DEVTOOLS_HOST__') ||
|
|
635
|
+
code.includes('__TANSTACK_DEVTOOLS_PROTOCOL__')
|
|
636
|
+
if (!hasPlaceholder) return
|
|
618
637
|
if (
|
|
619
638
|
!id.includes('@tanstack/devtools') &&
|
|
620
639
|
!id.includes('@tanstack/event-bus')
|
|
621
640
|
)
|
|
622
641
|
return
|
|
623
642
|
|
|
624
|
-
// Replace
|
|
643
|
+
// Replace placeholders with actual values (or fallback defaults)
|
|
625
644
|
const portValue = devtoolsPort ?? 4206
|
|
626
|
-
|
|
645
|
+
const hostValue = devtoolsHost ?? 'localhost'
|
|
646
|
+
const protocolValue = devtoolsProtocol ?? 'http'
|
|
647
|
+
|
|
648
|
+
let result = code
|
|
649
|
+
result = result.replace(
|
|
650
|
+
/__TANSTACK_DEVTOOLS_PORT__/g,
|
|
651
|
+
String(portValue),
|
|
652
|
+
)
|
|
653
|
+
result = result.replace(
|
|
654
|
+
/__TANSTACK_DEVTOOLS_HOST__/g,
|
|
655
|
+
JSON.stringify(hostValue),
|
|
656
|
+
)
|
|
657
|
+
result = result.replace(
|
|
658
|
+
/__TANSTACK_DEVTOOLS_PROTOCOL__/g,
|
|
659
|
+
JSON.stringify(protocolValue),
|
|
660
|
+
)
|
|
661
|
+
return result
|
|
627
662
|
},
|
|
628
663
|
},
|
|
629
664
|
]
|