diff --git a/.vscode/launch.json b/.vscode/launch.json
index eb3021f..58a4893 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -47,6 +47,13 @@
"${workspaceFolder}/packages/vscode-messenger-devtools/lib/**/*.js",
"${workspaceFolder}/packages/vscode-messenger/lib/**/*.js",
],
+ "debugWebviews": true,
+ "rendererDebugOptions": {
+ "webRoot": "${workspaceFolder}/packages/vscode-messenger-devtools/webview-ui",
+ "outFiles": [
+ "${workspaceFolder}/packages/vscode-messenger-devtools/webview-ui/build/**/*.js"
+ ]
+ },
"preLaunchTask": "Watch All"
}
]
diff --git a/README.md b/README.md
index 1f21f78..0753e02 100644
--- a/README.md
+++ b/README.md
@@ -7,88 +7,151 @@ RPC messaging library for the VS Code extension platform. Makes the communicatio
[](https://github.com/TypeFox/vscode-messenger/blob/main/LICENSE)
[](https://codespaces.new/TypeFox/vscode-messenger)
-#### Supported features
-
-- Sending notification or a request from an __extension to a view__, a __view group__ or __broadcast__ to all registered views
-- Sending notification or a request from a __view to other view__, a view group or the host extension
-- Support for __sync and async__ request/notification handlers
-- Support for __request cancellation__
-- __Typed__ API
-- Automatically unregister views on view dispose
+## Features
+
+- Send notifications or requests from an **extension to a view**, a **view group**, or **broadcast** to all registered views
+- Send notifications or requests from a **view to another view**, a view group, or the host extension
+- **Typed API** — `RequestType
` and `NotificationType
` enforce matching parameter and result types on both sides
+- Sync and async request/notification handlers
+- Request cancellation
+- Automatically unregisters views on dispose
- Configurable logging
-#### Diagnostics vs-code extension
+## Packages
-[](https://marketplace.visualstudio.com/items?itemName=typefox.vscode-messenger-devtools)
+Install only what each side needs:
+
+| Package | Install in | Purpose |
+|---|---|---|
+| [`vscode-messenger`](https://www.npmjs.com/package/vscode-messenger) | Extension host | `Messenger` class, view registration, diagnostic API |
+| [`vscode-messenger-webview`](https://www.npmjs.com/package/vscode-messenger-webview) | Webview script | `Messenger` class for webview, `createCancellationToken` |
+| [`vscode-messenger-common`](https://www.npmjs.com/package/vscode-messenger-common) | Shared module | `NotificationType`, `RequestType`, `HOST_EXTENSION`, `BROADCAST` |
-[Devtool vscode extension](https://github.com/TypeFox/vscode-messenger/tree/main/packages/vscode-messenger-devtools) helps inspecting messages interaction between your extension components.
+**Tip:** Keep all `NotificationType` / `RequestType` declarations in a shared TypeScript module imported by both the extension and the webview. The same `method` string and parameter/result types must match on both ends.
-#### Usage in an extension (TS example)
+## Usage in an extension (TypeScript)
```ts
+import * as vscode from 'vscode';
+import { Messenger } from 'vscode-messenger';
+import { NotificationType, RequestType } from 'vscode-messenger-common';
+
const messenger = new Messenger();
-// register one or more views
+// Register a webview view (or use registerWebviewPanel for WebviewPanel)
messenger.registerWebviewView(webviewView);
-
-// Handle incoming view notification
+// Define message types — declare once, import on both sides
const colorSelectType: NotificationType = { method: 'colorSelected' };
+const availableColorsType: RequestType = { method: 'availableColor' };
+const colorModifyType: NotificationType = { method: 'colorModify' };
-messenger.onNotification(colorSelectType, (params: string) => {
- vscode.window.activeTextEditor?.insertSnippet(new vscode.SnippetString(`#${params}`));
+// Handle a notification from the webview
+messenger.onNotification(colorSelectType, (color: string) => {
+ vscode.window.activeTextEditor?.insertSnippet(new vscode.SnippetString(`#${color}`));
});
-// Handle view requests and return a result
-const availableColorsType: RequestType = { method: 'availableColor' };
-
-messenger.onRequest(availableColorsType, (params: string) => {
+// Handle a request from the webview and return a result
+messenger.onRequest(availableColorsType, (_params: string) => {
return ['020202', 'f1eeee', 'a85b20', 'daab70', 'efcb99'];
});
-// Send a notification to a view of type 'calicoColors.colorsView'
-const colorModifyType: NotificationType = { method: 'colorModify' };
+// Send a notification to all views of a given type
+messenger.sendNotification(colorModifyType, { type: 'webview', webviewType: 'calicoColors.colorsView' }, 'clear');
+
+// Send a request to a view and await the result
+const selectedColor = await messenger.sendRequest(
+ { method: 'getSelectedColor' },
+ { type: 'webview', webviewType: 'calicoColors.colorsView' },
+ ''
+);
+```
-messenger.sendNotification(colorModifyType, {type: 'webview', webviewType: 'calicoColors.colorsView' }, 'clear');
+## Usage in a webview (TypeScript)
+```ts
+import { Messenger } from 'vscode-messenger-webview';
+import { HOST_EXTENSION } from 'vscode-messenger-common';
+import { colorModifyType, availableColorsType, colorSelectType } from './shared/message-types';
-// Send a request to a view of type 'calicoColors.colorsView' and get a result
-const selectedColor = await messenger.sendRequest({ method: 'getSelectedColor' }, {type: 'webview', webviewType: 'calicoColors.colorsView' }, '');
-```
+const messenger = new Messenger(); // acquireVsCodeApi() is called automatically
-#### Usage in a webview (JS Example)
-
-Using JS in this example for simplicity. You can use TypeScript as well.
-
-```js
-const vscode = acquireVsCodeApi();
-const vscode_messenger = require("vscode-messenger-webview");
-
-const messenger = new vscode_messenger.Messenger(vscode);
-
-// Handle extension Notifications. For requests use `onRequest()`
-messenger.onNotification({method: 'colorModify'}, (params) => {
- switch(params) {
- case 'add': {
- addColor();
- break;
- }
- case 'clear': {
- colors = [];
- updateColorList(colors);
- break;
- }
- }
+// Handle notifications from the extension
+messenger.onNotification(colorModifyType, (action: string) => {
+ if (action === 'clear') clearColors();
+ if (action === 'add') addColor();
});
-messenger.start(); // start listening for incoming events
-// Send a request to your extension.
-// For notification use `sendNotification()`
- const colors = await messenger.sendRequest({ method: 'availableColors'}, HOST_EXTENSION, '');
- console.log(colors);
+messenger.start(); // required — starts listening for incoming messages
+
+// Send a request to the host extension
+const colors = await messenger.sendRequest(availableColorsType, HOST_EXTENSION, '');
+
+// Send a notification to the host extension
+messenger.sendNotification(colorSelectType, HOST_EXTENSION, 'a85b20');
+```
+
+> **Note:** `messenger.start()` must be called before any messages can be received. Forgetting it causes all incoming messages to be silently dropped.
+
+## Key concepts
+
+### Message participants
+
+| Participant | How to construct | Use for |
+|---|---|---|
+| Host extension | `HOST_EXTENSION` | Targeting the extension from a webview |
+| Webview by type | `{ type: 'webview', webviewType: '...' }` | All instances of a view type |
+| Webview by id | returned by `registerWebviewView` / `registerWebviewPanel` | One specific instance |
+| Broadcast | `BROADCAST` | All registered views (notifications only) |
+### Request cancellation
+
+```ts
+// Extension side — pass any CancellationToken
+const cts = new vscode.CancellationTokenSource();
+const result = await messenger.sendRequest(longOpType, target, params, cts.token);
+cts.cancel();
+
+// Webview side — bridge an AbortSignal
+import { createCancellationToken } from 'vscode-messenger-webview';
+const ctrl = new AbortController();
+const result = await messenger.sendRequest(longOpType, HOST_EXTENSION, params, createCancellationToken(ctrl.signal));
+ctrl.abort('timeout');
+```
+
+### Broadcast notifications
+
+A webview receives a broadcast only when registered with `broadcastMethods` listing the method:
+
+```ts
+// Extension: opt the view in to specific broadcast methods
+messenger.registerWebviewView(view, { broadcastMethods: [refreshType.method] });
+
+// Either side: broadcast to all opted-in views
+messenger.sendNotification(refreshType, BROADCAST);
+```
+
+## Diagnostics and devtools
+
+[](https://marketplace.visualstudio.com/items?itemName=typefox.vscode-messenger-devtools)
+
+The companion **[VS Code Messenger Developer Tool](https://marketplace.visualstudio.com/items?itemName=typefox.vscode-messenger-devtools)** extension visualizes live message traffic — requests, responses, and notifications — between the extension host and its webviews. To enable it, expose `messenger.diagnosticApi()` from your extension's `activate` return value:
+
+```ts
+import { Messenger, type MessengerDiagnostic } from 'vscode-messenger';
+
+const messenger = new Messenger();
+
+export function activate(context: vscode.ExtensionContext): MessengerDiagnostic {
+ // ... register views, handlers, etc.
+ return messenger.diagnosticApi();
+}
```
-#### More examples
+Open the devtool with **Developer: Open vscode-messenger devtools** from the Command Palette.
+
+See the [devtools README](packages/vscode-messenger-devtools/README.md) for full setup instructions, `DiagnosticOptions`, the event schema, and troubleshooting.
+
+## More examples
-See tests for more examples.
+The [calico-colors example](examples/calico-colors) demonstrates a complete extension with a `WebviewView` and a `WebviewPanel` sharing a single `Messenger` instance, typed message definitions in a shared module, broadcast usage, and diagnostic API integration.
diff --git a/eslint.config.js b/eslint.config.js
index 7a0cb1c..e6e9bbc 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -47,9 +47,10 @@ module.exports = {
"no-multiple-empty-lines": ["error", { "max": 1 }], // two or more empty lines need to be fused to one
"no-new-wrappers": "error", // there is no reason to wrap primitve values
"no-throw-literal": "error", // only throw Error but no objects {}
- "no-trailing-spaces": "error", // trim end of lines
+ "no-trailing-spaces": "off", // trim end of lines
"no-unsafe-finally": "error", // safe try/catch/finally behavior
"no-var": "error", // use const and let instead of var
+ "no-constant-binary-expression": "warn", // warn about expressions like if (a === 1 || 0) which are always true
"space-before-function-paren": ["error", { // space in function decl: f() vs async () => {}
"anonymous": "never",
"asyncArrow": "always",
diff --git a/package-lock.json b/package-lock.json
index 637f958..405162c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -45,9 +45,9 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz",
- "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -60,9 +60,9 @@
}
},
"node_modules/@babel/compat-data": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz",
- "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
+ "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -70,21 +70,21 @@
}
},
"node_modules/@babel/core": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz",
- "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
+ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/generator": "^7.28.6",
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
"@babel/helper-compilation-targets": "^7.28.6",
"@babel/helper-module-transforms": "^7.28.6",
"@babel/helpers": "^7.28.6",
- "@babel/parser": "^7.28.6",
+ "@babel/parser": "^7.29.0",
"@babel/template": "^7.28.6",
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6",
+ "@babel/traverse": "^7.29.0",
+ "@babel/types": "^7.29.0",
"@jridgewell/remapping": "^2.3.5",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
@@ -118,14 +118,14 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz",
- "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==",
+ "version": "7.29.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
+ "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.28.6",
- "@babel/types": "^7.28.6",
+ "@babel/parser": "^7.29.0",
+ "@babel/types": "^7.29.0",
"@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
@@ -244,27 +244,27 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
- "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
+ "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/template": "^7.28.6",
- "@babel/types": "^7.28.6"
+ "@babel/types": "^7.29.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
- "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
+ "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.28.6"
+ "@babel/types": "^7.29.0"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -529,9 +529,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
- "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
+ "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
"dev": true,
"license": "MIT",
"engines": {
@@ -554,18 +554,18 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz",
- "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/generator": "^7.28.6",
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
"@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.28.6",
+ "@babel/parser": "^7.29.0",
"@babel/template": "^7.28.6",
- "@babel/types": "^7.28.6",
+ "@babel/types": "^7.29.0",
"debug": "^4.3.1"
},
"engines": {
@@ -573,9 +573,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
- "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1065,24 +1065,31 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.21.1",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
- "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
+ "version": "0.21.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz",
+ "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/object-schema": "^2.1.7",
"debug": "^4.3.1",
- "minimatch": "^3.1.2"
+ "minimatch": "^3.1.5"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@eslint/config-array/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@eslint/config-array/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
+ "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1091,9 +1098,9 @@
}
},
"node_modules/@eslint/config-array/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -1130,20 +1137,20 @@
}
},
"node_modules/@eslint/eslintrc": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
- "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
+ "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ajv": "^6.12.4",
+ "ajv": "^6.14.0",
"debug": "^4.3.2",
"espree": "^10.0.1",
"globals": "^14.0.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.1",
- "minimatch": "^3.1.2",
+ "minimatch": "^3.1.5",
"strip-json-comments": "^3.1.1"
},
"engines": {
@@ -1153,10 +1160,17 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/@eslint/eslintrc/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
+ "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1175,9 +1189,9 @@
}
},
"node_modules/@eslint/eslintrc/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -1188,9 +1202,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.39.2",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
- "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz",
+ "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1224,6 +1238,65 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
+ "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.11"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.6",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
+ "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.5",
+ "@floating-ui/utils": "^0.2.11"
+ }
+ },
+ "node_modules/@floating-ui/react": {
+ "version": "0.27.19",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.19.tgz",
+ "integrity": "sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.1.8",
+ "@floating-ui/utils": "^0.2.11",
+ "tabbable": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=17.0.0",
+ "react-dom": ">=17.0.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
+ "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.6"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/react/node_modules/tabbable": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz",
+ "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==",
+ "license": "MIT"
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
+ "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
+ "license": "MIT"
+ },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1736,46 +1809,6 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/@microsoft/fast-element": {
- "version": "1.14.0",
- "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.14.0.tgz",
- "integrity": "sha512-zXvuSOzvsu8zDTy9eby8ix8VqLop2rwKRgp++ZN2kTCsoB3+QJVoaGD2T/Cyso2ViZQFXNpiNCVKfnmxBvmWkQ==",
- "license": "MIT"
- },
- "node_modules/@microsoft/fast-foundation": {
- "version": "2.50.0",
- "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.50.0.tgz",
- "integrity": "sha512-8mFYG88Xea1jZf2TI9Lm/jzZ6RWR8x29r24mGuLojNYqIR2Bl8+hnswoV6laApKdCbGMPKnsAL/O68Q0sRxeVg==",
- "license": "MIT",
- "dependencies": {
- "@microsoft/fast-element": "^1.14.0",
- "@microsoft/fast-web-utilities": "^5.4.1",
- "tabbable": "^5.2.0",
- "tslib": "^1.13.0"
- }
- },
- "node_modules/@microsoft/fast-react-wrapper": {
- "version": "0.1.48",
- "resolved": "https://registry.npmjs.org/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.1.48.tgz",
- "integrity": "sha512-9NvEjru9Kn5ZKjomAMX6v+eF0DR+eDkxKDwDfi+Wb73kTbrNzcnmlwd4diN15ygH97kldgj2+lpvI4CKLQQWLg==",
- "license": "MIT",
- "dependencies": {
- "@microsoft/fast-element": "^1.9.0",
- "@microsoft/fast-foundation": "^2.41.1"
- },
- "peerDependencies": {
- "react": ">=16.9.0"
- }
- },
- "node_modules/@microsoft/fast-web-utilities": {
- "version": "5.4.1",
- "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz",
- "integrity": "sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg==",
- "license": "MIT",
- "dependencies": {
- "exenv-es6": "^1.1.1"
- }
- },
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.27",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
@@ -1784,9 +1817,9 @@
"license": "MIT"
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz",
- "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
+ "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
"cpu": [
"arm"
],
@@ -1798,9 +1831,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz",
- "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
+ "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
"cpu": [
"arm64"
],
@@ -1812,9 +1845,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz",
- "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
+ "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
"cpu": [
"arm64"
],
@@ -1826,9 +1859,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz",
- "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
+ "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
"cpu": [
"x64"
],
@@ -1840,9 +1873,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz",
- "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
+ "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
"cpu": [
"arm64"
],
@@ -1854,9 +1887,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz",
- "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
+ "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
"cpu": [
"x64"
],
@@ -1868,9 +1901,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz",
- "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
+ "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
"cpu": [
"arm"
],
@@ -1882,9 +1915,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz",
- "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
+ "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
"cpu": [
"arm"
],
@@ -1896,9 +1929,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz",
- "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
+ "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
"cpu": [
"arm64"
],
@@ -1910,9 +1943,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz",
- "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
+ "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
"cpu": [
"arm64"
],
@@ -1924,9 +1957,9 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz",
- "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
+ "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
"cpu": [
"loong64"
],
@@ -1938,9 +1971,9 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-musl": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz",
- "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
+ "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
"cpu": [
"loong64"
],
@@ -1952,9 +1985,9 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz",
- "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
+ "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
"cpu": [
"ppc64"
],
@@ -1966,9 +1999,9 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-musl": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz",
- "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
+ "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
"cpu": [
"ppc64"
],
@@ -1980,9 +2013,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz",
- "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
+ "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
"cpu": [
"riscv64"
],
@@ -1994,9 +2027,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz",
- "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
+ "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
"cpu": [
"riscv64"
],
@@ -2008,9 +2041,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz",
- "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
+ "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
"cpu": [
"s390x"
],
@@ -2022,9 +2055,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz",
- "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
"cpu": [
"x64"
],
@@ -2036,9 +2069,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz",
- "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
+ "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
"cpu": [
"x64"
],
@@ -2050,9 +2083,9 @@
]
},
"node_modules/@rollup/rollup-openbsd-x64": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz",
- "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
+ "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
"cpu": [
"x64"
],
@@ -2064,9 +2097,9 @@
]
},
"node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz",
- "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
+ "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
"cpu": [
"arm64"
],
@@ -2078,9 +2111,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz",
- "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
+ "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
"cpu": [
"arm64"
],
@@ -2092,9 +2125,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz",
- "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
+ "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
"cpu": [
"ia32"
],
@@ -2106,9 +2139,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz",
- "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
"cpu": [
"x64"
],
@@ -2120,9 +2153,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz",
- "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
+ "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
"cpu": [
"x64"
],
@@ -2160,6 +2193,39 @@
"@sinonjs/commons": "^1.7.0"
}
},
+ "node_modules/@tanstack/react-table": {
+ "version": "8.21.3",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz",
+ "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/table-core": "8.21.3"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/@tanstack/table-core": {
+ "version": "8.21.3",
+ "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz",
+ "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@@ -2170,12 +2236,6 @@
"node": ">= 6"
}
},
- "node_modules/@tweenjs/tween.js": {
- "version": "25.0.0",
- "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-25.0.0.tgz",
- "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==",
- "license": "MIT"
- },
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -2319,42 +2379,26 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@types/prop-types": {
- "version": "15.7.15",
- "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
- "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/react": {
- "version": "17.0.90",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.90.tgz",
- "integrity": "sha512-P9beVR/x06U9rCJzSxtENnOr4BrbJ6VrsrDTc+73TtHv9XHhryXKbjGRB+6oooB2r0G/pQkD/S4dHo/7jUfwFw==",
+ "version": "19.2.14",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
+ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/prop-types": "*",
- "@types/scheduler": "^0.16",
"csstype": "^3.2.2"
}
},
"node_modules/@types/react-dom": {
- "version": "17.0.26",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.26.tgz",
- "integrity": "sha512-Z+2VcYXJwOqQ79HreLU/1fyQ88eXSSFh6I3JdrEHQIfYSI0kCQpTGvOrbE6jFGGYXKsHuwY9tBa/w5Uo6KzrEg==",
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
- "@types/react": "^17.0.0"
+ "@types/react": "^19.2.0"
}
},
- "node_modules/@types/scheduler": {
- "version": "0.16.8",
- "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
- "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/stack-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
@@ -2370,9 +2414,9 @@
"license": "MIT"
},
"node_modules/@types/vscode": {
- "version": "1.108.1",
- "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.108.1.tgz",
- "integrity": "sha512-DerV0BbSzt87TbrqmZ7lRDIYaMiqvP8tmJTzW2p49ZBVtGUnGAu2RGQd1Wv4XMzEVUpaHbsemVM5nfuQJj7H6w==",
+ "version": "1.110.0",
+ "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.110.0.tgz",
+ "integrity": "sha512-AGuxUEpU4F4mfuQjxPPaQVyuOMhs+VT/xRok1jiHVBubHK7lBRvCuOMZG0LKUwxncrPorJ5qq/uil3IdZBd5lA==",
"dev": true,
"license": "MIT"
},
@@ -2401,17 +2445,17 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.53.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.0.tgz",
- "integrity": "sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==",
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.1.tgz",
+ "integrity": "sha512-Gn3aqnvNl4NGc6x3/Bqk1AOn0thyTU9bqDRhiRnUWezgvr2OnhYCWCgC8zXXRVqBsIL1pSDt7T9nJUe0oM0kDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
- "@typescript-eslint/scope-manager": "8.53.0",
- "@typescript-eslint/type-utils": "8.53.0",
- "@typescript-eslint/utils": "8.53.0",
- "@typescript-eslint/visitor-keys": "8.53.0",
+ "@typescript-eslint/scope-manager": "8.57.1",
+ "@typescript-eslint/type-utils": "8.57.1",
+ "@typescript-eslint/utils": "8.57.1",
+ "@typescript-eslint/visitor-keys": "8.57.1",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.4.0"
@@ -2424,22 +2468,22 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^8.53.0",
- "eslint": "^8.57.0 || ^9.0.0",
+ "@typescript-eslint/parser": "^8.57.1",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.53.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.0.tgz",
- "integrity": "sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==",
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.57.1.tgz",
+ "integrity": "sha512-k4eNDan0EIMTT/dUKc/g+rsJ6wcHYhNPdY19VoX/EOtaAG8DLtKCykhrUnuHPYvinn5jhAPgD2Qw9hXBwrahsw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.53.0",
- "@typescript-eslint/types": "8.53.0",
- "@typescript-eslint/typescript-estree": "8.53.0",
- "@typescript-eslint/visitor-keys": "8.53.0",
+ "@typescript-eslint/scope-manager": "8.57.1",
+ "@typescript-eslint/types": "8.57.1",
+ "@typescript-eslint/typescript-estree": "8.57.1",
+ "@typescript-eslint/visitor-keys": "8.57.1",
"debug": "^4.4.3"
},
"engines": {
@@ -2450,19 +2494,19 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/project-service": {
- "version": "8.53.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.0.tgz",
- "integrity": "sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==",
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.1.tgz",
+ "integrity": "sha512-vx1F37BRO1OftsYlmG9xay1TqnjNVlqALymwWVuYTdo18XuKxtBpCj1QlzNIEHlvlB27osvXFWptYiEWsVdYsg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.53.0",
- "@typescript-eslint/types": "^8.53.0",
+ "@typescript-eslint/tsconfig-utils": "^8.57.1",
+ "@typescript-eslint/types": "^8.57.1",
"debug": "^4.4.3"
},
"engines": {
@@ -2477,14 +2521,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.53.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.0.tgz",
- "integrity": "sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==",
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.1.tgz",
+ "integrity": "sha512-hs/QcpCwlwT2L5S+3fT6gp0PabyGk4Q0Rv2doJXA0435/OpnSR3VRgvrp8Xdoc3UAYSg9cyUjTeFXZEPg/3OKg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.53.0",
- "@typescript-eslint/visitor-keys": "8.53.0"
+ "@typescript-eslint/types": "8.57.1",
+ "@typescript-eslint/visitor-keys": "8.57.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2495,9 +2539,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.53.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.0.tgz",
- "integrity": "sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==",
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.1.tgz",
+ "integrity": "sha512-0lgOZB8cl19fHO4eI46YUx2EceQqhgkPSuCGLlGi79L2jwYY1cxeYc1Nae8Aw1xjgW3PKVDLlr3YJ6Bxx8HkWg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2512,15 +2556,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.53.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.0.tgz",
- "integrity": "sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==",
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.57.1.tgz",
+ "integrity": "sha512-+Bwwm0ScukFdyoJsh2u6pp4S9ktegF98pYUU0hkphOOqdMB+1sNQhIz8y5E9+4pOioZijrkfNO/HUJVAFFfPKA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.53.0",
- "@typescript-eslint/typescript-estree": "8.53.0",
- "@typescript-eslint/utils": "8.53.0",
+ "@typescript-eslint/types": "8.57.1",
+ "@typescript-eslint/typescript-estree": "8.57.1",
+ "@typescript-eslint/utils": "8.57.1",
"debug": "^4.4.3",
"ts-api-utils": "^2.4.0"
},
@@ -2532,14 +2576,14 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.53.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz",
- "integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==",
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.1.tgz",
+ "integrity": "sha512-S29BOBPJSFUiblEl6RzPPjJt6w25A6XsBqRVDt53tA/tlL8q7ceQNZHTjPeONt/3S7KRI4quk+yP9jK2WjBiPQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2551,18 +2595,18 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.53.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.0.tgz",
- "integrity": "sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==",
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.1.tgz",
+ "integrity": "sha512-ybe2hS9G6pXpqGtPli9Gx9quNV0TWLOmh58ADlmZe9DguLq0tiAKVjirSbtM1szG6+QH6rVXyU6GTLQbWnMY+g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.53.0",
- "@typescript-eslint/tsconfig-utils": "8.53.0",
- "@typescript-eslint/types": "8.53.0",
- "@typescript-eslint/visitor-keys": "8.53.0",
+ "@typescript-eslint/project-service": "8.57.1",
+ "@typescript-eslint/tsconfig-utils": "8.57.1",
+ "@typescript-eslint/types": "8.57.1",
+ "@typescript-eslint/visitor-keys": "8.57.1",
"debug": "^4.4.3",
- "minimatch": "^9.0.5",
+ "minimatch": "^10.2.2",
"semver": "^7.7.3",
"tinyglobby": "^0.2.15",
"ts-api-utils": "^2.4.0"
@@ -2579,16 +2623,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.53.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.0.tgz",
- "integrity": "sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==",
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.1.tgz",
+ "integrity": "sha512-XUNSJ/lEVFttPMMoDVA2r2bwrl8/oPx8cURtczkSEswY5T3AeLmCy+EKWQNdL4u0MmAHOjcWrqJp2cdvgjn8dQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.53.0",
- "@typescript-eslint/types": "8.53.0",
- "@typescript-eslint/typescript-estree": "8.53.0"
+ "@typescript-eslint/scope-manager": "8.57.1",
+ "@typescript-eslint/types": "8.57.1",
+ "@typescript-eslint/typescript-estree": "8.57.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2598,19 +2642,19 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.53.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.0.tgz",
- "integrity": "sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==",
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.1.tgz",
+ "integrity": "sha512-YWnmJkXbofiz9KbnbbwuA2rpGkFPLbAIetcCNO6mJ8gdhdZ/v7WDXsoGFAJuM6ikUFKTlSQnjWnVO4ux+UzS6A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.53.0",
- "eslint-visitor-keys": "^4.2.1"
+ "@typescript-eslint/types": "8.57.1",
+ "eslint-visitor-keys": "^5.0.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2621,13 +2665,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": "^20.19.0 || ^22.13.0 || >=24"
},
"funding": {
"url": "https://opencollective.com/eslint"
@@ -2661,21 +2705,6 @@
"dev": true,
"license": "CC-BY-4.0"
},
- "node_modules/@vscode/webview-ui-toolkit": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.0.1.tgz",
- "integrity": "sha512-jitA17enYUoMadv9exoHJiYcBK+X+gTlUyyIFvXRrA/mhHrxZfel5Eh6z/u57UZScK/i0Sn7EtlEYV1ZKFbeHw==",
- "deprecated": "This package has been deprecated, https://github.com/microsoft/vscode-webview-ui-toolkit/issues/561",
- "license": "MIT",
- "dependencies": {
- "@microsoft/fast-element": "^1.6.2",
- "@microsoft/fast-foundation": "^2.38.0",
- "@microsoft/fast-react-wrapper": "^0.1.18"
- },
- "peerDependencies": {
- "react": ">=16.9.0"
- }
- },
"node_modules/abab": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -2684,19 +2713,10 @@
"dev": true,
"license": "BSD-3-Clause"
},
- "node_modules/accessor-fn": {
- "version": "1.5.3",
- "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz",
- "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/acorn": {
- "version": "8.15.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
- "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"dev": true,
"license": "MIT",
"bin": {
@@ -2775,26 +2795,6 @@
"node": ">=0.4.0"
}
},
- "node_modules/ag-grid-community": {
- "version": "31.3.4",
- "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-31.3.4.tgz",
- "integrity": "sha512-jOxQO86C6eLnk1GdP24HB6aqaouFzMWizgfUwNY5MnetiWzz9ZaAmOGSnW/XBvdjXvC5Fpk3gSbvVKKQ7h9kBw==",
- "license": "MIT"
- },
- "node_modules/ag-grid-react": {
- "version": "31.3.4",
- "resolved": "https://registry.npmjs.org/ag-grid-react/-/ag-grid-react-31.3.4.tgz",
- "integrity": "sha512-WmPASHRFGSTxCMRStWG5bRtln0Ugsdqbb3+Y8sEyGHeLw4hXqfpqie3lT9kqCOl7wPWUjCpwmFdXzRnWPmyyeg==",
- "license": "MIT",
- "dependencies": {
- "ag-grid-community": "31.3.4",
- "prop-types": "^15.8.1"
- },
- "peerDependencies": {
- "react": "^16.3.0 || ^17.0.0 || ^18.0.0",
- "react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0"
- }
- },
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -2809,9 +2809,9 @@
}
},
"node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
+ "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2901,9 +2901,9 @@
}
},
"node_modules/asn1.js/node_modules/bn.js": {
- "version": "4.12.2",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz",
- "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==",
+ "version": "4.12.3",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz",
+ "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==",
"dev": true,
"license": "MIT"
},
@@ -3058,11 +3058,14 @@
}
},
"node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
},
"node_modules/base64-js": {
"version": "1.5.1",
@@ -3086,40 +3089,36 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
- "version": "2.9.14",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz",
- "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==",
+ "version": "2.10.9",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.9.tgz",
+ "integrity": "sha512-OZd0e2mU11ClX8+IdXe3r0dbqMEznRiT4TfbhYIbcRPZkqJ7Qwer8ij3GZAmLsRKa+II9V1v5czCkvmHH3XZBg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
- "baseline-browser-mapping": "dist/cli.js"
- }
- },
- "node_modules/bezier-js": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz",
- "integrity": "sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==",
- "license": "MIT",
- "funding": {
- "type": "individual",
- "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md"
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
}
},
"node_modules/bn.js": {
- "version": "5.2.2",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz",
- "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==",
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz",
+ "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==",
"dev": true,
"license": "MIT"
},
"node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
+ "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0"
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
}
},
"node_modules/braces": {
@@ -3504,9 +3503,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001764",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz",
- "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==",
+ "version": "1.0.30001780",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz",
+ "integrity": "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==",
"dev": true,
"funding": [
{
@@ -3524,18 +3523,6 @@
],
"license": "CC-BY-4.0"
},
- "node_modules/canvas-color-tracker": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.2.tgz",
- "integrity": "sha512-ryQkDX26yJ3CXzb3hxUVNlg1NKE4REc5crLBq661Nxzr8TNd236SaEf2ffYLXyI5tSABSeguHLqcVq4vf9L3Zg==",
- "license": "MIT",
- "dependencies": {
- "tinycolor2": "^1.6.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -3616,6 +3603,15 @@
"node": ">=12"
}
},
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -3810,9 +3806,9 @@
}
},
"node_modules/create-ecdh/node_modules/bn.js": {
- "version": "4.12.2",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz",
- "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==",
+ "version": "4.12.3",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz",
+ "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==",
"dev": true,
"license": "MIT"
},
@@ -3921,222 +3917,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/d3-array": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
- "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
- "license": "ISC",
- "dependencies": {
- "internmap": "1 - 2"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-binarytree": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz",
- "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==",
- "license": "MIT"
- },
- "node_modules/d3-color": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
- "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dispatch": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
- "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-drag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
- "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-selection": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-ease": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
- "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-force-3d": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz",
- "integrity": "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==",
- "license": "MIT",
- "dependencies": {
- "d3-binarytree": "1",
- "d3-dispatch": "1 - 3",
- "d3-octree": "1",
- "d3-quadtree": "1 - 3",
- "d3-timer": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-format": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
- "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-interpolate": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
- "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-octree": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz",
- "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==",
- "license": "MIT"
- },
- "node_modules/d3-quadtree": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
- "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-scale": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
- "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2.10.0 - 3",
- "d3-format": "1 - 3",
- "d3-interpolate": "1.2.0 - 3",
- "d3-time": "2.1.1 - 3",
- "d3-time-format": "2 - 4"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-scale-chromatic": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
- "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3",
- "d3-interpolate": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-selection": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
- "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
- "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time-format": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
- "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
- "license": "ISC",
- "dependencies": {
- "d3-time": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-timer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
- "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-transition": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
- "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3",
- "d3-dispatch": "1 - 3",
- "d3-ease": "1 - 3",
- "d3-interpolate": "1 - 3",
- "d3-timer": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "d3-selection": "2 - 3"
- }
- },
- "node_modules/d3-zoom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
- "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-drag": "2 - 3",
- "d3-interpolate": "1 - 3",
- "d3-selection": "2 - 3",
- "d3-transition": "2 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/dash-ast": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz",
@@ -4410,9 +4190,9 @@
}
},
"node_modules/diffie-hellman/node_modules/bn.js": {
- "version": "4.12.2",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz",
- "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==",
+ "version": "4.12.3",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz",
+ "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==",
"dev": true,
"license": "MIT"
},
@@ -4476,26 +4256,10 @@
"readable-stream": "^2.0.2"
}
},
- "node_modules/echarts": {
- "version": "5.6.0",
- "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.6.0.tgz",
- "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "2.3.0",
- "zrender": "5.6.1"
- }
- },
- "node_modules/echarts/node_modules/tslib": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
- "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
- "license": "0BSD"
- },
"node_modules/electron-to-chromium": {
- "version": "1.5.267",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
- "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
+ "version": "1.5.321",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.321.tgz",
+ "integrity": "sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ==",
"dev": true,
"license": "ISC"
},
@@ -4516,9 +4280,9 @@
}
},
"node_modules/elliptic/node_modules/bn.js": {
- "version": "4.12.2",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz",
- "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==",
+ "version": "4.12.3",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz",
+ "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==",
"dev": true,
"license": "MIT"
},
@@ -4689,25 +4453,25 @@
}
},
"node_modules/eslint": {
- "version": "9.39.2",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
- "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
+ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.21.1",
+ "@eslint/config-array": "^0.21.2",
"@eslint/config-helpers": "^0.4.2",
"@eslint/core": "^0.17.0",
- "@eslint/eslintrc": "^3.3.1",
- "@eslint/js": "9.39.2",
+ "@eslint/eslintrc": "^3.3.5",
+ "@eslint/js": "9.39.4",
"@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6",
- "ajv": "^6.12.4",
+ "ajv": "^6.14.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
@@ -4726,7 +4490,7 @@
"is-glob": "^4.0.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
+ "minimatch": "^3.1.5",
"natural-compare": "^1.4.0",
"optionator": "^0.9.3"
},
@@ -4797,10 +4561,17 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/eslint/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
+ "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4832,9 +4603,9 @@
}
},
"node_modules/eslint/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -4980,12 +4751,6 @@
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
- "node_modules/exenv-es6": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz",
- "integrity": "sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==",
- "license": "MIT"
- },
"node_modules/exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@@ -5108,26 +4873,12 @@
}
},
"node_modules/flatted": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
- "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
+ "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
"dev": true,
"license": "ISC"
},
- "node_modules/float-tooltip": {
- "version": "1.7.5",
- "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz",
- "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==",
- "license": "MIT",
- "dependencies": {
- "d3-selection": "2 - 3",
- "kapsule": "^1.16",
- "preact": "10"
- },
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/for-each": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
@@ -5144,32 +4895,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/force-graph": {
- "version": "1.51.0",
- "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.51.0.tgz",
- "integrity": "sha512-aTnihCmiMA0ItLJLCbrQYS9mzriopW24goFPgUnKAAmAlPogTSmFWqoBPMXzIfPb7bs04Hur5zEI4WYgLW3Sig==",
- "license": "MIT",
- "dependencies": {
- "@tweenjs/tween.js": "18 - 25",
- "accessor-fn": "1",
- "bezier-js": "3 - 6",
- "canvas-color-tracker": "^1.3",
- "d3-array": "1 - 3",
- "d3-drag": "2 - 3",
- "d3-force-3d": "2 - 3",
- "d3-scale": "1 - 4",
- "d3-scale-chromatic": "1 - 3",
- "d3-selection": "2 - 3",
- "d3-zoom": "2 - 3",
- "float-tooltip": "^1.7",
- "index-array-by": "1",
- "kapsule": "^1.16",
- "lodash-es": "4"
- },
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/form-data": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
@@ -5322,7 +5047,7 @@
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -5353,10 +5078,17 @@
"node": ">=10.13.0"
}
},
+ "node_modules/glob/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/glob/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
+ "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5365,9 +5097,9 @@
}
},
"node_modules/glob/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -5679,15 +5411,6 @@
"node": ">=0.8.19"
}
},
- "node_modules/index-array-by": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz",
- "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -5749,15 +5472,6 @@
"insert-module-globals": "bin/cmd.js"
}
},
- "node_modules/internmap": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
- "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/is-arguments": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
@@ -6041,15 +5755,6 @@
"node": ">=8"
}
},
- "node_modules/jerrypick": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/jerrypick/-/jerrypick-1.1.2.tgz",
- "integrity": "sha512-YKnxXEekXKzhpf7CLYA0A+oDP8V0OhICNCr5lv96FvSsDEmrb0GKM776JgQvHTMjr7DTTPEVv/1Ciaw0uEWzBA==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/jest": {
"version": "28.1.3",
"resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz",
@@ -6270,9 +5975,9 @@
}
},
"node_modules/jest-environment-jsdom/node_modules/@tootallnate/once": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
- "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz",
+ "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -6996,18 +6701,6 @@
"node": "*"
}
},
- "node_modules/kapsule": {
- "version": "1.16.3",
- "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz",
- "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==",
- "license": "MIT",
- "dependencies": {
- "lodash-es": "4"
- },
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -7087,18 +6780,12 @@
}
},
"node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"dev": true,
"license": "MIT"
},
- "node_modules/lodash-es": {
- "version": "4.17.22",
- "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz",
- "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==",
- "license": "MIT"
- },
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -7118,6 +6805,7 @@
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
@@ -7226,9 +6914,9 @@
}
},
"node_modules/miller-rabin/node_modules/bn.js": {
- "version": "4.12.2",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz",
- "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==",
+ "version": "4.12.3",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz",
+ "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==",
"dev": true,
"license": "MIT"
},
@@ -7280,16 +6968,16 @@
"license": "MIT"
},
"node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "version": "10.2.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
+ "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
"dev": true,
- "license": "ISC",
+ "license": "BlueOak-1.0.0",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "brace-expansion": "^5.0.2"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -7350,9 +7038,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "version": "3.3.12",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
+ "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
"dev": true,
"funding": [
{
@@ -7383,9 +7071,9 @@
"license": "MIT"
},
"node_modules/node-releases": {
- "version": "2.0.27",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
- "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+ "version": "2.0.36",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
+ "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==",
"dev": true,
"license": "MIT"
},
@@ -7419,15 +7107,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
@@ -7718,9 +7397,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -7820,9 +7499,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
- "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "version": "8.5.15",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
+ "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
"dev": true,
"funding": [
{
@@ -7840,7 +7519,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.11",
+ "nanoid": "^3.3.12",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -7848,16 +7527,6 @@
"node": "^10 || ^12 || >=14"
}
},
- "node_modules/preact": {
- "version": "10.28.2",
- "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.2.tgz",
- "integrity": "sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA==",
- "license": "MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/preact"
- }
- },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -7928,23 +7597,6 @@
"node": ">= 6"
}
},
- "node_modules/prop-types": {
- "version": "15.8.1",
- "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
- "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "license": "MIT",
- "dependencies": {
- "loose-envify": "^1.4.0",
- "object-assign": "^4.1.1",
- "react-is": "^16.13.1"
- }
- },
- "node_modules/prop-types/node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "license": "MIT"
- },
"node_modules/psl": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
@@ -7974,9 +7626,9 @@
}
},
"node_modules/public-encrypt/node_modules/bn.js": {
- "version": "4.12.2",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz",
- "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==",
+ "version": "4.12.3",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz",
+ "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==",
"dev": true,
"license": "MIT"
},
@@ -7991,9 +7643,9 @@
}
},
"node_modules/qs": {
- "version": "6.14.1",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
- "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
+ "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -8044,47 +7696,30 @@
}
},
"node_modules/react": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
- "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "loose-envify": "^1.1.0",
- "object-assign": "^4.1.1"
+ "loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
- "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
- "object-assign": "^4.1.1",
- "scheduler": "^0.20.2"
+ "scheduler": "^0.23.2"
},
"peerDependencies": {
- "react": "17.0.2"
- }
- },
- "node_modules/react-force-graph-2d": {
- "version": "1.24.4",
- "resolved": "https://registry.npmjs.org/react-force-graph-2d/-/react-force-graph-2d-1.24.4.tgz",
- "integrity": "sha512-TRJiS0wlOgcTmFm3RqX/FEGoNz1P/YdNMhN+ht02ZzDcaVXw7jsIXgrMLi9WJc5EzFi6DJvcI7x1iZvLsW+PTA==",
- "license": "MIT",
- "dependencies": {
- "force-graph": "1",
- "prop-types": "15",
- "react-kapsule": "2"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "react": "*"
+ "react": "^18.3.1"
}
},
"node_modules/react-is": {
@@ -8094,21 +7729,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/react-kapsule": {
- "version": "2.5.7",
- "resolved": "https://registry.npmjs.org/react-kapsule/-/react-kapsule-2.5.7.tgz",
- "integrity": "sha512-kifAF4ZPD77qZKc4CKLmozq6GY1sBzPEJTIJb0wWFK6HsePJatK3jXplZn2eeAt3x67CDozgi7/rO8fNQ/AL7A==",
- "license": "MIT",
- "dependencies": {
- "jerrypick": "^1.1.1"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "react": ">=16.13.1"
- }
- },
"node_modules/react-refresh": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
@@ -8291,9 +7911,9 @@
}
},
"node_modules/rollup": {
- "version": "4.55.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz",
- "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==",
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
+ "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8307,31 +7927,31 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.55.1",
- "@rollup/rollup-android-arm64": "4.55.1",
- "@rollup/rollup-darwin-arm64": "4.55.1",
- "@rollup/rollup-darwin-x64": "4.55.1",
- "@rollup/rollup-freebsd-arm64": "4.55.1",
- "@rollup/rollup-freebsd-x64": "4.55.1",
- "@rollup/rollup-linux-arm-gnueabihf": "4.55.1",
- "@rollup/rollup-linux-arm-musleabihf": "4.55.1",
- "@rollup/rollup-linux-arm64-gnu": "4.55.1",
- "@rollup/rollup-linux-arm64-musl": "4.55.1",
- "@rollup/rollup-linux-loong64-gnu": "4.55.1",
- "@rollup/rollup-linux-loong64-musl": "4.55.1",
- "@rollup/rollup-linux-ppc64-gnu": "4.55.1",
- "@rollup/rollup-linux-ppc64-musl": "4.55.1",
- "@rollup/rollup-linux-riscv64-gnu": "4.55.1",
- "@rollup/rollup-linux-riscv64-musl": "4.55.1",
- "@rollup/rollup-linux-s390x-gnu": "4.55.1",
- "@rollup/rollup-linux-x64-gnu": "4.55.1",
- "@rollup/rollup-linux-x64-musl": "4.55.1",
- "@rollup/rollup-openbsd-x64": "4.55.1",
- "@rollup/rollup-openharmony-arm64": "4.55.1",
- "@rollup/rollup-win32-arm64-msvc": "4.55.1",
- "@rollup/rollup-win32-ia32-msvc": "4.55.1",
- "@rollup/rollup-win32-x64-gnu": "4.55.1",
- "@rollup/rollup-win32-x64-msvc": "4.55.1",
+ "@rollup/rollup-android-arm-eabi": "4.59.0",
+ "@rollup/rollup-android-arm64": "4.59.0",
+ "@rollup/rollup-darwin-arm64": "4.59.0",
+ "@rollup/rollup-darwin-x64": "4.59.0",
+ "@rollup/rollup-freebsd-arm64": "4.59.0",
+ "@rollup/rollup-freebsd-x64": "4.59.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.59.0",
+ "@rollup/rollup-linux-arm64-musl": "4.59.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.59.0",
+ "@rollup/rollup-linux-loong64-musl": "4.59.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
+ "@rollup/rollup-linux-ppc64-musl": "4.59.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.59.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.59.0",
+ "@rollup/rollup-linux-x64-gnu": "4.59.0",
+ "@rollup/rollup-linux-x64-musl": "4.59.0",
+ "@rollup/rollup-openbsd-x64": "4.59.0",
+ "@rollup/rollup-openharmony-arm64": "4.59.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.59.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.59.0",
+ "@rollup/rollup-win32-x64-gnu": "4.59.0",
+ "@rollup/rollup-win32-x64-msvc": "4.59.0",
"fsevents": "~2.3.2"
}
},
@@ -8412,19 +8032,19 @@
}
},
"node_modules/scheduler": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
- "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "loose-envify": "^1.1.0",
- "object-assign": "^4.1.1"
+ "loose-envify": "^1.1.0"
}
},
"node_modules/semver": {
- "version": "7.7.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
- "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -8938,12 +8558,6 @@
"acorn-node": "^1.2.0"
}
},
- "node_modules/tabbable": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz",
- "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==",
- "license": "MIT"
- },
"node_modules/terminal-link": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
@@ -8976,10 +8590,17 @@
"node": ">=8"
}
},
+ "node_modules/test-exclude/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/test-exclude/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
+ "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8988,9 +8609,9 @@
}
},
"node_modules/test-exclude/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -9030,12 +8651,6 @@
"node": ">=0.6.0"
}
},
- "node_modules/tinycolor2": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
- "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
- "license": "MIT"
- },
"node_modules/tinyglobby": {
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
@@ -9072,9 +8687,9 @@
}
},
"node_modules/tinyglobby/node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -9166,9 +8781,9 @@
}
},
"node_modules/ts-api-utils": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
- "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
+ "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -9222,12 +8837,6 @@
}
}
},
- "node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
- "license": "0BSD"
- },
"node_modules/tty-browserify": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
@@ -9468,9 +9077,9 @@
"license": "MIT"
},
"node_modules/vite": {
- "version": "6.4.1",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
- "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
+ "version": "6.4.2",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz",
+ "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -9561,9 +9170,9 @@
}
},
"node_modules/vite/node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -9760,9 +9369,9 @@
}
},
"node_modules/ws": {
- "version": "8.19.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
- "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+ "version": "8.20.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
+ "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
"dev": true,
"license": "MIT",
"engines": {
@@ -9864,21 +9473,23 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/zrender": {
- "version": "5.6.1",
- "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.6.1.tgz",
- "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "tslib": "2.3.0"
+ "node_modules/zustand": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
+ "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.7.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ }
}
},
- "node_modules/zrender/node_modules/tslib": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
- "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
- "license": "0BSD"
- },
"packages/vscode-messenger": {
"version": "0.6.1",
"license": "MIT",
@@ -9897,12 +9508,10 @@
"version": "0.6.0",
"license": "MIT",
"dependencies": {
- "@vscode/webview-ui-toolkit": "~1.0.0",
"vscode-messenger": "^0.6"
},
"devDependencies": {
"@types/vscode": "^1.70.0",
- "@types/vscode-webview": "^1.57.0",
"concurrently": "^7.6.0",
"esbuild": "^0.25.0"
},
@@ -9910,22 +9519,74 @@
"vscode": "^1.70.0"
}
},
+ "packages/vscode-messenger-devtools/node_modules/baukasten-ui": {
+ "version": "0.3.0-next.027be66",
+ "resolved": "https://registry.npmjs.org/baukasten-ui/-/baukasten-ui-0.3.0-next.027be66.tgz",
+ "integrity": "sha512-Y4ta8bxlbuZiCPnQMrdal3pFzb51MUa5ag/z/55dsnsmaAM4al+fIe52aPfyODRL9AMrm7ktZyXmdJuJjE6yCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react": "^0.27.16",
+ "@vscode/codicons": "^0.0.41",
+ "clsx": "^2.1.1"
+ },
+ "peerDependencies": {
+ "@tanstack/react-table": "^8.21.3",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@tanstack/react-table": {
+ "optional": true
+ }
+ }
+ },
+ "packages/vscode-messenger-devtools/node_modules/baukasten-ui/node_modules/@vscode/codicons": {
+ "version": "0.0.41",
+ "resolved": "https://registry.npmjs.org/@vscode/codicons/-/codicons-0.0.41.tgz",
+ "integrity": "sha512-v6/8nx76zau3Joxjzi3eN/FVw+7jKBq4j7LTZY5FhFhq2g0OoFebZ3vRZbv/pUopGpbCnJJ4FOz+NzbjVsmoiw==",
+ "license": "CC-BY-4.0"
+ },
+ "packages/vscode-messenger-devtools/node_modules/react": {
+ "version": "19.2.6",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz",
+ "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "packages/vscode-messenger-devtools/node_modules/react-dom": {
+ "version": "19.2.6",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz",
+ "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.27.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.6"
+ }
+ },
+ "packages/vscode-messenger-devtools/node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
"packages/vscode-messenger-devtools/webview-ui": {
"name": "devtools-ui",
"version": "0.6.0",
"dependencies": {
- "@vscode/webview-ui-toolkit": "^1.0.0",
- "ag-grid-community": "~31.3.4",
- "ag-grid-react": "~31.3.4",
- "echarts": "^5.3.3",
- "react": "^17.0.0",
- "react-dom": "^17.0.0",
- "react-force-graph-2d": "~1.24.0",
- "vscode-messenger-webview": "~0.6.0"
+ "@tanstack/react-table": "~8.21.3",
+ "baukasten-ui": "0.3.0-next.027be66",
+ "react": "~19.2",
+ "react-dom": "~19.2",
+ "vscode-messenger-webview": "~0.6.0",
+ "zustand": "^3.7.2"
},
"devDependencies": {
- "@types/react": "^17.0.0",
- "@types/react-dom": "^17.0.0",
+ "@types/react": "~19.2",
+ "@types/react-dom": "~19.2",
"@types/vscode-webview": "^1.57.0",
"@vitejs/plugin-react": "^4.7.0",
"@vscode/codicons": "0.0.20",
diff --git a/packages/vscode-messenger-devtools/README.md b/packages/vscode-messenger-devtools/README.md
index 5a56cfe..d9f7a0d 100644
--- a/packages/vscode-messenger-devtools/README.md
+++ b/packages/vscode-messenger-devtools/README.md
@@ -1,29 +1,123 @@
# VS Code Messenger Developer Tool
-Shows messages sended between extension and registered extension webviews. Provides information about installed extensions that uses
-[vscode-messenger](https://github.com/TypeFox/vscode-messenger) library.
+Visualizes message traffic — requests, responses, and notifications — between a VS Code extension host and its registered webviews for extensions that use the [vscode-messenger](https://github.com/TypeFox/vscode-messenger) library. It is the fastest way to answer "is the message actually being sent?", "did the receiver get it?", and "what does the payload look like?" while developing or debugging.
-## Open Devtool View
+## Open the devtool view
-Open _Command Palette..._ (Shift + Cmd + P)
-Type _devtools_, execute command 'Developer: Open vscode-messenger devtools'
+Open the Command Palette (`Shift+Cmd+P` / `Ctrl+Shift+P`) and run **Developer: Open vscode-messenger devtools**.
-
+The devtool lists every installed extension that depends on `vscode-messenger`. Select yours to see its registered webviews, pending requests, registered handlers, and a live event log.
-**Note:** Your extension must export `Messenger.diagnosticApi()` as public API. Otherwise it is not possible to display relevant information.
+
+
+## Exposing the diagnostic API from your extension
+
+The devtool reads from the public API your `activate` function returns. Your extension must call `messenger.diagnosticApi()` and return the result — otherwise the devtool can see that your extension uses the library but cannot display any traffic.
```ts
import * as vscode from 'vscode';
-import { Messenger } from 'vscode-messenger';
+import { Messenger, type MessengerDiagnostic } from 'vscode-messenger';
const messenger = new Messenger();
-export function activate(context: vscode.ExtensionContext) {
+export function activate(context: vscode.ExtensionContext): MessengerDiagnostic {
// Your activation code...
return messenger.diagnosticApi();
}
```
-[Devtools Repository](https://github.com/TypeFox/vscode-messenger/tree/main/packages/vscode-messenger-devtools#readme)
+If your extension already exports a public API, spread the diagnostic methods into it:
+
+```ts
+export function activate(context: vscode.ExtensionContext) {
+ // Your activation code...
+ return {
+ ...yourApi,
+ ...messenger.diagnosticApi()
+ };
+}
+```
+
+The devtool checks `isMessengerDiagnostic(api)` against the returned object — it looks for `extensionInfo`, `addEventListener`, and `removeEventListener` on the value. Spreading preserves those.
+
+## `DiagnosticOptions`
+
+`diagnosticApi(options?)` accepts two optional flags. Both default to `false` to avoid leaking sensitive payload data to anything that can read your extension's public API.
+
+| Option | Default | Effect |
+|---|---|---|
+| `withParameterData` | `false` | Includes request/notification `params` as `MessengerEvent.parameter` in every event. |
+| `withResponseData` | `false` | Includes response `result` as `MessengerEvent.parameter` on `type: 'response'` events. |
+
+Enable both during development to see full payload values in the event details panel:
+
+```ts
+return messenger.diagnosticApi({ withParameterData: true, withResponseData: true });
+```
+
+## What the devtool shows
+
+The devtool calls `extensionInfo()` to populate the overview panel:
+
+- **webviews** — registered webview instances (`{ id, type }`)
+- **handlers** — registered message handlers (`{ method, count }`)
+- **pendingRequest** — count of in-flight requests
+- **diagnosticListeners** — count of active event subscribers
+
+It also subscribes via `addEventListener` to receive a `MessengerEvent` for every message that passes through the host-side `Messenger`:
+
+| Field | Description |
+|---|---|
+| `type` | `'request'`, `'response'`, `'notification'`, or `'unknown'` |
+| `id?` | Request id — set for requests and their matching responses |
+| `method?` | Message method name (absent on `response` events — correlate by `id`) |
+| `sender`, `receiver` | Stringified participants: `'host extension'`, `webviewId`, `webviewType`, or `'broadcast'` |
+| `parameter?` | Payload — only populated when `withParameterData` / `withResponseData` is enabled |
+| `error?` | Error message for failed responses |
+| `size` | Serialized payload byte-size estimate |
+| `timestamp` | `Date.now()` at the moment the event was emitted |
+
+## Customizing events before they reach the devtool
+
+You can wrap `addEventListener` to mutate events before any listener — including the devtool — sees them. A useful pattern is to decorate method names with their parameter values so the event timeline is easier to read:
+
+```ts
+export function activate(context: vscode.ExtensionContext): MessengerDiagnostic {
+ // Your activation code...
+
+ const diagnostics = messenger.diagnosticApi({
+ withParameterData: true,
+ withResponseData: true
+ });
+
+ return {
+ ...diagnostics,
+ addEventListener: (listener) => diagnostics.addEventListener(event => {
+ if (event.method === 'colorSelected') {
+ event.method = `colorSelected(${JSON.stringify(event.parameter)})`;
+ }
+ listener(event);
+ })
+ };
+}
+```
+
+The wrapper must still satisfy `isMessengerDiagnostic` — keep the original `extensionInfo` and `removeEventListener` on the returned object (the spread above handles this).
+
+## Troubleshooting
+
+**No row for my extension in the devtool**
+The devtool detected that your extension depends on `vscode-messenger` but `activate` either threw, returned `undefined`, or returned something where `isMessengerDiagnostic` is false. Confirm that `activate` returns the diagnostic object (or a spread that includes its three methods: `extensionInfo`, `addEventListener`, `removeEventListener`).
+
+**Extension is listed, but no events appear**
+`activate` returned the diagnostic API, but no traffic has been produced yet — trigger a message. Note that the host-side `Messenger` only observes host-side traffic; webview-internal processing does not produce events until a message is posted back to the host.
+
+**Events appear but `parameter` is always empty**
+`withParameterData` and `withResponseData` are both `false` by default. Pass `{ withParameterData: true, withResponseData: true }` to `diagnosticApi` in your dev build.
+
+**Events visible for one webview only**
+The diagnostic API observes only the `Messenger` instance you exposed. If your extension creates multiple `Messenger` instances (uncommon), each needs its own diagnostic export.
+
+---
-[Messenger Repository](https://github.com/TypeFox/vscode-messenger#readme)
+[Devtools Repository](https://github.com/TypeFox/vscode-messenger/tree/main/packages/vscode-messenger-devtools#readme) · [Messenger Repository](https://github.com/TypeFox/vscode-messenger#readme)
diff --git a/packages/vscode-messenger-devtools/media/view-screenshot.png b/packages/vscode-messenger-devtools/media/view-screenshot.png
index 5afda7a..8cb6833 100644
Binary files a/packages/vscode-messenger-devtools/media/view-screenshot.png and b/packages/vscode-messenger-devtools/media/view-screenshot.png differ
diff --git a/packages/vscode-messenger-devtools/package.json b/packages/vscode-messenger-devtools/package.json
index 35c1eaa..3eb0391 100644
--- a/packages/vscode-messenger-devtools/package.json
+++ b/packages/vscode-messenger-devtools/package.json
@@ -51,12 +51,10 @@
"test": "node ./lib/test/runTest.js"
},
"dependencies": {
- "@vscode/webview-ui-toolkit": "~1.0.0",
"vscode-messenger": "^0.6"
},
"devDependencies": {
"@types/vscode": "^1.70.0",
- "@types/vscode-webview": "^1.57.0",
"concurrently": "^7.6.0",
"esbuild": "^0.25.0"
},
diff --git a/packages/vscode-messenger-devtools/src/devtool-ext.ts b/packages/vscode-messenger-devtools/src/devtool-ext.ts
index 736030a..4c6cc92 100644
--- a/packages/vscode-messenger-devtools/src/devtool-ext.ts
+++ b/packages/vscode-messenger-devtools/src/devtool-ext.ts
@@ -4,31 +4,19 @@
* terms of the MIT License, which is available in the project root.
*/
-import * as vscode from 'vscode';
import * as path from 'path';
+import * as vscode from 'vscode';
import type { ExtensionInfo, MessengerDiagnostic, MessengerEvent } from 'vscode-messenger';
import { isMessengerDiagnostic, Messenger } from 'vscode-messenger';
+import type { WebviewTypeMessageParticipant } from 'vscode-messenger-common';
import { MessagesPanel, WEBVIEW_TYPE } from './panels/MessagesPanel';
-import type { NotificationType, RequestType, WebviewTypeMessageParticipant } from 'vscode-messenger-common';
+import { ExtensionListRequest, PushDataNotification } from './messenger-types';
const devtoolsView: WebviewTypeMessageParticipant = {
type: 'webview',
webviewType: WEBVIEW_TYPE
};
-type DataEvent = {
- extension: string;
- event: MessengerEvent;
-};
-
-const PushDataNotification: NotificationType = {
- method: 'pushData'
-};
-
-const ExtensionListRequest: RequestType = {
- method: 'extensionList'
-};
-
const msg = new Messenger({ debugLog: false });
const listeners = new Map();
let panel: vscode.WebviewPanel | undefined;
@@ -52,7 +40,7 @@ export function activate(context: vscode.ExtensionContext) {
active: ext.isActive,
exportsDiagnosticApi: supportedApi,
info: supportedApi ? getExtensionInfo(ext) : undefined
- } as ExtensionData;
+ };
});
});
@@ -90,13 +78,13 @@ export function activate(context: vscode.ExtensionContext) {
lastExportDirectory = path.dirname(uri.fsPath);
await vscode.workspace.fs.writeFile(uri, Buffer.from(params.content, 'utf8'));
vscode.window.showInformationMessage(`File exported: ${uri.fsPath}`);
- return true;
+ return 'success';
}
- return false;
+ return 'cancelled';
} catch (error) {
console.error('Error saving file:', error);
vscode.window.showErrorMessage(`Failed to save file: ${error}`);
- return false;
+ return 'error';
}
});
@@ -158,7 +146,6 @@ function listenToNotifications(messengerExts: Array>):
}
function listenToNotification(extension: vscode.Extension): void {
- console.debug(`Extension '${extension.id}' uses vscode-messenger. Extension active: ${extension.isActive}`);
const publicApi = diagnosticApi(extension);
if (publicApi && !listeners.has(extension.id)) {
const eventListener = (event: MessengerEvent) => {
@@ -177,11 +164,3 @@ function listenToNotification(extension: vscode.Extension): void {
}
}
-interface ExtensionData {
- id: string
- name: string
- active: boolean
- exportsDiagnosticApi: boolean
- info?: ExtensionInfo
- events?: MessengerEvent[]
-}
diff --git a/packages/vscode-messenger-devtools/src/messenger-types.ts b/packages/vscode-messenger-devtools/src/messenger-types.ts
new file mode 100644
index 0000000..6424496
--- /dev/null
+++ b/packages/vscode-messenger-devtools/src/messenger-types.ts
@@ -0,0 +1,23 @@
+import type { ExtensionInfo, MessengerEvent } from 'vscode-messenger';
+import type { NotificationType, RequestType } from 'vscode-messenger-common';
+
+export type DataEvent = {
+ extension: string;
+ event: MessengerEvent;
+};
+
+export const PushDataNotification: NotificationType = {
+ method: 'pushData'
+};
+
+export const ExtensionListRequest: RequestType = {
+ method: 'extensionList'
+};
+
+export interface ExtensionData {
+ id: string
+ name: string
+ active: boolean
+ exportsDiagnosticApi: boolean
+ info?: ExtensionInfo
+}
diff --git a/packages/vscode-messenger-devtools/webview-ui/css/devtools-view.css b/packages/vscode-messenger-devtools/webview-ui/css/devtools-view.css
index 59c2d54..df04786 100644
--- a/packages/vscode-messenger-devtools/webview-ui/css/devtools-view.css
+++ b/packages/vscode-messenger-devtools/webview-ui/css/devtools-view.css
@@ -34,7 +34,14 @@ html {
body {
height: 100%;
- --event-table-class: ag-theme-alpine
+ --event-table-class: ag-theme-alpine;
+
+ /* Shared message-type colors used by the data table rows (rowType_*)
+ and the messenger chart (.messenger-chart__bar). Override these to
+ re-skin the entire devtools UI in one place. */
+ --messenger-color-request: var(--vscode-textLink-foreground);
+ --messenger-color-response: var(--vscode-editorGutter-addedBackground);
+ --messenger-color-notification: var(--vscode-editorMarkerNavigationWarning-background);
}
body[data-vscode-theme-kind="vscode-dark"] {
@@ -66,6 +73,177 @@ body[data-vscode-theme-kind="vscode-dark"] {
#charts {
display: flex;
flex-direction: row;
+ align-items: flex-start;
+ gap: 12px;
+ padding: 8px 0 4px 0;
+}
+
+/* MessengerChart component */
+.messenger-chart {
+ position: relative;
+ flex: 1 1 0;
+ min-width: 0;
+ display: flex;
+ flex-direction: column;
+ font-family: var(--vscode-font-family);
+ font-size: var(--vscode-font-size);
+ color: var(--vscode-foreground);
+ background: color-mix(in srgb, var(--vscode-editor-background) 92%, transparent);
+ border: 1px solid var(--vscode-panel-border, color-mix(in srgb, var(--vscode-foreground) 12%, transparent));
+ border-radius: 8px;
+ padding: 12px 0 4px 0;
+ box-sizing: border-box;
+ z-index: 0;
+}
+
+.messenger-chart:hover {
+ z-index: 1;
+}
+
+.messenger-chart__title {
+ font-size: 11px;
+ font-weight: 600;
+ letter-spacing: 0.04em;
+ text-transform: uppercase;
+ color: var(--vscode-descriptionForeground, var(--vscode-foreground));
+ margin-bottom: 8px;
+ padding: 0 14px;
+ box-sizing: border-box;
+}
+
+.messenger-chart__legend {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+ margin-bottom: 10px;
+ padding: 0 14px;
+ box-sizing: border-box;
+}
+
+.messenger-chart__legend-item {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ font-size: 11px;
+ color: var(--vscode-descriptionForeground, var(--vscode-foreground));
+}
+
+.messenger-chart__legend-swatch {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ border-radius: 3px;
+ flex-shrink: 0;
+}
+
+.messenger-chart__legend-label {
+ text-transform: capitalize;
+}
+
+.messenger-chart__canvas {
+ position: relative;
+ flex: 1 1 auto;
+ min-width: 0;
+ overflow: hidden;
+ padding: 0 14px;
+ box-sizing: border-box;
+}
+
+.messenger-chart__svg {
+ display: block;
+ width: 100%;
+ height: 100%;
+ overflow: visible;
+ cursor: default;
+ user-select: none;
+}
+
+.messenger-chart__gridline {
+ stroke: var(--vscode-charts-lines, color-mix(in srgb, var(--vscode-foreground) 14%, transparent));
+ stroke-width: 1;
+ stroke-dasharray: 2 4;
+ shape-rendering: crispEdges;
+}
+
+.messenger-chart__tick-label,
+.messenger-chart__sender-label,
+.messenger-chart__value-label {
+ fill: var(--vscode-descriptionForeground, var(--vscode-foreground));
+ font-size: 10.5px;
+ font-family: var(--vscode-font-family);
+}
+
+.messenger-chart__sender-label {
+ fill: var(--vscode-foreground);
+ font-size: 11px;
+}
+
+.messenger-chart__value-label {
+ font-variant-numeric: tabular-nums;
+}
+
+.messenger-chart__track {
+ fill: color-mix(in srgb, var(--vscode-foreground) 6%, transparent);
+}
+
+.messenger-chart__bar {
+ transition: width 240ms cubic-bezier(0.2, 0.8, 0.2, 1),
+ x 240ms cubic-bezier(0.2, 0.8, 0.2, 1),
+ opacity 160ms ease;
+ cursor: default;
+}
+
+.messenger-chart__bar:hover {
+ opacity: 0.85;
+}
+
+.messenger-chart__empty {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 12px;
+ color: var(--vscode-descriptionForeground, var(--vscode-foreground));
+ opacity: 0.7;
+}
+
+.messenger-chart__tooltip {
+ position: absolute;
+ pointer-events: none;
+ background: var(--vscode-editorHoverWidget-background, var(--vscode-editor-background));
+ color: var(--vscode-editorHoverWidget-foreground, var(--vscode-foreground));
+ border: 1px solid var(--vscode-editorHoverWidget-border, var(--vscode-panel-border, transparent));
+ border-radius: 6px;
+ padding: 6px 8px;
+ font-size: 11px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
+ white-space: nowrap;
+ z-index: 100;
+ max-width: 280px;
+}
+
+.messenger-chart__tooltip-sender {
+ font-weight: 600;
+ margin-bottom: 4px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.messenger-chart__tooltip-row {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.messenger-chart__tooltip-type {
+ text-transform: capitalize;
+}
+
+.messenger-chart__tooltip-value {
+ margin-left: auto;
+ font-variant-numeric: tabular-nums;
+ font-weight: 600;
}
#diagram {
@@ -76,31 +254,29 @@ body[data-vscode-theme-kind="vscode-dark"] {
.refresh-button,
.export-json-button,
.export-csv-button,
-.clear-button {
+.trashcan-button {
margin-left: 4px;
margin-top: auto;
}
+/* unused */
.toggle-charts-button {
margin-left: auto;
margin-top: auto;
}
-span.info-param-name {
- margin-right: 10px;
-}
-
-.ext-info-badge {
- vertical-align: 'center';
- margin-right: 10px;
+span.codicon.codicon-pass,
+i.codicon.codicon-pass {
+ color: green;
}
-
-span.ext-info-badge.codicon.codicon-warning {
+span.codicon.codicon-warning,
+i.codicon.codicon-warning {
color: #eba800;
}
-span.ext-info-badge.codicon.codicon-stop {
+span.codicon.codicon-stop,
+i.codicon.codicon-stop {
color: #ec3f00;
}
@@ -110,25 +286,19 @@ span.table-cell.codicon.codicon-stop {
padding-left: 10px;
}
-span.ext-info-badge.codicon.codicon-pass {
- color: green;
-}
-/* Table row colors*/
+/* Table row colors - share variables with .messenger-chart bars */
div.rowType_request {
- color: var(--vscode-textLink-foreground)
- /* blue */
+ color: var(--messenger-color-request);
}
div.rowType_response {
- color: var(--vscode-editorGutter-addedBackground)
- /* green */
+ color: var(--messenger-color-response);
}
div.rowType_notification {
- color: var(--vscode-editorMarkerNavigationWarning-background)
- /* orange/braun */
+ color: var(--messenger-color-notification);
}
/* Graph
diff --git a/packages/vscode-messenger-devtools/webview-ui/package.json b/packages/vscode-messenger-devtools/webview-ui/package.json
index 9b93712..1e5d84e 100644
--- a/packages/vscode-messenger-devtools/webview-ui/package.json
+++ b/packages/vscode-messenger-devtools/webview-ui/package.json
@@ -6,24 +6,22 @@
"start": "vite",
"clean": "rimraf build",
"build": "tsc && vite build",
- "watch": "tsc -w & vite build --watch",
+ "watch": "tsc -w & vite build --watch --mode development",
"preview": "vite preview",
"lint": "eslint src"
},
"dependencies": {
- "@vscode/webview-ui-toolkit": "^1.0.0",
- "ag-grid-community": "~31.3.4",
- "ag-grid-react": "~31.3.4",
- "echarts": "^5.3.3",
- "react": "^17.0.0",
- "react-dom": "^17.0.0",
- "react-force-graph-2d": "~1.24.0",
- "vscode-messenger-webview": "~0.6.0"
+ "vscode-messenger-webview": "~0.6.0",
+ "baukasten-ui": "0.3.0-next.027be66",
+ "@tanstack/react-table": "~8.21.3",
+ "zustand": "^3.7.2",
+ "react": "~19.2",
+ "react-dom": "~19.2"
},
"devDependencies": {
- "@types/react": "^17.0.0",
- "@types/react-dom": "^17.0.0",
"@types/vscode-webview": "^1.57.0",
+ "@types/react": "~19.2",
+ "@types/react-dom": "~19.2",
"@vitejs/plugin-react": "^4.7.0",
"@vscode/codicons": "0.0.20",
"vite": "^6.4.1"
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/data-table.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/data-table.tsx
new file mode 100644
index 0000000..de9abaa
--- /dev/null
+++ b/packages/vscode-messenger-devtools/webview-ui/src/components/data-table.tsx
@@ -0,0 +1,133 @@
+import { type ColumnDef, DataTable, type DataTableProps, Tooltip } from 'baukasten-ui';
+import type { DataTableRef } from 'baukasten-ui/extra';
+import { forwardRef } from 'react';
+import type { ExtendedMessengerEvent } from '../model/messenger-types';
+import { useDevtoolsStore } from '../utilities/data-store';
+
+function renderPayloadInfo(payloadInfo: string) {
+ const newlineIdx = payloadInfo.indexOf('\n');
+ if (newlineIdx === -1) {
+ return {payloadInfo} ;
+ }
+ const label = payloadInfo.slice(0, newlineIdx);
+ const json = payloadInfo.slice(newlineIdx + 1);
+ return (
+
+ );
+}
+
+const columnsDef: Array> = [
+ {
+ accessorKey: 'type',
+ header: 'Type',
+ size: 110,
+ cell: ({ row, getValue }) => {
+ const data = row.original;
+ const rowType = data.type ?? 'unknown';
+ const error = data.error ? : undefined;
+ const content = {String(getValue())} {error}
;
+ return data.payloadInfo
+ ? {content}
+ : content;
+ },
+ },
+ {
+ accessorKey: 'sender',
+ header: 'Sender',
+ size: 180,
+ },
+ {
+ accessorKey: 'receiver',
+ header: 'Receiver',
+ size: 180,
+ },
+ {
+ accessorKey: 'method',
+ header: 'Method',
+ size: 135,
+ cell: ({ row, getValue }) => {
+ const value = String(getValue() ?? '');
+ return row.original.payloadInfo
+ ? {value}
+ : value;
+ },
+ },
+ {
+ accessorKey: 'size',
+ header: 'Size (Time)',
+ size: 135,
+ cell: ({ row }) => {
+ const event = row.original;
+ const charsCount = Intl.NumberFormat('en', { notation: 'compact' }).format(event.size);
+ let text = charsCount;
+ if (event.type === 'response' && typeof event.timeAfterRequest === 'number') {
+ const tookMs = event.timeAfterRequest % 1000;
+ const tookSec = Math.trunc(event.timeAfterRequest / 1000);
+ const secPart = (tookSec > 0) ? `${tookSec}s ` : '';
+ text = `${charsCount} (${secPart}${tookMs}ms)`;
+ }
+ return {text} ;
+ },
+ },
+ {
+ accessorKey: 'id',
+ header: 'ID',
+ },
+ {
+ accessorKey: 'timestamp',
+ header: 'Timestamp',
+ size: 135,
+ cell: ({ getValue }) => {
+ const time = getValue() as number;
+ if (typeof time === 'number') {
+ const date = new Date(time);
+ const prependZero = (n: number) => ('0' + n).slice(-2);
+ return `${prependZero(date.getHours())}:${prependZero(date.getMinutes())}:${prependZero(date.getSeconds())}-${('00' + date.getMilliseconds()).slice(-3)}`;
+ }
+ return String(time);
+ },
+ },
+ {
+ accessorKey: 'error',
+ header: 'Error',
+ },
+];
+
+export const EventTable = forwardRef>(
+ function EventTable(_, ref) {
+ const extensionId = useDevtoolsStore((state) => state.selectedExtension);
+ const selectedData = useDevtoolsStore((state) => state.getSelectedExtension());
+ const events = selectedData?.events ?? [];
+
+ const tableOptions: Partial> = {
+ enableSorting: true,
+ enableRowSelection: true,
+ enableColumnResizing: true,
+ fillHeight: true,
+ stickyHeader: true,
+ size: 'sm',
+ variant: 'zebra',
+ };
+
+ return (
+
+ );
+ }
+);
\ No newline at end of file
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/diagram.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/diagram.tsx
deleted file mode 100644
index d8e17ed..0000000
--- a/packages/vscode-messenger-devtools/webview-ui/src/components/diagram.tsx
+++ /dev/null
@@ -1,207 +0,0 @@
-import { useEffect, useRef, useState } from 'react';
-import type { ForceGraphMethods, GraphData, LinkObject, NodeObject } from 'react-force-graph-2d';
-import ForceGraph2D from 'react-force-graph-2d';
-import { HOST_EXTENSION_NAME } from '../devtools-view';
-
-type GraphObjectExtension = {
- name: string;
- value: number;
-}
-
-type ComponentNode = NodeObject & GraphObjectExtension & {
- shortName: string;
- outdated: boolean;
-}
-type ComponentLink = LinkObject & GraphObjectExtension
-
-let graphData: GraphData = { nodes: [], links: [] };
-
-let storedProps: DiagramProps = {
- extensionName: '',
- webviews: [],
- outdatedWebviews: [],
- doCenter: false
-};
-
-type WebviewInfo = {
- id: string
- type: string
-}
-
-type DiagramProps = {
- extensionName: string
- webviews: WebviewInfo[]
- outdatedWebviews: string[]
- doCenter: boolean
-}
-
-function createDiagramData(componentProps: DiagramProps): GraphData {
- if (!componentProps) {
- return graphData;
- }
- const toCompareString = (state: DiagramProps) =>
- `${state.extensionName} ${[...state.webviews.map(wv => wv.id), ...state.outdatedWebviews.map(wvId => '#' + wvId)].join(',')}`;
- if (toCompareString(storedProps) === toCompareString(componentProps)) {
- // same data, just return the existing graph data
- return graphData;
- }
- // reset graphData, store new state
- graphData = { nodes: [], links: [] };
-
- storedProps = componentProps;
-
- const unqualifiedName = (name: string) => name.split('.').pop();
-
- if (componentProps.extensionName) {
- graphData.nodes.push({
- id: HOST_EXTENSION_NAME,
- name: componentProps.extensionName,
- shortName: unqualifiedName(componentProps.extensionName),
- nodeLabel: 'Host',
- outdated: false,
- value: 10
- } as ComponentNode);
-
- }
-
- const createNodeAndLinks = (webview: WebviewInfo, outdated = false) => {
- const linkDist = outdated ? 30 : 40;
- graphData.nodes.push({
- id: webview.id,
- name: webview.type,
- shortName: unqualifiedName(webview.type),
- outdated,
- value: outdated ? 7 : 7,
- } as ComponentNode);
- // connect both ends to send particles both directions
- graphData.links.push({
- source: HOST_EXTENSION_NAME,
- target: webview.id,
- name: `${HOST_EXTENSION_NAME} to ${webview.id}`,
- value: linkDist
- } as ComponentLink);
- graphData.links.push({
- source: webview.id,
- target: HOST_EXTENSION_NAME,
- name: `${webview.id} to ${HOST_EXTENSION_NAME}`,
- value: linkDist
- } as ComponentLink);
- };
- componentProps.webviews.forEach(view => createNodeAndLinks(view));
- componentProps.outdatedWebviews.forEach(view =>
- createNodeAndLinks({ id: view, type: view }, true)
- );
- return graphData;
-}
-
-export type HighlightData = { link: string | string[], type: string }
-
-export let updateLinks: (update: HighlightData[]) => void = () => void 0;
-
-export function Diagram(props: DiagramProps): JSX.Element {
-
- const [highlightLinks, setHighlightLinks] = useState(Array());
- updateLinks = setHighlightLinks;
-
- function toParticleColor(type: string | undefined): string {
- switch (type) {
- case 'request': return '#0088ff';
- case 'response': return '#27ba10';
- case 'notification': return '#ebe809';
- default: return '';
- }
- }
- const diagramRef = useRef();
-
- useEffect(() => {
- setTimeout(() => {
- if (diagramRef.current && props.doCenter) {
- // set distance between nodes
- diagramRef.current.d3Force('link')?.distance((link: { value: number }) => link.value);
- // center diagram after diagram panel is shown
- diagramRef.current.zoomToFit(500, 50);
- }
- }, 150);
- }, [props.doCenter]);
-
- const graphData = createDiagramData(props);
- let particleSize = 0;
- let particleColor: string | undefined = undefined;
-
- useEffect(() => {
- highlightLinks.forEach((highlight, index) => {
- const initiateParticle = (linkStr: string) => {
- const linkObj = graphData.links.find(link => linkStr === linkId(link));
- if (linkObj) {
- setTimeout(() => {
- particleSize = 12;
- particleColor = toParticleColor(highlight.type);
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (linkObj as unknown as any).color = particleColor;
- diagramRef.current?.emitParticle(linkObj);
- }, index * 600);
- }
- };
- if (Array.isArray(highlight.link)) {
- // broadcast case
- highlight.link.forEach(initiateParticle);
- } else {
- initiateParticle(highlight.link);
- }
- });
- }, [highlightLinks]);
-
- return (link.target as NodeObject)?.id === HOST_EXTENSION_NAME ? 1 : 3}
- nodeCanvasObject={(rawNode, ctx, _globalScale) => {
- rawNode.vx = 10;
- rawNode.vy = 10;
- paintNode(rawNode, (rawNode as { color: string }).color, ctx);
- }}
- nodePointerAreaPaint={paintNode}
- />;
-
-}
-
-function linkId(link: LinkObject): string {
- return toLinkId((link.source as NodeObject).id, (link.target as NodeObject).id);
-}
-
-export function toLinkId(source: string | number | undefined, target: string | number | undefined): string {
- return `${source}->${target}`;
-}
-
-function paintNode(rawNode: NodeObject, color: string, ctx: CanvasRenderingContext2D) {
- const node = rawNode as NodeObject & ComponentNode;
- if (node.x && node.y) {
- ctx.fillStyle = color;
- ctx.beginPath();
- const radius = node.value;
- const circleData = { x: node.x, y: node.y, radius: node.outdated ? radius - 3 : radius };
- ctx.arc(circleData.x, circleData.y, circleData.radius, 0, 2 * Math.PI);
- ctx.fill();
- ctx.setLineDash([]);
- ctx.lineWidth = 0.3;
- ctx.strokeStyle = '#888888';
- ctx.stroke();
- ctx.closePath();
-
- if (node.outdated) {
- ctx.beginPath();
- ctx.setLineDash([1, 1]);
- ctx.strokeStyle = '#aabbbb';
- ctx.arc(circleData.x, circleData.y, circleData.radius + 1, 0, 2 * Math.PI);
- ctx.stroke();
- ctx.closePath();
- }
- }
-}
\ No newline at end of file
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/event-table.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/event-table.tsx
deleted file mode 100644
index 9cbf2e9..0000000
--- a/packages/vscode-messenger-devtools/webview-ui/src/components/event-table.tsx
+++ /dev/null
@@ -1,139 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { ColDef, GridApi } from 'ag-grid-community';
-import 'ag-grid-community/styles/ag-grid.css';
-import 'ag-grid-community/styles/ag-theme-alpine.css';
-import { AgGridReact } from 'ag-grid-react';
-import React from 'react';
-import type { MessengerEvent } from 'vscode-messenger';
-import type { ExtendedMessengerEvent } from '../devtools-view';
-
-const columnDefs: ColDef[] = [
- {
- field: 'type',
- initialWidth: 110,
- cellRenderer: (params: any) => {
- const rowType = params.data.type ?? 'unknown';
- const error = params.data.error ? : undefined;
- return {params.value} {error}
;
- },
- tooltipField: 'payloadInfo'
- },
- { field: 'sender', initialWidth: 180 },
- { field: 'receiver', initialWidth: 180 },
- {
- field: 'method', initialWidth: 135,
- tooltipField: 'payloadInfo'
- },
- {
- field: 'size', headerName: 'Size (Time)', initialWidth: 135,
- cellRenderer: (params: any) => {
- const event = (params.data as ExtendedMessengerEvent);
- const charsCount = Intl.NumberFormat('en', { notation: 'compact' }).format(event.size);
- if (event.type === 'response' && typeof event.timeAfterRequest === 'number') {
- const tookMs = event.timeAfterRequest % 1000;
- const tookSec = Math.trunc(event.timeAfterRequest / 1000);
- const secPart = (tookSec > 0) ? `${tookSec}s ` : '';
- return `${charsCount} (${secPart}${tookMs}ms)`;
- }
- return charsCount;
-
- }
- },
- { field: 'id' },
- {
- field: 'timestamp',
- initialWidth: 135,
- cellRenderer: (params: any) => {
- const time = params.data.timestamp;
- if (typeof time === 'number') {
- const date = new Date(time);
- const prependZero = (n: number) => ('0' + n).slice(-2);
- return `${prependZero(date.getHours())}:${prependZero(date.getMinutes())}:${prependZero(date.getSeconds())}-${('00' + date.getMilliseconds()).slice(-3)}`;
- }
- return String(time);
- }
- },
- { field: 'error' },
-];
-
-/**
- * Table that shows messages exchanged between the extension and the webviews.
- */
-export class EventTable extends React.Component {
-
- gridRefObj: React.RefObject>;
- props: { gridRowSelected: (e: any) => void };
-
- constructor(props: { gridRowSelected: (e: any) => void }) {
- super({});
- this.props = props;
- this.gridRefObj = React.createRef();
- }
-
- getGridApi(): GridApi | undefined {
- return this.gridRefObj.current?.api;
- }
-
- /**
- * Export grid data as JSON
- * @param onlySelected - if true, exports only selected rows
- * @returns JSON string of the grid data
- */
- exportAsJSON(onlySelected: boolean = false): string {
- const api = this.getGridApi();
- if (!api) return '[]';
-
- const rowData: any[] = [];
-
- if (onlySelected) {
- // Export only selected rows
- const selectedNodes = api.getSelectedNodes();
- selectedNodes.forEach(node => {
- if (node.data) {
- rowData.push(node.data);
- }
- });
- } else {
- // Export all rows (respecting current filter/sort)
- api.forEachNodeAfterFilterAndSort(node => {
- if (node.data) {
- rowData.push(node.data);
- }
- });
- }
-
- return JSON.stringify(rowData, null, 2);
- }
-
- render(): JSX.Element {
- return (
-
-
{
- return {
- filter: true, resizable: true, sortable: true,
- cellStyle: (params: any) => {
- if (params.value === 'Police') {
- return { color: 'red', backgroundColor: 'green' };
- }
- return null;
- },
- tooltipField: col.field,
- ...col
- };
- })}
- rowHeight={25}
- headerHeight={28}
- enableBrowserTooltips={true}
- rowSelection="multiple"
- onCellFocused={(e) => this.props.gridRowSelected(e)}
- onSelectionChanged={(e) => this.props.gridRowSelected(e)}
- >
-
-
- );
- }
-}
\ No newline at end of file
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/extension-info.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/extension-info.tsx
new file mode 100644
index 0000000..c4b140a
--- /dev/null
+++ b/packages/vscode-messenger-devtools/webview-ui/src/components/extension-info.tsx
@@ -0,0 +1,78 @@
+import type { CodiconName } from 'baukasten-ui';
+import { Badge, Icon, Text } from 'baukasten-ui';
+import React from 'react';
+import type { ExtendedExtensionData } from '../model/messenger-types';
+import { useDevtoolsStore } from '../utilities/data-store';
+
+interface ExtensionInfoPanelProps {
+ selectedExtensionProp?: ExtendedExtensionData;
+}
+
+export const ExtensionInfoPanel: React.FC = ({ selectedExtensionProp }) => {
+ const selectedExtension = selectedExtensionProp ?? useDevtoolsStore((state) => state.getSelectedExtension());
+ const statusData: OptionalInfoBadgeProps =
+ (selectedExtension) ?
+ {
+ icon: !selectedExtension?.active ? 'warning' : (!selectedExtension?.exportsDiagnosticApi ? 'stop' : 'pass'),
+ title:
+ 'Extension '
+ + (!selectedExtension?.active ? 'is not active' :
+ (!selectedExtension?.exportsDiagnosticApi ? "doesn't export diagnostic API"
+ : 'is active and exports diagnostic API.'))
+ }
+ : {
+ icon: 'question',
+ title: 'No extension selected'
+ };
+ const webviewsData = {
+ value: selectedExtension?.info?.webviews?.length ?? 0,
+ title: 'Registered views:\n' + (selectedExtension?.info?.webviews ?? []).map(entry => ' ' + entry.id)
+ .join('\n')
+ };
+ const handlersData = {
+ value: selectedExtension?.info?.handlers?.length ?? 0,
+ title: 'Number of added method handlers: \n'
+ + (selectedExtension?.info?.handlers ?? []).map(entry => ' ' + entry.method + ': ' + entry.count)
+ .join('\n')
+ };
+ return (
+ <>
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+type OptionalInfoBadgeProps = {
+ value?: string | number;
+ icon?: CodiconName;
+ title?: string;
+};
+
+function InfoBadge(props: { label: string } & OptionalInfoBadgeProps): React.JSX.Element {
+ // TODO move back to css file
+ const marginRight = { marginRight: '10px' };
+ return (<>
+ {props.label}
+ {props.icon &&
+
+ }
+ {props.value !== undefined &&
+
+ {props.value ?? '?'}
+
+ }
+ >);
+}
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/messenger-chart.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/messenger-chart.tsx
new file mode 100644
index 0000000..29ac496
--- /dev/null
+++ b/packages/vscode-messenger-devtools/webview-ui/src/components/messenger-chart.tsx
@@ -0,0 +1,444 @@
+import React, { useEffect, useId, useMemo, useRef, useState } from 'react';
+import type { MessengerEvent } from 'vscode-messenger';
+
+export type MessengerEventType = 'request' | 'response' | 'notification';
+
+export interface MessengerSenderStats {
+ sender: string;
+ count: Record;
+ size: Record;
+}
+
+export type ChartLayout = 'stacked' | 'grouped';
+export type ChartMetric = 'count' | 'size';
+
+export interface MessengerChartProps {
+ data: MessengerSenderStats[];
+ metric: ChartMetric;
+ layout?: ChartLayout;
+ title?: string;
+ /** Suffix appended to values in legend/tooltip, e.g. " chars". */
+ unitSuffix?: string;
+ /** Optional fixed SVG height. When omitted, height is derived from row count. */
+ height?: number;
+}
+
+const EVENT_TYPES: readonly MessengerEventType[] = ['request', 'response', 'notification'] as const;
+
+// Sourced from CSS custom properties defined on `body` in devtools-view.css.
+// The same variables drive the data table's rowType_* classes, so changing them
+// in one place updates both the table and the chart.
+const TYPE_COLORS: Record = {
+ request: 'var(--messenger-color-request, #3794ff)',
+ response: 'var(--messenger-color-response, #6cc063)',
+ notification: 'var(--messenger-color-notification, #d18616)'
+};
+
+const STACKED_BAR_HEIGHT = 22;
+const STACKED_ROW_GAP = 14;
+const GROUPED_BAR_HEIGHT = 9;
+const GROUPED_BAR_GAP = 2;
+const GROUPED_OUTER_GAP = 14;
+const TOP_PADDING = 8;
+const BOTTOM_PADDING = 20;
+const LEFT_GUTTER = 140;
+const RIGHT_PADDING = 56;
+const MIN_WIDTH = 280;
+const MAX_LABEL_CHARS = 18;
+
+const valueFormatter = new Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 1 });
+const fullFormatter = new Intl.NumberFormat('en');
+
+/**
+ * Aggregate raw messenger events into per-sender request/response/notification totals.
+ */
+export function collectSenderStats(events: MessengerEvent[]): MessengerSenderStats[] {
+ const map = new Map();
+ const ensure = (sender: string): MessengerSenderStats => {
+ let stats = map.get(sender);
+ if (!stats) {
+ stats = {
+ sender,
+ count: { request: 0, response: 0, notification: 0 },
+ size: { request: 0, response: 0, notification: 0 }
+ };
+ map.set(sender, stats);
+ }
+ return stats;
+ };
+
+ for (const event of events) {
+ const type = event.type as MessengerEventType;
+ if (type !== 'request' && type !== 'response' && type !== 'notification') continue;
+ const stats = ensure(event.sender ?? 'unknown');
+ stats.count[type] += 1;
+ stats.size[type] += event.size;
+ }
+
+ return Array.from(map.values()).sort((a, b) => a.sender.localeCompare(b.sender));
+}
+
+interface NiceScale { max: number; ticks: number[]; }
+
+function niceScale(rawMax: number, tickCount = 4): NiceScale {
+ if (rawMax <= 0) {
+ return { max: 1, ticks: [0, 1] };
+ }
+ const exp = Math.floor(Math.log10(rawMax));
+ const fraction = rawMax / Math.pow(10, exp);
+ let niceFraction: number;
+ if (fraction <= 1) niceFraction = 1;
+ else if (fraction <= 2) niceFraction = 2;
+ else if (fraction <= 5) niceFraction = 5;
+ else niceFraction = 10;
+ const niceMax = niceFraction * Math.pow(10, exp);
+ const step = niceMax / tickCount;
+ const ticks: number[] = [];
+ for (let i = 0; i <= tickCount; i++) ticks.push(step * i);
+ return { max: niceMax, ticks };
+}
+
+function truncate(value: string, max: number): string {
+ if (value.length <= max) return value;
+ const half = Math.floor((max - 1) / 2);
+ return value.slice(0, half) + '\u2026' + value.slice(value.length - (max - 1 - half));
+}
+
+interface TooltipState {
+ x: number;
+ y: number;
+ sender: string;
+ type: MessengerEventType;
+ value: number;
+}
+
+export function MessengerChart({
+ data,
+ metric,
+ layout = 'stacked',
+ title,
+ unitSuffix,
+ height
+}: MessengerChartProps): React.JSX.Element {
+ const containerRef = useRef(null);
+ const clipBaseId = useId();
+ const [width, setWidth] = useState(0);
+ const [tooltip, setTooltip] = useState(null);
+
+ useEffect(() => {
+ const el = containerRef.current;
+ if (!el) return;
+ const observer = new ResizeObserver(entries => {
+ for (const entry of entries) {
+ setWidth(entry.contentRect.width);
+ }
+ });
+ observer.observe(el);
+ setWidth(el.clientWidth);
+ return () => observer.disconnect();
+ }, []);
+
+ const senders = data;
+
+ const rawMax = useMemo(() => {
+ if (senders.length === 0) return 0;
+ if (layout === 'stacked') {
+ return senders.reduce((acc, s) => {
+ const total = EVENT_TYPES.reduce((sum, t) => sum + s[metric][t], 0);
+ return Math.max(acc, total);
+ }, 0);
+ }
+ return senders.reduce(
+ (acc, s) => EVENT_TYPES.reduce((sub, t) => Math.max(sub, s[metric][t]), acc),
+ 0
+ );
+ }, [senders, metric, layout]);
+
+ const scale = useMemo(() => niceScale(rawMax, 4), [rawMax]);
+
+ const computedRowsHeight = useMemo(() => {
+ if (senders.length === 0) return 60;
+ if (layout === 'stacked') {
+ return senders.length * (STACKED_BAR_HEIGHT + STACKED_ROW_GAP) - STACKED_ROW_GAP;
+ }
+ const groupHeight = GROUPED_BAR_HEIGHT * 3 + GROUPED_BAR_GAP * 2;
+ return senders.length * (groupHeight + GROUPED_OUTER_GAP) - GROUPED_OUTER_GAP;
+ }, [senders.length, layout]);
+
+ const svgHeight = height ?? (TOP_PADDING + computedRowsHeight + BOTTOM_PADDING);
+
+ const effectiveWidth = Math.max(MIN_WIDTH, width || MIN_WIDTH);
+ const chartWidth = Math.max(40, effectiveWidth - LEFT_GUTTER - RIGHT_PADDING);
+ const chartLeft = LEFT_GUTTER;
+ const chartRight = chartLeft + chartWidth;
+
+ const valueToX = (v: number): number =>
+ chartLeft + (scale.max === 0 ? 0 : (v / scale.max) * chartWidth);
+
+ const handleHover = (
+ sender: string,
+ type: MessengerEventType,
+ value: number,
+ event: React.MouseEvent
+ ): void => {
+ const rect = containerRef.current?.getBoundingClientRect();
+ if (!rect) return;
+ setTooltip({
+ x: event.clientX - rect.left,
+ y: event.clientY - rect.top,
+ sender,
+ type,
+ value
+ });
+ };
+ const handleLeave = (): void => setTooltip(null);
+
+ return (
+
+ {title &&
{title}
}
+
+ {EVENT_TYPES.map(type => (
+
+
+
+ {type}{unitSuffix ?? ''}
+
+
+ ))}
+
+
+ {senders.length === 0 ? (
+
No events yet
+ ) : (
+
+
+ {senders.map((s, idx) => {
+ const rowY = layout === 'stacked'
+ ? TOP_PADDING + idx * (STACKED_BAR_HEIGHT + STACKED_ROW_GAP)
+ : 0;
+ return (
+
+
+
+ );
+ })}
+
+
+ {scale.ticks.map((tick, i) => {
+ const x = valueToX(tick);
+ return (
+
+
+ {valueFormatter.format(tick)}
+
+ );
+ })}
+
+ {senders.map((s, idx) => (
+ layout === 'stacked'
+ ? renderStackedRow({
+ s, idx, metric, scale, chartLeft, chartWidth, chartRight,
+ clipId: `${clipBaseId}-row-${idx}`,
+ unitSuffix, onHover: handleHover, onLeave: handleLeave
+ })
+ : renderGroupedRow({
+ s, idx, metric, scale, chartLeft, chartWidth,
+ onHover: handleHover, onLeave: handleLeave
+ })
+ ))}
+
+ )}
+
+ {tooltip && (
+
+
{tooltip.sender}
+
+
+ {tooltip.type}
+
+ {fullFormatter.format(tooltip.value)}{unitSuffix ?? ''}
+
+
+
+ )}
+
+ );
+}
+
+interface StackedRowArgs {
+ s: MessengerSenderStats;
+ idx: number;
+ metric: ChartMetric;
+ scale: NiceScale;
+ chartLeft: number;
+ chartWidth: number;
+ chartRight: number;
+ clipId: string;
+ unitSuffix?: string;
+ onHover: (sender: string, type: MessengerEventType, value: number, e: React.MouseEvent) => void;
+ onLeave: () => void;
+}
+
+function renderStackedRow(args: StackedRowArgs): React.JSX.Element {
+ const { s, idx, metric, scale, chartLeft, chartWidth, chartRight, clipId, unitSuffix, onHover, onLeave } = args;
+ const rowY = TOP_PADDING + idx * (STACKED_BAR_HEIGHT + STACKED_ROW_GAP);
+ const total = EVENT_TYPES.reduce((sum, t) => sum + s[metric][t], 0);
+ let cursor = chartLeft;
+ return (
+
+
+ {truncate(s.sender, MAX_LABEL_CHARS)}
+
+
+
+ {EVENT_TYPES.map(type => {
+ const value = s[metric][type];
+ if (value <= 0) return null;
+ const segWidth = scale.max === 0 ? 0 : (value / scale.max) * chartWidth;
+ const x = cursor;
+ cursor += segWidth;
+ return (
+ onHover(s.sender, type, value, e)}
+ onMouseLeave={onLeave}
+ />
+ );
+ })}
+
+ {total > 0 && (
+ {valueFormatter.format(total)}{unitSuffix ?? ''}
+ )}
+
+ );
+}
+
+interface GroupedRowArgs {
+ s: MessengerSenderStats;
+ idx: number;
+ metric: ChartMetric;
+ scale: NiceScale;
+ chartLeft: number;
+ chartWidth: number;
+ onHover: (sender: string, type: MessengerEventType, value: number, e: React.MouseEvent) => void;
+ onLeave: () => void;
+}
+
+function renderGroupedRow(args: GroupedRowArgs): React.JSX.Element {
+ const { s, idx, metric, scale, chartLeft, chartWidth, onHover, onLeave } = args;
+ const groupHeight = GROUPED_BAR_HEIGHT * 3 + GROUPED_BAR_GAP * 2;
+ const groupY = TOP_PADDING + idx * (groupHeight + GROUPED_OUTER_GAP);
+ return (
+
+
+ {truncate(s.sender, MAX_LABEL_CHARS)}
+
+ {EVENT_TYPES.map((type, ti) => {
+ const value = s[metric][type];
+ const barY = groupY + ti * (GROUPED_BAR_HEIGHT + GROUPED_BAR_GAP);
+ const barWidth = scale.max === 0 ? 0 : (value / scale.max) * chartWidth;
+ return (
+
+
+ onHover(s.sender, type, value, e)}
+ onMouseLeave={onLeave}
+ />
+
+ );
+ })}
+
+ );
+}
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/react-echart.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/react-echart.tsx
deleted file mode 100644
index 85e7bfa..0000000
--- a/packages/vscode-messenger-devtools/webview-ui/src/components/react-echart.tsx
+++ /dev/null
@@ -1,169 +0,0 @@
-import type { ECharts, EChartsOption, SetOptionOpts } from 'echarts';
-import { getInstanceByDom, init } from 'echarts';
-import type { CSSProperties } from 'react';
-import { useEffect, useRef } from 'react';
-import type { MessengerEvent } from 'vscode-messenger';
-
-export interface ReactEChartsProps {
- option: EChartsOption;
- style?: CSSProperties;
- settings?: SetOptionOpts;
- loading?: boolean;
- theme?: 'light' | 'dark';
-}
-
-export type ChartData = Map;
-
-export function createOptions(charSeries: Array<{ name: string, data: number[] }>, yAxis: string[], legendFormat = '', theme?: 'light' | 'dark'): ReactEChartsProps['option'] {
- // Use VS Code theme colors for better integration
- // In dark theme, use a lighter gray; in light theme, use a darker gray for better contrast
- const legendTextColor = theme === 'dark' ? '#cccccc' : '#616161';
-
- const option: ReactEChartsProps['option'] = {
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow',
- },
- },
- legend: {
- orient: 'horizontal',
- formatter: `{name}${legendFormat}`,
- textStyle: {
- color: legendTextColor
- }
- },
- grid: {
- show: true,
- top: 30,
- left: 1,
- bottom: '2%',
- containLabel: true
- },
- xAxis: {
- type: 'value',
- boundaryGap: [0, 0.01]
- },
- yAxis: {
- type: 'category',
- data: yAxis
- },
- series: charSeries.map((chunk) => { return { ...chunk, type: 'bar' }; })
- };
- return option;
-}
-
-export function collectChartData(renderingData: MessengerEvent[]): { series: [Array<{ name: string, data: number[] }>, Array<{ name: string, data: number[] }>], senderY: string[] } {
- const chartData: ChartData = new Map();
- const charSeries: [Array<{ name: string, data: number[] }>, Array<{ name: string, data: number[] }>] = [[], []];
- renderingData.map(d => d.sender ?? 'unknown').filter((value, index, self) => self.indexOf(value) === index).sort().forEach((it) => {
- chartData.set(it, {
- notification: [0, 0],
- response: [0, 0],
- request: [0, 0]
- });
- });
-
- renderingData.forEach((entry) => {
- const value = chartData.get(entry.sender ?? 'unknown');
- if (value) {
- switch (entry.type) {
- case 'request':
- value.request[0] += entry.size;
- value.request[1] += 1;
- break;
- case 'response':
- value.response[0] += entry.size;
- value.response[1] += 1;
- break;
- case 'notification':
- value.notification[0] += entry.size;
- value.notification[1] += 1;
- break;
- }
- }
- });
- ['request', 'response', 'notification'].forEach(type => {
- const data = Array.from(chartData.values()).map(value => {
- if (type === 'request')
- return value.request;
- else if (type === 'response')
- return value.response;
- else if (type === 'notification')
- return value.notification;
- else
- return [0, 0];
- });
- charSeries[0].push({
- name: type,
- data: data.map(senderData => senderData[0])
- });
- charSeries[1].push({
- name: type,
- data: data.map(senderData => senderData[1])
- });
- });
- return { series: charSeries, senderY: Array.from(chartData.keys()) };
-}
-export function ReactECharts({
- option,
- style,
- settings,
- loading,
- theme
-}: ReactEChartsProps): JSX.Element {
- const chartRef = useRef(null);
-
- useEffect(() => {
- // Initialize chart
- let chart: ECharts | undefined;
- if (chartRef.current !== null) {
- chart = init(chartRef.current, theme);
- }
-
- // Add chart resize listener
- // ResizeObserver is leading to a bit janky UX
- function resizeChart() {
- chart?.resize();
- }
- window.addEventListener('resize', resizeChart);
-
- // Return cleanup function
- return () => {
- chart?.dispose();
- window.removeEventListener('resize', resizeChart);
- };
- }, [theme]);
-
- useEffect(() => {
- // Resize chart when shown
- let chart: ECharts | undefined;
- if (chartRef.current !== null) {
- chart = init(chartRef.current, theme);
- }
- chart?.resize();
- }, [option]); // Whenever theme changes we need to add option and setting due to it being deleted in cleanup function
-
- useEffect(() => {
- // Update chart
- if (chartRef.current !== null) {
- const chart = getInstanceByDom(chartRef.current);
- if (chart)
- chart.setOption(option, settings);
- }
- }, [option, settings, theme]); // Whenever theme changes we need to add option and setting due to it being deleted in cleanup function
-
- useEffect(() => {
- // Update chart
- if (chartRef.current !== null) {
- const chart = getInstanceByDom(chartRef.current);
- if (chart) {
- if (loading === true)
- chart.showLoading();
- else
- chart.hideLoading();
- }
- }
- }, [loading, theme]);
- return
;
-}
\ No newline at end of file
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/view-header.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/view-header.tsx
index 2d44629..58d40b8 100644
--- a/packages/vscode-messenger-devtools/webview-ui/src/components/view-header.tsx
+++ b/packages/vscode-messenger-devtools/webview-ui/src/components/view-header.tsx
@@ -1,52 +1,106 @@
-import { VSCodeButton, VSCodeDropdown, VSCodeOption } from '@vscode/webview-ui-toolkit/react';
-import type { MouseEventHandler } from 'react';
-import type { ExtensionData } from '../devtools-view';
+import type { CodiconName } from 'baukasten-ui';
+import { Select, Tooltip } from 'baukasten-ui';
+
+import { Icon, IconButton } from 'baukasten-ui/core';
+import React, { useEffect, type CSSProperties, type MouseEventHandler } from 'react';
+import { HOST_EXTENSION } from 'vscode-messenger-common';
+import type { Messenger } from 'vscode-messenger-webview';
+import { ExtensionListRequest, MESSENGER_EXTENSION_ID, type ExtensionData } from '../model/messenger-types';
+import { useDevtoolsStore } from '../utilities/data-store';
export function ViewHeader(props: {
- state: { selectedExtension: string | undefined; extensions: ExtensionData[]; },
+ messenger: Messenger
+ state: { selectedExtension: string | undefined; extensions: ExtensionData[] | undefined; },
onExtensionSelected: (extId: string) => void,
- onRefreshClicked: MouseEventHandler | undefined,
onClearClicked: (extId: string | undefined) => void,
+ onRefreshClicked: MouseEventHandler | undefined,
onToggleCharts: MouseEventHandler | undefined,
- onToggleDiagram: () => void,
onExportJSON?: () => void,
onExportCSV?: () => void,
-}): JSX.Element {
+}): React.JSX.Element {
+
+ const selectedExtensionId: string | undefined = props.state.selectedExtension ?? useDevtoolsStore((state) => state.selectedExtension);;
+
+ const loadedExtensions: ExtensionData[] = props.state.extensions ?? useDevtoolsStore((state) => state.getExtensions());
+ const updateExtensionData = useDevtoolsStore((state) => state.updateExtensionData);
+ const updateEvents = useDevtoolsStore((state) => state.updateEvents);
+ const updateSelectedExtension = useDevtoolsStore((state) => state.updateSelectedExtension);
+ const updateVisualization = useDevtoolsStore((state) => state.updateVisualizationSelect);
+
+ useEffect(() => {
+ // Initial load of extensions
+ (async () => {
+ const extensions = await props?.messenger?.sendRequest(ExtensionListRequest, HOST_EXTENSION, true);
+ if (!extensions) {
+ return;
+ }
+ updateExtensionData(extensions);
+ if (selectedExtensionId === '' && extensions.length > 0) {
+ // set first not vscode-messenger entry as selected extension
+ let extensionToPreset = extensions[0];
+ if (extensions.length > 1) {
+ extensionToPreset = extensions.find(ex => ex.id !== MESSENGER_EXTENSION_ID) ?? extensionToPreset;
+ }
+ if (extensionToPreset) {
+ updateSelectedExtension(extensionToPreset.id);
+ }
+ }
+ })();
+ }, []);
+
return (
-
+ >
+ );
+}
+
+function BIconButton(props: { icon: CodiconName, title: string, onClick: MouseEventHandler | undefined, sx?: CSSProperties }): React.JSX.Element {
+ return (
+ }
+ style={{ ...props.sx }}
+ variant='ghost' />
);
-}
\ No newline at end of file
+}
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/visualization.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/visualization.tsx
new file mode 100644
index 0000000..61d5bf6
--- /dev/null
+++ b/packages/vscode-messenger-devtools/webview-ui/src/components/visualization.tsx
@@ -0,0 +1,45 @@
+import React, { useEffect, useRef } from 'react';
+import { useDevtoolsStore } from '../utilities/data-store';
+import { collectSenderStats, MessengerChart } from './messenger-chart';
+
+export interface VisualizationComponentProps {
+ onNaturalHeightChange?: (height: number) => void;
+}
+
+export function VisualizationComponent({ onNaturalHeightChange }: VisualizationComponentProps): React.JSX.Element {
+ const showDiagram = useDevtoolsStore(state => state.diagramShown);
+ const showCharts = useDevtoolsStore(state => state.chartsShown);
+
+ const _selectedExtension = useDevtoolsStore(state => state.selectedExtension);
+ const selectedExt = useDevtoolsStore(state => state.datasetSrc.get(_selectedExtension));
+
+ const stats = collectSenderStats(selectedExt?.events ?? []);
+ const placeholderRef = useRef(null);
+
+ useEffect(() => {
+ const el = placeholderRef.current;
+ if (!el || !onNaturalHeightChange) return;
+ const observer = new ResizeObserver(() => {
+ onNaturalHeightChange(el.scrollHeight);
+ });
+ observer.observe(el);
+ return () => observer.disconnect();
+ }, [onNaturalHeightChange]);
+
+ return (
+
+ {/* Chart Components */}
+
+
+
+
+ {/* Diagram Components */}
+
+ {
+ showDiagram &&
+ Fancy diagram
+ }
+
+
+ );
+}
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/devtools-view.tsx b/packages/vscode-messenger-devtools/webview-ui/src/devtools-view.tsx
deleted file mode 100644
index e38752f..0000000
--- a/packages/vscode-messenger-devtools/webview-ui/src/devtools-view.tsx
+++ /dev/null
@@ -1,456 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import '@vscode/codicons/dist/codicon.css';
-import '@vscode/codicons/dist/codicon.ttf';
-import { VSCodeBadge } from '@vscode/webview-ui-toolkit/react';
-import React from 'react';
-import type { ExtensionInfo, MessengerEvent } from 'vscode-messenger';
-import type { NotificationType, RequestType } from 'vscode-messenger-common';
-import { BROADCAST, HOST_EXTENSION } from 'vscode-messenger-common';
-import { Messenger } from 'vscode-messenger-webview';
-import '../css/devtools-view.css';
-import type { HighlightData } from './components/diagram';
-import { Diagram, toLinkId, updateLinks } from './components/diagram';
-import { EventTable } from './components/event-table';
-import { ReactECharts, collectChartData, createOptions } from './components/react-echart';
-import { ViewHeader } from './components/view-header';
-import type { DevtoolsComponentState } from './utilities/view-state';
-import { restoreState, storeState, vsCodeApi, getVSCodeTheme } from './utilities/view-state';
-
-type DataEvent = {
- extension: string;
- event: MessengerEvent;
-};
-
-const PushDataNotification: NotificationType = {
- method: 'pushData'
-};
-
-const ExtensionListRequest: RequestType = {
- method: 'extensionList'
-};
-
-const SaveFileRequest: RequestType<{ filename: string; content: string; }, boolean> = {
- method: 'saveFile'
-};
-
-export interface ExtensionData {
- id: string
- name: string
- active: boolean
- exportsDiagnosticApi: boolean
- info?: ExtensionInfo
- events: ExtendedMessengerEvent[]
-}
-export interface ExtendedMessengerEvent extends MessengerEvent {
- timeAfterRequest?: number
- payloadInfo?: string
-}
-
-const MESSENGER_EXTENSION_ID = 'TypeFox.vscode-messenger-devtools';
-export const HOST_EXTENSION_NAME = 'host extension';
-
-class DevtoolsComponent extends React.Component, DevtoolsComponentState> {
-
- messenger: Messenger;
- eventTable: EventTable;
- private themeObserver: MutationObserver | null = null;
-
- constructor() {
- super({});
- const storedState = restoreState();
- this.state = {
- selectedExtension: storedState?.selectedExtension ?? '',
- datasetSrc: storedState?.datasetSrc ? new Map() : new Map(),
- chartsShown: storedState?.chartsShown ?? false,
- diagramShown: storedState?.diagramShown ?? false,
- theme: storedState?.theme ?? getVSCodeTheme()
- };
- this.eventTable = new EventTable({ gridRowSelected: (e) => this.gridRowSelected(e) });
- this.messenger = new Messenger(vsCodeApi, { debugLog: true });
- this.messenger.onNotification(PushDataNotification, event => this.handleDataPush(event));
- this.messenger.start();
- this.fillExtensionsList(false).then(() => {
- if (this.state.selectedExtension === '' && this.state.datasetSrc.size > 0) {
- // set first not vscode-messenger entry as selected extension
- let extensionToPreset = this.state.datasetSrc.keys().next().value;
- if (this.state.datasetSrc.size > 1) {
- extensionToPreset = Array.from(this.state.datasetSrc.keys()).filter(key => key !== MESSENGER_EXTENSION_ID)[0] ?? extensionToPreset;
- }
- if (extensionToPreset) {
- this.updateState({ ...this.state, selectedExtension: extensionToPreset }, true);
- }
- } else {
- this.updateState(this.state, true);
- }
- return;
- }).catch(err => console.error(err));
-
- // Set up theme change observer
- this.setupThemeObserver();
- }
-
- componentWillUnmount() {
- // Clean up theme observer
- if (this.themeObserver) {
- this.themeObserver.disconnect();
- this.themeObserver = null;
- }
- }
-
- private setupThemeObserver() {
- // Watch for changes to the data-vscode-theme-kind attribute
- this.themeObserver = new MutationObserver((mutations) => {
- mutations.forEach((mutation) => {
- if (mutation.type === 'attributes' && mutation.attributeName === 'data-vscode-theme-kind') {
- const newTheme = getVSCodeTheme();
- if (newTheme !== this.state.theme) {
- // Update state with new theme - this will trigger chart re-render
- // and table will automatically pick up new CSS theme class
- this.updateState({ ...this.state, theme: newTheme }, true);
- }
- }
- });
- });
-
- // Start observing
- this.themeObserver.observe(document.body, {
- attributes: true,
- attributeFilter: ['data-vscode-theme-kind']
- });
-
- }
-
- render() {
- const theme = this.state.theme;
- const charSeries = collectChartData(this.selectedExtensionData()?.events ?? []);
- const optionSize = createOptions(charSeries.series[0], charSeries.senderY, ' (chars)', theme);
- const optionCount = createOptions(charSeries.series[1], charSeries.senderY, '', theme);
-
- const selectedExt = this.selectedExtensionData();
- const updateState = (selectedId: string) => {
- this.updateState({ ...this.state, selectedExtension: selectedId }, true);
- };
-
- const headerToggleDiagram = () => {
- this.updateState({ ...this.state, diagramShown: !this.state.diagramShown, chartsShown: false }, false);
- const diagramDiv = document.getElementById('diagram');
- if (diagramDiv) {
- if (diagramDiv.style.display === 'none') {
- diagramDiv.style.display = 'flex';
- diagramDiv.style.visibility = 'visible';
- if (updateLinks)
- updateLinks([]);
- } else {
- diagramDiv.style.display = 'none';
- diagramDiv.style.visibility = 'hidden';
- }
- }
- };
- const onToggleCharts =
- () => {
- this.updateState({ ...this.state, chartsShown: !this.state.chartsShown, diagramShown: false }, false);
- const chartsDiv = document.getElementById('charts');
- if (chartsDiv) {
- if (chartsDiv.style.display === 'none') {
- chartsDiv.style.display = 'flex';
- chartsDiv.style.visibility = 'visible';
- optionCount.animation = true; // triggers chats resize
- } else {
- chartsDiv.style.display = 'none';
- chartsDiv.style.visibility = 'hidden';
- optionCount.animation = false;
- }
- }
- };
-
- function collectOutdatedViews(selectedExt: ExtensionData | undefined): string[] {
- if (!selectedExt) return [];
- const unknownViews = new Set();
- const isKnown = (id: string): boolean => {
- if (id === BROADCAST.type || id === HOST_EXTENSION_NAME) {
- return true;
- }
- return selectedExt.info?.webviews.findIndex(view => view.id === id || view.type === id) !== -1;
- };
- selectedExt.events.forEach(event => {
- if (!isKnown(event.sender!)) {
- unknownViews.add(event.sender!);
- }
- if (!isKnown(event.receiver)) {
- unknownViews.add(event.receiver);
- }
- });
- return Array.from(unknownViews);
- }
-
- return (
- <>
- updateState(extId)}
- onRefreshClicked={() => this.fillExtensionsList(true)}
- onClearClicked={async (extId: string | undefined) => await this.clearExtensionData(extId)}
- onToggleDiagram={headerToggleDiagram}
- onToggleCharts={onToggleCharts}
- onExportJSON={() => this.exportTableData('json')}
- onExportCSV={() => this.exportTableData('csv')}
- />
-
- Status:
-
-
- Views:
- ' ' + entry.id).join('\n')
- }>{selectedExt?.info?.webviews.length ?? 0}
-
- Listeners:
- {selectedExt?.info?.diagnosticListeners ?? 0}
-
- Handlers:
- ' ' + entry.method + ': ' + entry.count).join('\n')
- }>{Array.from(selectedExt?.info?.handlers?.values() ?? []).length}
- Pending Req.:
- {selectedExt?.info?.pendingRequest ?? 0}
-
- Events:
- {selectedExt?.events.length ?? 0}
-
-
- {/* Table Component */}
- {this.eventTable.render()}
-
- {/* Chart Components */}
-
-
-
-
-
- {
- this.state.diagramShown &&
-
- }
-
- >
- );
- }
-
- private handleDataPush(dataEvent: DataEvent & { event: ExtendedMessengerEvent }): void {
- if (!this.state.datasetSrc.has(dataEvent.extension)) {
- this.updateExtensionData({ id: dataEvent.extension, name: '', active: true, exportsDiagnosticApi: true, events: [] });
- }
- const extensionData = this.state.datasetSrc.get(dataEvent.extension)!;
-
- const highlight: HighlightData[] = [];
- const isResponse = dataEvent.event.type === 'response';
- if (isResponse && dataEvent.event.timestamp) {
- // Take max 200 entries to look-up
- const request = extensionData.events.slice(0, 200).find(event => event.type === 'request' && event.id === dataEvent.event.id);
- if (request && request.timestamp) {
- dataEvent.event.timeAfterRequest = dataEvent.event.timestamp - request.timestamp;
- highlight.push({ link: toLinkId(dataEvent.event.receiver, dataEvent.event.sender), type: 'request' });
- }
- }
-
- if (dataEvent.event.parameter) {
- dataEvent.event.payloadInfo = `${isResponse ? 'Response' : 'Parameter'} (max 500 chars):\n ${JSON.stringify(dataEvent.event.parameter, undefined, ' ').substring(0, 499)}`;
- } else {
- dataEvent.event.payloadInfo = 'Payload information is empty or suppressed using diagnostic API options.';
- }
-
- extensionData.events.unshift(dataEvent.event);
-
- highlight.push(...this.createHighlightData(extensionData, dataEvent.event));
- this.updateDiagramEventHighlight(...highlight);
-
- this.updateState(this.state, this.state.selectedExtension === dataEvent.extension);
- }
-
- updateDiagramEventHighlight(...highlights: HighlightData[]): void {
- if (updateLinks) {
- updateLinks(highlights);
- }
- }
-
- createHighlightData(extensionData: ExtensionData, msgEvent: ExtendedMessengerEvent): HighlightData[] {
- const viewsByType = extensionData.info?.webviews.filter(view => msgEvent.receiver === BROADCAST.type || view.type === msgEvent.receiver) ?? [];
- if (viewsByType.length > 0) {
- if (msgEvent.receiver === BROADCAST.type) {
- // for broadcast, events first send event to the extension host. Then the host sends the event to all webviews.
- return [
- { link: toLinkId(msgEvent.sender, HOST_EXTENSION_NAME), type: msgEvent.type },
- {
- link: viewsByType.map(targetView => toLinkId(HOST_EXTENSION_NAME, targetView.id)), type: msgEvent.type
- }
-
- ];
- }
- // webview type receiver
- return viewsByType.map(view => { return { link: toLinkId(msgEvent.sender, view.id), type: msgEvent.type }; });
- } else {
- return [{ link: toLinkId(msgEvent.sender, msgEvent.receiver), type: msgEvent.type }];
- }
- }
-
- updateState(newState: DevtoolsComponentState, refreshTable: boolean) {
- this.setState(newState, () => {
- // Callback after `this.state`was updated
- storeState(this.state);
- if (refreshTable) {
- // refresh table
- this.eventTable.getGridApi()?.setRowData(this.selectedExtensionData()?.events ?? []);
- }
- });
- }
-
- selectedExtensionData(): ExtensionData | undefined {
- return this.state.datasetSrc.get(this.state.selectedExtension);
- }
-
- async fillExtensionsList(refresh: boolean): Promise {
- const extensions = await this.messenger.sendRequest(ExtensionListRequest, HOST_EXTENSION, refresh);
- extensions.forEach(ext => this.updateExtensionData(ext));
- this.updateState(this.state, true);
- }
-
- async clearExtensionData(extensionId: string | undefined): Promise {
- if (!extensionId) {
- return;
- }
- const extData = this.state.datasetSrc.get(extensionId);
- if (extData) {
- extData.events = [];
- this.updateState(this.state, true);
- }
- }
-
- updateExtensionData(ext: ExtensionData) {
- const data = this.state.datasetSrc;
- if (!data.has(ext.id)) {
- data.set(ext.id, { ...ext, events: [] }); // received ExtensionData don't have events
- } else {
- const existing = data.get(ext.id);
- // merge data
- data.set(ext.id, { ...ext, events: existing?.events ?? [] });
- }
- }
-
- exportTableData(format: 'json' | 'csv'): void {
- const api = this.eventTable.getGridApi();
- if (!api) {
- console.warn('Grid API not available for export');
- return;
- }
-
- const selectedExtension = this.selectedExtensionData();
- const extensionName = selectedExtension?.id || 'messenger-events';
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
- const filename = `${extensionName}-${timestamp}`;
-
- try {
- const dataToExport = api.getSelectedNodes().length > 0 ? api.getSelectedRows() : selectedExtension?.events ?? [];
- if (format === 'json') {
- const jsonData = JSON.stringify(dataToExport, null, 2);
- this.saveFileViaVSCode(`${filename}.json`, jsonData);
- } else if (format === 'csv') {
- const csvData = this.toCsv(dataToExport);
- this.saveFileViaVSCode(`${filename}.csv`, csvData);
- }
- } catch (error) {
- console.error(`Failed to export as ${format}:`, error);
- }
- }
-
- private toCsv(dataToExport: MessengerEvent[]) {
- if (dataToExport.length === 0) {
- return '';
- }
-
- // Define headers based on MessengerEvent/ExtendedMessengerEvent properties
- const headers = ['id', 'type', 'sender', 'receiver', 'method', 'error', 'size', 'timestamp', 'parameter', 'timeAfterRequest', 'payloadInfo'];
-
- const escapeCSVValue = (value: any): string => {
- if (value === null || value === undefined) {
- return '';
- }
-
- let stringValue: string;
- if (typeof value === 'object') {
- try {
- stringValue = JSON.stringify(value);
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- } catch (_error) {
- stringValue = String(value);
- }
- } else {
- stringValue = String(value);
- }
-
- // If value contains comma, newline, or double quote, wrap in quotes and escape internal quotes
- if (stringValue.includes(',') || stringValue.includes('\n') || stringValue.includes('\r') || stringValue.includes('"')) {
- return `"${stringValue.replace(/"/g, '""')}"`;
- }
-
- return stringValue;
- };
-
- const rows = dataToExport.map(event => {
- const extendedEvent = event as ExtendedMessengerEvent;
- return headers.map(header =>
- escapeCSVValue((extendedEvent as any)[header])
- ).join(',');
- });
-
- return [headers.join(','), ...rows].join('\n');
- }
-
- private async saveFileViaVSCode(filename: string, content: string): Promise {
- try {
- const success = await this.messenger.sendRequest(SaveFileRequest, HOST_EXTENSION, { filename, content });
- if (!success) {
- console.error('File save failed');
- }
- } catch (error) {
- console.error('Error saving file via VS Code API:', error);
- }
- }
-
- gridRowSelected(event: any): void {
- const selectedExt = this.selectedExtensionData();
- if (!selectedExt) return;
-
- // Handle both CellFocusedEvent and SelectionChangedEvent
- if (event.type === 'selectionChanged') {
- // Handle row selection change - highlight the first selected row
- const selectedNodes = event.api.getSelectedNodes();
- if (selectedNodes.length > 0 && selectedNodes[0].data) {
- this.updateDiagramEventHighlight(...this.createHighlightData(selectedExt, selectedNodes[0].data));
- }
- } else if (event.rowIndex !== null && event.rowIndex !== undefined) {
- // Handle cell focus
- const row = event.api.getDisplayedRowAtIndex(event.rowIndex);
- if (row?.data) {
- this.updateDiagramEventHighlight(...this.createHighlightData(selectedExt, row.data));
- }
- }
- }
-}
-
-export default DevtoolsComponent;
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/index.tsx b/packages/vscode-messenger-devtools/webview-ui/src/index.tsx
index bce8bf4..80b38ec 100644
--- a/packages/vscode-messenger-devtools/webview-ui/src/index.tsx
+++ b/packages/vscode-messenger-devtools/webview-ui/src/index.tsx
@@ -1,10 +1,12 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import DevtoolsComponent from './devtools-view';
+import { SplitPane } from 'baukasten-ui';
+import { createRoot } from 'react-dom/client';
+import { MessengerView } from './messenger-view';
-ReactDOM.render(
-
-
- ,
- document.getElementById('root')
+const root = createRoot(document.getElementById('root')!);
+root.render(
+
+
+
+
+
);
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/messenger-view.tsx b/packages/vscode-messenger-devtools/webview-ui/src/messenger-view.tsx
new file mode 100644
index 0000000..7610dbd
--- /dev/null
+++ b/packages/vscode-messenger-devtools/webview-ui/src/messenger-view.tsx
@@ -0,0 +1,111 @@
+import { Pane, SplitPane } from 'baukasten-ui';
+import type { DataTableRef } from 'baukasten-ui/extra';
+import 'baukasten-ui/dist/baukasten-base.css';
+import 'baukasten-ui/dist/baukasten-vscode.css';
+import React, { useRef } from 'react';
+import { Messenger } from 'vscode-messenger-webview';
+import '../css/devtools-view.css';
+import { EventTable } from './components/data-table';
+import type { ExtendedMessengerEvent } from './model/messenger-types';
+import { ExtensionInfoPanel } from './components/extension-info';
+import { ViewHeader } from './components/view-header';
+import { VisualizationComponent } from './components/visualization';
+import type { DataEvent } from './model/messenger-types';
+import { PushDataNotification } from './model/messenger-types';
+import { useDevtoolsStore } from './utilities/data-store';
+import { vsCodeApi } from './utilities/view-state';
+import { TableDataExporter } from './utilities/table-data-export';
+
+const messenger = new Messenger(vsCodeApi, { debugLog: true });
+messenger.start();
+
+const tableExport = new TableDataExporter(messenger);
+
+export function MessengerView(): React.JSX.Element {
+
+ const tableRef = useRef>(null);
+ const [vizHeight, setVizHeight] = React.useState(200);
+
+ const updateEvents = useDevtoolsStore((state) => state.updateEvents);
+ const updateExtensionData = useDevtoolsStore((state) => state.updateExtensionData);
+ const loadedExtensions = useDevtoolsStore(state => state.getExtensions());
+ const showDiagram = useDevtoolsStore(state => state.diagramShown);
+ const showCharts = useDevtoolsStore(state => state.chartsShown);
+
+ messenger.onNotification(PushDataNotification, event => {
+ const extension = loadedExtensions.find(ext => ext.id === event.extension);
+ if (extension) {
+ const processedEvent = processDataEvent(event, extension.events);
+ updateEvents(extension.id, [processedEvent, ...extension.events]);
+ } else {
+ // Unknown extension
+ updateExtensionData([{
+ id: event.extension, name: '',
+ active: true,
+ exportsDiagnosticApi: true
+ }]);
+ const processedEvent = processDataEvent(event, []);
+ updateEvents(event.extension, [processedEvent]);
+ console.debug('Received data for unknown extension: ', event.extension);
+ }
+ });
+
+ function exportTableData(format: 'json' | 'csv') {
+ const state = useDevtoolsStore.getState();
+ const selectedExtensionData = state.getSelectedExtension();
+ const allEvents = selectedExtensionData?.events ?? [];
+ const selectedEvents = tableRef.current?.getSelectedRows() ?? [];
+ tableExport.exportTableData(allEvents, selectedEvents, state.selectedExtension, format);
+ }
+ return
+
+ {/* Header Control Component */}
+ { }}
+ onRefreshClicked={async () => { }}
+ onClearClicked={async (extId: string | undefined) => {
+ const id = extId ?? useDevtoolsStore.getState().selectedExtension;
+ if (id) {
+ updateEvents(id, []);
+ }
+ }}
+ onToggleCharts={() => { }}
+ onExportJSON={() => exportTableData('json')}
+ onExportCSV={() => exportTableData('csv')}
+ messenger={messenger}
+ />
+
+ {/* Extension status Component */}
+
+
+
+
+
+
+ ;
+}
+
+/**
+ * Process an incoming data event: compute timing for responses and format payload info.
+ * Assigns a unique row ID via `ensureRowId`.
+ * Returns the processed event (does NOT mutate the events array).
+ */
+function processDataEvent(dataEvent: DataEvent & { event: ExtendedMessengerEvent }, extEvents: ExtendedMessengerEvent[]): ExtendedMessengerEvent {
+ const isResponse = dataEvent.event.type === 'response';
+ if (isResponse && dataEvent.event.timestamp) {
+ // Take max 200 entries to look-up
+ const request = extEvents.slice(0, 200).find(event => event.type === 'request' && event.id === dataEvent.event.id);
+ if (request && request.timestamp) {
+ dataEvent.event.timeAfterRequest = dataEvent.event.timestamp - request.timestamp;
+ }
+ }
+
+ if (dataEvent.event.parameter) {
+ dataEvent.event.payloadInfo = `${isResponse ? 'Response' : 'Parameter'} (max 500 chars):\n ${JSON.stringify(dataEvent.event.parameter, undefined, ' ').substring(0, 499)}`;
+ } else {
+ dataEvent.event.payloadInfo = 'Payload information is empty or suppressed using diagnostic API options.';
+ }
+
+ return dataEvent.event;
+}
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/model/messenger-types.ts b/packages/vscode-messenger-devtools/webview-ui/src/model/messenger-types.ts
new file mode 100644
index 0000000..e1bac0b
--- /dev/null
+++ b/packages/vscode-messenger-devtools/webview-ui/src/model/messenger-types.ts
@@ -0,0 +1,41 @@
+import type { ExtensionInfo, MessengerEvent } from 'vscode-messenger';
+import type { NotificationType, RequestType } from 'vscode-messenger-common';
+
+export type DataEvent = {
+ extension: string;
+ event: MessengerEvent;
+};
+
+export const PushDataNotification: NotificationType = {
+ method: 'pushData'
+};
+
+export const ExtensionListRequest: RequestType = {
+ method: 'extensionList'
+};
+
+export interface ExtensionData {
+ id: string
+ name: string
+ active: boolean
+ exportsDiagnosticApi: boolean
+ info?: ExtensionInfo
+}
+
+type SaveFileResult = 'success' | 'cancelled' | 'error';
+
+export const SaveFileRequest: RequestType<{ filename: string; content: string; }, SaveFileResult> = {
+ method: 'saveFile'
+};
+
+export interface ExtendedMessengerEvent extends MessengerEvent {
+ timeAfterRequest?: number
+ payloadInfo?: string
+}
+
+export interface ExtendedExtensionData extends ExtensionData {
+ events: ExtendedMessengerEvent[]
+}
+
+export const MESSENGER_EXTENSION_ID = 'TypeFox.vscode-messenger-devtools';
+export const HOST_EXTENSION_NAME = 'host extension';
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/utilities/data-store.ts b/packages/vscode-messenger-devtools/webview-ui/src/utilities/data-store.ts
new file mode 100644
index 0000000..2c3cc45
--- /dev/null
+++ b/packages/vscode-messenger-devtools/webview-ui/src/utilities/data-store.ts
@@ -0,0 +1,82 @@
+import create from 'zustand';
+import type { ExtendedExtensionData, ExtendedMessengerEvent, ExtensionData } from '../model/messenger-types';
+import { getVSCodeTheme, restoreState, storeState } from './view-state';
+
+export interface DevtoolsComponentState {
+ selectedExtension: string
+ datasetSrc: Map
+ chartsShown: boolean
+ diagramShown: boolean
+ theme: 'light' | 'dark'
+}
+
+type Accessors = {
+ getSelectedExtension: () => ExtendedExtensionData | undefined
+ getExtensions: () => ExtendedExtensionData[]
+
+ updateSelectedExtension: (extId: string) => void
+ updateExtensionData: (extensionData: ExtensionData[]) => void
+ updateEvents: (extId: string, events: ExtendedMessengerEvent[]) => void
+ updateTheme: (theme: 'light' | 'dark') => void
+ updateVisualizationSelect: (kind: 'charts' | 'diag') => void
+}
+
+const restoredState = restoreState();
+
+export const useDevtoolsStore = create((set, get) => ({
+ selectedExtension: restoredState?.selectedExtension ?? '',
+ datasetSrc: restoredState?.datasetSrc ?? new Map(),
+ chartsShown: restoredState?.chartsShown ?? false,
+ diagramShown: restoredState?.diagramShown ?? false,
+ theme: restoredState?.theme ?? getVSCodeTheme(),
+
+ getSelectedExtension: () => get().datasetSrc.get(get().selectedExtension) ?? undefined,
+ getExtensions: () => Array.from(get().datasetSrc.values()),
+
+ updateExtensionData(extensions) {
+ const newDatasetSrc = new Map(get().datasetSrc);
+ extensions.forEach(ext => {
+ const data = newDatasetSrc;
+ const existing = data.get(ext.id);
+ if (!existing) {
+ // received new ExtensionData
+ data.set(ext.id, {...ext, events: []});
+ } else {
+ // merge extension metadata, but keep existing events
+ data.set(ext.id, { ...ext, events: existing.events });
+ }
+ });
+ set({ datasetSrc: newDatasetSrc });
+ },
+ updateEvents(extId, events) {
+ const datasetSrc = get().datasetSrc;
+ if (datasetSrc.has(extId)) {
+ const extData = datasetSrc.get(extId)!;
+ const newDatasetSrc = new Map(datasetSrc);
+ newDatasetSrc.set(extId, { ...extData, events });
+ set({ datasetSrc: newDatasetSrc });
+ } else {
+ console.warn(`Trying to update events for unknown extension: ${extId}`);
+ }
+ },
+ updateSelectedExtension: (extId: string) => set({ selectedExtension: extId }),
+ updateVisualizationSelect: (kind: 'charts' | 'diag') => {
+ if (kind === 'charts') {
+ set((state) => ({
+ chartsShown: !state.chartsShown,
+ diagramShown: !state.chartsShown ? false : state.diagramShown
+ }));
+ } else if (kind === 'diag') {
+ set((state) => ({
+ diagramShown: !state.diagramShown,
+ chartsShown: !state.diagramShown ? false : state.chartsShown
+ }));
+ }
+ },
+ updateTheme: (theme: 'light' | 'dark') => set({ theme })
+}));
+
+// Persist store state changes to VS Code webview state
+useDevtoolsStore.subscribe((state) => {
+ storeState(state);
+});
\ No newline at end of file
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/utilities/table-data-export.ts b/packages/vscode-messenger-devtools/webview-ui/src/utilities/table-data-export.ts
new file mode 100644
index 0000000..290d4c5
--- /dev/null
+++ b/packages/vscode-messenger-devtools/webview-ui/src/utilities/table-data-export.ts
@@ -0,0 +1,91 @@
+import type { MessengerEvent } from 'vscode-messenger';
+import { HOST_EXTENSION } from 'vscode-messenger-common';
+import type { Messenger } from 'vscode-messenger-webview';
+import type { ExtendedMessengerEvent } from '../model/messenger-types';
+import { SaveFileRequest } from '../model/messenger-types';
+
+export class TableDataExporter {
+
+ private readonly messenger: Messenger;
+
+ constructor(messenger: Messenger) {
+ this.messenger = messenger;
+ }
+
+ exportTableData(
+ allEvents: ExtendedMessengerEvent[],
+ selectedEvents: ExtendedMessengerEvent[],
+ extensionId: string,
+ format: 'json' | 'csv'
+ ): void {
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
+ const filename = `${extensionId || 'messenger-events'}-${timestamp}`;
+ const dataToExport = selectedEvents.length > 0 ? selectedEvents : allEvents;
+
+ try {
+ if (format === 'json') {
+ const jsonData = JSON.stringify(dataToExport, null, 2);
+ this.saveFileViaVSCode(`${filename}.json`, jsonData);
+ } else if (format === 'csv') {
+ const csvData = this.toCsv(dataToExport);
+ this.saveFileViaVSCode(`${filename}.csv`, csvData);
+ }
+ } catch (error) {
+ console.error(`Failed to export as ${format}:`, error);
+ }
+ }
+
+ private toCsv(dataToExport: MessengerEvent[]) {
+ if (dataToExport.length === 0) {
+ return '';
+ }
+
+ const headers = ['id', 'type', 'sender', 'receiver', 'method', 'error', 'size', 'timestamp', 'parameter', 'timeAfterRequest', 'payloadInfo'];
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const escapeCSVValue = (value: any): string => {
+ if (value === null || value === undefined) {
+ return '';
+ }
+
+ let stringValue: string;
+ if (typeof value === 'object') {
+ try {
+ stringValue = JSON.stringify(value);
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ } catch (_error) {
+ stringValue = String(value);
+ }
+ } else {
+ stringValue = String(value);
+ }
+
+ if (stringValue.includes(',') || stringValue.includes('\n') || stringValue.includes('\r') || stringValue.includes('"')) {
+ return `"${stringValue.replace(/"/g, '""')}"`;
+ }
+
+ return stringValue;
+ };
+
+ const rows = dataToExport.map(event => {
+ const extendedEvent = event as ExtendedMessengerEvent;
+ return headers.map(header =>
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ escapeCSVValue((extendedEvent as any)[header])
+ ).join(',');
+ });
+
+ return [headers.join(','), ...rows].join('\n');
+ }
+
+ private async saveFileViaVSCode(filename: string, content: string): Promise {
+ try {
+ const result = await this.messenger.sendRequest(SaveFileRequest, HOST_EXTENSION, { filename, content });
+ if (result === 'error') {
+ console.error('File save failed');
+ }
+ } catch (error) {
+ console.error('Error saving file via VS Code API:', error);
+ }
+ }
+}
diff --git a/packages/vscode-messenger-devtools/webview-ui/src/utilities/view-state.ts b/packages/vscode-messenger-devtools/webview-ui/src/utilities/view-state.ts
index 337115a..2ccac73 100644
--- a/packages/vscode-messenger-devtools/webview-ui/src/utilities/view-state.ts
+++ b/packages/vscode-messenger-devtools/webview-ui/src/utilities/view-state.ts
@@ -1,4 +1,4 @@
-import type { ExtensionData } from '../devtools-view';
+import type { DevtoolsComponentState } from './data-store';
export const vsCodeApi = acquireVsCodeApi();
@@ -12,7 +12,7 @@ export function storeState(uiState: DevtoolsComponentState): void {
});
}
-export function restoreState(): DevtoolsComponentState | undefined {
+export function restoreState(): DevtoolsComponentState | undefined {
const stored = vsCodeApi.getState() as DevtoolsComponentState;
if (stored && Array.isArray(stored.datasetSrc)) {
return {
@@ -31,11 +31,3 @@ export function getVSCodeTheme(): 'light' | 'dark' {
const themeKind = document.body.getAttribute('data-vscode-theme-kind');
return themeKind?.includes('dark') ? 'dark' : 'light';
}
-
-export interface DevtoolsComponentState {
- selectedExtension: string
- datasetSrc: Map
- chartsShown: boolean
- diagramShown: boolean
- theme: 'light' | 'dark'
-}
diff --git a/packages/vscode-messenger-devtools/webview-ui/tsconfig.json b/packages/vscode-messenger-devtools/webview-ui/tsconfig.json
index dd0b688..3d3d1e0 100644
--- a/packages/vscode-messenger-devtools/webview-ui/tsconfig.json
+++ b/packages/vscode-messenger-devtools/webview-ui/tsconfig.json
@@ -5,12 +5,11 @@
"useDefineForClassFields": true,
"allowJs": false,
"skipLibCheck": true,
- "esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
- "moduleResolution": "node",
+ "moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
diff --git a/packages/vscode-messenger-devtools/webview-ui/vite.config.ts b/packages/vscode-messenger-devtools/webview-ui/vite.config.ts
index a9c7b12..a530c7c 100644
--- a/packages/vscode-messenger-devtools/webview-ui/vite.config.ts
+++ b/packages/vscode-messenger-devtools/webview-ui/vite.config.ts
@@ -3,14 +3,18 @@ import { resolve } from 'path';
import { defineConfig } from 'vite';
// https://vitejs.dev/config/
-export default defineConfig({
- mode: 'development',
+export default defineConfig(({ mode }) => (
+ console.log('Vite mode: ', mode),
+ {
plugins: [
react(),
],
assetsInclude: [
'**/codicon.css',
],
+ define: {
+ 'process.env.NODE_ENV': JSON.stringify(mode),
+ },
resolve: {
// otherwise rollup fails to resolve exported vscode-messenger-webview types
preserveSymlinks: true
@@ -25,9 +29,12 @@ export default defineConfig({
chunkFileNames: 'assets/[name].js',
assetFileNames: 'assets/[name].[ext]',
sourcemapBaseUrl: `file://${resolve(__dirname)}/build/assets/`, // <-- resolves tsx sources in debugger
- sourcemap: true
+ sourcemap: true,
+ manualChunks: {
+ 'vendor-baukasten': ['baukasten-ui'],
+ }
},
},
- minify: 'esbuild'
+ minify: mode === 'production' ? 'esbuild' : false
},
-});
+}));