@tanstack/devtools-vite 0.3.5 → 0.3.7

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/src/plugin.ts CHANGED
@@ -1,11 +1,18 @@
1
+ import { devtoolsEventClient } from '@tanstack/devtools-client'
1
2
  import { ServerEventBus } from '@tanstack/devtools-event-bus/server'
2
3
  import { normalizePath } from 'vite'
3
4
  import chalk from 'chalk'
4
- import { handleDevToolsViteRequest } from './utils'
5
+ import { handleDevToolsViteRequest, readPackageJson } from './utils'
5
6
  import { DEFAULT_EDITOR_CONFIG, handleOpenSource } from './editor'
6
7
  import { removeDevtools } from './remove-devtools'
7
8
  import { addSourceToJsx } from './inject-source'
8
9
  import { enhanceConsoleLog } from './enhance-logs'
10
+ import { detectDevtoolsFile, injectPluginIntoFile } from './inject-plugin'
11
+ import {
12
+ addPluginToDevtools,
13
+ emitOutdatedDeps,
14
+ installPackage,
15
+ } from './package-manager'
9
16
  import type { Plugin } from 'vite'
10
17
  import type { EditorConfig } from './editor'
11
18
  import type { ServerEventBusConfig } from '@tanstack/devtools-event-bus/server'
