From 3f131902baf2972d56562c6a6d711bd2588dad41 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 13:04:16 +0200 Subject: [PATCH 01/16] feat(bundler-core): scaffold @tanstack/devtools-bundler-core package --- .../devtools-bundler-core/eslint.config.js | 10 +++++ packages/devtools-bundler-core/package.json | 45 +++++++++++++++++++ packages/devtools-bundler-core/src/index.ts | 1 + .../devtools-bundler-core/tsconfig.docs.json | 4 ++ packages/devtools-bundler-core/tsconfig.json | 1 + packages/devtools-bundler-core/vite.config.ts | 19 ++++++++ pnpm-lock.yaml | 31 +++++++++++++ 7 files changed, 111 insertions(+) create mode 100644 packages/devtools-bundler-core/eslint.config.js create mode 100644 packages/devtools-bundler-core/package.json create mode 100644 packages/devtools-bundler-core/src/index.ts create mode 100644 packages/devtools-bundler-core/tsconfig.docs.json create mode 100644 packages/devtools-bundler-core/tsconfig.json create mode 100644 packages/devtools-bundler-core/vite.config.ts diff --git a/packages/devtools-bundler-core/eslint.config.js b/packages/devtools-bundler-core/eslint.config.js new file mode 100644 index 00000000..e472c69e --- /dev/null +++ b/packages/devtools-bundler-core/eslint.config.js @@ -0,0 +1,10 @@ +// @ts-check + +import rootConfig from '../../eslint.config.js' + +export default [ + ...rootConfig, + { + rules: {}, + }, +] diff --git a/packages/devtools-bundler-core/package.json b/packages/devtools-bundler-core/package.json new file mode 100644 index 00000000..09f3b017 --- /dev/null +++ b/packages/devtools-bundler-core/package.json @@ -0,0 +1,45 @@ +{ + "name": "@tanstack/devtools-bundler-core", + "version": "0.0.1", + "description": "Framework-agnostic core shared by TanStack devtools bundler plugins", + "author": "Tanner Linsley", + "license": "MIT", + "repository": { "type": "git", "url": "git+https://github.com/TanStack/devtools.git", "directory": "packages/devtools-bundler-core" }, + "homepage": "https://tanstack.com/devtools", + "bugs": { "url": "https://github.com/TanStack/devtools/issues" }, + "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" }, + "keywords": ["devtools"], + "type": "module", + "types": "dist/esm/index.d.ts", + "module": "dist/esm/index.js", + "exports": { + ".": { "import": { "types": "./dist/esm/index.d.ts", "default": "./dist/esm/index.js" } }, + "./package.json": "./package.json" + }, + "sideEffects": false, + "engines": { "node": ">=18" }, + "files": ["dist/", "src"], + "scripts": { + "clean": "premove ./build ./dist", + "lint:fix": "eslint ./src --fix", + "test:eslint": "eslint ./src", + "test:lib": "vitest", + "test:lib:dev": "pnpm test:lib --watch", + "test:types": "tsc", + "test:build": "publint --strict", + "build": "vite build" + }, + "dependencies": { + "@tanstack/devtools-client": "workspace:*", + "@tanstack/devtools-event-bus": "workspace:*", + "chalk": "^5.6.2", + "launch-editor": "^2.11.1", + "magic-string": "^0.30.0", + "oxc-parser": "^0.120.0", + "picomatch": "^4.0.3" + }, + "devDependencies": { + "@types/picomatch": "^4.0.2", + "happy-dom": "^20.0.0" + } +} diff --git a/packages/devtools-bundler-core/src/index.ts b/packages/devtools-bundler-core/src/index.ts new file mode 100644 index 00000000..336ce12b --- /dev/null +++ b/packages/devtools-bundler-core/src/index.ts @@ -0,0 +1 @@ +export {} diff --git a/packages/devtools-bundler-core/tsconfig.docs.json b/packages/devtools-bundler-core/tsconfig.docs.json new file mode 100644 index 00000000..2880b4df --- /dev/null +++ b/packages/devtools-bundler-core/tsconfig.docs.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["tests", "src"] +} diff --git a/packages/devtools-bundler-core/tsconfig.json b/packages/devtools-bundler-core/tsconfig.json new file mode 100644 index 00000000..f5be8dcd --- /dev/null +++ b/packages/devtools-bundler-core/tsconfig.json @@ -0,0 +1 @@ +{ "extends": "../../tsconfig.json", "include": ["src", "eslint.config.js", "vite.config.ts"] } diff --git a/packages/devtools-bundler-core/vite.config.ts b/packages/devtools-bundler-core/vite.config.ts new file mode 100644 index 00000000..760700c8 --- /dev/null +++ b/packages/devtools-bundler-core/vite.config.ts @@ -0,0 +1,19 @@ +import { defineConfig, mergeConfig } from 'vitest/config' +import { tanstackViteConfig } from '@tanstack/vite-config' +import packageJson from './package.json' + +const config = defineConfig({ + plugins: [], + test: { + name: packageJson.name, + dir: './', + watch: false, + environment: 'happy-dom', + globals: true, + }, +}) + +export default mergeConfig( + config, + tanstackViteConfig({ cjs: false, entry: ['./src/index.ts'], srcDir: './src' }), +) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index caa6e33a..d60624fa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1555,6 +1555,37 @@ importers: specifier: ^2.11.11 version: 2.11.12(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@8.0.12(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + packages/devtools-bundler-core: + dependencies: + '@tanstack/devtools-client': + specifier: workspace:* + version: link:../devtools-client + '@tanstack/devtools-event-bus': + specifier: workspace:* + version: link:../event-bus + chalk: + specifier: ^5.6.2 + version: 5.6.2 + launch-editor: + specifier: ^2.11.1 + version: 2.13.2 + magic-string: + specifier: ^0.30.0 + version: 0.30.21 + oxc-parser: + specifier: ^0.120.0 + version: 0.120.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + picomatch: + specifier: ^4.0.3 + version: 4.0.4 + devDependencies: + '@types/picomatch': + specifier: ^4.0.2 + version: 4.0.3 + happy-dom: + specifier: ^20.0.0 + version: 20.9.0 + packages/devtools-client: dependencies: '@tanstack/devtools-event-client': From e208dc0ae871bd8e4d3c05469e8612d7ad665a47 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 13:11:58 +0200 Subject: [PATCH 02/16] feat(bundler-core): move framework-agnostic logic out of devtools-vite --- .../src/ast-utils.test.ts | 0 .../src/ast-utils.ts | 0 .../src/devtools-packages.test.ts | 0 .../src/devtools-packages.ts | 0 .../src/editor.test.ts | 0 .../src/editor.ts | 0 .../src/enhance-logs.test.ts | 0 .../src/enhance-logs.ts | 2 +- packages/devtools-bundler-core/src/index.ts | 16 +++- .../src/inject-plugin.test.ts | 0 .../src/inject-plugin.ts | 0 .../src/inject-source.test.ts | 0 .../src/inject-source.ts | 2 +- .../src/matcher.test.ts | 0 .../src/matcher.ts | 0 .../src/normalize-path.ts | 2 + .../src/offset-to-loc.test.ts | 0 .../src/offset-to-loc.ts | 0 .../src/package-manager.ts | 0 .../src/remove-devtools.test.ts | 0 .../src/remove-devtools.ts | 0 .../src/runtime-bridge.test.ts | 0 .../src/runtime-bridge.ts | 0 packages/devtools-bundler-core/src/types.ts | 76 +++++++++++++++++++ .../src/utils.test.ts | 0 .../src/utils.ts | 13 ++-- .../src/virtual-console.test.ts | 0 .../src/virtual-console.ts | 2 +- 28 files changed, 103 insertions(+), 10 deletions(-) rename packages/{devtools-vite => devtools-bundler-core}/src/ast-utils.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/ast-utils.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/devtools-packages.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/devtools-packages.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/editor.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/editor.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/enhance-logs.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/enhance-logs.ts (98%) rename packages/{devtools-vite => devtools-bundler-core}/src/inject-plugin.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/inject-plugin.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/inject-source.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/inject-source.ts (99%) rename packages/{devtools-vite => devtools-bundler-core}/src/matcher.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/matcher.ts (100%) create mode 100644 packages/devtools-bundler-core/src/normalize-path.ts rename packages/{devtools-vite => devtools-bundler-core}/src/offset-to-loc.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/offset-to-loc.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/package-manager.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/remove-devtools.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/remove-devtools.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/runtime-bridge.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/runtime-bridge.ts (100%) create mode 100644 packages/devtools-bundler-core/src/types.ts rename packages/{devtools-vite => devtools-bundler-core}/src/utils.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/utils.ts (96%) rename packages/{devtools-vite => devtools-bundler-core}/src/virtual-console.test.ts (100%) rename packages/{devtools-vite => devtools-bundler-core}/src/virtual-console.ts (99%) diff --git a/packages/devtools-vite/src/ast-utils.test.ts b/packages/devtools-bundler-core/src/ast-utils.test.ts similarity index 100% rename from packages/devtools-vite/src/ast-utils.test.ts rename to packages/devtools-bundler-core/src/ast-utils.test.ts diff --git a/packages/devtools-vite/src/ast-utils.ts b/packages/devtools-bundler-core/src/ast-utils.ts similarity index 100% rename from packages/devtools-vite/src/ast-utils.ts rename to packages/devtools-bundler-core/src/ast-utils.ts diff --git a/packages/devtools-vite/src/devtools-packages.test.ts b/packages/devtools-bundler-core/src/devtools-packages.test.ts similarity index 100% rename from packages/devtools-vite/src/devtools-packages.test.ts rename to packages/devtools-bundler-core/src/devtools-packages.test.ts diff --git a/packages/devtools-vite/src/devtools-packages.ts b/packages/devtools-bundler-core/src/devtools-packages.ts similarity index 100% rename from packages/devtools-vite/src/devtools-packages.ts rename to packages/devtools-bundler-core/src/devtools-packages.ts diff --git a/packages/devtools-vite/src/editor.test.ts b/packages/devtools-bundler-core/src/editor.test.ts similarity index 100% rename from packages/devtools-vite/src/editor.test.ts rename to packages/devtools-bundler-core/src/editor.test.ts diff --git a/packages/devtools-vite/src/editor.ts b/packages/devtools-bundler-core/src/editor.ts similarity index 100% rename from packages/devtools-vite/src/editor.ts rename to packages/devtools-bundler-core/src/editor.ts diff --git a/packages/devtools-vite/src/enhance-logs.test.ts b/packages/devtools-bundler-core/src/enhance-logs.test.ts similarity index 100% rename from packages/devtools-vite/src/enhance-logs.test.ts rename to packages/devtools-bundler-core/src/enhance-logs.test.ts diff --git a/packages/devtools-vite/src/enhance-logs.ts b/packages/devtools-bundler-core/src/enhance-logs.ts similarity index 98% rename from packages/devtools-vite/src/enhance-logs.ts rename to packages/devtools-bundler-core/src/enhance-logs.ts index 018876d7..8e9811dd 100644 --- a/packages/devtools-vite/src/enhance-logs.ts +++ b/packages/devtools-bundler-core/src/enhance-logs.ts @@ -1,5 +1,5 @@ import chalk from 'chalk' -import { normalizePath } from 'vite' +import { normalizePath } from './normalize-path' import MagicString from 'magic-string' import { parseSync } from 'oxc-parser' import { createLocMapper } from './offset-to-loc' diff --git a/packages/devtools-bundler-core/src/index.ts b/packages/devtools-bundler-core/src/index.ts index 336ce12b..f942a2bc 100644 --- a/packages/devtools-bundler-core/src/index.ts +++ b/packages/devtools-bundler-core/src/index.ts @@ -1 +1,15 @@ -export {} +export * from './normalize-path' +export * from './types' +export * from './ast-utils' +export * from './devtools-packages' +export * from './editor' +export * from './enhance-logs' +export * from './inject-plugin' +export * from './inject-source' +export * from './matcher' +export * from './offset-to-loc' +export * from './package-manager' +export * from './remove-devtools' +export * from './runtime-bridge' +export * from './virtual-console' +export * from './utils' diff --git a/packages/devtools-vite/src/inject-plugin.test.ts b/packages/devtools-bundler-core/src/inject-plugin.test.ts similarity index 100% rename from packages/devtools-vite/src/inject-plugin.test.ts rename to packages/devtools-bundler-core/src/inject-plugin.test.ts diff --git a/packages/devtools-vite/src/inject-plugin.ts b/packages/devtools-bundler-core/src/inject-plugin.ts similarity index 100% rename from packages/devtools-vite/src/inject-plugin.ts rename to packages/devtools-bundler-core/src/inject-plugin.ts diff --git a/packages/devtools-vite/src/inject-source.test.ts b/packages/devtools-bundler-core/src/inject-source.test.ts similarity index 100% rename from packages/devtools-vite/src/inject-source.test.ts rename to packages/devtools-bundler-core/src/inject-source.test.ts diff --git a/packages/devtools-vite/src/inject-source.ts b/packages/devtools-bundler-core/src/inject-source.ts similarity index 99% rename from packages/devtools-vite/src/inject-source.ts rename to packages/devtools-bundler-core/src/inject-source.ts index b2a830a8..59aefc62 100644 --- a/packages/devtools-vite/src/inject-source.ts +++ b/packages/devtools-bundler-core/src/inject-source.ts @@ -1,4 +1,4 @@ -import { normalizePath } from 'vite' +import { normalizePath } from './normalize-path' import MagicString from 'magic-string' import { parseSync } from 'oxc-parser' import { createLocMapper } from './offset-to-loc' diff --git a/packages/devtools-vite/src/matcher.test.ts b/packages/devtools-bundler-core/src/matcher.test.ts similarity index 100% rename from packages/devtools-vite/src/matcher.test.ts rename to packages/devtools-bundler-core/src/matcher.test.ts diff --git a/packages/devtools-vite/src/matcher.ts b/packages/devtools-bundler-core/src/matcher.ts similarity index 100% rename from packages/devtools-vite/src/matcher.ts rename to packages/devtools-bundler-core/src/matcher.ts diff --git a/packages/devtools-bundler-core/src/normalize-path.ts b/packages/devtools-bundler-core/src/normalize-path.ts new file mode 100644 index 00000000..1c6177e1 --- /dev/null +++ b/packages/devtools-bundler-core/src/normalize-path.ts @@ -0,0 +1,2 @@ +// ponytail: Vite's normalizePath does exactly this (backslash -> forward slash). +export const normalizePath = (p: string): string => p.replace(/\\/g, '/') diff --git a/packages/devtools-vite/src/offset-to-loc.test.ts b/packages/devtools-bundler-core/src/offset-to-loc.test.ts similarity index 100% rename from packages/devtools-vite/src/offset-to-loc.test.ts rename to packages/devtools-bundler-core/src/offset-to-loc.test.ts diff --git a/packages/devtools-vite/src/offset-to-loc.ts b/packages/devtools-bundler-core/src/offset-to-loc.ts similarity index 100% rename from packages/devtools-vite/src/offset-to-loc.ts rename to packages/devtools-bundler-core/src/offset-to-loc.ts diff --git a/packages/devtools-vite/src/package-manager.ts b/packages/devtools-bundler-core/src/package-manager.ts similarity index 100% rename from packages/devtools-vite/src/package-manager.ts rename to packages/devtools-bundler-core/src/package-manager.ts diff --git a/packages/devtools-vite/src/remove-devtools.test.ts b/packages/devtools-bundler-core/src/remove-devtools.test.ts similarity index 100% rename from packages/devtools-vite/src/remove-devtools.test.ts rename to packages/devtools-bundler-core/src/remove-devtools.test.ts diff --git a/packages/devtools-vite/src/remove-devtools.ts b/packages/devtools-bundler-core/src/remove-devtools.ts similarity index 100% rename from packages/devtools-vite/src/remove-devtools.ts rename to packages/devtools-bundler-core/src/remove-devtools.ts diff --git a/packages/devtools-vite/src/runtime-bridge.test.ts b/packages/devtools-bundler-core/src/runtime-bridge.test.ts similarity index 100% rename from packages/devtools-vite/src/runtime-bridge.test.ts rename to packages/devtools-bundler-core/src/runtime-bridge.test.ts diff --git a/packages/devtools-vite/src/runtime-bridge.ts b/packages/devtools-bundler-core/src/runtime-bridge.ts similarity index 100% rename from packages/devtools-vite/src/runtime-bridge.ts rename to packages/devtools-bundler-core/src/runtime-bridge.ts diff --git a/packages/devtools-bundler-core/src/types.ts b/packages/devtools-bundler-core/src/types.ts new file mode 100644 index 00000000..a653329a --- /dev/null +++ b/packages/devtools-bundler-core/src/types.ts @@ -0,0 +1,76 @@ +import type { EditorConfig } from './editor' +import type { ServerEventBusConfig } from '@tanstack/devtools-event-bus/server' + +export type ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug' + +export type TanStackDevtoolsConfig = { + /** + * Configuration for the editor integration. Defaults to opening in VS code + */ + editor?: EditorConfig + /** + * The configuration options for the server event bus + */ + eventBusConfig?: ServerEventBusConfig & { + /** + * Should the server event bus be enabled or not + * @default true + */ + enabled?: boolean // defaults to true + } + /** + * Configuration for enhanced logging. + */ + enhancedLogs?: { + /** + * Whether to enable enhanced logging. + * @default true + */ + enabled: boolean + } + /** + * Whether to remove devtools from the production build. + * @default true + */ + removeDevtoolsOnBuild?: boolean + + /** + * Whether to log information to the console. + * @default true + */ + logging?: boolean + /** + * Configuration for source injection. + */ + injectSource?: { + /** + * Whether to enable source injection via data-tsd-source. + * @default true + */ + enabled: boolean + /** + * List of files or patterns to ignore for source injection. + */ + ignore?: { + files?: Array + components?: Array + } + } + /** + * Configuration for console piping between client and server. + * When enabled, console logs from the client will appear in the terminal, + * and server logs will appear in the browser console. + */ + consolePiping?: { + /** + * Whether to enable console piping. + * @default true + */ + enabled?: boolean + /** + * Which console methods to pipe. + * @default ['log', 'warn', 'error', 'info', 'debug'] + */ + levels?: Array + } +} diff --git a/packages/devtools-vite/src/utils.test.ts b/packages/devtools-bundler-core/src/utils.test.ts similarity index 100% rename from packages/devtools-vite/src/utils.test.ts rename to packages/devtools-bundler-core/src/utils.test.ts diff --git a/packages/devtools-vite/src/utils.ts b/packages/devtools-bundler-core/src/utils.ts similarity index 96% rename from packages/devtools-vite/src/utils.ts rename to packages/devtools-bundler-core/src/utils.ts index 428813fb..885820d2 100644 --- a/packages/devtools-vite/src/utils.ts +++ b/packages/devtools-bundler-core/src/utils.ts @@ -1,25 +1,26 @@ import fs from 'node:fs/promises' -import { normalizePath } from 'vite' -import type { Connect } from 'vite' +import { normalizePath } from './normalize-path' import type { IncomingMessage, ServerResponse } from 'node:http' import type { PackageJson } from '@tanstack/devtools-client' type DevToolsRequestHandler = (data: any) => void +type NextFunction = (err?: unknown) => void + type DevToolsViteRequestOptions = { onOpenSource?: DevToolsRequestHandler onConsolePipe?: (entries: Array) => void onServerConsolePipe?: (entries: Array) => void onConsolePipeSSE?: ( res: ServerResponse, - req: Connect.IncomingMessage, + req: IncomingMessage, ) => void } -export const handleDevToolsViteRequest = ( - req: Connect.IncomingMessage, +export const handleDevToolsRequest = ( + req: IncomingMessage & { url?: string }, res: ServerResponse, - next: Connect.NextFunction, + next: NextFunction, cbOrOptions: DevToolsRequestHandler | DevToolsViteRequestOptions, ) => { // Normalize to options object for backward compatibility diff --git a/packages/devtools-vite/src/virtual-console.test.ts b/packages/devtools-bundler-core/src/virtual-console.test.ts similarity index 100% rename from packages/devtools-vite/src/virtual-console.test.ts rename to packages/devtools-bundler-core/src/virtual-console.test.ts diff --git a/packages/devtools-vite/src/virtual-console.ts b/packages/devtools-bundler-core/src/virtual-console.ts similarity index 99% rename from packages/devtools-vite/src/virtual-console.ts rename to packages/devtools-bundler-core/src/virtual-console.ts index 27bb6b39..04aa0252 100644 --- a/packages/devtools-vite/src/virtual-console.ts +++ b/packages/devtools-bundler-core/src/virtual-console.ts @@ -1,4 +1,4 @@ -import type { ConsoleLevel } from './plugin' +import type { ConsoleLevel } from './types' // export const VIRTUAL_MODULE_ID = 'virtual:tanstack-devtools-console' // export const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID From 1d5100664a61e5ce385ca060b4d3a44e9b0f6b15 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 13:19:32 +0200 Subject: [PATCH 03/16] feat(bundler-core): add dev-state singleton for loader/plugin sharing --- .../src/connection.test.ts | 18 ++++++++++++++++++ .../devtools-bundler-core/src/connection.ts | 9 +++++++++ packages/devtools-bundler-core/src/index.ts | 1 + 3 files changed, 28 insertions(+) create mode 100644 packages/devtools-bundler-core/src/connection.test.ts create mode 100644 packages/devtools-bundler-core/src/connection.ts diff --git a/packages/devtools-bundler-core/src/connection.test.ts b/packages/devtools-bundler-core/src/connection.test.ts new file mode 100644 index 00000000..f15d9750 --- /dev/null +++ b/packages/devtools-bundler-core/src/connection.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from 'vitest' +import { + getDevtoolsConnection, setDevtoolsConnection, + getDevtoolsFileId, setDevtoolsFileId, +} from './connection' + +describe('connection singleton', () => { + it('returns sensible defaults before anything is set', () => { + expect(getDevtoolsConnection()).toEqual({ port: 4206, host: 'localhost', protocol: 'http' }) + expect(getDevtoolsFileId()).toBeNull() + }) + it('round-trips connection and file id', () => { + setDevtoolsConnection({ port: 5000, host: '0.0.0.0', protocol: 'https' }) + expect(getDevtoolsConnection()).toEqual({ port: 5000, host: '0.0.0.0', protocol: 'https' }) + setDevtoolsFileId('/app/src/main.tsx') + expect(getDevtoolsFileId()).toBe('/app/src/main.tsx') + }) +}) diff --git a/packages/devtools-bundler-core/src/connection.ts b/packages/devtools-bundler-core/src/connection.ts new file mode 100644 index 00000000..1021780d --- /dev/null +++ b/packages/devtools-bundler-core/src/connection.ts @@ -0,0 +1,9 @@ +export type DevtoolsConnection = { port: number; host: string; protocol: 'http' | 'https' } + +let connection: DevtoolsConnection = { port: 4206, host: 'localhost', protocol: 'http' } +let devtoolsFileId: string | null = null + +export const setDevtoolsConnection = (c: DevtoolsConnection) => { connection = c } +export const getDevtoolsConnection = (): DevtoolsConnection => connection +export const setDevtoolsFileId = (id: string | null) => { devtoolsFileId = id } +export const getDevtoolsFileId = (): string | null => devtoolsFileId diff --git a/packages/devtools-bundler-core/src/index.ts b/packages/devtools-bundler-core/src/index.ts index f942a2bc..75d29936 100644 --- a/packages/devtools-bundler-core/src/index.ts +++ b/packages/devtools-bundler-core/src/index.ts @@ -1,6 +1,7 @@ export * from './normalize-path' export * from './types' export * from './ast-utils' +export * from './connection' export * from './devtools-packages' export * from './editor' export * from './enhance-logs' From fcb4f8f223f2f4817439efc1730368238c3bacbc Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 13:29:45 +0200 Subject: [PATCH 04/16] refactor(devtools-vite): consume @tanstack/devtools-bundler-core --- packages/devtools-vite/package.json | 8 +- packages/devtools-vite/src/plugin.ts | 122 +++++---------------- packages/devtools-vite/tests/index.test.ts | 8 +- packages/devtools-vite/tests/utils.test.ts | 34 ++---- pnpm-lock.yaml | 18 +-- 5 files changed, 45 insertions(+), 145 deletions(-) diff --git a/packages/devtools-vite/package.json b/packages/devtools-vite/package.json index ae333ffb..409044a8 100644 --- a/packages/devtools-vite/package.json +++ b/packages/devtools-vite/package.json @@ -59,16 +59,12 @@ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "dependencies": { + "@tanstack/devtools-bundler-core": "workspace:*", "@tanstack/devtools-client": "workspace:*", "@tanstack/devtools-event-bus": "workspace:*", - "chalk": "^5.6.2", - "launch-editor": "^2.11.1", - "magic-string": "^0.30.0", - "oxc-parser": "^0.120.0", - "picomatch": "^4.0.3" + "chalk": "^5.6.2" }, "devDependencies": { - "@types/picomatch": "^4.0.2", "happy-dom": "^20.0.0" } } diff --git a/packages/devtools-vite/src/plugin.ts b/packages/devtools-vite/src/plugin.ts index aa415e27..8c7acdd6 100644 --- a/packages/devtools-vite/src/plugin.ts +++ b/packages/devtools-vite/src/plugin.ts @@ -1,109 +1,37 @@ import { devtoolsEventClient } from '@tanstack/devtools-client' import { ServerEventBus } from '@tanstack/devtools-event-bus/server' -import { normalizePath } from 'vite' import chalk from 'chalk' import { - handleDevToolsViteRequest, - readPackageJson, - stripEnhancedLogPrefix, -} from './utils' -import { DEFAULT_EDITOR_CONFIG, handleOpenSource } from './editor' -import { removeDevtools } from './remove-devtools' -import { addSourceToJsx } from './inject-source' -import { enhanceConsoleLog } from './enhance-logs' -import { detectDevtoolsFile, injectPluginIntoFile } from './inject-plugin' -import { TANSTACK_DEVTOOLS_PACKAGES } from './devtools-packages' -import { + DEFAULT_EDITOR_CONFIG, + TANSTACK_DEVTOOLS_PACKAGES, addPluginToDevtools, + addSourceToJsx, + detectDevtoolsFile, emitOutdatedDeps, - installPackage, -} from './package-manager' -import { generateConsolePipeCode } from './virtual-console' -import { + enhanceConsoleLog, + generateConsolePipeCode, + handleDevToolsRequest, + handleOpenSource, + injectPluginIntoFile, injectRuntimeBridge, + installPackage, + normalizePath, + readPackageJson, + removeDevtools, + stripEnhancedLogPrefix, wireRuntimeBridgeChannels, -} from './runtime-bridge' +} from '@tanstack/devtools-bundler-core' +import type { + ConsoleLevel, + EditorConfig, + TanStackDevtoolsConfig, +} from '@tanstack/devtools-bundler-core' import type { ServerResponse } from 'node:http' import type { Plugin } from 'vite' -import type { EditorConfig } from './editor' -import type { - HttpServerLike, - ServerEventBusConfig, -} from '@tanstack/devtools-event-bus/server' - -export type ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug' - -export type TanStackDevtoolsViteConfig = { - /** - * Configuration for the editor integration. Defaults to opening in VS code - */ - editor?: EditorConfig - /** - * The configuration options for the server event bus - */ - eventBusConfig?: ServerEventBusConfig & { - /** - * Should the server event bus be enabled or not - * @default true - */ - enabled?: boolean // defaults to true - } - /** - * Configuration for enhanced logging. - */ - enhancedLogs?: { - /** - * Whether to enable enhanced logging. - * @default true - */ - enabled: boolean - } - /** - * Whether to remove devtools from the production build. - * @default true - */ - removeDevtoolsOnBuild?: boolean - - /** - * Whether to log information to the console. - * @default true - */ - logging?: boolean - /** - * Configuration for source injection. - */ - injectSource?: { - /** - * Whether to enable source injection via data-tsd-source. - * @default true - */ - enabled: boolean - /** - * List of files or patterns to ignore for source injection. - */ - ignore?: { - files?: Array - components?: Array - } - } - /** - * Configuration for console piping between client and server. - * When enabled, console logs from the client will appear in the terminal, - * and server logs will appear in the browser console. - */ - consolePiping?: { - /** - * Whether to enable console piping. - * @default true - */ - enabled?: boolean - /** - * Which console methods to pipe. - * @default ['log', 'warn', 'error', 'info', 'debug'] - */ - levels?: Array - } -} +import type { HttpServerLike } from '@tanstack/devtools-event-bus/server' + +export type { ConsoleLevel } from '@tanstack/devtools-bundler-core' +export type TanStackDevtoolsViteConfig = TanStackDevtoolsConfig export const defineDevtoolsConfig = (config: TanStackDevtoolsViteConfig) => config @@ -250,7 +178,7 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array => { const consolePipingEnabled = consolePipingConfig.enabled ?? true server.middlewares.use((req, res, next) => - handleDevToolsViteRequest(req, res, next, { + handleDevToolsRequest(req, res, next, { onOpenSource: (parsedData) => { const { data, routine } = parsedData if (routine === 'open-source') { diff --git a/packages/devtools-vite/tests/index.test.ts b/packages/devtools-vite/tests/index.test.ts index b33b6f86..73118c05 100644 --- a/packages/devtools-vite/tests/index.test.ts +++ b/packages/devtools-vite/tests/index.test.ts @@ -1,15 +1,15 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { devtools } from '../src/plugin' import type { Plugin } from 'vite' -import type * as Utils from '../src/utils' +import type * as Core from '@tanstack/devtools-bundler-core' let capturedOnConsolePipe: ((entries: Array) => void) | undefined -vi.mock('../src/utils', async (importOriginal) => { - const actual = await importOriginal() +vi.mock('@tanstack/devtools-bundler-core', async (importOriginal) => { + const actual = await importOriginal() return { ...actual, - handleDevToolsViteRequest: vi.fn( + handleDevToolsRequest: vi.fn( (_req: any, _res: any, _next: any, handlers: any) => { if (typeof handlers === 'object' && handlers?.onConsolePipe) { capturedOnConsolePipe = handlers.onConsolePipe diff --git a/packages/devtools-vite/tests/utils.test.ts b/packages/devtools-vite/tests/utils.test.ts index 6913c216..ad6e1fc9 100644 --- a/packages/devtools-vite/tests/utils.test.ts +++ b/packages/devtools-vite/tests/utils.test.ts @@ -1,7 +1,9 @@ import { EventEmitter } from 'node:events' import { beforeEach, describe, expect, it, vi } from 'vitest' -import { normalizePath } from 'vite' -import { handleDevToolsViteRequest, parseOpenSourceParam } from '../src/utils' +import { + handleDevToolsRequest, + normalizePath, +} from '@tanstack/devtools-bundler-core' function createMockReq(url?: string) { const emitter = new EventEmitter() as unknown as EventEmitter & { @@ -20,7 +22,7 @@ function createMockRes() { } } -describe('handleDevToolsViteRequest', () => { +describe('handleDevToolsRequest', () => { let next: ReturnType let cb: ReturnType @@ -33,7 +35,7 @@ describe('handleDevToolsViteRequest', () => { const req = createMockReq('/some/other/path') const res = createMockRes() - handleDevToolsViteRequest(req, res as any, next as any, cb as any) + handleDevToolsRequest(req, res as any, next as any, cb as any) expect(next).toHaveBeenCalledTimes(1) expect(cb).not.toHaveBeenCalled() @@ -51,7 +53,7 @@ describe('handleDevToolsViteRequest', () => { const req = createMockReq(url) const res = createMockRes() - handleDevToolsViteRequest(req, res as any, next as any, cb as any) + handleDevToolsRequest(req, res as any, next as any, cb as any) // callback payload expect(cb).toHaveBeenCalledTimes(1) @@ -79,7 +81,7 @@ describe('handleDevToolsViteRequest', () => { const req = createMockReq('/__tsd/open-source') const res = createMockRes() - handleDevToolsViteRequest(req, res as any, next as any, cb as any) + handleDevToolsRequest(req, res as any, next as any, cb as any) expect(cb).not.toHaveBeenCalled() expect(res.setHeader).not.toHaveBeenCalled() @@ -93,7 +95,7 @@ describe('handleDevToolsViteRequest', () => { const req = createMockReq(`/__tsd/open-source?source=${malformed}`) const res = createMockRes() - handleDevToolsViteRequest(req, res as any, next as any, cb as any) + handleDevToolsRequest(req, res as any, next as any, cb as any) expect(cb).not.toHaveBeenCalled() expect(res.setHeader).not.toHaveBeenCalled() @@ -106,7 +108,7 @@ describe('handleDevToolsViteRequest', () => { const req = createMockReq('/__tsd/some-endpoint') const res = createMockRes() - handleDevToolsViteRequest(req, res as any, next as any, cb as any) + handleDevToolsRequest(req, res as any, next as any, cb as any) // simulate streaming body const chunks = [Buffer.from('{"foo":'), Buffer.from('1}')] @@ -128,7 +130,7 @@ describe('handleDevToolsViteRequest', () => { const req = createMockReq('/__tsd/another') const res = createMockRes() - handleDevToolsViteRequest(req, res as any, next as any, cb as any) + handleDevToolsRequest(req, res as any, next as any, cb as any) req.emit('data', Buffer.from('{ invalid json')) req.emit('end') @@ -137,17 +139,3 @@ describe('handleDevToolsViteRequest', () => { expect(res.end).toHaveBeenCalled() }) }) - -describe('parseOpenSourceParam', () => { - it('parses simple filename foo.tsx with line/column', () => { - const input = 'foo.tsx:10:20' - const parsed = parseOpenSourceParam(input) - expect(parsed).toEqual({ file: 'foo.tsx', line: '10', column: '20' }) - }) - - it('parses filename containing colon bar:baz.tsx with line/column', () => { - const input = 'bar:baz.tsx:3:7' - const parsed = parseOpenSourceParam(input) - expect(parsed).toEqual({ file: 'bar:baz.tsx', line: '3', column: '7' }) - }) -}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d60624fa..61e8fdfa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1650,6 +1650,9 @@ importers: packages/devtools-vite: dependencies: + '@tanstack/devtools-bundler-core': + specifier: workspace:* + version: link:../devtools-bundler-core '@tanstack/devtools-client': specifier: workspace:* version: link:../devtools-client @@ -1659,25 +1662,10 @@ importers: chalk: specifier: ^5.6.2 version: 5.6.2 - launch-editor: - specifier: ^2.11.1 - version: 2.13.2 - magic-string: - specifier: ^0.30.0 - version: 0.30.21 - oxc-parser: - specifier: ^0.120.0 - version: 0.120.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) - picomatch: - specifier: ^4.0.3 - version: 4.0.4 vite: specifier: ^6.0.0 || ^7.0.0 || ^8.0.0 version: 8.0.12(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) devDependencies: - '@types/picomatch': - specifier: ^4.0.2 - version: 4.0.3 happy-dom: specifier: ^20.0.0 version: 20.9.0 From 2517593523397a8020ff9541a1973f57eb6c9451 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 13:40:10 +0200 Subject: [PATCH 05/16] test(bundler-core): relocate handleDevToolsRequest routing tests from devtools-vite --- .../devtools-bundler-core/src/utils.test.ts | 145 +++++++++++++++++- packages/devtools-vite/tests/utils.test.ts | 141 ----------------- 2 files changed, 143 insertions(+), 143 deletions(-) delete mode 100644 packages/devtools-vite/tests/utils.test.ts diff --git a/packages/devtools-bundler-core/src/utils.test.ts b/packages/devtools-bundler-core/src/utils.test.ts index b760aee3..39d57c6d 100644 --- a/packages/devtools-bundler-core/src/utils.test.ts +++ b/packages/devtools-bundler-core/src/utils.test.ts @@ -1,5 +1,11 @@ -import { describe, expect, test } from 'vitest' -import { parseOpenSourceParam, stripEnhancedLogPrefix } from './utils' +import { EventEmitter } from 'node:events' +import { beforeEach, describe, expect, it, test, vi } from 'vitest' +import { + handleDevToolsRequest, + parseOpenSourceParam, + stripEnhancedLogPrefix, +} from './utils' +import { normalizePath } from './normalize-path' describe('parseOpenSourceParam', () => { test('parses simple file:line:column format', () => { @@ -182,3 +188,138 @@ describe('stripEnhancedLogPrefix', () => { ]) }) }) + +function createMockReq(url?: string) { + const emitter = new EventEmitter() as unknown as EventEmitter & { + url?: string + on: (event: string, listener: (...args: Array) => void) => any + } + ;(emitter as any).url = url + return emitter as any +} + +function createMockRes() { + return { + setHeader: vi.fn(), + write: vi.fn(), + end: vi.fn(), + } +} + +describe('handleDevToolsRequest', () => { + let next: ReturnType + let cb: ReturnType + + beforeEach(() => { + next = vi.fn() + cb = vi.fn() + }) + + it('calls next() when url does not include __tsd', () => { + const req = createMockReq('/some/other/path') + const res = createMockRes() + + handleDevToolsRequest(req, res as any, next as any, cb as any) + + expect(next).toHaveBeenCalledTimes(1) + expect(cb).not.toHaveBeenCalled() + expect(res.setHeader).not.toHaveBeenCalled() + expect(res.write).not.toHaveBeenCalled() + expect(res.end).not.toHaveBeenCalled() + }) + + it('handles __tsd/open-source with valid source and responds/ends', () => { + const file = 'src/file.ts' + const line = '12' + const column = '5' + const url = `/__tsd/open-source?source=${encodeURIComponent(`${file}:${line}:${column}`)}` + + const req = createMockReq(url) + const res = createMockRes() + + handleDevToolsRequest(req, res as any, next as any, cb as any) + + // callback payload + expect(cb).toHaveBeenCalledTimes(1) + const payload = cb.mock.calls[0]?.[0] + expect(payload).toMatchObject({ + type: 'open-source', + routine: 'open-source', + }) + expect(payload.data.line).toBe(line) + expect(payload.data.column).toBe(column) + + const expectedSource = normalizePath(`${process.cwd()}/${file}`) + expect(payload.data.source).toBe(expectedSource) + + // response behavior + expect(res.setHeader).toHaveBeenCalledWith('Content-Type', 'text/html') + expect(res.write).toHaveBeenCalledWith('') + expect(res.end).toHaveBeenCalled() + + // next() is not called for handled route + expect(next).not.toHaveBeenCalled() + }) + + it('does nothing for __tsd/open-source when source is missing', () => { + const req = createMockReq('/__tsd/open-source') + const res = createMockRes() + + handleDevToolsRequest(req, res as any, next as any, cb as any) + + expect(cb).not.toHaveBeenCalled() + expect(res.setHeader).not.toHaveBeenCalled() + expect(res.write).not.toHaveBeenCalled() + expect(res.end).not.toHaveBeenCalled() + expect(next).not.toHaveBeenCalled() + }) + + it('does nothing for __tsd/open-source when source is malformed', () => { + const malformed = encodeURIComponent('src/file.ts:abc:def') + const req = createMockReq(`/__tsd/open-source?source=${malformed}`) + const res = createMockRes() + + handleDevToolsRequest(req, res as any, next as any, cb as any) + + expect(cb).not.toHaveBeenCalled() + expect(res.setHeader).not.toHaveBeenCalled() + expect(res.write).not.toHaveBeenCalled() + expect(res.end).not.toHaveBeenCalled() + expect(next).not.toHaveBeenCalled() + }) + + it('parses JSON body for other __tsd requests and writes OK', () => { + const req = createMockReq('/__tsd/some-endpoint') + const res = createMockRes() + + handleDevToolsRequest(req, res as any, next as any, cb as any) + + // simulate streaming body + const chunks = [Buffer.from('{"foo":'), Buffer.from('1}')] + req.emit('data', chunks[0]) + req.emit('data', chunks[1]) + req.emit('end') + + expect(cb).toHaveBeenCalledTimes(1) + expect(cb).toHaveBeenCalledWith({ foo: 1 }) + expect(res.write).toHaveBeenCalledWith('OK') + expect(res.end).toHaveBeenCalled() + + // these are not used in this branch + expect(res.setHeader).not.toHaveBeenCalled() + expect(next).not.toHaveBeenCalled() + }) + + it('swallows JSON parse errors but still writes OK', () => { + const req = createMockReq('/__tsd/another') + const res = createMockRes() + + handleDevToolsRequest(req, res as any, next as any, cb as any) + req.emit('data', Buffer.from('{ invalid json')) + req.emit('end') + + expect(cb).not.toHaveBeenCalled() + expect(res.write).toHaveBeenCalledWith('OK') + expect(res.end).toHaveBeenCalled() + }) +}) diff --git a/packages/devtools-vite/tests/utils.test.ts b/packages/devtools-vite/tests/utils.test.ts deleted file mode 100644 index ad6e1fc9..00000000 --- a/packages/devtools-vite/tests/utils.test.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { EventEmitter } from 'node:events' -import { beforeEach, describe, expect, it, vi } from 'vitest' -import { - handleDevToolsRequest, - normalizePath, -} from '@tanstack/devtools-bundler-core' - -function createMockReq(url?: string) { - const emitter = new EventEmitter() as unknown as EventEmitter & { - url?: string - on: (event: string, listener: (...args: Array) => void) => any - } - ;(emitter as any).url = url - return emitter as any -} - -function createMockRes() { - return { - setHeader: vi.fn(), - write: vi.fn(), - end: vi.fn(), - } -} - -describe('handleDevToolsRequest', () => { - let next: ReturnType - let cb: ReturnType - - beforeEach(() => { - next = vi.fn() - cb = vi.fn() - }) - - it('calls next() when url does not include __tsd', () => { - const req = createMockReq('/some/other/path') - const res = createMockRes() - - handleDevToolsRequest(req, res as any, next as any, cb as any) - - expect(next).toHaveBeenCalledTimes(1) - expect(cb).not.toHaveBeenCalled() - expect(res.setHeader).not.toHaveBeenCalled() - expect(res.write).not.toHaveBeenCalled() - expect(res.end).not.toHaveBeenCalled() - }) - - it('handles __tsd/open-source with valid source and responds/ends', () => { - const file = 'src/file.ts' - const line = '12' - const column = '5' - const url = `/__tsd/open-source?source=${encodeURIComponent(`${file}:${line}:${column}`)}` - - const req = createMockReq(url) - const res = createMockRes() - - handleDevToolsRequest(req, res as any, next as any, cb as any) - - // callback payload - expect(cb).toHaveBeenCalledTimes(1) - const payload = cb.mock.calls[0]?.[0] - expect(payload).toMatchObject({ - type: 'open-source', - routine: 'open-source', - }) - expect(payload.data.line).toBe(line) - expect(payload.data.column).toBe(column) - - const expectedSource = normalizePath(`${process.cwd()}/${file}`) - expect(payload.data.source).toBe(expectedSource) - - // response behavior - expect(res.setHeader).toHaveBeenCalledWith('Content-Type', 'text/html') - expect(res.write).toHaveBeenCalledWith('') - expect(res.end).toHaveBeenCalled() - - // next() is not called for handled route - expect(next).not.toHaveBeenCalled() - }) - - it('does nothing for __tsd/open-source when source is missing', () => { - const req = createMockReq('/__tsd/open-source') - const res = createMockRes() - - handleDevToolsRequest(req, res as any, next as any, cb as any) - - expect(cb).not.toHaveBeenCalled() - expect(res.setHeader).not.toHaveBeenCalled() - expect(res.write).not.toHaveBeenCalled() - expect(res.end).not.toHaveBeenCalled() - expect(next).not.toHaveBeenCalled() - }) - - it('does nothing for __tsd/open-source when source is malformed', () => { - const malformed = encodeURIComponent('src/file.ts:abc:def') - const req = createMockReq(`/__tsd/open-source?source=${malformed}`) - const res = createMockRes() - - handleDevToolsRequest(req, res as any, next as any, cb as any) - - expect(cb).not.toHaveBeenCalled() - expect(res.setHeader).not.toHaveBeenCalled() - expect(res.write).not.toHaveBeenCalled() - expect(res.end).not.toHaveBeenCalled() - expect(next).not.toHaveBeenCalled() - }) - - it('parses JSON body for other __tsd requests and writes OK', () => { - const req = createMockReq('/__tsd/some-endpoint') - const res = createMockRes() - - handleDevToolsRequest(req, res as any, next as any, cb as any) - - // simulate streaming body - const chunks = [Buffer.from('{"foo":'), Buffer.from('1}')] - req.emit('data', chunks[0]) - req.emit('data', chunks[1]) - req.emit('end') - - expect(cb).toHaveBeenCalledTimes(1) - expect(cb).toHaveBeenCalledWith({ foo: 1 }) - expect(res.write).toHaveBeenCalledWith('OK') - expect(res.end).toHaveBeenCalled() - - // these are not used in this branch - expect(res.setHeader).not.toHaveBeenCalled() - expect(next).not.toHaveBeenCalled() - }) - - it('swallows JSON parse errors but still writes OK', () => { - const req = createMockReq('/__tsd/another') - const res = createMockRes() - - handleDevToolsRequest(req, res as any, next as any, cb as any) - req.emit('data', Buffer.from('{ invalid json')) - req.emit('end') - - expect(cb).not.toHaveBeenCalled() - expect(res.write).toHaveBeenCalledWith('OK') - expect(res.end).toHaveBeenCalled() - }) -}) From feb8b7ce1a1f294997b37942cb6d8cb99b1b3a69 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 13:48:12 +0200 Subject: [PATCH 06/16] feat(devtools-rspack): scaffold package with skeleton exports --- packages/devtools-rspack/CHANGELOG.md | 1 + packages/devtools-rspack/README.md | 29 +++ packages/devtools-rspack/eslint.config.js | 10 + packages/devtools-rspack/package.json | 43 +++++ packages/devtools-rspack/src/index.ts | 10 + packages/devtools-rspack/src/plugin.ts | 4 + packages/devtools-rspack/tsconfig.docs.json | 4 + packages/devtools-rspack/tsconfig.json | 1 + packages/devtools-rspack/vite.config.ts | 19 ++ pnpm-lock.yaml | 196 ++++++++++++++++++++ 10 files changed, 317 insertions(+) create mode 100644 packages/devtools-rspack/CHANGELOG.md create mode 100644 packages/devtools-rspack/README.md create mode 100644 packages/devtools-rspack/eslint.config.js create mode 100644 packages/devtools-rspack/package.json create mode 100644 packages/devtools-rspack/src/index.ts create mode 100644 packages/devtools-rspack/src/plugin.ts create mode 100644 packages/devtools-rspack/tsconfig.docs.json create mode 100644 packages/devtools-rspack/tsconfig.json create mode 100644 packages/devtools-rspack/vite.config.ts diff --git a/packages/devtools-rspack/CHANGELOG.md b/packages/devtools-rspack/CHANGELOG.md new file mode 100644 index 00000000..1d3f898f --- /dev/null +++ b/packages/devtools-rspack/CHANGELOG.md @@ -0,0 +1 @@ +# @tanstack/devtools-rspack diff --git a/packages/devtools-rspack/README.md b/packages/devtools-rspack/README.md new file mode 100644 index 00000000..28573524 --- /dev/null +++ b/packages/devtools-rspack/README.md @@ -0,0 +1,29 @@ +# @tanstack/devtools-rspack + +This package is still under active development and might have breaking changes in the future. Please use it with caution. + +## General Usage + +The `@tanstack/devtools-rspack` package is designed to work with Rspack projects. +Plug it into your plugins array: + +```js +const { devtools } = require('@tanstack/devtools-rspack') + +module.exports = { + plugins: [ + // Important to include it first! + devtools({ + /* options */ + }), + // ...rest of the plugins + ], +} +``` + +## Parity caveats + +This package aims for 1:1 feature parity with `@tanstack/devtools-vite`, with two known caveats: + +- **Runtime bridge channel wiring is Vite-only.** Vite's `wireRuntimeBridgeChannels` relies on Vite's SSR `server.environments[].hot` API, which has no Rspack equivalent. The code-injection half of the runtime bridge (`injectRuntimeBridge`) still runs for server-target builds, but the live channel wiring is not available under Rspack. +- **The `__tsd/*` dev endpoints require `@rspack/dev-server`.** The plugin wraps `devServer.setupMiddlewares` to mount the devtools middleware, so these endpoints are only available when the dev server reads and honors `compiler.options.devServer`. If your setup does not go through `@rspack/dev-server`'s standard config wiring, you may need to wire `setupMiddlewares` manually. diff --git a/packages/devtools-rspack/eslint.config.js b/packages/devtools-rspack/eslint.config.js new file mode 100644 index 00000000..e472c69e --- /dev/null +++ b/packages/devtools-rspack/eslint.config.js @@ -0,0 +1,10 @@ +// @ts-check + +import rootConfig from '../../eslint.config.js' + +export default [ + ...rootConfig, + { + rules: {}, + }, +] diff --git a/packages/devtools-rspack/package.json b/packages/devtools-rspack/package.json new file mode 100644 index 00000000..0f56b4d6 --- /dev/null +++ b/packages/devtools-rspack/package.json @@ -0,0 +1,43 @@ +{ + "name": "@tanstack/devtools-rspack", + "version": "0.0.1", + "description": "TanStack Rspack plugin used to enhance the core devtools with additional functionalities", + "author": "Tanner Linsley", + "license": "MIT", + "repository": { "type": "git", "url": "git+https://github.com/TanStack/devtools.git", "directory": "packages/devtools-rspack" }, + "homepage": "https://tanstack.com/devtools", + "bugs": { "url": "https://github.com/TanStack/devtools/issues" }, + "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" }, + "keywords": ["devtools", "rspack"], + "type": "module", + "types": "dist/esm/index.d.ts", + "module": "dist/esm/index.js", + "exports": { + ".": { "import": { "types": "./dist/esm/index.d.ts", "default": "./dist/esm/index.js" } }, + "./package.json": "./package.json" + }, + "sideEffects": false, + "engines": { "node": ">=18" }, + "files": ["dist/", "src"], + "scripts": { + "clean": "premove ./build ./dist", + "lint:fix": "eslint ./src --fix", + "test:eslint": "eslint ./src", + "test:lib": "vitest", + "test:lib:dev": "pnpm test:lib --watch", + "test:types": "tsc", + "test:build": "publint --strict", + "build": "vite build" + }, + "peerDependencies": { "@rspack/core": "^1.0.0" }, + "dependencies": { + "@tanstack/devtools-bundler-core": "workspace:*", + "@tanstack/devtools-client": "workspace:*", + "@tanstack/devtools-event-bus": "workspace:*", + "chalk": "^5.6.2" + }, + "devDependencies": { + "@rspack/core": "^1.0.0", + "happy-dom": "^20.0.0" + } +} diff --git a/packages/devtools-rspack/src/index.ts b/packages/devtools-rspack/src/index.ts new file mode 100644 index 00000000..0158cfbb --- /dev/null +++ b/packages/devtools-rspack/src/index.ts @@ -0,0 +1,10 @@ +import { TanStackDevtoolsRspackPlugin } from './plugin' +import type { TanStackDevtoolsConfig } from '@tanstack/devtools-bundler-core' + +export type { ConsoleLevel } from '@tanstack/devtools-bundler-core' +export type TanStackDevtoolsRspackConfig = TanStackDevtoolsConfig + +export const defineDevtoolsConfig = (config: TanStackDevtoolsRspackConfig) => config + +export const devtools = (args?: TanStackDevtoolsRspackConfig) => + new TanStackDevtoolsRspackPlugin(args) diff --git a/packages/devtools-rspack/src/plugin.ts b/packages/devtools-rspack/src/plugin.ts new file mode 100644 index 00000000..2ccc778a --- /dev/null +++ b/packages/devtools-rspack/src/plugin.ts @@ -0,0 +1,4 @@ +export class TanStackDevtoolsRspackPlugin { + constructor(_?: unknown) {} + apply(_: unknown) {} +} diff --git a/packages/devtools-rspack/tsconfig.docs.json b/packages/devtools-rspack/tsconfig.docs.json new file mode 100644 index 00000000..2880b4df --- /dev/null +++ b/packages/devtools-rspack/tsconfig.docs.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["tests", "src"] +} diff --git a/packages/devtools-rspack/tsconfig.json b/packages/devtools-rspack/tsconfig.json new file mode 100644 index 00000000..f5be8dcd --- /dev/null +++ b/packages/devtools-rspack/tsconfig.json @@ -0,0 +1 @@ +{ "extends": "../../tsconfig.json", "include": ["src", "eslint.config.js", "vite.config.ts"] } diff --git a/packages/devtools-rspack/vite.config.ts b/packages/devtools-rspack/vite.config.ts new file mode 100644 index 00000000..760700c8 --- /dev/null +++ b/packages/devtools-rspack/vite.config.ts @@ -0,0 +1,19 @@ +import { defineConfig, mergeConfig } from 'vitest/config' +import { tanstackViteConfig } from '@tanstack/vite-config' +import packageJson from './package.json' + +const config = defineConfig({ + plugins: [], + test: { + name: packageJson.name, + dir: './', + watch: false, + environment: 'happy-dom', + globals: true, + }, +}) + +export default mergeConfig( + config, + tanstackViteConfig({ cjs: false, entry: ['./src/index.ts'], srcDir: './src' }), +) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 61e8fdfa..4f140245 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1592,6 +1592,28 @@ importers: specifier: workspace:^ version: link:../event-bus-client + packages/devtools-rspack: + dependencies: + '@tanstack/devtools-bundler-core': + specifier: workspace:* + version: link:../devtools-bundler-core + '@tanstack/devtools-client': + specifier: workspace:* + version: link:../devtools-client + '@tanstack/devtools-event-bus': + specifier: workspace:* + version: link:../event-bus + chalk: + specifier: ^5.6.2 + version: 5.6.2 + devDependencies: + '@rspack/core': + specifier: ^1.0.0 + version: 1.7.12 + happy-dom: + specifier: ^20.0.0 + version: 20.9.0 + packages/devtools-ui: dependencies: clsx: @@ -3585,6 +3607,24 @@ packages: '@cfworker/json-schema': optional: true + '@module-federation/error-codes@0.22.0': + resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} + + '@module-federation/runtime-core@0.22.0': + resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} + + '@module-federation/runtime-tools@0.22.0': + resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} + + '@module-federation/runtime@0.22.0': + resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} + + '@module-federation/sdk@0.22.0': + resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} + + '@module-federation/webpack-bundler-runtime@0.22.0': + resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} cpu: [arm64] @@ -3734,6 +3774,9 @@ packages: '@napi-rs/wasm-runtime@0.2.4': resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} + '@napi-rs/wasm-runtime@1.0.7': + resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + '@napi-rs/wasm-runtime@1.1.4': resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} peerDependencies: @@ -4804,6 +4847,74 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + '@rspack/binding-darwin-arm64@1.7.12': + resolution: {integrity: sha512-rbFprJaJiqrmfy8SHth8EsoRS0wg4bXcucwj9NiMzpGFq14Opw8c04iQ6H9BECYzgmN0PKZ9rh41LdVvhdZe4A==} + cpu: [arm64] + os: [darwin] + + '@rspack/binding-darwin-x64@1.7.12': + resolution: {integrity: sha512-jnOp+/UXOJa9xqUb8KXH03sysoO2e4Ij6tw6MqDdmdj8n/A8PQENRPUbW9AwXpPtVDJPus9r4fi7b3+6e4B8Hg==} + cpu: [x64] + os: [darwin] + + '@rspack/binding-linux-arm64-gnu@1.7.12': + resolution: {integrity: sha512-C8owWG+yvo7X0oVLIXetkoJhIFBP1LYNcAQqtgLmJnQLQDklGuP83dKC+zISGQWpjawHfZ1ER96vLgoTrxKZdw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rspack/binding-linux-arm64-musl@1.7.12': + resolution: {integrity: sha512-i51WWI64aRpsfSki6rN0aepPqXkVfS+vZM7+4bWDcmnhUmdMvhIPcYg0QRk3DtyJnu33jqNLM0WHY78k00NyfA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rspack/binding-linux-x64-gnu@1.7.12': + resolution: {integrity: sha512-MSos0FuPEefqo9V92ULd5hggKG29EkSNg1zDcypy0OkpsKh5pfjVxTLYFXgTcVyFoUQQbdG8zFBzYbwmJ8V4ew==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rspack/binding-linux-x64-musl@1.7.12': + resolution: {integrity: sha512-JcAMVKXOnjfpC3coWjCFPWD3Yl8RBw6a+IXQQ8mfRlHaHMIiOv8IfZqx15XRxMUn49CtP7Z0Na8iiAg2aKrcfw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rspack/binding-wasm32-wasi@1.7.12': + resolution: {integrity: sha512-n+ZqP6ZMc0nhOgvadg5VhEs9ojtbES80AcWeFnmGkbzIszvGSO63GKNiRkXtjJ9KFuRzytbbmsCqkUVH+Tywxg==} + cpu: [wasm32] + + '@rspack/binding-win32-arm64-msvc@1.7.12': + resolution: {integrity: sha512-8+h5fYDXYdmugbdfZ+D1y8IQ3rv2EhSfyGP7vBe+bjNyaMa4jWrpucmZbtxojUL1AzaeuHbvMdj9UO/gelk/+g==} + cpu: [arm64] + os: [win32] + + '@rspack/binding-win32-ia32-msvc@1.7.12': + resolution: {integrity: sha512-cDMGwTRSa2p9fNBVe1wTRkF2AEXZ9ARWW36QeC5CkLaI0Ezz8lvhF2+CSOPnhaQ1O1qtn0L0SF+lFnrY+I7xGQ==} + cpu: [ia32] + os: [win32] + + '@rspack/binding-win32-x64-msvc@1.7.12': + resolution: {integrity: sha512-wIqFvlgFqrgUyj/6S/FJcvShnkZOmIeXTfqvheLY67MGq8qd8jb1YimQVKAIrmWB3yuJKUFACI3Ag1UBtEedEA==} + cpu: [x64] + os: [win32] + + '@rspack/binding@1.7.12': + resolution: {integrity: sha512-f4HHuLbvuld8Ba4iB/4ibse5XrKxFrgmM3S4P2AOKnPlekAFlBjmltCuaTL/W2ggYvILaVY+YcFXrEH1rrKeQA==} + + '@rspack/core@1.7.12': + resolution: {integrity: sha512-6CwFIHlhRmXfZoMj3v9MZ1SMTPBn+cHVXeMIeaGp5sufqinKsISbsqHu6ZMJu2wDSmZLdmQJX6zLxkhcAUlhkQ==} + engines: {node: '>=18.12.0'} + peerDependencies: + '@swc/helpers': '>=0.5.1' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@rspack/lite-tapable@1.1.0': + resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==} + '@rushstack/node-core-library@5.7.0': resolution: {integrity: sha512-Ff9Cz/YlWu9ce4dmqNBZpA45AEya04XaBFIjV7xTVeEf+y/kTjEasmozqFELXlNG4ROdevss75JrrZ5WgufDkQ==} peerDependencies: @@ -13466,6 +13577,31 @@ snapshots: - supports-color optional: true + '@module-federation/error-codes@0.22.0': {} + + '@module-federation/runtime-core@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@module-federation/runtime-tools@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/webpack-bundler-runtime': 0.22.0 + + '@module-federation/runtime@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/runtime-core': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@module-federation/sdk@0.22.0': {} + + '@module-federation/webpack-bundler-runtime@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': optional: true @@ -13569,6 +13705,13 @@ snapshots: '@emnapi/runtime': 1.10.0 '@tybys/wasm-util': 0.9.0 + '@napi-rs/wasm-runtime@1.0.7': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.2 + optional: true + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: '@emnapi/core': 1.10.0 @@ -14311,6 +14454,59 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + '@rspack/binding-darwin-arm64@1.7.12': + optional: true + + '@rspack/binding-darwin-x64@1.7.12': + optional: true + + '@rspack/binding-linux-arm64-gnu@1.7.12': + optional: true + + '@rspack/binding-linux-arm64-musl@1.7.12': + optional: true + + '@rspack/binding-linux-x64-gnu@1.7.12': + optional: true + + '@rspack/binding-linux-x64-musl@1.7.12': + optional: true + + '@rspack/binding-wasm32-wasi@1.7.12': + dependencies: + '@napi-rs/wasm-runtime': 1.0.7 + optional: true + + '@rspack/binding-win32-arm64-msvc@1.7.12': + optional: true + + '@rspack/binding-win32-ia32-msvc@1.7.12': + optional: true + + '@rspack/binding-win32-x64-msvc@1.7.12': + optional: true + + '@rspack/binding@1.7.12': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.7.12 + '@rspack/binding-darwin-x64': 1.7.12 + '@rspack/binding-linux-arm64-gnu': 1.7.12 + '@rspack/binding-linux-arm64-musl': 1.7.12 + '@rspack/binding-linux-x64-gnu': 1.7.12 + '@rspack/binding-linux-x64-musl': 1.7.12 + '@rspack/binding-wasm32-wasi': 1.7.12 + '@rspack/binding-win32-arm64-msvc': 1.7.12 + '@rspack/binding-win32-ia32-msvc': 1.7.12 + '@rspack/binding-win32-x64-msvc': 1.7.12 + + '@rspack/core@1.7.12': + dependencies: + '@module-federation/runtime-tools': 0.22.0 + '@rspack/binding': 1.7.12 + '@rspack/lite-tapable': 1.1.0 + + '@rspack/lite-tapable@1.1.0': {} + '@rushstack/node-core-library@5.7.0(@types/node@22.19.15)': dependencies: ajv: 8.13.0 From f0ca7d86bc0e554af671a57f9fafb2ec60cdd50d Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 14:09:12 +0200 Subject: [PATCH 07/16] feat(devtools-rspack): transform pipeline loader --- packages/devtools-rspack/src/loader.test.ts | 45 ++++++ packages/devtools-rspack/src/loader.ts | 146 ++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 packages/devtools-rspack/src/loader.test.ts create mode 100644 packages/devtools-rspack/src/loader.ts diff --git a/packages/devtools-rspack/src/loader.test.ts b/packages/devtools-rspack/src/loader.test.ts new file mode 100644 index 00000000..96d9ffe6 --- /dev/null +++ b/packages/devtools-rspack/src/loader.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from 'vitest' +import { runPipeline } from './loader' + +const dev = (over = {}) => ({ + mode: 'development' as const, + config: { injectSource: { enabled: true }, enhancedLogs: { enabled: true }, + consolePiping: { enabled: true }, removeDevtoolsOnBuild: true }, + connection: { port: 4206, host: 'localhost', protocol: 'http' as const }, + target: 'web', + ...over, +}) + +describe('runPipeline', () => { + it('injects data-tsd-source into JSX in dev', () => { + const out = runPipeline('const A = () =>
hi
', '/proj/src/a.tsx', dev()) + expect(out).toContain('data-tsd-source') + }) + + it('enhances console.* calls in dev', () => { + const out = runPipeline('console.log("x")', '/proj/src/b.ts', dev()) + expect(out).not.toBe('console.log("x")') // enhanced with source location + }) + + it('replaces connection placeholders', () => { + const code = 'const p = __TANSTACK_DEVTOOLS_PORT__; const h = __TANSTACK_DEVTOOLS_HOST__' + const out = runPipeline(code, '/proj/node_modules/@tanstack/devtools/x.js', + dev({ connection: { port: 9000, host: 'localhost', protocol: 'http' } })) + expect(out).toContain('9000') + expect(out).toContain('"localhost"') + }) + + it('strips devtools code in production builds', () => { + const code = 'import { TanStackDevtools } from "@tanstack/react-devtools"\nconst App = () => ' + const out = runPipeline(code, '/proj/src/main.tsx', + { ...dev(), mode: 'production' }) + expect(out).not.toContain('TanStackDevtools') + expect(out).not.toContain('@tanstack/react-devtools') + }) + + it('leaves node_modules untouched for source injection', () => { + const code = 'const A = () =>
hi
' + const out = runPipeline(code, '/proj/node_modules/pkg/a.tsx', dev()) + expect(out).not.toContain('data-tsd-source') + }) +}) diff --git a/packages/devtools-rspack/src/loader.ts b/packages/devtools-rspack/src/loader.ts new file mode 100644 index 00000000..c03d3422 --- /dev/null +++ b/packages/devtools-rspack/src/loader.ts @@ -0,0 +1,146 @@ +import { + TANSTACK_DEVTOOLS_PACKAGES, + addSourceToJsx, + detectDevtoolsFile, + enhanceConsoleLog, + generateConsolePipeCode, + getDevtoolsConnection, + injectRuntimeBridge, + removeDevtools, + setDevtoolsFileId, +} from '@tanstack/devtools-bundler-core' +import type { + ConsoleLevel, + DevtoolsConnection, + TanStackDevtoolsConfig, +} from '@tanstack/devtools-bundler-core' + +const EXCLUDE = /node_modules|\?raw|[\\/](dist|build)[\\/]/ +const isServerTarget = (target: string) => /node|async-node/.test(target) + +const DEFAULT_LEVELS: Array = [ + 'log', + 'warn', + 'error', + 'info', + 'debug', +] + +export interface PipelineCtx { + mode: 'development' | 'production' | 'none' + config: TanStackDevtoolsConfig + connection: DevtoolsConnection + target: string +} + +export function runPipeline( + code: string, + id: string, + ctx: PipelineCtx, +): string { + const { mode, config, connection, target } = ctx + const isDev = mode === 'development' + const filePath = id.split('?')[0] ?? id + const excluded = EXCLUDE.test(id) + let result = code + + const injectEnabled = config.injectSource?.enabled ?? true + const logsEnabled = config.enhancedLogs?.enabled ?? true + const pipeEnabled = config.consolePiping?.enabled ?? true + const removeEnabled = config.removeDevtoolsOnBuild ?? true + const levels = config.consolePiping?.levels ?? DEFAULT_LEVELS + + // 1. source injection (dev, JSX/TSX, not excluded) + // addSourceToJsx returns `{ code, map } | undefined` (verified against core). + if (isDev && injectEnabled && !excluded && /\.[jt]sx$/.test(filePath)) { + const injected = addSourceToJsx(result, id, config.injectSource?.ignore) + if (injected) result = injected.code + } + + // 2. enhanced console logs (dev, contains console., not excluded) + // enhanceConsoleLog returns `{ code, map } | undefined` (verified against core). + if (isDev && logsEnabled && !excluded && result.includes('console.')) { + const enhanced = enhanceConsoleLog(result, id, connection.port) + if (enhanced) result = enhanced.code + } + + // 3. console-pipe injection into root entry files (dev, js/ts, not excluded, not already piped) + if ( + isDev && + pipeEnabled && + !excluded && + /\.[cm]?[jt]sx?$/.test(filePath) && + !result.includes('__tsdConsolePipe') + ) { + const isRootEntry = + /]/i.test(result) || + result.includes('StartClient') || + result.includes('hydrateRoot') || + result.includes('createRoot') || + (result.includes('solid-js/web') && result.includes('render(')) + if (isRootEntry) { + const serverUrl = `${connection.protocol}://${connection.host}:${connection.port}` + result = `${generateConsolePipeCode(levels, serverUrl)}\n${result}` + } + } + + // 4. connection placeholder replacement (@tanstack/devtools|event-bus modules) + if ( + (result.includes('__TANSTACK_DEVTOOLS_PORT__') || + result.includes('__TANSTACK_DEVTOOLS_HOST__') || + result.includes('__TANSTACK_DEVTOOLS_PROTOCOL__')) && + (id.includes('@tanstack/devtools') || id.includes('@tanstack/event-bus')) + ) { + result = result + .replace(/__TANSTACK_DEVTOOLS_PORT__/g, String(connection.port)) + .replace(/__TANSTACK_DEVTOOLS_HOST__/g, JSON.stringify(connection.host)) + .replace( + /__TANSTACK_DEVTOOLS_PROTOCOL__/g, + JSON.stringify(connection.protocol), + ) + } + + // 5. runtime bridge (server target only; code-injection half — see parity caveat) + // injectRuntimeBridge returns `string | undefined` (verified against core). + if (isDev && !id.includes('?')) { + const env = isServerTarget(target) ? 'server' : 'client' + result = injectRuntimeBridge(result, id, env) ?? result + } + + // 6. devtools file detection (records id for package-manager auto-injection) + if (isDev && detectDevtoolsFile(result)) { + setDevtoolsFileId(filePath) + } + + // 7. remove devtools in production build + // removeDevtools returns `{ code, map } | undefined` (verified against core). + if ( + mode === 'production' && + removeEnabled && + !id.includes('node_modules') && + !id.includes('?raw') && + TANSTACK_DEVTOOLS_PACKAGES.some((pkg) => result.includes(pkg)) + ) { + const transformed = removeDevtools(result, id) + if (transformed) result = transformed.code + } + + return result +} + +// webpack/rspack loader entry +export default function tanstackDevtoolsLoader( + this: any, + source: string, +): string { + const opts = (this.getOptions?.() ?? {}) as { + config?: TanStackDevtoolsConfig + } + const target = String(this._compiler?.options?.target ?? 'web') + return runPipeline(source, this.resourcePath, { + mode: this.mode ?? 'development', + config: opts.config ?? {}, + connection: getDevtoolsConnection(), + target, + }) +} From 1ee17d9e2331b8636ce0d5d3528f65498624a710 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 14:36:52 +0200 Subject: [PATCH 08/16] feat(devtools-rspack): plugin (loader injection, event bus, dev middleware, package manager) + dev-server port routing --- .../devtools-bundler-core/src/connection.ts | 13 + packages/devtools-rspack/src/loader.ts | 30 +- packages/devtools-rspack/src/plugin.test.ts | 54 +++ packages/devtools-rspack/src/plugin.ts | 367 +++++++++++++++++- packages/devtools-rspack/vite.config.ts | 6 +- 5 files changed, 464 insertions(+), 6 deletions(-) create mode 100644 packages/devtools-rspack/src/plugin.test.ts diff --git a/packages/devtools-bundler-core/src/connection.ts b/packages/devtools-bundler-core/src/connection.ts index 1021780d..1b10e37e 100644 --- a/packages/devtools-bundler-core/src/connection.ts +++ b/packages/devtools-bundler-core/src/connection.ts @@ -7,3 +7,16 @@ export const setDevtoolsConnection = (c: DevtoolsConnection) => { connection = c export const getDevtoolsConnection = (): DevtoolsConnection => connection export const setDevtoolsFileId = (id: string | null) => { devtoolsFileId = id } export const getDevtoolsFileId = (): string | null => devtoolsFileId + +/** + * Origin of the bundler dev server (e.g. rspack-dev-server). This is where the + * `__tsd/*` middleware endpoints are mounted, and it is DISTINCT from the event + * bus connection above (which the devtools client connects to on port 4206). + * The dev-server origin is used to build the absolute `/__tsd/open-source` URL + * baked into enhanced console logs and the SSR-side `/__tsd/console-pipe/server` + * POST target. + */ +export type DevServerOrigin = { port: number; host: string; protocol: 'http' | 'https' } +let devServerOrigin: DevServerOrigin | null = null +export const setDevServerOrigin = (o: DevServerOrigin) => { devServerOrigin = o } +export const getDevServerOrigin = (): DevServerOrigin | null => devServerOrigin diff --git a/packages/devtools-rspack/src/loader.ts b/packages/devtools-rspack/src/loader.ts index c03d3422..93ba98e4 100644 --- a/packages/devtools-rspack/src/loader.ts +++ b/packages/devtools-rspack/src/loader.ts @@ -4,6 +4,7 @@ import { detectDevtoolsFile, enhanceConsoleLog, generateConsolePipeCode, + getDevServerOrigin, getDevtoolsConnection, injectRuntimeBridge, removeDevtools, @@ -11,6 +12,7 @@ import { } from '@tanstack/devtools-bundler-core' import type { ConsoleLevel, + DevServerOrigin, DevtoolsConnection, TanStackDevtoolsConfig, } from '@tanstack/devtools-bundler-core' @@ -29,7 +31,18 @@ const DEFAULT_LEVELS: Array = [ export interface PipelineCtx { mode: 'development' | 'production' | 'none' config: TanStackDevtoolsConfig + /** + * The event-bus connection (devtools client <-> event bus, default port 4206). + * Used ONLY for `__TANSTACK_DEVTOOLS_*` placeholder replacement. + */ connection: DevtoolsConnection + /** + * The dev-server origin where the `__tsd/*` middleware endpoints are mounted. + * Used for the `/__tsd/open-source` URL baked into enhanced logs and the + * SSR-side `/__tsd/console-pipe/server` POST target. Falls back to + * `connection` when absent (e.g. in unit tests). + */ + devServer?: DevServerOrigin target: string } @@ -38,7 +51,7 @@ export function runPipeline( id: string, ctx: PipelineCtx, ): string { - const { mode, config, connection, target } = ctx + const { mode, config, connection, devServer, target } = ctx const isDev = mode === 'development' const filePath = id.split('?')[0] ?? id const excluded = EXCLUDE.test(id) @@ -59,8 +72,14 @@ export function runPipeline( // 2. enhanced console logs (dev, contains console., not excluded) // enhanceConsoleLog returns `{ code, map } | undefined` (verified against core). + // The port here builds the absolute `/__tsd/open-source` URL, which is served + // by the DEV SERVER middleware — use the dev-server port, not the event bus. if (isDev && logsEnabled && !excluded && result.includes('console.')) { - const enhanced = enhanceConsoleLog(result, id, connection.port) + const enhanced = enhanceConsoleLog( + result, + id, + devServer?.port ?? connection.port, + ) if (enhanced) result = enhanced.code } @@ -79,7 +98,11 @@ export function runPipeline( result.includes('createRoot') || (result.includes('solid-js/web') && result.includes('render(')) if (isRootEntry) { - const serverUrl = `${connection.protocol}://${connection.host}:${connection.port}` + // The SSR runtime POSTs to `${serverUrl}/__tsd/console-pipe/server`, an + // endpoint mounted on the DEV SERVER — use the dev-server origin, not the + // event bus. Falls back to the connection origin when absent (unit tests). + const origin = devServer ?? connection + const serverUrl = `${origin.protocol}://${origin.host}:${origin.port}` result = `${generateConsolePipeCode(levels, serverUrl)}\n${result}` } } @@ -141,6 +164,7 @@ export default function tanstackDevtoolsLoader( mode: this.mode ?? 'development', config: opts.config ?? {}, connection: getDevtoolsConnection(), + devServer: getDevServerOrigin() ?? undefined, target, }) } diff --git a/packages/devtools-rspack/src/plugin.test.ts b/packages/devtools-rspack/src/plugin.test.ts new file mode 100644 index 00000000..a99ae8f2 --- /dev/null +++ b/packages/devtools-rspack/src/plugin.test.ts @@ -0,0 +1,54 @@ +import { getDevServerOrigin } from '@tanstack/devtools-bundler-core' +import { describe, expect, it, vi } from 'vitest' +import { TanStackDevtoolsRspackPlugin } from './plugin' + +function mockCompiler(mode: 'development' | 'production') { + return { + options: { + mode, + module: { rules: [] as Array }, + devServer: {} as any, + target: 'web', + }, + hooks: { + watchRun: { tapPromise: vi.fn() }, + done: { tap: vi.fn() }, + }, + } +} + +describe('TanStackDevtoolsRspackPlugin', () => { + it('injects the loader rule for js/ts/jsx/tsx', () => { + const c = mockCompiler('development') + new TanStackDevtoolsRspackPlugin().apply(c as any) + // The task-specified rule test is `/\.[cm]?[jt]sx?$/`; assert it functionally + // matches every extension rather than relying on a brittle string include. + const rule = c.options.module.rules.find( + (r: any) => r.test instanceof RegExp && r.test.test('foo.jsx'), + ) + expect(rule).toBeTruthy() + expect(rule.test.test('foo.js')).toBe(true) + expect(rule.test.test('foo.ts')).toBe(true) + expect(rule.test.test('foo.tsx')).toBe(true) + expect(String(rule.use?.[0]?.loader ?? rule.loader)).toContain('loader') + }) + + it('wraps devServer.setupMiddlewares in development', () => { + const c = mockCompiler('development') + new TanStackDevtoolsRspackPlugin().apply(c as any) + expect(typeof c.options.devServer.setupMiddlewares).toBe('function') + }) + + it('does not wrap setupMiddlewares in production', () => { + const c = mockCompiler('production') + new TanStackDevtoolsRspackPlugin().apply(c as any) + expect(c.options.devServer.setupMiddlewares).toBeUndefined() + }) + + it('records the dev-server origin from options.devServer.port', () => { + const c = mockCompiler('development') + c.options.devServer.port = 3100 + new TanStackDevtoolsRspackPlugin().apply(c as any) + expect(getDevServerOrigin()?.port).toBe(3100) + }) +}) diff --git a/packages/devtools-rspack/src/plugin.ts b/packages/devtools-rspack/src/plugin.ts index 2ccc778a..49bad4ed 100644 --- a/packages/devtools-rspack/src/plugin.ts +++ b/packages/devtools-rspack/src/plugin.ts @@ -1,4 +1,367 @@ +import { createRequire } from 'node:module' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import { devtoolsEventClient } from '@tanstack/devtools-client' +import { ServerEventBus } from '@tanstack/devtools-event-bus/server' +import chalk from 'chalk' +import { + DEFAULT_EDITOR_CONFIG, + addPluginToDevtools, + emitOutdatedDeps, + getDevtoolsFileId, + handleDevToolsRequest, + handleOpenSource, + injectPluginIntoFile, + installPackage, + readPackageJson, + setDevServerOrigin, + setDevtoolsConnection, + stripEnhancedLogPrefix, +} from '@tanstack/devtools-bundler-core' +import type { + ConsoleLevel, + EditorConfig, + TanStackDevtoolsConfig, +} from '@tanstack/devtools-bundler-core' +import type { IncomingMessage, ServerResponse } from 'node:http' +import type { PackageJson } from '@tanstack/devtools-client' + +const require = createRequire(import.meta.url) +const DIRNAME = path.dirname(fileURLToPath(import.meta.url)) +const DEFAULT_LEVELS: Array = [ + 'log', + 'warn', + 'error', + 'info', + 'debug', +] +const PLUGIN = '@tanstack/devtools-rspack' +const DEFAULT_DEV_SERVER_PORT = 8080 + +/** + * Resolves the emitted loader module. At runtime the plugin executes from + * `dist/esm/plugin.js` and the loader ships as `dist/esm/loader.js`. During unit + * tests it runs from `src/plugin.ts` and the sibling is `src/loader.ts`. Try the + * candidates in order; fall back to the expected built path so the injected rule + * still carries a `loader` string even before the package is built. + */ +function resolveLoaderPath(): string { + const candidates = ['loader.js', 'loader.cjs', 'loader.mjs', 'loader.ts'] + for (const candidate of candidates) { + try { + return require.resolve(path.join(DIRNAME, candidate)) + } catch { + // try next candidate + } + } + return path.join(DIRNAME, 'loader.js') +} + export class TanStackDevtoolsRspackPlugin { - constructor(_?: unknown) {} - apply(_: unknown) {} + private args: TanStackDevtoolsConfig + constructor(args?: TanStackDevtoolsConfig) { + this.args = args ?? {} + } + + apply(compiler: any) { + const args = this.args + const isDev = compiler.options.mode === 'development' + const logging = args.logging ?? true + + // 1. inject the loader for every js/ts/jsx/tsx module. Injected in BOTH modes: + // production still needs the remove-devtools transform. + const loaderPath = resolveLoaderPath() + compiler.options.module = compiler.options.module ?? { rules: [] } + compiler.options.module.rules = compiler.options.module.rules ?? [] + compiler.options.module.rules.push({ + test: /\.[cm]?[jt]sx?$/, + exclude: /node_modules/, + enforce: 'pre', + use: [{ loader: loaderPath, options: { config: args } }], + }) + + // Server features are dev-only. + if (!isDev) return + + // Record the dev-server origin early so it is available even before the + // first `setupMiddlewares` call. The `__tsd/*` endpoints are mounted on the + // dev server, so enhanced-log / SSR-console-pipe URLs must target IT (not the + // event bus). Refined with the real port once the dev server is known. + setDevServerOrigin({ + port: compiler.options.devServer?.port ?? DEFAULT_DEV_SERVER_PORT, + host: 'localhost', + protocol: 'http', + }) + + const serverBusEnabled = args.eventBusConfig?.enabled ?? true + const consolePipeEnabled = args.consolePiping?.enabled ?? true + const levels = args.consolePiping?.levels ?? DEFAULT_LEVELS + const editor: EditorConfig = args.editor ?? DEFAULT_EDITOR_CONFIG + + // 2. wire package-manager + package.json events (Vite event-client-setup analog) + this.wirePackageManager(compiler, logging) + + // 3. mount __tsd/* endpoints on the dev server (Vite custom-server analog). + // The event bus is started lazily here (rather than in `apply`) so unit + // tests that never boot a dev server don't open real sockets. + const prev = compiler.options.devServer?.setupMiddlewares + compiler.options.devServer = compiler.options.devServer ?? {} + + const openInEditor: EditorConfig['open'] = async ( + filePath, + lineNum, + columnNum, + ) => { + if (!filePath) return + await editor.open(filePath, lineNum, columnNum) + } + + const originalConsole = Object.fromEntries( + levels.map((l) => [l, console[l].bind(console)]), + ) as Partial> + + const sseClients: Array<{ res: ServerResponse; id: number }> = [] + let sseClientId = 0 + let busStarted = false + + compiler.options.devServer.setupMiddlewares = ( + middlewares: Array, + server: any, + ) => { + // Refine the dev-server origin with the real, resolved port. + const devServerPort = + server?.options?.port ?? + compiler.options.devServer?.port ?? + DEFAULT_DEV_SERVER_PORT + setDevServerOrigin({ + port: devServerPort, + host: 'localhost', + protocol: 'http', + }) + + // Start the event bus once and record the resolved connection for the + // loader's placeholder replacement (devtools client <-> event bus). + if (serverBusEnabled && !busStarted) { + busStarted = true + const bus = new ServerEventBus({ + ...args.eventBusConfig, + port: args.eventBusConfig?.port ?? 4206, + host: 'localhost', + }) + // start() handles EADDRINUSE and returns the actual bound port. + void bus.start().then((port) => { + setDevtoolsConnection({ port, host: 'localhost', protocol: 'http' }) + }) + } + + const base = prev ? prev(middlewares, server) : middlewares + base.unshift({ + name: 'tanstack-devtools', + middleware: ( + req: IncomingMessage & { url?: string }, + res: ServerResponse, + next: (err?: unknown) => void, + ) => + handleDevToolsRequest(req, res, next, { + onOpenSource: (parsedData: any) => { + const { data, routine } = parsedData + if (routine === 'open-source') { + return handleOpenSource({ + data: { type: data.type, data }, + openInEditor, + }) + } + return + }, + ...(consolePipeEnabled + ? { + onConsolePipe: (entries: Array) => { + for (const entry of entries) { + const prefix = chalk.cyan('[Client]') + const logMethod = + originalConsole[entry.level as ConsoleLevel] ?? + originalConsole.log! + const cleanedArgs = stripEnhancedLogPrefix( + entry.args, + (loc) => chalk.gray(loc), + ) + logMethod(prefix, ...cleanedArgs) + } + }, + onConsolePipeSSE: (res: ServerResponse, req: IncomingMessage) => { + res.setHeader('Content-Type', 'text/event-stream') + res.setHeader('Cache-Control', 'no-cache') + res.setHeader('Connection', 'keep-alive') + res.setHeader('Access-Control-Allow-Origin', '*') + ;(res as any).flushHeaders?.() + + const clientId = ++sseClientId + sseClients.push({ res, id: clientId }) + + req.on('close', () => { + const index = sseClients.findIndex( + (c) => c.id === clientId, + ) + if (index !== -1) sseClients.splice(index, 1) + }) + }, + onServerConsolePipe: (entries: Array) => { + try { + const data = JSON.stringify({ + entries: entries.map((e) => ({ + level: e.level, + args: e.args, + source: 'server', + timestamp: e.timestamp || Date.now(), + })), + }) + for (const client of sseClients) { + client.res.write(`data: ${data}\n\n`) + } + } catch { + // swallow serialization / write errors + } + }, + } + : {}), + }), + }) + return base + } + } + + private wirePackageManager(compiler: any, logging: boolean) { + let packageJson: PackageJson | null = null + let outdatedDeps: ReturnType = Promise.resolve(null) + + const refresh = async () => { + packageJson = await readPackageJson() + outdatedDeps = emitOutdatedDeps() + } + + // Prime package.json/outdated deps once the first compilation finishes. + compiler.hooks.done.tap(PLUGIN, () => { + if (!packageJson) void refresh() + }) + + // Re-read package.json on rebuilds (Vite handleHotUpdate analog). + compiler.hooks.watchRun?.tapPromise?.(PLUGIN, async () => { + await refresh() + }) + + // Whenever a client mounts, send it the current package info. + devtoolsEventClient.on('mounted', async () => { + devtoolsEventClient.emit('outdated-deps-read', { + outdatedDeps: await outdatedDeps, + }) + devtoolsEventClient.emit('package-json-read', { packageJson }) + }) + + devtoolsEventClient.on('install-devtools', async (event) => { + const result = await installPackage(event.payload.packageName) + devtoolsEventClient.emit('devtools-installed', { + packageName: event.payload.packageName, + success: result.success, + error: result.error, + }) + + if (result.success) { + const { packageName, pluginName, pluginImport } = event.payload + if (logging) { + console.log( + chalk.blueBright( + `[@tanstack/devtools-rspack] Auto-adding ${packageName} to devtools...`, + ), + ) + } + const injectResult = addPluginToDevtools( + getDevtoolsFileId(), + packageName, + pluginName, + pluginImport, + ) + if (injectResult.success) { + devtoolsEventClient.emit('plugin-added', { + packageName, + success: true, + }) + devtoolsEventClient.emit('package-json-read', { + packageJson: await readPackageJson(), + }) + } + } + }) + + devtoolsEventClient.on('add-plugin-to-devtools', (event) => { + const { packageName, pluginName, pluginImport } = event.payload + if (logging) { + console.log( + chalk.blueBright( + `[@tanstack/devtools-rspack] Adding ${packageName} to devtools...`, + ), + ) + } + const result = addPluginToDevtools( + getDevtoolsFileId(), + packageName, + pluginName, + pluginImport, + ) + devtoolsEventClient.emit('plugin-added', { + packageName, + success: result.success, + error: result.error, + }) + }) + + devtoolsEventClient.on('bump-package-version', async (event) => { + const { packageName, devtoolsPackage, pluginName, minVersion, pluginImport } = + event.payload + if (logging) { + console.log( + chalk.blueBright( + `[@tanstack/devtools-rspack] Bumping ${packageName} to version ${minVersion}...`, + ), + ) + } + const packageWithVersion = minVersion + ? `${packageName}@^${minVersion}` + : packageName + const result = await installPackage(packageWithVersion) + + if (!result.success) { + devtoolsEventClient.emit('devtools-installed', { + packageName: devtoolsPackage, + success: false, + error: result.error, + }) + return + } + + const fileId = getDevtoolsFileId() + if (!fileId) { + devtoolsEventClient.emit('devtools-installed', { + packageName: devtoolsPackage, + success: true, + }) + return + } + + const injectResult = injectPluginIntoFile(fileId, { + packageName: devtoolsPackage, + pluginName, + pluginImport, + }) + devtoolsEventClient.emit('plugin-added', { + packageName: devtoolsPackage, + success: injectResult.success, + error: injectResult.error, + }) + if (injectResult.success) { + devtoolsEventClient.emit('package-json-read', { + packageJson: await readPackageJson(), + }) + } + }) + } } diff --git a/packages/devtools-rspack/vite.config.ts b/packages/devtools-rspack/vite.config.ts index 760700c8..04355631 100644 --- a/packages/devtools-rspack/vite.config.ts +++ b/packages/devtools-rspack/vite.config.ts @@ -15,5 +15,9 @@ const config = defineConfig({ export default mergeConfig( config, - tanstackViteConfig({ cjs: false, entry: ['./src/index.ts'], srcDir: './src' }), + tanstackViteConfig({ + cjs: false, + entry: ['./src/index.ts', './src/loader.ts'], + srcDir: './src', + }), ) From 43334696c4b3decc7b4f92bd70dbb132f08d8c75 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 14:48:08 +0200 Subject: [PATCH 09/16] chore(devtools): fix core import ordering + guard rspack package-manager wiring in CI --- packages/devtools-bundler-core/src/connection.test.ts | 4 ++-- packages/devtools-bundler-core/src/enhance-logs.ts | 2 +- packages/devtools-bundler-core/src/inject-source.ts | 2 +- packages/devtools-rspack/src/plugin.ts | 8 ++++++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/devtools-bundler-core/src/connection.test.ts b/packages/devtools-bundler-core/src/connection.test.ts index f15d9750..69af5d8e 100644 --- a/packages/devtools-bundler-core/src/connection.test.ts +++ b/packages/devtools-bundler-core/src/connection.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest' import { - getDevtoolsConnection, setDevtoolsConnection, - getDevtoolsFileId, setDevtoolsFileId, + getDevtoolsConnection, getDevtoolsFileId, + setDevtoolsConnection, setDevtoolsFileId, } from './connection' describe('connection singleton', () => { diff --git a/packages/devtools-bundler-core/src/enhance-logs.ts b/packages/devtools-bundler-core/src/enhance-logs.ts index 8e9811dd..7ba43769 100644 --- a/packages/devtools-bundler-core/src/enhance-logs.ts +++ b/packages/devtools-bundler-core/src/enhance-logs.ts @@ -1,7 +1,7 @@ import chalk from 'chalk' -import { normalizePath } from './normalize-path' import MagicString from 'magic-string' import { parseSync } from 'oxc-parser' +import { normalizePath } from './normalize-path' import { createLocMapper } from './offset-to-loc' import { walk } from './ast-utils' diff --git a/packages/devtools-bundler-core/src/inject-source.ts b/packages/devtools-bundler-core/src/inject-source.ts index 59aefc62..03ddc3f9 100644 --- a/packages/devtools-bundler-core/src/inject-source.ts +++ b/packages/devtools-bundler-core/src/inject-source.ts @@ -1,6 +1,6 @@ -import { normalizePath } from './normalize-path' import MagicString from 'magic-string' import { parseSync } from 'oxc-parser' +import { normalizePath } from './normalize-path' import { createLocMapper } from './offset-to-loc' import { matcher } from './matcher' import { forEachChild } from './ast-utils' diff --git a/packages/devtools-rspack/src/plugin.ts b/packages/devtools-rspack/src/plugin.ts index 49bad4ed..94574cfd 100644 --- a/packages/devtools-rspack/src/plugin.ts +++ b/packages/devtools-rspack/src/plugin.ts @@ -98,8 +98,12 @@ export class TanStackDevtoolsRspackPlugin { const levels = args.consolePiping?.levels ?? DEFAULT_LEVELS const editor: EditorConfig = args.editor ?? DEFAULT_EDITOR_CONFIG - // 2. wire package-manager + package.json events (Vite event-client-setup analog) - this.wirePackageManager(compiler, logging) + // 2. wire package-manager + package.json events (Vite event-client-setup analog). + // Guarded like Vite's `event-client-setup` sub-plugin so CI runs don't + // trigger `emitOutdatedDeps()` (which may spawn a package-manager subprocess). + if (!process.env.CI && process.env.NODE_ENV === 'development') { + this.wirePackageManager(compiler, logging) + } // 3. mount __tsd/* endpoints on the dev server (Vite custom-server analog). // The event bus is started lazily here (rather than in `apply`) so unit From 04f546ea600117e97b2e919ce71469877ec76b03 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 14:55:24 +0200 Subject: [PATCH 10/16] test(devtools-rspack): entry factory test --- packages/devtools-rspack/src/index.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 packages/devtools-rspack/src/index.test.ts diff --git a/packages/devtools-rspack/src/index.test.ts b/packages/devtools-rspack/src/index.test.ts new file mode 100644 index 00000000..e50fbe93 --- /dev/null +++ b/packages/devtools-rspack/src/index.test.ts @@ -0,0 +1,13 @@ +import { describe, expect, it } from 'vitest' +import { defineDevtoolsConfig, devtools } from './index' + +describe('devtools-rspack entry', () => { + it('devtools() returns a plugin with an apply method', () => { + const plugin = devtools({ logging: false }) + expect(typeof (plugin as any).apply).toBe('function') + }) + it('defineDevtoolsConfig is identity', () => { + const cfg = { logging: false } + expect(defineDevtoolsConfig(cfg)).toBe(cfg) + }) +}) From ac33c7f84bcf8186da0557eb04df21a9d935eccf Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 15:22:06 +0200 Subject: [PATCH 11/16] test(devtools-rspack): react rspack example + e2e smoke --- examples/react-rspack/index.html | 12 + examples/react-rspack/package.json | 22 + examples/react-rspack/rspack.config.mjs | 48 + examples/react-rspack/src/App.tsx | 16 + examples/react-rspack/src/main.tsx | 15 + examples/react-rspack/tsconfig.json | 14 + packages/devtools-rspack/README.md | 33 +- pnpm-lock.yaml | 1256 ++++++++++++++++++++++- 8 files changed, 1397 insertions(+), 19 deletions(-) create mode 100644 examples/react-rspack/index.html create mode 100644 examples/react-rspack/package.json create mode 100644 examples/react-rspack/rspack.config.mjs create mode 100644 examples/react-rspack/src/App.tsx create mode 100644 examples/react-rspack/src/main.tsx create mode 100644 examples/react-rspack/tsconfig.json diff --git a/examples/react-rspack/index.html b/examples/react-rspack/index.html new file mode 100644 index 00000000..99b840ff --- /dev/null +++ b/examples/react-rspack/index.html @@ -0,0 +1,12 @@ + + + + + + React Rspack Example - TanStack Devtools + + + +
+ + diff --git a/examples/react-rspack/package.json b/examples/react-rspack/package.json new file mode 100644 index 00000000..9cd8c01c --- /dev/null +++ b/examples/react-rspack/package.json @@ -0,0 +1,22 @@ +{ + "name": "react-rspack-example", + "private": true, + "scripts": { + "dev": "rspack serve", + "build": "rspack build --mode=production" + }, + "dependencies": { + "@tanstack/devtools-rspack": "workspace:*", + "@tanstack/react-devtools": "workspace:*", + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@rspack/cli": "^1.5.0", + "@rspack/core": "^1.5.0", + "@rspack/dev-server": "^1.1.4", + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", + "typescript": "^5.9.2" + } +} diff --git a/examples/react-rspack/rspack.config.mjs b/examples/react-rspack/rspack.config.mjs new file mode 100644 index 00000000..821ca056 --- /dev/null +++ b/examples/react-rspack/rspack.config.mjs @@ -0,0 +1,48 @@ +// @ts-check +import { HtmlRspackPlugin } from '@rspack/core' +import { devtools } from '@tanstack/devtools-rspack' + +// NOTE: `@tanstack/devtools-rspack` ships as an ESM-only package, so this +// config is authored as ESM (`rspack.config.mjs`). A CommonJS config would +// need `const { devtools } = await import('@tanstack/devtools-rspack')`. + +/** @type {(env: unknown, argv: { mode?: string }) => import('@rspack/core').Configuration} */ +export default (_env, argv) => ({ + mode: argv.mode === 'production' ? 'production' : 'development', + entry: './src/main.tsx', + // No source maps in production so the devtools-strip check is unambiguous + // (a source map would embed the original, un-stripped `TanStackDevtools` source). + devtool: argv.mode === 'production' ? false : 'eval-source-map', + plugins: [devtools(), new HtmlRspackPlugin({ template: './index.html' })], + devServer: { + port: 3100, + }, + module: { + rules: [ + { + test: /\.[jt]sx?$/, + exclude: /node_modules/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'typescript', + tsx: true, + }, + transform: { + react: { + runtime: 'automatic', + development: true, + }, + }, + }, + }, + }, + }, + ], + }, + resolve: { + extensions: ['.tsx', '.ts', '.jsx', '.js'], + }, +}) diff --git a/examples/react-rspack/src/App.tsx b/examples/react-rspack/src/App.tsx new file mode 100644 index 00000000..c067cd68 --- /dev/null +++ b/examples/react-rspack/src/App.tsx @@ -0,0 +1,16 @@ +import { useState } from 'react' + +export default function App() { + const [count, setCount] = useState(0) + + // enhanced-logs has something to transform + console.log('React Rspack example mounted, count =', count) + + return ( +
+

TanStack Devtools React + Rspack Example

+

Current count: {count}

+ +
+ ) +} diff --git a/examples/react-rspack/src/main.tsx b/examples/react-rspack/src/main.tsx new file mode 100644 index 00000000..6d9073b7 --- /dev/null +++ b/examples/react-rspack/src/main.tsx @@ -0,0 +1,15 @@ +import { createRoot } from 'react-dom/client' +import { TanStackDevtools } from '@tanstack/react-devtools' +import App from './App' + +function Root() { + return ( + <> + + + + ) +} + +const root = createRoot(document.getElementById('root')!) +root.render() diff --git a/examples/react-rspack/tsconfig.json b/examples/react-rspack/tsconfig.json new file mode 100644 index 00000000..990ef4a1 --- /dev/null +++ b/examples/react-rspack/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ESNext", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "module": "ESNext", + "moduleResolution": "Bundler", + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src"] +} diff --git a/packages/devtools-rspack/README.md b/packages/devtools-rspack/README.md index 28573524..3dce8e3a 100644 --- a/packages/devtools-rspack/README.md +++ b/packages/devtools-rspack/README.md @@ -5,12 +5,16 @@ This package is still under active development and might have breaking changes i ## General Usage The `@tanstack/devtools-rspack` package is designed to work with Rspack projects. -Plug it into your plugins array: +Plug it into your plugins array. + +This package is **ESM-only**, so author your Rspack config as ESM +(`rspack.config.mjs`, or `rspack.config.js` with `"type": "module"`): ```js -const { devtools } = require('@tanstack/devtools-rspack') +// rspack.config.mjs +import { devtools } from '@tanstack/devtools-rspack' -module.exports = { +export default { plugins: [ // Important to include it first! devtools({ @@ -21,9 +25,30 @@ module.exports = { } ``` +If you must use a CommonJS config (`rspack.config.js` without `"type": "module"`, +or `rspack.config.cjs`), load the plugin with a dynamic import from an async +config, since `require()` cannot resolve this ESM-only package: + +```js +// rspack.config.cjs +module.exports = async () => { + const { devtools } = await import('@tanstack/devtools-rspack') + return { + plugins: [devtools(/* options */)], + // ...rest of the config + } +} +``` + +> Devtools-stripping (`removeDevtoolsOnBuild`) runs only for `production`-mode +> builds. Rspack honors the `mode` in your config, so make sure production +> builds actually run in production mode (e.g. `rspack build --mode=production` +> or `mode: 'production'` in the config) — unlike some bundlers, `rspack build` +> does not force production mode on its own. + ## Parity caveats This package aims for 1:1 feature parity with `@tanstack/devtools-vite`, with two known caveats: - **Runtime bridge channel wiring is Vite-only.** Vite's `wireRuntimeBridgeChannels` relies on Vite's SSR `server.environments[].hot` API, which has no Rspack equivalent. The code-injection half of the runtime bridge (`injectRuntimeBridge`) still runs for server-target builds, but the live channel wiring is not available under Rspack. -- **The `__tsd/*` dev endpoints require `@rspack/dev-server`.** The plugin wraps `devServer.setupMiddlewares` to mount the devtools middleware, so these endpoints are only available when the dev server reads and honors `compiler.options.devServer`. If your setup does not go through `@rspack/dev-server`'s standard config wiring, you may need to wire `setupMiddlewares` manually. +- **The `__tsd/*` dev endpoints require `@rspack/dev-server`.** The plugin wraps `compiler.options.devServer.setupMiddlewares` to mount the devtools middleware. This auto-wiring is **verified working** against `@rspack/dev-server` (`@rspack/cli` 1.7.x, `@rspack/dev-server` 1.x): the `examples/react-rspack` e2e smoke boots `rspack serve` and confirms `GET /__tsd/open-source` returns `200` with no manual wiring. The endpoints are therefore available out of the box whenever the dev server reads and honors `compiler.options.devServer` (the standard `@rspack/dev-server` path). Only if your setup bypasses `@rspack/dev-server`'s config wiring (e.g. a fully custom server) would you need to install the `setupMiddlewares` handler yourself. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4f140245..d362aa57 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -716,6 +716,40 @@ importers: specifier: ^8.0.0 version: 8.0.12(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) + examples/react-rspack: + dependencies: + '@tanstack/devtools-rspack': + specifier: workspace:* + version: link:../../packages/devtools-rspack + '@tanstack/react-devtools': + specifier: workspace:* + version: link:../../packages/react-devtools + react: + specifier: ^19.2.0 + version: 19.2.6 + react-dom: + specifier: ^19.2.0 + version: 19.2.6(react@19.2.6) + devDependencies: + '@rspack/cli': + specifier: ^1.5.0 + version: 1.7.12(@rspack/core@1.7.12)(@types/express@4.17.25)(tslib@2.8.1) + '@rspack/core': + specifier: ^1.5.0 + version: 1.7.12 + '@rspack/dev-server': + specifier: ^1.1.4 + version: 1.2.1(@rspack/core@1.7.12)(tslib@2.8.1) + '@types/react': + specifier: ^19.2.0 + version: 19.2.14 + '@types/react-dom': + specifier: ^19.2.0 + version: 19.2.3(@types/react@19.2.14) + typescript: + specifier: ^5.9.2 + version: 5.9.3 + examples/react/a11y-devtools: dependencies: '@tanstack/devtools-a11y': @@ -2431,6 +2465,10 @@ packages: '@deno/shim-deno@0.19.2': resolution: {integrity: sha512-q3VTHl44ad8T2Tw2SpeAvghdGOjlnLPDNO2cpOxwMrBE/PVas6geWpbpIgrM+czOCH0yejp0yi8OaTuB+NU40Q==} + '@discoveryjs/json-ext@0.5.7': + resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} + engines: {node: '>=10.0.0'} + '@drizzle-team/brocli@0.10.2': resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} @@ -3528,6 +3566,129 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/base64@17.67.0': + resolution: {integrity: sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/buffers@1.2.1': + resolution: {integrity: sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/buffers@17.67.0': + resolution: {integrity: sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@1.0.0': + resolution: {integrity: sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@17.67.0': + resolution: {integrity: sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-core@4.64.0': + resolution: {integrity: sha512-zs2TAq7Six5jgMuoMNjpspAvOP3mhtgq/k1UyQodEzCtQi/N83y2/y+zcvnZSGp/Rxq96DBN+bValOBQAyn/ew==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-fsa@4.64.0': + resolution: {integrity: sha512-nMWOVbkLFyEgmXZih3wyvxA9XpgyyqyfrINMHvEFqhi7uqfRl7c9ERJt6yX7vgMPrB9Uo+OJO+Spa0cFzPD01w==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-builtins@4.64.0': + resolution: {integrity: sha512-/o7WRFhUWaM/fOrslwLZGnzn4RmRILykn+lAL+mNObqqRNw+CQSiij6hpCeZ+C7buhdoVo7go/OYqzaSUfDYmA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-to-fsa@4.64.0': + resolution: {integrity: sha512-WDD9WVs0hb7UAEKTgZW2f66WDrbj7gIIWwpP3spbLyXa0rghtUaFTB8L4gdR3ZCWwiKIsj38/CNijpVmpnuPUw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-utils@4.64.0': + resolution: {integrity: sha512-k5Indsx9hWW9xSF7Y6oSKKwtCUNhzZxadub3owhIlitc+iMRVlPPdX2duTKQWBL3qNWpXya8jykgaaWpheeS4w==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node@4.64.0': + resolution: {integrity: sha512-dO+NNkODbUli4uV42bcNrrLvq5rE7SNpdZ5TNd0dtbLsAaNK3MDiIC9lUi+brboGoIjW6vd2fB1qao60nrk5xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-print@4.64.0': + resolution: {integrity: sha512-PHZFccchvkhWrwPWHjmVAhbC3vSHCtyZvlZfJJ3ho2bnzl450hXri6/8e6pbkWdH+SkmLXNml0sV8e5HDAfxKw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-snapshot@4.64.0': + resolution: {integrity: sha512-oM7UDeL83q6NBzzsfKAsYKXKVXlykKFqqOLh4xZZKAzzROTlInkPbc6LTDGThEOnPiFiUzA7tYziHG9xavd76Q==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.21.0': + resolution: {integrity: sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@17.67.0': + resolution: {integrity: sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@1.0.2': + resolution: {integrity: sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@17.67.0': + resolution: {integrity: sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.9.0': + resolution: {integrity: sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@17.67.0': + resolution: {integrity: sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@leichtgewicht/ip-codec@2.0.5': + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + '@listr2/prompt-adapter-inquirer@3.0.5': resolution: {integrity: sha512-WELs+hj6xcilkloBXYf9XXK8tYEnKsgLj01Xl5ONUJpKjmT5hGVUzNUS5tooUxs7pGMrw+jFD/41WpqW4V3LDA==} engines: {node: '>=20.0.0'} @@ -4903,6 +5064,12 @@ packages: '@rspack/binding@1.7.12': resolution: {integrity: sha512-f4HHuLbvuld8Ba4iB/4ibse5XrKxFrgmM3S4P2AOKnPlekAFlBjmltCuaTL/W2ggYvILaVY+YcFXrEH1rrKeQA==} + '@rspack/cli@1.7.12': + resolution: {integrity: sha512-aiVj5hm12/rhkH/KTvs9BugpRuLEutIw5o3KmQDvSMd6EqEIASuCCUI3/97uaNP58hqZSl7mAotsLcwn/OCbJQ==} + hasBin: true + peerDependencies: + '@rspack/core': ^1.0.0-alpha || ^1.x + '@rspack/core@1.7.12': resolution: {integrity: sha512-6CwFIHlhRmXfZoMj3v9MZ1SMTPBn+cHVXeMIeaGp5sufqinKsISbsqHu6ZMJu2wDSmZLdmQJX6zLxkhcAUlhkQ==} engines: {node: '>=18.12.0'} @@ -4912,6 +5079,18 @@ packages: '@swc/helpers': optional: true + '@rspack/dev-server@1.1.5': + resolution: {integrity: sha512-cwz0qc6iqqoJhyWqxP7ZqE2wyYNHkBMQUXxoQ0tNoZ4YNRkDyQ4HVJ/3oPSmMKbvJk/iJ16u7xZmwG6sK47q/A==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': '*' + + '@rspack/dev-server@1.2.1': + resolution: {integrity: sha512-e/ARvskYn2Qdd02qLvc0i6H9BnOmzP0xGHS2XCr7GZ3t2k5uC5ZlLkeN1iEebU0FkAW+6ot89NahFo3nupKuww==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': '*' + '@rspack/lite-tapable@1.1.0': resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==} @@ -5714,12 +5893,24 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/body-parser@1.19.6': + resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} + + '@types/bonjour@3.5.13': + resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} + '@types/braces@3.0.5': resolution: {integrity: sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w==} '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/connect-history-api-fallback@1.5.4': + resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/d3-array@3.2.2': resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} @@ -5831,12 +6022,24 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/express-serve-static-core@4.19.9': + resolution: {integrity: sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==} + + '@types/express@4.17.25': + resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} + '@types/geojson@7946.0.16': resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/http-errors@2.0.5': + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + + '@types/http-proxy@1.17.17': + resolution: {integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -5849,9 +6052,15 @@ packages: '@types/micromatch@4.0.10': resolution: {integrity: sha512-5jOhFDElqr4DKTrTEbnW8DZ4Hz5LRUEmyrGpCMrD/NphYv3nUnaF08xmSLx1rGGnyEs/kFnhiw6dCgcDqMr5PQ==} + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node-forge@1.3.14': + resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==} + '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} @@ -5861,6 +6070,12 @@ packages: '@types/picomatch@4.0.3': resolution: {integrity: sha512-iG0T6+nYJ9FAPmx9SsUlnwcq1ZVRuCXcVEvWnntoPlrOpwtSTKNDC9uVAxTsC3PUvJ+99n4RpAcNgBbHX3JSnQ==} + '@types/qs@6.15.1': + resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: @@ -5875,6 +6090,24 @@ packages: '@types/retry@0.12.0': resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + '@types/retry@0.12.2': + resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} + + '@types/send@0.17.6': + resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} + + '@types/send@1.2.1': + resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} + + '@types/serve-index@1.9.4': + resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} + + '@types/serve-static@1.15.10': + resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + + '@types/sockjs@0.3.36': + resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -6208,6 +6441,10 @@ packages: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} @@ -6231,6 +6468,10 @@ packages: peerDependencies: acorn: '>=8.9.0' + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} + engines: {node: '>=0.4.0'} + acorn@8.16.0: resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} @@ -6248,6 +6489,14 @@ packages: ajv: optional: true + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -6256,6 +6505,11 @@ packages: ajv: optional: true + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} @@ -6283,6 +6537,11 @@ packages: resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} engines: {node: '>=18'} + ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -6339,6 +6598,9 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -6467,6 +6729,9 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + beasties@0.4.1: resolution: {integrity: sha512-2Imdcw3LznDuxAbJM26RHniOLAzE6WgrK8OuvVXCQtNBS8rsnD9zsSEa3fHl4hHpUY7BYTlrpvtPVbvu9G6neg==} engines: {node: '>=18.0.0'} @@ -6500,10 +6765,17 @@ packages: blake3-wasm@2.1.5: resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + body-parser@1.20.6: + resolution: {integrity: sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-parser@2.2.2: resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} engines: {node: '>=18'} + bonjour-service@1.4.3: + resolution: {integrity: sha512-2Kd5UYlFUVgAKMTyuBLl6w49wqfOnbxHqmuH0oCl/n7TfAikR0zoowNOP5BU4dfXmm+Vr9JyEN370auSMx+CNg==} + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -6781,6 +7053,14 @@ packages: resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==} engines: {node: '>= 14'} + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.8.1: + resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==} + engines: {node: '>= 0.8.0'} + computeds@0.0.1: resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} @@ -6793,10 +7073,18 @@ packages: confbox@0.2.4: resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} + connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + consola@3.4.2: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + content-disposition@1.1.0: resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} engines: {node: '>=18'} @@ -6820,6 +7108,9 @@ packages: cookie-es@3.1.1: resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==} + cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + cookie-signature@1.2.2: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} @@ -7118,6 +7409,9 @@ packages: de-indent@1.0.2: resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + debounce@1.2.1: + resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -7185,6 +7479,10 @@ packages: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} + depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -7212,6 +7510,9 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + devalue@5.8.0: resolution: {integrity: sha512-2zA9pFEsnp7vWBZbXF5JAgAq0fsUIt/1XPbRiAmRV3lp/2C3upzH+sADiyy66aFCihoLEsrQHxNM5w1gIDfsBg==} @@ -7226,6 +7527,10 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} + dns-packet@5.6.1: + resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} + engines: {node: '>=6'} + dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} @@ -7798,6 +8103,10 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + exit-hook@4.0.0: + resolution: {integrity: sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==} + engines: {node: '>=18'} + expect-type@1.3.0: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} @@ -7811,6 +8120,10 @@ packages: peerDependencies: express: '>= 4.11' + express@4.22.2: + resolution: {integrity: sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==} + engines: {node: '>= 0.10.0'} + express@5.2.1: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} @@ -7846,6 +8159,10 @@ packages: fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + fd-package-json@2.0.0: resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} @@ -7880,6 +8197,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + finalhandler@1.3.2: + resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} + engines: {node: '>= 0.8'} + finalhandler@2.1.1: resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} engines: {node: '>= 18.0.0'} @@ -8033,6 +8354,12 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regex.js@1.2.0: + resolution: {integrity: sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} @@ -8088,6 +8415,10 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + gzip-size@7.0.0: resolution: {integrity: sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -8121,6 +8452,9 @@ packages: hachure-fill@0.5.2: resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} + handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + happy-dom@20.9.0: resolution: {integrity: sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ==} engines: {node: '>=20.0.0'} @@ -8215,6 +8549,9 @@ packages: resolution: {integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==} engines: {node: ^20.17.0 || >=22.9.0} + hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + html-encoding-sniffer@6.0.0: resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -8222,6 +8559,9 @@ packages: html-entities@2.3.3: resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-link-extractor@1.0.5: resolution: {integrity: sha512-ADd49pudM157uWHwHQPUSX4ssMsvR/yHIswOR5CUfBdK9g9ZYGMhVSE6KZVHJ6kCkR0gH4htsfzU6zECDNVwyw==} @@ -8240,14 +8580,33 @@ packages: http-cache-semantics@4.2.0: resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + + http-errors@1.8.1: + resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} + engines: {node: '>= 0.6'} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} + http-parser-js@0.5.10: + resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} + http-proxy-middleware@2.0.10: + resolution: {integrity: sha512-RKzRWNPxUZqbuk3BC5mGVJbBnWgr+diEnjJexIOytFbBzDy88Fbh/YvBr3DsNrl1jYAfjWfpATEv0NO35FDuPQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + http-proxy@1.18.1: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} @@ -8277,6 +8636,14 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -8356,6 +8723,10 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} + ipaddr.js@2.4.0: + resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} + engines: {node: '>= 10'} + iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} @@ -8431,6 +8802,10 @@ packages: is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + is-network-error@1.3.2: + resolution: {integrity: sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==} + engines: {node: '>=16'} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -8439,6 +8814,10 @@ packages: resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} engines: {node: '>=12'} + is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} @@ -8970,14 +9349,26 @@ packages: mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + media-typer@1.1.0: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} + memfs@4.64.0: + resolution: {integrity: sha512-Kw72fgY7Wn+sD8KmtNWSafl1dz0UvAsE/PHs3YVfLiaZuA3HxNm9sRLqAu0ATiBGJvME1PxZXbBZPv5GycDeAw==} + peerDependencies: + tslib: '2' + merge-anything@5.1.7: resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} engines: {node: '>=12.13'} + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-descriptors@2.0.0: resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} engines: {node: '>=18'} @@ -8992,6 +9383,10 @@ packages: mermaid@11.13.0: resolution: {integrity: sha512-fEnci+Immw6lKMFI8sqzjlATTyjLkRa6axrEgLV2yHTfv8r+h1wjFbV6xeRtd4rUV1cS4EpR9rwp3Rci7TRWDw==} + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -9164,6 +9559,9 @@ packages: engines: {node: '>=22.0.0'} hasBin: true + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + minimatch@10.2.5: resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} engines: {node: 18 || 20 || >=22} @@ -9248,6 +9646,10 @@ packages: muggle-string@0.4.1: resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + multicast-dns@7.2.5: + resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} + hasBin: true + mute-stream@2.0.0: resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} engines: {node: ^18.17.0 || >=20.5.0} @@ -9281,6 +9683,14 @@ packages: engines: {node: '>= 4.4.x'} hasBin: true + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + negotiator@1.0.0: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} @@ -9507,6 +9917,9 @@ packages: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} + obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + obug@2.1.3: resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} engines: {node: '>=12.20.0'} @@ -9533,6 +9946,10 @@ packages: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} + on-headers@1.1.0: + resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} + engines: {node: '>= 0.8'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -9581,6 +9998,10 @@ packages: zod: optional: true + opener@1.5.2: + resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} + hasBin: true + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -9638,6 +10059,10 @@ packages: resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} engines: {node: '>=8'} + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -9721,6 +10146,9 @@ packages: resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} engines: {node: 18 || 20 || >=22} + path-to-regexp@0.1.13: + resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==} + path-to-regexp@6.3.0: resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} @@ -9989,6 +10417,10 @@ packages: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} + raw-body@3.0.2: resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} engines: {node: '>= 0.10'} @@ -10290,9 +10722,20 @@ packages: scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} + engines: {node: '>= 10.13.0'} + scule@1.3.0: resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} + select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true @@ -10333,6 +10776,10 @@ packages: resolution: {integrity: sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==} engines: {node: '>=10'} + serve-index@1.9.2: + resolution: {integrity: sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==} + engines: {node: '>= 0.8.0'} + serve-placeholder@2.0.2: resolution: {integrity: sha512-/TMG8SboeiQbZJWRlfTCqMs2DD3SZgWp0kDQePz9yUuCnDfDh/92gf7/PxGhzXTKBIPASIHxFcZndoNbp6QOLQ==} @@ -10446,6 +10893,10 @@ packages: simple-code-frame@1.3.0: resolution: {integrity: sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w==} + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + sirv@3.0.2: resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} @@ -10483,6 +10934,9 @@ packages: resolution: {integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==} engines: {node: '>= 18'} + sockjs@0.3.24: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + socks-proxy-agent@8.0.5: resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} engines: {node: '>= 14'} @@ -10540,6 +10994,13 @@ packages: spdx-license-ids@3.0.23: resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} + spdy-transport@3.0.0: + resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} + + spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} + split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} @@ -10578,6 +11039,10 @@ packages: standard-as-callback@2.1.0: resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} @@ -10757,6 +11222,15 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + thingies@2.6.0: + resolution: {integrity: sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 + + thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -10824,6 +11298,12 @@ packages: resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} engines: {node: '>=20'} + tree-dump@1.1.0: + resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -10923,6 +11403,10 @@ packages: resolution: {integrity: sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==} engines: {node: '>=20'} + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + type-is@2.0.1: resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} engines: {node: '>= 0.6'} @@ -11223,10 +11707,19 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + uuid@11.1.0: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + validate-npm-package-name@7.0.2: resolution: {integrity: sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==} engines: {node: ^20.17.0 || >=22.9.0} @@ -11538,6 +12031,9 @@ packages: resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} engines: {node: '>=10.13.0'} + wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} @@ -11561,9 +12057,44 @@ packages: resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} engines: {node: '>=20'} + webpack-bundle-analyzer@4.10.2: + resolution: {integrity: sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==} + engines: {node: '>= 10.13.0'} + hasBin: true + + webpack-dev-middleware@7.4.5: + resolution: {integrity: sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + + webpack-dev-server@5.2.2: + resolution: {integrity: sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==} + engines: {node: '>= 18.12.0'} + hasBin: true + peerDependencies: + webpack: ^5.0.0 + webpack-cli: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + websocket-driver@0.7.5: + resolution: {integrity: sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==} + engines: {node: '>=0.8.0'} + + websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} @@ -11653,6 +12184,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@7.5.11: + resolution: {integrity: sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@8.18.0: resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} engines: {node: '>=10.0.0'} @@ -12628,6 +13171,8 @@ snapshots: '@deno/shim-deno-test': 0.5.0 which: 4.0.0 + '@discoveryjs/json-ext@0.5.7': {} + '@drizzle-team/brocli@0.10.2': {} '@emnapi/core@1.10.0': @@ -13435,27 +13980,157 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@listr2/prompt-adapter-inquirer@3.0.5(@inquirer/prompts@7.10.1(@types/node@22.19.15))(@types/node@22.19.15)(listr2@9.0.5)': + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': dependencies: - '@inquirer/prompts': 7.10.1(@types/node@22.19.15) - '@inquirer/type': 3.0.10(@types/node@22.19.15) - listr2: 9.0.5 - transitivePeerDependencies: - - '@types/node' + tslib: 2.8.1 - '@lmdb/lmdb-darwin-arm64@3.5.1': - optional: true + '@jsonjoy.com/base64@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 - '@lmdb/lmdb-darwin-x64@3.5.1': - optional: true + '@jsonjoy.com/buffers@1.2.1(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 - '@lmdb/lmdb-linux-arm64@3.5.1': - optional: true + '@jsonjoy.com/buffers@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 - '@lmdb/lmdb-linux-arm@3.5.1': - optional: true + '@jsonjoy.com/codegen@1.0.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 - '@lmdb/lmdb-linux-x64@3.5.1': + '@jsonjoy.com/codegen@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/fs-core@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-fsa@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-builtins@4.64.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-to-fsa@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-fsa': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-utils@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.64.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-print@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-snapshot@4.64.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/json-pack': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@1.21.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 1.0.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pointer@1.0.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pointer@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@1.9.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@leichtgewicht/ip-codec@2.0.5': {} + + '@listr2/prompt-adapter-inquirer@3.0.5(@inquirer/prompts@7.10.1(@types/node@22.19.15))(@types/node@22.19.15)(listr2@9.0.5)': + dependencies: + '@inquirer/prompts': 7.10.1(@types/node@22.19.15) + '@inquirer/type': 3.0.10(@types/node@22.19.15) + listr2: 9.0.5 + transitivePeerDependencies: + - '@types/node' + + '@lmdb/lmdb-darwin-arm64@3.5.1': + optional: true + + '@lmdb/lmdb-darwin-x64@3.5.1': + optional: true + + '@lmdb/lmdb-linux-arm64@3.5.1': + optional: true + + '@lmdb/lmdb-linux-arm@3.5.1': + optional: true + + '@lmdb/lmdb-linux-x64@3.5.1': optional: true '@lmdb/lmdb-win32-arm64@3.5.1': @@ -14499,12 +15174,86 @@ snapshots: '@rspack/binding-win32-ia32-msvc': 1.7.12 '@rspack/binding-win32-x64-msvc': 1.7.12 + '@rspack/cli@1.7.12(@rspack/core@1.7.12)(@types/express@4.17.25)(tslib@2.8.1)': + dependencies: + '@discoveryjs/json-ext': 0.5.7 + '@rspack/core': 1.7.12 + '@rspack/dev-server': 1.1.5(@rspack/core@1.7.12)(@types/express@4.17.25)(tslib@2.8.1) + exit-hook: 4.0.0 + webpack-bundle-analyzer: 4.10.2 + transitivePeerDependencies: + - '@types/express' + - bufferutil + - debug + - supports-color + - tslib + - utf-8-validate + - webpack + - webpack-cli + '@rspack/core@1.7.12': dependencies: '@module-federation/runtime-tools': 0.22.0 '@rspack/binding': 1.7.12 '@rspack/lite-tapable': 1.1.0 + '@rspack/dev-server@1.1.5(@rspack/core@1.7.12)(@types/express@4.17.25)(tslib@2.8.1)': + dependencies: + '@rspack/core': 1.7.12 + chokidar: 3.6.0 + http-proxy-middleware: 2.0.10(@types/express@4.17.25) + p-retry: 6.2.1 + webpack-dev-server: 5.2.2(tslib@2.8.1) + ws: 8.20.0 + transitivePeerDependencies: + - '@types/express' + - bufferutil + - debug + - supports-color + - tslib + - utf-8-validate + - webpack + - webpack-cli + + '@rspack/dev-server@1.2.1(@rspack/core@1.7.12)(tslib@2.8.1)': + dependencies: + '@rspack/core': 1.7.12 + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.25 + '@types/express-serve-static-core': 4.19.9 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.10 + '@types/sockjs': 0.3.36 + '@types/ws': 8.18.1 + ansi-html-community: 0.0.8 + bonjour-service: 1.4.3 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.8.1 + connect-history-api-fallback: 2.0.0 + express: 4.22.2 + graceful-fs: 4.2.11 + http-proxy-middleware: 2.0.10(@types/express@4.17.25) + ipaddr.js: 2.4.0 + launch-editor: 2.13.2 + open: 10.2.0 + p-retry: 6.2.1 + schema-utils: 4.3.3 + selfsigned: 2.4.1 + serve-index: 1.9.2 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 7.4.5(tslib@2.8.1) + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - tslib + - utf-8-validate + - webpack + '@rspack/lite-tapable@1.1.0': {} '@rushstack/node-core-library@5.7.0(@types/node@22.19.15)': @@ -15633,6 +16382,15 @@ snapshots: dependencies: '@babel/types': 7.29.0 + '@types/body-parser@1.19.6': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.19.15 + + '@types/bonjour@3.5.13': + dependencies: + '@types/node': 22.19.15 + '@types/braces@3.0.5': {} '@types/chai@5.2.3': @@ -15640,6 +16398,15 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 + '@types/connect-history-api-fallback@1.5.4': + dependencies: + '@types/express-serve-static-core': 4.19.9 + '@types/node': 22.19.15 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 22.19.15 + '@types/d3-array@3.2.2': {} '@types/d3-axis@3.0.6': @@ -15773,12 +16540,32 @@ snapshots: '@types/estree@1.0.9': {} + '@types/express-serve-static-core@4.19.9': + dependencies: + '@types/node': 22.19.15 + '@types/qs': 6.15.1 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 + + '@types/express@4.17.25': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 4.19.9 + '@types/qs': 6.15.1 + '@types/serve-static': 1.15.10 + '@types/geojson@7946.0.16': {} '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 + '@types/http-errors@2.0.5': {} + + '@types/http-proxy@1.17.17': + dependencies: + '@types/node': 22.19.15 + '@types/json-schema@7.0.15': {} '@types/katex@0.16.8': {} @@ -15791,8 +16578,14 @@ snapshots: dependencies: '@types/braces': 3.0.5 + '@types/mime@1.3.5': {} + '@types/ms@2.1.0': {} + '@types/node-forge@1.3.14': + dependencies: + '@types/node': 22.19.15 + '@types/node@12.20.55': {} '@types/node@22.19.15': @@ -15801,6 +16594,10 @@ snapshots: '@types/picomatch@4.0.3': {} + '@types/qs@6.15.1': {} + + '@types/range-parser@1.2.7': {} + '@types/react-dom@19.2.3(@types/react@19.2.14)': dependencies: '@types/react': 19.2.14 @@ -15813,6 +16610,31 @@ snapshots: '@types/retry@0.12.0': {} + '@types/retry@0.12.2': {} + + '@types/send@0.17.6': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.19.15 + + '@types/send@1.2.1': + dependencies: + '@types/node': 22.19.15 + + '@types/serve-index@1.9.4': + dependencies: + '@types/express': 4.17.25 + + '@types/serve-static@1.15.10': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 22.19.15 + '@types/send': 0.17.6 + + '@types/sockjs@0.3.36': + dependencies: + '@types/node': 22.19.15 + '@types/trusted-types@2.0.7': {} '@types/unist@2.0.11': {} @@ -16209,6 +17031,11 @@ snapshots: dependencies: event-target-shim: 5.0.1 + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + accepts@2.0.0: dependencies: mime-types: 3.0.2 @@ -16230,6 +17057,10 @@ snapshots: dependencies: acorn: 8.16.0 + acorn-walk@8.3.5: + dependencies: + acorn: 8.16.0 + acorn@8.16.0: {} agent-base@7.1.4: {} @@ -16238,6 +17069,10 @@ snapshots: optionalDependencies: ajv: 8.13.0 + ajv-formats@2.1.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + ajv-formats@3.0.1(ajv@8.13.0): optionalDependencies: ajv: 8.13.0 @@ -16246,6 +17081,11 @@ snapshots: optionalDependencies: ajv: 8.18.0 + ajv-keywords@5.1.0(ajv@8.18.0): + dependencies: + ajv: 8.18.0 + fast-deep-equal: 3.1.3 + ajv@6.14.0: dependencies: fast-deep-equal: 3.1.3 @@ -16301,6 +17141,8 @@ snapshots: dependencies: environment: 1.1.0 + ansi-html-community@0.0.8: {} + ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} @@ -16360,6 +17202,8 @@ snapshots: aria-query@5.3.2: {} + array-flatten@1.1.1: {} + array-union@2.1.0: {} assertion-error@2.0.1: {} @@ -16465,6 +17309,8 @@ snapshots: baseline-browser-mapping@2.10.13: {} + batch@0.6.1: {} + beasties@0.4.1: dependencies: css-select: 6.0.0 @@ -16505,6 +17351,23 @@ snapshots: blake3-wasm@2.1.5: {} + body-parser@1.20.6: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.15.1 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + body-parser@2.2.2: dependencies: bytes: 3.1.2 @@ -16519,6 +17382,11 @@ snapshots: transitivePeerDependencies: - supports-color + bonjour-service@1.4.3: + dependencies: + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + boolbase@1.0.0: {} boxen@8.0.1: @@ -16819,6 +17687,22 @@ snapshots: normalize-path: 3.0.0 readable-stream: 4.7.0 + compressible@2.0.18: + dependencies: + mime-db: 1.54.0 + + compression@1.8.1: + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9 + negotiator: 0.6.4 + on-headers: 1.1.0 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + computeds@0.0.1: {} concat-map@0.0.1: {} @@ -16827,8 +17711,14 @@ snapshots: confbox@0.2.4: {} + connect-history-api-fallback@2.0.0: {} + consola@3.4.2: {} + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + content-disposition@1.1.0: {} content-type@1.0.5: {} @@ -16843,6 +17733,8 @@ snapshots: cookie-es@3.1.1: {} + cookie-signature@1.0.7: {} + cookie-signature@1.2.2: {} cookie@0.7.2: {} @@ -17143,6 +18035,8 @@ snapshots: de-indent@1.0.2: {} + debounce@1.2.1: {} + debug@2.6.9: dependencies: ms: 2.0.0 @@ -17188,6 +18082,8 @@ snapshots: denque@2.1.0: {} + depd@1.1.2: {} + depd@2.0.0: {} dependency-graph@1.0.0: {} @@ -17202,6 +18098,8 @@ snapshots: detect-libc@2.1.2: {} + detect-node@2.1.0: {} + devalue@5.8.0: {} devlop@1.1.0: @@ -17214,6 +18112,10 @@ snapshots: dependencies: path-type: 4.0.0 + dns-packet@5.6.1: + dependencies: + '@leichtgewicht/ip-codec': 2.0.5 + dom-accessibility-api@0.5.16: {} dom-accessibility-api@0.6.3: {} @@ -17860,6 +18762,8 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + exit-hook@4.0.0: {} + expect-type@1.3.0: {} exponential-backoff@3.1.3: {} @@ -17869,6 +18773,42 @@ snapshots: express: 5.2.1 ip-address: 10.1.0 + express@4.22.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.6 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.2 + fresh: 0.5.2 + http-errors: 2.0.1 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.13 + proxy-addr: 2.0.7 + qs: 6.15.1 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.2 + serve-static: 1.16.3 + setprototypeof: 1.2.0 + statuses: 2.0.2 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + express@5.2.1: dependencies: accepts: 2.0.0 @@ -17930,6 +18870,10 @@ snapshots: dependencies: reusify: 1.1.0 + faye-websocket@0.11.4: + dependencies: + websocket-driver: 0.7.5 + fd-package-json@2.0.0: dependencies: walk-up-path: 4.0.0 @@ -17959,6 +18903,18 @@ snapshots: dependencies: to-regex-range: 5.0.1 + finalhandler@1.3.2: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + finalhandler@2.1.1: dependencies: debug: 4.4.3 @@ -18126,6 +19082,10 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regex.js@1.2.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + glob-to-regexp@0.4.1: {} glob@10.5.0: @@ -18190,6 +19150,10 @@ snapshots: graceful-fs@4.2.11: {} + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + gzip-size@7.0.0: dependencies: duplexer: 0.1.2 @@ -18241,6 +19205,8 @@ snapshots: hachure-fill@0.5.2: {} + handle-thing@2.0.1: {} + happy-dom@20.9.0: dependencies: '@types/node': 22.19.15 @@ -18413,6 +19379,13 @@ snapshots: dependencies: lru-cache: 11.2.7 + hpack.js@2.1.6: + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + html-encoding-sniffer@6.0.0: dependencies: '@exodus/bytes': 1.15.0 @@ -18421,6 +19394,8 @@ snapshots: html-entities@2.3.3: {} + html-escaper@2.0.2: {} + html-link-extractor@1.0.5: dependencies: cheerio: 1.2.0 @@ -18440,6 +19415,16 @@ snapshots: http-cache-semantics@4.2.0: {} + http-deceiver@1.2.7: {} + + http-errors@1.8.1: + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 1.5.0 + toidentifier: 1.0.1 + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -18448,6 +19433,8 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 + http-parser-js@0.5.10: {} + http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 @@ -18455,6 +19442,18 @@ snapshots: transitivePeerDependencies: - supports-color + http-proxy-middleware@2.0.10(@types/express@4.17.25): + dependencies: + '@types/http-proxy': 1.17.17 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.8 + optionalDependencies: + '@types/express': 4.17.25 + transitivePeerDependencies: + - debug + http-proxy@1.18.1: dependencies: eventemitter3: 4.0.7 @@ -18482,6 +19481,12 @@ snapshots: human-signals@5.0.0: {} + hyperdyperid@1.2.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -18548,6 +19553,8 @@ snapshots: ipaddr.js@1.9.1: {} + ipaddr.js@2.4.0: {} + iron-webcrypto@1.2.1: {} is-alphabetical@2.0.1: {} @@ -18607,10 +19614,14 @@ snapshots: is-module@1.0.0: {} + is-network-error@1.3.2: {} + is-number@7.0.0: {} is-path-inside@4.0.0: {} + is-plain-obj@3.0.0: {} + is-plain-obj@4.1.0: {} is-potential-custom-element-name@1.0.1: {} @@ -19283,12 +20294,33 @@ snapshots: mdurl@2.0.0: {} + media-typer@0.3.0: {} + media-typer@1.1.0: {} + memfs@4.64.0(tslib@2.8.1): + dependencies: + '@jsonjoy.com/fs-core': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-to-fsa': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.64.0(tslib@2.8.1) + '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + merge-anything@5.1.7: dependencies: is-what: 4.1.16 + merge-descriptors@1.0.3: {} + merge-descriptors@2.0.0: {} merge-stream@2.0.0: {} @@ -19319,6 +20351,8 @@ snapshots: ts-dedent: 2.2.0 uuid: 11.1.0 + methods@1.1.2: {} + micromark-core-commonmark@2.0.3: dependencies: decode-named-character-reference: 1.3.0 @@ -19595,6 +20629,8 @@ snapshots: - bufferutil - utf-8-validate + minimalistic-assert@1.0.1: {} + minimatch@10.2.5: dependencies: brace-expansion: 5.0.5 @@ -19689,6 +20725,11 @@ snapshots: muggle-string@0.4.1: {} + multicast-dns@7.2.5: + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + mute-stream@2.0.0: {} mz@2.7.0: @@ -19715,6 +20756,10 @@ snapshots: sax: 1.6.0 optional: true + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + negotiator@1.0.0: {} nf3@0.3.17: {} @@ -20138,6 +21183,8 @@ snapshots: object-inspect@1.13.4: {} + obuf@1.1.2: {} + obug@2.1.3: {} ocache@0.1.4: @@ -20166,6 +21213,8 @@ snapshots: dependencies: ee-first: 1.1.1 + on-headers@1.1.0: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -20223,6 +21272,8 @@ snapshots: ws: 8.20.0 zod: 4.4.3 + opener@1.5.2: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -20342,6 +21393,12 @@ snapshots: '@types/retry': 0.12.0 retry: 0.13.1 + p-retry@6.2.1: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.3.2 + retry: 0.13.1 + p-try@2.2.0: {} package-json-from-dist@1.0.1: {} @@ -20443,6 +21500,8 @@ snapshots: lru-cache: 11.2.7 minipass: 7.1.3 + path-to-regexp@0.1.13: {} + path-to-regexp@6.3.0: {} path-to-regexp@8.4.2: {} @@ -20668,6 +21727,13 @@ snapshots: range-parser@1.2.1: {} + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + raw-body@3.0.2: dependencies: bytes: 3.1.2 @@ -21096,8 +22162,22 @@ snapshots: scheduler@0.27.0: {} + schema-utils@4.3.3: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.18.0 + ajv-formats: 2.1.1(ajv@8.18.0) + ajv-keywords: 5.1.0(ajv@8.18.0) + scule@1.3.0: {} + select-hose@2.0.0: {} + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.14 + node-forge: 1.4.0 + semver@5.7.2: optional: true @@ -21151,6 +22231,18 @@ snapshots: seroval@1.5.4: {} + serve-index@1.9.2: + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.8.1 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + serve-placeholder@2.0.2: dependencies: defu: 6.1.4 @@ -21320,6 +22412,12 @@ snapshots: dependencies: kolorist: 1.8.0 + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + sirv@3.0.2: dependencies: '@polka/url': 1.0.0-next.29 @@ -21356,6 +22454,12 @@ snapshots: smol-toml@1.6.1: {} + sockjs@0.3.24: + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.5 + socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.4 @@ -21420,6 +22524,27 @@ snapshots: spdx-license-ids@3.0.23: {} + spdy-transport@3.0.0: + dependencies: + debug: 4.4.3 + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + + spdy@4.0.2: + dependencies: + debug: 4.4.3 + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color + split2@4.2.0: {} sprintf-js@1.0.3: {} @@ -21442,6 +22567,8 @@ snapshots: standard-as-callback@2.1.0: {} + statuses@1.5.0: {} + statuses@2.0.2: {} std-env@3.10.0: {} @@ -21682,6 +22809,12 @@ snapshots: dependencies: any-promise: 1.3.0 + thingies@2.6.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + thunky@1.1.0: {} + tiny-invariant@1.3.3: {} tinybench@2.9.0: {} @@ -21732,6 +22865,10 @@ snapshots: dependencies: punycode: 2.3.1 + tree-dump@1.1.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + tree-kill@1.2.2: {} trim-lines@3.0.1: {} @@ -21832,6 +22969,11 @@ snapshots: dependencies: tagged-tag: 1.0.0 + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + type-is@2.0.1: dependencies: content-type: 1.0.5 @@ -22079,8 +23221,12 @@ snapshots: util-deprecate@1.0.2: {} + utils-merge@1.0.1: {} + uuid@11.1.0: {} + uuid@8.3.2: {} + validate-npm-package-name@7.0.2: {} vary@1.1.2: {} @@ -22482,6 +23628,10 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 + wbuf@1.7.3: + dependencies: + minimalistic-assert: 1.0.1 + wcwidth@1.0.1: dependencies: defaults: 1.0.4 @@ -22499,8 +23649,82 @@ snapshots: webidl-conversions@8.0.1: {} + webpack-bundle-analyzer@4.10.2: + dependencies: + '@discoveryjs/json-ext': 0.5.7 + acorn: 8.16.0 + acorn-walk: 8.3.5 + commander: 7.2.0 + debounce: 1.2.1 + escape-string-regexp: 4.0.0 + gzip-size: 6.0.0 + html-escaper: 2.0.2 + opener: 1.5.2 + picocolors: 1.1.1 + sirv: 2.0.4 + ws: 7.5.11 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + webpack-dev-middleware@7.4.5(tslib@2.8.1): + dependencies: + colorette: 2.0.20 + memfs: 4.64.0(tslib@2.8.1) + mime-types: 3.0.2 + on-finished: 2.4.1 + range-parser: 1.2.1 + schema-utils: 4.3.3 + transitivePeerDependencies: + - tslib + + webpack-dev-server@5.2.2(tslib@2.8.1): + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.25 + '@types/express-serve-static-core': 4.19.9 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.10 + '@types/sockjs': 0.3.36 + '@types/ws': 8.18.1 + ansi-html-community: 0.0.8 + bonjour-service: 1.4.3 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.8.1 + connect-history-api-fallback: 2.0.0 + express: 4.22.2 + graceful-fs: 4.2.11 + http-proxy-middleware: 2.0.10(@types/express@4.17.25) + ipaddr.js: 2.4.0 + launch-editor: 2.13.2 + open: 10.2.0 + p-retry: 6.2.1 + schema-utils: 4.3.3 + selfsigned: 2.4.1 + serve-index: 1.9.2 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 7.4.5(tslib@2.8.1) + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - tslib + - utf-8-validate + webpack-virtual-modules@0.6.2: {} + websocket-driver@0.7.5: + dependencies: + http-parser-js: 0.5.10 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + + websocket-extensions@0.1.4: {} + whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 @@ -22596,6 +23820,8 @@ snapshots: wrappy@1.0.2: {} + ws@7.5.11: {} + ws@8.18.0: {} ws@8.20.0: {} From 3d643aeeff705b4ad8051eb861896a67dc7c86e7 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 16:08:42 +0200 Subject: [PATCH 12/16] chore: changesets for devtools-bundler-core + devtools-rspack Also removes the redundant @rspack/core devDependency from devtools-rspack (already declared as peerDependency, unused otherwise per knip). --- .changeset/devtools-bundler-core.md | 5 +++++ .changeset/devtools-vite-bundler-core-refactor.md | 5 +++++ .changeset/rspack-plugin.md | 5 +++++ packages/devtools-rspack/package.json | 1 - pnpm-lock.yaml | 6 +++--- 5 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 .changeset/devtools-bundler-core.md create mode 100644 .changeset/devtools-vite-bundler-core-refactor.md create mode 100644 .changeset/rspack-plugin.md diff --git a/.changeset/devtools-bundler-core.md b/.changeset/devtools-bundler-core.md new file mode 100644 index 00000000..bd38a603 --- /dev/null +++ b/.changeset/devtools-bundler-core.md @@ -0,0 +1,5 @@ +--- +"@tanstack/devtools-bundler-core": minor +--- + +Introduce `@tanstack/devtools-bundler-core`, the framework-agnostic core (transforms, editor integration, package-manager, dev-state) shared by the TanStack devtools bundler plugins. diff --git a/.changeset/devtools-vite-bundler-core-refactor.md b/.changeset/devtools-vite-bundler-core-refactor.md new file mode 100644 index 00000000..35badc7a --- /dev/null +++ b/.changeset/devtools-vite-bundler-core-refactor.md @@ -0,0 +1,5 @@ +--- +"@tanstack/devtools-vite": patch +--- + +Internal refactor: consume `@tanstack/devtools-bundler-core` for shared logic. No public API or behavior change. diff --git a/.changeset/rspack-plugin.md b/.changeset/rspack-plugin.md new file mode 100644 index 00000000..4897acfc --- /dev/null +++ b/.changeset/rspack-plugin.md @@ -0,0 +1,5 @@ +--- +"@tanstack/devtools-rspack": minor +--- + +Add `@tanstack/devtools-rspack` — Rspack plugin with 1:1 feature parity to `@tanstack/devtools-vite` (source injection, enhanced logs, console piping, devtools removal on build, editor integration, event bus, package manager). diff --git a/packages/devtools-rspack/package.json b/packages/devtools-rspack/package.json index 0f56b4d6..02900b4c 100644 --- a/packages/devtools-rspack/package.json +++ b/packages/devtools-rspack/package.json @@ -37,7 +37,6 @@ "chalk": "^5.6.2" }, "devDependencies": { - "@rspack/core": "^1.0.0", "happy-dom": "^20.0.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d362aa57..20d2861c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1628,6 +1628,9 @@ importers: packages/devtools-rspack: dependencies: + '@rspack/core': + specifier: ^1.0.0 + version: 1.7.12 '@tanstack/devtools-bundler-core': specifier: workspace:* version: link:../devtools-bundler-core @@ -1641,9 +1644,6 @@ importers: specifier: ^5.6.2 version: 5.6.2 devDependencies: - '@rspack/core': - specifier: ^1.0.0 - version: 1.7.12 happy-dom: specifier: ^20.0.0 version: 20.9.0 From 960284af50800a2f93278eb5ce0b58ff595697ae Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 17:40:53 +0200 Subject: [PATCH 13/16] fix(devtools-rspack): process @tanstack node_modules for connection placeholder + runtime-bridge injection The single loader rule excluded all of node_modules, so the __TANSTACK_DEVTOOLS_* connection placeholders (which live in @tanstack/devtools-event-bus's client, under node_modules for real consumers) were never replaced -- breaking a custom eventBusConfig.port/host/protocol. Add a second loader rule scoped to @tanstack/devtools*|event-bus* under node_modules (flat + pnpm nested layouts), and normalize the step-4 id gate to posix so it matches on Windows. Matches vite's connection-injection, which does not exclude node_modules. --- packages/devtools-rspack/README.md | 2 +- packages/devtools-rspack/src/loader.ts | 7 +++- packages/devtools-rspack/src/plugin.test.ts | 37 +++++++++++++++++++++ packages/devtools-rspack/src/plugin.ts | 22 ++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/packages/devtools-rspack/README.md b/packages/devtools-rspack/README.md index 3dce8e3a..ed48ffe1 100644 --- a/packages/devtools-rspack/README.md +++ b/packages/devtools-rspack/README.md @@ -50,5 +50,5 @@ module.exports = async () => { This package aims for 1:1 feature parity with `@tanstack/devtools-vite`, with two known caveats: -- **Runtime bridge channel wiring is Vite-only.** Vite's `wireRuntimeBridgeChannels` relies on Vite's SSR `server.environments[].hot` API, which has no Rspack equivalent. The code-injection half of the runtime bridge (`injectRuntimeBridge`) still runs for server-target builds, but the live channel wiring is not available under Rspack. +- **Runtime bridge channel wiring is Vite-only.** Vite's `wireRuntimeBridgeChannels` relies on Vite's SSR `server.environments[].hot` API, which has no Rspack equivalent — that live channel wiring is not available under Rspack. The code-injection half (`injectRuntimeBridge`) does run: it targets the `@tanstack/devtools`/`@tanstack/devtools-event-bus` event-client module, reached via a loader rule scoped to those packages under `node_modules` (in addition to the app's own source). However, the injected guard checks `import.meta.hot`, which is inert under Rspack (Rspack exposes HMR via `module.hot`, not `import.meta.hot`), so the injected code never activates — only the parity-preserving code-injection itself is real, not a working bridge. - **The `__tsd/*` dev endpoints require `@rspack/dev-server`.** The plugin wraps `compiler.options.devServer.setupMiddlewares` to mount the devtools middleware. This auto-wiring is **verified working** against `@rspack/dev-server` (`@rspack/cli` 1.7.x, `@rspack/dev-server` 1.x): the `examples/react-rspack` e2e smoke boots `rspack serve` and confirms `GET /__tsd/open-source` returns `200` with no manual wiring. The endpoints are therefore available out of the box whenever the dev server reads and honors `compiler.options.devServer` (the standard `@rspack/dev-server` path). Only if your setup bypasses `@rspack/dev-server`'s config wiring (e.g. a fully custom server) would you need to install the `setupMiddlewares` handler yourself. diff --git a/packages/devtools-rspack/src/loader.ts b/packages/devtools-rspack/src/loader.ts index 93ba98e4..0900d465 100644 --- a/packages/devtools-rspack/src/loader.ts +++ b/packages/devtools-rspack/src/loader.ts @@ -108,11 +108,16 @@ export function runPipeline( } // 4. connection placeholder replacement (@tanstack/devtools|event-bus modules) + // `id` is the loader's `resourcePath`, which on Windows uses native `\` + // separators (rspack/webpack do not normalize it) -- normalize before the + // substring check below so this gate isn't silently skipped on Windows. + const posixId = id.replace(/\\/g, '/') if ( (result.includes('__TANSTACK_DEVTOOLS_PORT__') || result.includes('__TANSTACK_DEVTOOLS_HOST__') || result.includes('__TANSTACK_DEVTOOLS_PROTOCOL__')) && - (id.includes('@tanstack/devtools') || id.includes('@tanstack/event-bus')) + (posixId.includes('@tanstack/devtools') || + posixId.includes('@tanstack/event-bus')) ) { result = result .replace(/__TANSTACK_DEVTOOLS_PORT__/g, String(connection.port)) diff --git a/packages/devtools-rspack/src/plugin.test.ts b/packages/devtools-rspack/src/plugin.test.ts index a99ae8f2..e968639b 100644 --- a/packages/devtools-rspack/src/plugin.test.ts +++ b/packages/devtools-rspack/src/plugin.test.ts @@ -33,6 +33,43 @@ describe('TanStackDevtoolsRspackPlugin', () => { expect(String(rule.use?.[0]?.loader ?? rule.loader)).toContain('loader') }) + it('also injects a node_modules-scoped rule for @tanstack/devtools|event-bus packages', () => { + const c = mockCompiler('development') + new TanStackDevtoolsRspackPlugin().apply(c as any) + + expect(c.options.module.rules).toHaveLength(2) + + // Exactly one rule has no `exclude` and a narrow `include` matching only + // @tanstack/devtools*/@tanstack/event-bus* packages under node_modules + // (covering both a flat node_modules layout and pnpm's nested + // `.pnpm//node_modules/` virtual-store layout). + const scopedRules = c.options.module.rules.filter( + (r: any) => r.exclude === undefined && r.include instanceof RegExp, + ) + expect(scopedRules).toHaveLength(1) + const scopedRule = scopedRules[0] + + const nodeModulesSample = + '/repo/node_modules/@tanstack/devtools-event-bus/dist/client/client.js' + const pnpmNestedSample = + '/repo/node_modules/.pnpm/@tanstack+devtools-event-bus@1.0.0/node_modules/@tanstack/devtools-event-bus/dist/client/client.js' + expect(scopedRule.include.test(nodeModulesSample)).toBe(true) + expect(scopedRule.include.test(pnpmNestedSample)).toBe(true) + expect( + String(scopedRule.use?.[0]?.loader ?? scopedRule.loader), + ).toContain('loader') + + // The general rule (the other one) still excludes ordinary node_modules + // code and processes ordinary app source. + const generalRule = c.options.module.rules.find( + (r: any) => r !== scopedRule, + ) + expect(generalRule.exclude.test('/repo/node_modules/react/index.js')).toBe( + true, + ) + expect(generalRule.exclude.test('/repo/src/app.tsx')).toBe(false) + }) + it('wraps devServer.setupMiddlewares in development', () => { const c = mockCompiler('development') new TanStackDevtoolsRspackPlugin().apply(c as any) diff --git a/packages/devtools-rspack/src/plugin.ts b/packages/devtools-rspack/src/plugin.ts index 94574cfd..4d1d4048 100644 --- a/packages/devtools-rspack/src/plugin.ts +++ b/packages/devtools-rspack/src/plugin.ts @@ -80,6 +80,28 @@ export class TanStackDevtoolsRspackPlugin { use: [{ loader: loaderPath, options: { config: args } }], }) + // 1b. ALSO process the `@tanstack/devtools*` / `@tanstack/event-bus*` + // packages when THEY resolve under `node_modules` (the common case for + // real consumers, as opposed to this repo's own workspace symlinks). + // The general rule above excludes all of `node_modules`, so without + // this second, narrowly-scoped rule the `__TANSTACK_DEVTOOLS_*` + // connection placeholders (step 4 of `runPipeline`) and the + // runtime-bridge injection (step 5) would never run on that code, + // breaking a custom `eventBusConfig.port` / host / protocol for any + // consumer whose install resolves these packages under + // `node_modules` (flat npm/yarn installs, or pnpm's nested + // `.pnpm//node_modules/` virtual-store layout). Note this + // rule has NO `exclude`; `runPipeline`'s per-step gating already + // no-ops the JSX/source/console-pipe steps for these built files, so + // only steps 4 and 5 actually fire here. + compiler.options.module.rules.push({ + test: /\.[cm]?jsx?$/, + include: + /node_modules[\\/](\.pnpm[\\/][^\\/]+[\\/]node_modules[\\/])?@tanstack[\\/](devtools|event-bus)/, + enforce: 'pre', + use: [{ loader: loaderPath, options: { config: args } }], + }) + // Server features are dev-only. if (!isDev) return From 6bfceee623a54434404e13314993ceec621c61b8 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 18:12:18 +0200 Subject: [PATCH 14/16] fix(devtools-rspack): eager event-bus connection, gate dep-refresh on package.json, port-routing tests, doc accuracy --- .../src/normalize-path.ts | 4 +- packages/devtools-rspack/README.md | 4 +- packages/devtools-rspack/src/loader.test.ts | 43 ++++++++++ packages/devtools-rspack/src/plugin.ts | 79 ++++++++++++++++--- 4 files changed, 115 insertions(+), 15 deletions(-) diff --git a/packages/devtools-bundler-core/src/normalize-path.ts b/packages/devtools-bundler-core/src/normalize-path.ts index 1c6177e1..baa09e9b 100644 --- a/packages/devtools-bundler-core/src/normalize-path.ts +++ b/packages/devtools-bundler-core/src/normalize-path.ts @@ -1,2 +1,4 @@ -// ponytail: Vite's normalizePath does exactly this (backslash -> forward slash). +// Matches the backslash -> forward-slash half of Vite's normalizePath. Vite +// additionally runs path.posix.normalize, which we don't need for these +// substring checks. export const normalizePath = (p: string): string => p.replace(/\\/g, '/') diff --git a/packages/devtools-rspack/README.md b/packages/devtools-rspack/README.md index ed48ffe1..9cc0740b 100644 --- a/packages/devtools-rspack/README.md +++ b/packages/devtools-rspack/README.md @@ -50,5 +50,5 @@ module.exports = async () => { This package aims for 1:1 feature parity with `@tanstack/devtools-vite`, with two known caveats: -- **Runtime bridge channel wiring is Vite-only.** Vite's `wireRuntimeBridgeChannels` relies on Vite's SSR `server.environments[].hot` API, which has no Rspack equivalent — that live channel wiring is not available under Rspack. The code-injection half (`injectRuntimeBridge`) does run: it targets the `@tanstack/devtools`/`@tanstack/devtools-event-bus` event-client module, reached via a loader rule scoped to those packages under `node_modules` (in addition to the app's own source). However, the injected guard checks `import.meta.hot`, which is inert under Rspack (Rspack exposes HMR via `module.hot`, not `import.meta.hot`), so the injected code never activates — only the parity-preserving code-injection itself is real, not a working bridge. -- **The `__tsd/*` dev endpoints require `@rspack/dev-server`.** The plugin wraps `compiler.options.devServer.setupMiddlewares` to mount the devtools middleware. This auto-wiring is **verified working** against `@rspack/dev-server` (`@rspack/cli` 1.7.x, `@rspack/dev-server` 1.x): the `examples/react-rspack` e2e smoke boots `rspack serve` and confirms `GET /__tsd/open-source` returns `200` with no manual wiring. The endpoints are therefore available out of the box whenever the dev server reads and honors `compiler.options.devServer` (the standard `@rspack/dev-server` path). Only if your setup bypasses `@rspack/dev-server`'s config wiring (e.g. a fully custom server) would you need to install the `setupMiddlewares` handler yourself. +- **Runtime bridge channel wiring is Vite-only.** Vite's `wireRuntimeBridgeChannels` relies on Vite's SSR `server.environments[].hot` API, which has no Rspack equivalent — that live channel wiring is not available under Rspack. The code-injection half (`injectRuntimeBridge`) only runs for **server-target builds** (`target: 'node'` / `'async-node'`); a client/web build — like `examples/react-rspack`, which sets no `target` and so defaults to `web` — never triggers it. When it does run it targets the `@tanstack/devtools`/`@tanstack/devtools-event-bus` event-client module, reached via a loader rule scoped to those packages under `node_modules` (in addition to the app's own source). Even then, the injected guard checks `import.meta.hot`, which is inert under Rspack (Rspack exposes HMR via `module.hot`, not `import.meta.hot`), so the injected code never activates — only the parity-preserving code-injection itself is real, not a working bridge. +- **The `__tsd/*` dev endpoints require `@rspack/dev-server`.** The plugin mounts the devtools middleware by wrapping `compiler.options.devServer.setupMiddlewares`. This auto-wiring was **manually verified** against `@rspack/dev-server` (`@rspack/cli` 1.x, `@rspack/dev-server` 1.x): booting `rspack serve` on `examples/react-rspack` and confirming `GET /__tsd/open-source` returns `200` with no manual wiring (automated e2e coverage is a follow-up). The endpoints are therefore available out of the box whenever the dev server reads and honors `compiler.options.devServer` (the standard `@rspack/dev-server` path). Only if your setup bypasses `@rspack/dev-server`'s config wiring (e.g. a fully custom server) would you need to install the `setupMiddlewares` handler yourself. diff --git a/packages/devtools-rspack/src/loader.test.ts b/packages/devtools-rspack/src/loader.test.ts index 96d9ffe6..83187c35 100644 --- a/packages/devtools-rspack/src/loader.test.ts +++ b/packages/devtools-rspack/src/loader.test.ts @@ -42,4 +42,47 @@ describe('runPipeline', () => { const out = runPipeline(code, '/proj/node_modules/pkg/a.tsx', dev()) expect(out).not.toContain('data-tsd-source') }) + + // Port-routing regression tests: the `/__tsd/*` endpoints are mounted on the + // DEV SERVER, so enhanced-log / console-pipe URLs must target the dev-server + // origin, while the `__TANSTACK_DEVTOOLS_*` placeholders must use the + // event-bus connection. These must fail if the two ports were ever crossed. + it('enhanced-log URL uses the dev-server port, not the event-bus port', () => { + const out = runPipeline( + 'console.log("x")', + '/proj/src/b.ts', + dev({ + devServer: { port: 8080, host: 'localhost', protocol: 'http' }, + connection: { port: 4206, host: 'localhost', protocol: 'http' }, + }), + ) + expect(out).toContain('localhost:8080') + expect(out).not.toContain('localhost:4206') + }) + + it('console-pipe SSR target uses the dev-server origin, not the event bus', () => { + const out = runPipeline( + 'createRoot(document.getElementById("root"))', + '/proj/src/main.tsx', + dev({ + devServer: { port: 8080, host: 'localhost', protocol: 'http' }, + connection: { port: 4206, host: 'localhost', protocol: 'http' }, + }), + ) + expect(out).toContain('localhost:8080') + expect(out).not.toContain(':4206') + }) + + it('connection placeholders use the event-bus connection, not the dev-server origin', () => { + const out = runPipeline( + 'const p = __TANSTACK_DEVTOOLS_PORT__', + '/proj/node_modules/@tanstack/devtools/x.js', + dev({ + devServer: { port: 8080, host: 'localhost', protocol: 'http' }, + connection: { port: 4206, host: 'localhost', protocol: 'http' }, + }), + ) + expect(out).toContain('4206') + expect(out).not.toContain('8080') + }) }) diff --git a/packages/devtools-rspack/src/plugin.ts b/packages/devtools-rspack/src/plugin.ts index 4d1d4048..85175f2c 100644 --- a/packages/devtools-rspack/src/plugin.ts +++ b/packages/devtools-rspack/src/plugin.ts @@ -91,9 +91,12 @@ export class TanStackDevtoolsRspackPlugin { // consumer whose install resolves these packages under // `node_modules` (flat npm/yarn installs, or pnpm's nested // `.pnpm//node_modules/` virtual-store layout). Note this - // rule has NO `exclude`; `runPipeline`'s per-step gating already - // no-ops the JSX/source/console-pipe steps for these built files, so - // only steps 4 and 5 actually fire here. + // rule has NO `exclude`. Within `runPipeline`, steps 4 (connection + // placeholders) and 5 (runtime-bridge injection) are the only ones that + // produce an effect here; step 6 (`detectDevtoolsFile`) also runs but + // no-ops on these built package files, while steps 1-3 are + // excluded-gated (skipped for `node_modules`) and step 7 is + // production-only. compiler.options.module.rules.push({ test: /\.[cm]?jsx?$/, include: @@ -120,6 +123,28 @@ export class TanStackDevtoolsRspackPlugin { const levels = args.consolePiping?.levels ?? DEFAULT_LEVELS const editor: EditorConfig = args.editor ?? DEFAULT_EDITOR_CONFIG + // Resolve the event-bus connection (devtools client <-> event bus). + // `host` honors a user-supplied `eventBusConfig.host` and is NOT hardcoded. + // Protocol is always 'http': unlike Vite (which can piggyback its own https + // server), the rspack event bus is a standalone plain-http server on + // localhost, so 'http' is correct here — this is not a hardcoding bug. + const preferredPort = args.eventBusConfig?.port ?? 4206 + const busHost = args.eventBusConfig?.host ?? 'localhost' + + // Vite `await`s the bound port before any transform runs; rspack's `apply` + // is synchronous and cannot await, so record the connection EAGERLY (before + // any compilation transform reads it via `getDevtoolsConnection`) with the + // preferred port/host. This bakes a custom `eventBusConfig.port`/host into + // the loader's placeholder replacement for the common case. The actual + // bound port is refined once `bus.start()` resolves (covers EADDRINUSE). + if (serverBusEnabled) { + setDevtoolsConnection({ + port: preferredPort, + host: busHost, + protocol: 'http', + }) + } + // 2. wire package-manager + package.json events (Vite event-client-setup analog). // Guarded like Vite's `event-client-setup` sub-plugin so CI runs don't // trigger `emitOutdatedDeps()` (which may spawn a package-manager subprocess). @@ -165,19 +190,31 @@ export class TanStackDevtoolsRspackPlugin { protocol: 'http', }) - // Start the event bus once and record the resolved connection for the - // loader's placeholder replacement (devtools client <-> event bus). + // Start the event bus once (deferred here rather than in `apply` so unit + // tests that never boot a dev server don't open real sockets). The + // connection was already set eagerly in the dev block above; here we + // refine it to the actual bound port and surface any start failure. if (serverBusEnabled && !busStarted) { busStarted = true const bus = new ServerEventBus({ ...args.eventBusConfig, - port: args.eventBusConfig?.port ?? 4206, - host: 'localhost', + port: preferredPort, + host: busHost, }) // start() handles EADDRINUSE and returns the actual bound port. - void bus.start().then((port) => { - setDevtoolsConnection({ port, host: 'localhost', protocol: 'http' }) - }) + bus + .start() + .then((port) => + setDevtoolsConnection({ port, host: busHost, protocol: 'http' }), + ) + .catch((err) => + console.error( + chalk.red( + '[@tanstack/devtools-rspack] event bus failed to start:', + ), + err, + ), + ) } const base = prev ? prev(middlewares, server) : middlewares @@ -270,9 +307,27 @@ export class TanStackDevtoolsRspackPlugin { if (!packageJson) void refresh() }) - // Re-read package.json on rebuilds (Vite handleHotUpdate analog). + // Re-read package.json on rebuilds, but ONLY when package.json actually + // changed (Vite's handleHotUpdate analog gates on + // `file.endsWith('package.json')`). `refresh()` runs `emitOutdatedDeps()`, + // which spawns a `pnpm/npm outdated` subprocess, so running it on every + // rebuild would be wasteful. In rspack/webpack the changed paths for a + // rebuild are on `compiler.modifiedFiles` (a Set of absolute paths). compiler.hooks.watchRun?.tapPromise?.(PLUGIN, async () => { - await refresh() + const modified: Set | undefined = compiler.modifiedFiles + // `modifiedFiles` is undefined on the first watch run — prime deps once. + if (!modified) { + if (!packageJson) await refresh() + return + } + // Normalize `\` -> `/` so the basename check is separator-agnostic. + const packageJsonChanged = [...modified].some((file) => { + const normalized = file.replace(/\\/g, '/') + return ( + normalized.endsWith('/package.json') || normalized === 'package.json' + ) + }) + if (packageJsonChanged) await refresh() }) // Whenever a client mounts, send it the current package info. From 3242451b5fcb73713ef5c63c3596f74265eb844e Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 18:18:44 +0200 Subject: [PATCH 15/16] fix(devtools-rspack): emit package-json-read on package.json change (vite parity) --- packages/devtools-rspack/src/plugin.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/devtools-rspack/src/plugin.ts b/packages/devtools-rspack/src/plugin.ts index 85175f2c..d0b8cc3c 100644 --- a/packages/devtools-rspack/src/plugin.ts +++ b/packages/devtools-rspack/src/plugin.ts @@ -327,7 +327,12 @@ export class TanStackDevtoolsRspackPlugin { normalized.endsWith('/package.json') || normalized === 'package.json' ) }) - if (packageJsonChanged) await refresh() + if (packageJsonChanged) { + await refresh() + // Push the fresh package.json to connected clients (Vite's + // handleHotUpdate emits `package-json-read` on a package.json change). + devtoolsEventClient.emit('package-json-read', { packageJson }) + } }) // Whenever a client mounts, send it the current package info. From f389d2b1912f577f8b1b5fbc3fc42d0d9b754e35 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 14 Jul 2026 18:26:56 +0200 Subject: [PATCH 16/16] chore(devtools): formatting + lint fixes --- .changeset/devtools-bundler-core.md | 2 +- .../devtools-vite-bundler-core-refactor.md | 2 +- .changeset/rspack-plugin.md | 2 +- packages/devtools-bundler-core/package.json | 35 ++++++++++++---- .../src/connection.test.ts | 18 +++++++-- .../devtools-bundler-core/src/connection.ts | 30 +++++++++++--- packages/devtools-bundler-core/tsconfig.json | 5 ++- packages/devtools-bundler-core/vite.config.ts | 6 ++- packages/devtools-rspack/package.json | 40 +++++++++++++++---- packages/devtools-rspack/src/index.ts | 3 +- packages/devtools-rspack/src/loader.test.ts | 33 ++++++++++----- packages/devtools-rspack/src/plugin.test.ts | 6 +-- packages/devtools-rspack/src/plugin.ts | 17 ++++++-- packages/devtools-rspack/tsconfig.json | 5 ++- 14 files changed, 156 insertions(+), 48 deletions(-) diff --git a/.changeset/devtools-bundler-core.md b/.changeset/devtools-bundler-core.md index bd38a603..a57b04a5 100644 --- a/.changeset/devtools-bundler-core.md +++ b/.changeset/devtools-bundler-core.md @@ -1,5 +1,5 @@ --- -"@tanstack/devtools-bundler-core": minor +'@tanstack/devtools-bundler-core': minor --- Introduce `@tanstack/devtools-bundler-core`, the framework-agnostic core (transforms, editor integration, package-manager, dev-state) shared by the TanStack devtools bundler plugins. diff --git a/.changeset/devtools-vite-bundler-core-refactor.md b/.changeset/devtools-vite-bundler-core-refactor.md index 35badc7a..16f84819 100644 --- a/.changeset/devtools-vite-bundler-core-refactor.md +++ b/.changeset/devtools-vite-bundler-core-refactor.md @@ -1,5 +1,5 @@ --- -"@tanstack/devtools-vite": patch +'@tanstack/devtools-vite': patch --- Internal refactor: consume `@tanstack/devtools-bundler-core` for shared logic. No public API or behavior change. diff --git a/.changeset/rspack-plugin.md b/.changeset/rspack-plugin.md index 4897acfc..3e62ebb1 100644 --- a/.changeset/rspack-plugin.md +++ b/.changeset/rspack-plugin.md @@ -1,5 +1,5 @@ --- -"@tanstack/devtools-rspack": minor +'@tanstack/devtools-rspack': minor --- Add `@tanstack/devtools-rspack` — Rspack plugin with 1:1 feature parity to `@tanstack/devtools-vite` (source injection, enhanced logs, console piping, devtools removal on build, editor integration, event bus, package manager). diff --git a/packages/devtools-bundler-core/package.json b/packages/devtools-bundler-core/package.json index 09f3b017..af1f1a00 100644 --- a/packages/devtools-bundler-core/package.json +++ b/packages/devtools-bundler-core/package.json @@ -4,21 +4,42 @@ "description": "Framework-agnostic core shared by TanStack devtools bundler plugins", "author": "Tanner Linsley", "license": "MIT", - "repository": { "type": "git", "url": "git+https://github.com/TanStack/devtools.git", "directory": "packages/devtools-bundler-core" }, + "repository": { + "type": "git", + "url": "git+https://github.com/TanStack/devtools.git", + "directory": "packages/devtools-bundler-core" + }, "homepage": "https://tanstack.com/devtools", - "bugs": { "url": "https://github.com/TanStack/devtools/issues" }, - "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" }, - "keywords": ["devtools"], + "bugs": { + "url": "https://github.com/TanStack/devtools/issues" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "keywords": [ + "devtools" + ], "type": "module", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", "exports": { - ".": { "import": { "types": "./dist/esm/index.d.ts", "default": "./dist/esm/index.js" } }, + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + } + }, "./package.json": "./package.json" }, "sideEffects": false, - "engines": { "node": ">=18" }, - "files": ["dist/", "src"], + "engines": { + "node": ">=18" + }, + "files": [ + "dist/", + "src" + ], "scripts": { "clean": "premove ./build ./dist", "lint:fix": "eslint ./src --fix", diff --git a/packages/devtools-bundler-core/src/connection.test.ts b/packages/devtools-bundler-core/src/connection.test.ts index 69af5d8e..68da9ab2 100644 --- a/packages/devtools-bundler-core/src/connection.test.ts +++ b/packages/devtools-bundler-core/src/connection.test.ts @@ -1,17 +1,27 @@ import { describe, expect, it } from 'vitest' import { - getDevtoolsConnection, getDevtoolsFileId, - setDevtoolsConnection, setDevtoolsFileId, + getDevtoolsConnection, + getDevtoolsFileId, + setDevtoolsConnection, + setDevtoolsFileId, } from './connection' describe('connection singleton', () => { it('returns sensible defaults before anything is set', () => { - expect(getDevtoolsConnection()).toEqual({ port: 4206, host: 'localhost', protocol: 'http' }) + expect(getDevtoolsConnection()).toEqual({ + port: 4206, + host: 'localhost', + protocol: 'http', + }) expect(getDevtoolsFileId()).toBeNull() }) it('round-trips connection and file id', () => { setDevtoolsConnection({ port: 5000, host: '0.0.0.0', protocol: 'https' }) - expect(getDevtoolsConnection()).toEqual({ port: 5000, host: '0.0.0.0', protocol: 'https' }) + expect(getDevtoolsConnection()).toEqual({ + port: 5000, + host: '0.0.0.0', + protocol: 'https', + }) setDevtoolsFileId('/app/src/main.tsx') expect(getDevtoolsFileId()).toBe('/app/src/main.tsx') }) diff --git a/packages/devtools-bundler-core/src/connection.ts b/packages/devtools-bundler-core/src/connection.ts index 1b10e37e..4c51b234 100644 --- a/packages/devtools-bundler-core/src/connection.ts +++ b/packages/devtools-bundler-core/src/connection.ts @@ -1,11 +1,23 @@ -export type DevtoolsConnection = { port: number; host: string; protocol: 'http' | 'https' } +export type DevtoolsConnection = { + port: number + host: string + protocol: 'http' | 'https' +} -let connection: DevtoolsConnection = { port: 4206, host: 'localhost', protocol: 'http' } +let connection: DevtoolsConnection = { + port: 4206, + host: 'localhost', + protocol: 'http', +} let devtoolsFileId: string | null = null -export const setDevtoolsConnection = (c: DevtoolsConnection) => { connection = c } +export const setDevtoolsConnection = (c: DevtoolsConnection) => { + connection = c +} export const getDevtoolsConnection = (): DevtoolsConnection => connection -export const setDevtoolsFileId = (id: string | null) => { devtoolsFileId = id } +export const setDevtoolsFileId = (id: string | null) => { + devtoolsFileId = id +} export const getDevtoolsFileId = (): string | null => devtoolsFileId /** @@ -16,7 +28,13 @@ export const getDevtoolsFileId = (): string | null => devtoolsFileId * baked into enhanced console logs and the SSR-side `/__tsd/console-pipe/server` * POST target. */ -export type DevServerOrigin = { port: number; host: string; protocol: 'http' | 'https' } +export type DevServerOrigin = { + port: number + host: string + protocol: 'http' | 'https' +} let devServerOrigin: DevServerOrigin | null = null -export const setDevServerOrigin = (o: DevServerOrigin) => { devServerOrigin = o } +export const setDevServerOrigin = (o: DevServerOrigin) => { + devServerOrigin = o +} export const getDevServerOrigin = (): DevServerOrigin | null => devServerOrigin diff --git a/packages/devtools-bundler-core/tsconfig.json b/packages/devtools-bundler-core/tsconfig.json index f5be8dcd..eb638359 100644 --- a/packages/devtools-bundler-core/tsconfig.json +++ b/packages/devtools-bundler-core/tsconfig.json @@ -1 +1,4 @@ -{ "extends": "../../tsconfig.json", "include": ["src", "eslint.config.js", "vite.config.ts"] } +{ + "extends": "../../tsconfig.json", + "include": ["src", "eslint.config.js", "vite.config.ts"] +} diff --git a/packages/devtools-bundler-core/vite.config.ts b/packages/devtools-bundler-core/vite.config.ts index 760700c8..6dc88858 100644 --- a/packages/devtools-bundler-core/vite.config.ts +++ b/packages/devtools-bundler-core/vite.config.ts @@ -15,5 +15,9 @@ const config = defineConfig({ export default mergeConfig( config, - tanstackViteConfig({ cjs: false, entry: ['./src/index.ts'], srcDir: './src' }), + tanstackViteConfig({ + cjs: false, + entry: ['./src/index.ts'], + srcDir: './src', + }), ) diff --git a/packages/devtools-rspack/package.json b/packages/devtools-rspack/package.json index 02900b4c..f87ed317 100644 --- a/packages/devtools-rspack/package.json +++ b/packages/devtools-rspack/package.json @@ -4,21 +4,43 @@ "description": "TanStack Rspack plugin used to enhance the core devtools with additional functionalities", "author": "Tanner Linsley", "license": "MIT", - "repository": { "type": "git", "url": "git+https://github.com/TanStack/devtools.git", "directory": "packages/devtools-rspack" }, + "repository": { + "type": "git", + "url": "git+https://github.com/TanStack/devtools.git", + "directory": "packages/devtools-rspack" + }, "homepage": "https://tanstack.com/devtools", - "bugs": { "url": "https://github.com/TanStack/devtools/issues" }, - "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" }, - "keywords": ["devtools", "rspack"], + "bugs": { + "url": "https://github.com/TanStack/devtools/issues" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "keywords": [ + "devtools", + "rspack" + ], "type": "module", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", "exports": { - ".": { "import": { "types": "./dist/esm/index.d.ts", "default": "./dist/esm/index.js" } }, + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + } + }, "./package.json": "./package.json" }, "sideEffects": false, - "engines": { "node": ">=18" }, - "files": ["dist/", "src"], + "engines": { + "node": ">=18" + }, + "files": [ + "dist/", + "src" + ], "scripts": { "clean": "premove ./build ./dist", "lint:fix": "eslint ./src --fix", @@ -29,7 +51,9 @@ "test:build": "publint --strict", "build": "vite build" }, - "peerDependencies": { "@rspack/core": "^1.0.0" }, + "peerDependencies": { + "@rspack/core": "^1.0.0" + }, "dependencies": { "@tanstack/devtools-bundler-core": "workspace:*", "@tanstack/devtools-client": "workspace:*", diff --git a/packages/devtools-rspack/src/index.ts b/packages/devtools-rspack/src/index.ts index 0158cfbb..c94b9d85 100644 --- a/packages/devtools-rspack/src/index.ts +++ b/packages/devtools-rspack/src/index.ts @@ -4,7 +4,8 @@ import type { TanStackDevtoolsConfig } from '@tanstack/devtools-bundler-core' export type { ConsoleLevel } from '@tanstack/devtools-bundler-core' export type TanStackDevtoolsRspackConfig = TanStackDevtoolsConfig -export const defineDevtoolsConfig = (config: TanStackDevtoolsRspackConfig) => config +export const defineDevtoolsConfig = (config: TanStackDevtoolsRspackConfig) => + config export const devtools = (args?: TanStackDevtoolsRspackConfig) => new TanStackDevtoolsRspackPlugin(args) diff --git a/packages/devtools-rspack/src/loader.test.ts b/packages/devtools-rspack/src/loader.test.ts index 83187c35..361b1437 100644 --- a/packages/devtools-rspack/src/loader.test.ts +++ b/packages/devtools-rspack/src/loader.test.ts @@ -3,8 +3,12 @@ import { runPipeline } from './loader' const dev = (over = {}) => ({ mode: 'development' as const, - config: { injectSource: { enabled: true }, enhancedLogs: { enabled: true }, - consolePiping: { enabled: true }, removeDevtoolsOnBuild: true }, + config: { + injectSource: { enabled: true }, + enhancedLogs: { enabled: true }, + consolePiping: { enabled: true }, + removeDevtoolsOnBuild: true, + }, connection: { port: 4206, host: 'localhost', protocol: 'http' as const }, target: 'web', ...over, @@ -12,7 +16,11 @@ const dev = (over = {}) => ({ describe('runPipeline', () => { it('injects data-tsd-source into JSX in dev', () => { - const out = runPipeline('const A = () =>
hi
', '/proj/src/a.tsx', dev()) + const out = runPipeline( + 'const A = () =>
hi
', + '/proj/src/a.tsx', + dev(), + ) expect(out).toContain('data-tsd-source') }) @@ -22,17 +30,24 @@ describe('runPipeline', () => { }) it('replaces connection placeholders', () => { - const code = 'const p = __TANSTACK_DEVTOOLS_PORT__; const h = __TANSTACK_DEVTOOLS_HOST__' - const out = runPipeline(code, '/proj/node_modules/@tanstack/devtools/x.js', - dev({ connection: { port: 9000, host: 'localhost', protocol: 'http' } })) + const code = + 'const p = __TANSTACK_DEVTOOLS_PORT__; const h = __TANSTACK_DEVTOOLS_HOST__' + const out = runPipeline( + code, + '/proj/node_modules/@tanstack/devtools/x.js', + dev({ connection: { port: 9000, host: 'localhost', protocol: 'http' } }), + ) expect(out).toContain('9000') expect(out).toContain('"localhost"') }) it('strips devtools code in production builds', () => { - const code = 'import { TanStackDevtools } from "@tanstack/react-devtools"\nconst App = () => ' - const out = runPipeline(code, '/proj/src/main.tsx', - { ...dev(), mode: 'production' }) + const code = + 'import { TanStackDevtools } from "@tanstack/react-devtools"\nconst App = () => ' + const out = runPipeline(code, '/proj/src/main.tsx', { + ...dev(), + mode: 'production', + }) expect(out).not.toContain('TanStackDevtools') expect(out).not.toContain('@tanstack/react-devtools') }) diff --git a/packages/devtools-rspack/src/plugin.test.ts b/packages/devtools-rspack/src/plugin.test.ts index e968639b..c5d9e859 100644 --- a/packages/devtools-rspack/src/plugin.test.ts +++ b/packages/devtools-rspack/src/plugin.test.ts @@ -55,9 +55,9 @@ describe('TanStackDevtoolsRspackPlugin', () => { '/repo/node_modules/.pnpm/@tanstack+devtools-event-bus@1.0.0/node_modules/@tanstack/devtools-event-bus/dist/client/client.js' expect(scopedRule.include.test(nodeModulesSample)).toBe(true) expect(scopedRule.include.test(pnpmNestedSample)).toBe(true) - expect( - String(scopedRule.use?.[0]?.loader ?? scopedRule.loader), - ).toContain('loader') + expect(String(scopedRule.use?.[0]?.loader ?? scopedRule.loader)).toContain( + 'loader', + ) // The general rule (the other one) still excludes ordinary node_modules // code and processes ordinary app source. diff --git a/packages/devtools-rspack/src/plugin.ts b/packages/devtools-rspack/src/plugin.ts index d0b8cc3c..fe4b4fac 100644 --- a/packages/devtools-rspack/src/plugin.ts +++ b/packages/devtools-rspack/src/plugin.ts @@ -251,7 +251,10 @@ export class TanStackDevtoolsRspackPlugin { logMethod(prefix, ...cleanedArgs) } }, - onConsolePipeSSE: (res: ServerResponse, req: IncomingMessage) => { + onConsolePipeSSE: ( + res: ServerResponse, + req: IncomingMessage, + ) => { res.setHeader('Content-Type', 'text/event-stream') res.setHeader('Cache-Control', 'no-cache') res.setHeader('Connection', 'keep-alive') @@ -295,7 +298,8 @@ export class TanStackDevtoolsRspackPlugin { private wirePackageManager(compiler: any, logging: boolean) { let packageJson: PackageJson | null = null - let outdatedDeps: ReturnType = Promise.resolve(null) + let outdatedDeps: ReturnType = + Promise.resolve(null) const refresh = async () => { packageJson = await readPackageJson() @@ -401,8 +405,13 @@ export class TanStackDevtoolsRspackPlugin { }) devtoolsEventClient.on('bump-package-version', async (event) => { - const { packageName, devtoolsPackage, pluginName, minVersion, pluginImport } = - event.payload + const { + packageName, + devtoolsPackage, + pluginName, + minVersion, + pluginImport, + } = event.payload if (logging) { console.log( chalk.blueBright( diff --git a/packages/devtools-rspack/tsconfig.json b/packages/devtools-rspack/tsconfig.json index f5be8dcd..eb638359 100644 --- a/packages/devtools-rspack/tsconfig.json +++ b/packages/devtools-rspack/tsconfig.json @@ -1 +1,4 @@ -{ "extends": "../../tsconfig.json", "include": ["src", "eslint.config.js", "vite.config.ts"] } +{ + "extends": "../../tsconfig.json", + "include": ["src", "eslint.config.js", "vite.config.ts"] +}