@tanstack/devtools-vite 0.3.6 → 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,18 +1,18 @@
1
- import { exec } from 'node:child_process'
2
1
  import { devtoolsEventClient } from '@tanstack/devtools-client'
3
2
  import { ServerEventBus } from '@tanstack/devtools-event-bus/server'
4
3
  import { normalizePath } from 'vite'
5
4
  import chalk from 'chalk'
6
- import {
7
- handleDevToolsViteRequest,
8
- readPackageJson,
9
- tryParseJson,
10
- } from './utils'
5
+ import { handleDevToolsViteRequest, readPackageJson } from './utils'
11
6
  import { DEFAULT_EDITOR_CONFIG, handleOpenSource } from './editor'
12
7
  import { removeDevtools } from './remove-devtools'
13
8
  import { addSourceToJsx } from './inject-source'
14
9
  import { enhanceConsoleLog } from './enhance-logs'
15
- import type { OutdatedDeps } from '@tanstack/devtools-client'
10
+ import { detectDevtoolsFile, injectPluginIntoFile } from './inject-plugin'
11
+ import {
12
+ addPluginToDevtools,
13
+ emitOutdatedDeps,
14
+ installPackage,
15
+ } from './package-manager'
16
16
  import type { Plugin } from 'vite'
17
17
  import type { EditorConfig } from './editor'
18
18
  import type { ServerEventBusConfig } from '@tanstack/devtools-event-bus/server'
@@ -68,24 +68,6 @@ export type TanStackDevtoolsViteConfig = {
68
68
  export const defineDevtoolsConfig = (config: TanStackDevtoolsViteConfig) =>
69
69
  config
70
70
 
71
- const emitOutdatedDeps = async () => {
72
- return await new Promise<OutdatedDeps | null>((resolve) => {
73
- exec('npm outdated --json', (_, stdout) => {
74
- // npm outdated exits with code 1 if there are outdated packages, but still outputs valid JSON
75
- if (stdout) {
76
- const newOutdatedDeps = tryParseJson<OutdatedDeps>(stdout)
77
- if (!newOutdatedDeps) {
78
- return
79
- }
80
- devtoolsEventClient.emit('outdated-deps-read', {
81
- outdatedDeps: newOutdatedDeps,
82
- })
83
- resolve(newOutdatedDeps)
84
- }
85
- })
86
- })
87
- }
88
-
89
71
  export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
90
72
  let port = 5173
91
73
  const logging = args?.logging ?? true
@@ -95,6 +77,8 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
95
77
  const serverBusEnabled = args?.eventBusConfig?.enabled ?? true
96
78
  const bus = new ServerEventBus(args?.eventBusConfig)
97
79
 
80
+ let devtoolsFileId: string | null = null
81
+
98
82
  return [
99
83
  {
100
84
  enforce: 'pre',
@@ -231,6 +215,174 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
231
215
  const packageJson = await readPackageJson()
232
216
  const outdatedDeps = emitOutdatedDeps().then((deps) => deps)
233
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
+
234
386
  // whenever a client mounts we send all the current info to the subscribers
235
387
  devtoolsEventClient.on('mounted', async () => {
236
388
  devtoolsEventClient.emit('outdated-deps-read', {
@@ -271,5 +423,23 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
271
423
  return enhanceConsoleLog(code, id, port)
272
424
  },
273
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
+ },
274
444
  ]
275
445
  }