@@ -18,7 +25,13 @@ export type TanStackDevtoolsViteConfig = {
18
25
  /**
19
26
  * The configuration options for the server event bus
20
27
  */
21
- eventBusConfig?: ServerEventBusConfig
28
+ eventBusConfig?: ServerEventBusConfig & {
29
+ /**
30
+ * Should the server event bus be enabled or not
31
+ * @default true
32
+ */
33
+ enabled?: boolean // defaults to true
34
+ }
22
35
  /**
23
36
  * Configuration for enhanced logging.
24
37
  */
@@ -61,8 +74,11 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
61
74
  const enhancedLogsConfig = args?.enhancedLogs ?? { enabled: true }
62
75
  const injectSourceConfig = args?.injectSource ?? { enabled: true }
63
76
  const removeDevtoolsOnBuild = args?.removeDevtoolsOnBuild ?? true
77
+ const serverBusEnabled = args?.eventBusConfig?.enabled ?? true
64
78
  const bus = new ServerEventBus(args?.eventBusConfig)
65
79
 
80
+ let devtoolsFileId: string | null = null
81
+
66
82
  return [
67
83
  {
68
84
  enforce: 'pre',
@@ -117,7 +133,9 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
117
133
  return config.mode === 'development'
118
134
  },
119
135
  configureServer(server) {
120
- bus.start()
136
+ if (serverBusEnabled) {
137
+ bus.start()
138
+ }
121
139
 
122
140
  server.middlewares.use((req, _res, next) => {
123
141
  if (req.socket.localPort && req.socket.localPort !== port) {
@@ -182,6 +200,209 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
182
200
  return transform
183
201
  },
184
202
  },
203
+ {
204
+ name: '@tanstack/devtools:event-client-setup',
205
+ apply(config, { command }) {
206
+ if (
207
+ process.env.CI ||
208
+ process.env.NODE_ENV !== 'development' ||
209
+ command !== 'serve'
210
+ )
211
+ return false
212
+ return config.mode === 'development'
213
+ },
214
+ async configureServer() {
215
+ const packageJson = await readPackageJson()
216
+ const outdatedDeps = emitOutdatedDeps().then((deps) => deps)
217
+
218
+ // Listen for package installation requests
219
+ devtoolsEventClient.on('install-devtools', async (event) => {
220
+ const result = await installPackage(event.payload.packageName)
221
+ devtoolsEventClient.emit('devtools-installed', {
222
+ packageName: event.payload.packageName,
223
+ success: result.success,
224
+ error: result.error,
225
+ })
226
+
227
+ // If installation was successful, automatically add the plugin to devtools
228
+ if (result.success) {
229
+ const { packageName, pluginName, pluginImport } = event.payload
230
+
231
+ console.log(
232
+ chalk.blueBright(
233
+ `[@tanstack/devtools-vite] Auto-adding ${packageName} to devtools...`,
234
+ ),
235
+ )
236
+
237
+ const injectResult = addPluginToDevtools(
238
+ devtoolsFileId,
239
+ packageName,
240
+ pluginName,
241
+ pluginImport,
242
+ )
243
+
244
+ if (injectResult.success) {
245
+ // Emit plugin-added event so the UI updates
246
+ devtoolsEventClient.emit('plugin-added', {
247
+ packageName,
248
+ success: true,
249
+ })
250
+
251
+ // Also re-read package.json to update the UI with the newly installed package
252
+ const updatedPackageJson = await readPackageJson()
253
+ devtoolsEventClient.emit('package-json-read', {
254
+ packageJson: updatedPackageJson,
255
+ })
256
+ }
257
+ }
258
+ })
259
+
260
+ // Listen for add plugin to devtools requests
261
+ devtoolsEventClient.on('add-plugin-to-devtools', (event) => {
262
+ const { packageName, pluginName, pluginImport } = event.payload
263
+
264
+ console.log(
265
+ chalk.blueBright(
266
+ `[@tanstack/devtools-vite] Adding ${packageName} to devtools...`,
267
+ ),
268
+ )
269
+
270
+ const result = addPluginToDevtools(
271
+ devtoolsFileId,
272
+ packageName,
273
+ pluginName,
274
+ pluginImport,
275
+ )
276
+
277
+ devtoolsEventClient.emit('plugin-added', {
278
+ packageName,
279
+ success: result.success,
280
+ error: result.error,
281
+ })
282
+ })
283
+
284
+ // Handle bump-package-version event
285
+ devtoolsEventClient.on('bump-package-version', async (event) => {
286
+ const {
287
+ packageName,
288
+ devtoolsPackage,
289
+ pluginName,
290
+ minVersion,
291
+ pluginImport,
292
+ } = event.payload
293
+
294
+ console.log(
295
+ chalk.blueBright(
296
+ `[@tanstack/devtools-vite] Bumping ${packageName} to version ${minVersion}...`,
297
+ ),
298
+ )
299
+
300
+ // Install the package with the minimum version
301
+ const packageWithVersion = minVersion
302
+ ? `${packageName}@^${minVersion}`
303
+ : packageName
304
+
305
+ const result = await installPackage(packageWithVersion)
306
+
307
+ if (!result.success) {
308
+ console.log(
309
+ chalk.redBright(
310
+ `[@tanstack/devtools-vite] Failed to bump ${packageName}: ${result.error}`,
311
+ ),
312
+ )
313
+ devtoolsEventClient.emit('devtools-installed', {
314
+ packageName: devtoolsPackage,
315
+ success: false,
316
+ error: result.error,
317
+ })
318
+ return
319
+ }
320
+
321
+ console.log(
322
+ chalk.greenBright(
323
+ `[@tanstack/devtools-vite] Successfully bumped ${packageName} to ${minVersion}!`,
324
+ ),
325
+ )
326
+
327
+ // Check if we found the devtools file
328
+ if (!devtoolsFileId) {
329
+ console.log(
330
+ chalk.yellowBright(
331
+ `[@tanstack/devtools-vite] Devtools file not found. Skipping auto-injection.`,
332
+ ),
333
+ )
334
+ devtoolsEventClient.emit('devtools-installed', {
335
+ packageName: devtoolsPackage,
336
+ success: true,
337
+ })
338
+ return
339
+ }
340
+
341
+ // Now inject the devtools plugin
342
+ console.log(
343
+ chalk.blueBright(
344
+ `[@tanstack/devtools-vite] Adding ${devtoolsPackage} to devtools...`,
345
+ ),
346
+ )
347
+
348
+ const injectResult = injectPluginIntoFile(devtoolsFileId, {
349
+ packageName: devtoolsPackage,
350
+ pluginName,
351
+ pluginImport,
352
+ })
353
+
354
+ if (injectResult.success) {
355
+ console.log(
356
+ chalk.greenBright(
357
+ `[@tanstack/devtools-vite] Successfully added ${devtoolsPackage} to devtools!`,
358
+ ),
359
+ )
360
+
361
+ devtoolsEventClient.emit('plugin-added', {
362
+ packageName: devtoolsPackage,
363
+ success: true,
364
+ })
365
+
366
+ // Re-read package.json to update the UI
367
+ const updatedPackageJson = await readPackageJson()
368
+ devtoolsEventClient.emit('package-json-read', {
369
+ packageJson: updatedPackageJson,
370
+ })
371
+ } else {
372
+ console.log(
373
+ chalk.redBright(
374
+ `[@tanstack/devtools-vite] Failed to add ${devtoolsPackage} to devtools: ${injectResult.error}`,
375
+ ),
376
+ )
377
+
378
+ devtoolsEventClient.emit('plugin-added', {
379
+ packageName: devtoolsPackage,
380
+ success: false,
381
+ error: injectResult.error,
382
+ })
383
+ }
384
+ })
385
+
386
+ // whenever a client mounts we send all the current info to the subscribers
387
+ devtoolsEventClient.on('mounted', async () => {
388
+ devtoolsEventClient.emit('outdated-deps-read', {
389
+ outdatedDeps: await outdatedDeps,
390
+ })
391
+ devtoolsEventClient.emit('package-json-read', {
392
+ packageJson,
393
+ })
394
+ })
395
+ },
396
+ async handleHotUpdate({ file }) {
397
+ if (file.endsWith('package.json')) {
398
+ const newPackageJson = await readPackageJson()
399
+ devtoolsEventClient.emit('package-json-read', {
400
+ packageJson: newPackageJson,
401
+ })
402
+ emitOutdatedDeps()
403
+ }
404
+ },
405
+ },
185
406
  {
186
407
  name: '@tanstack/devtools:better-console-logs',
187
408
  enforce: 'pre',
@@ -202,5 +423,23 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
202
423
  return enhanceConsoleLog(code, id, port)
203
424
  },
204
425
  },
426
+ {
427
+ name: '@tanstack/devtools:inject-plugin',
428
+ apply(config, { command }) {
429
+ return config.mode === 'development' && command === 'serve'
430
+ },
431
+ transform(code, id) {
432
+ // First pass: find where TanStackDevtools is imported
433
+ if (!devtoolsFileId && detectDevtoolsFile(code)) {
434
+ // Extract actual file path (remove query params)
435
+ const [filePath] = id.split('?')
436
+ if (filePath) {
437
+ devtoolsFileId = filePath
438
+ }
439
+ }
440
+
441
+ return undefined
442
+ },
443
+ },
205
444
  ]
206
445
  }
package/src/utils.ts CHANGED
@@ -1,7 +1,8 @@
1
+ import fs from 'node:fs/promises'
1
2
  import { normalizePath } from 'vite'
2
- // import fs from 'node:fs/promises'
3
3
  import type { Connect } from 'vite'
4
4
  import type { IncomingMessage, ServerResponse } from 'node:http'
5
+ import type { PackageJson } from '@tanstack/devtools-client'
5
6
 
6
7
  export const handleDevToolsViteRequest = (
7
8
  req: Connect.IncomingMessage,
@@ -66,23 +67,28 @@ export const parseOpenSourceParam = (source: string) => {
66
67
  return { file, line, column }
67
68
  }
68
69
 
69
- /* export const tryReadFile = async (
70
- filePath: string
71
- ) => {
70
+ const tryReadFile = async (filePath: string) => {
72
71
  try {
73
72
  const data = await fs.readFile(filePath, 'utf-8')
74
73
  return data
75
74
  } catch (error) {
76
-
77
75
  return null
78
76
  }
79
77
  }
80
78
 
81
- export const tryParseJson = (jsonString: string) => {
79
+ export const tryParseJson = <T extends any>(
80
+ jsonString: string | null | undefined,
81
+ ) => {
82
+ if (!jsonString) {
83
+ return null
84
+ }
82
85
  try {
83
86
  const result = JSON.parse(jsonString)
84
- return result
87
+ return result as T
85
88
  } catch (error) {
86
89
  return null
87
90
  }
88
- } */
91
+ }
92
+
93
+ export const readPackageJson = async () =>
94
+ tryParseJson<PackageJson>(await tryReadFile(process.cwd() + '/package.json'))