From 7b511c1b1c59cbe54021bb0bfe2a116c1eb4f577 Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Tue, 23 Jun 2026 15:23:34 -0600 Subject: [PATCH 1/9] feat(vtk-wasm)!: update to v2 which require vtk>=9.6 --- examples/demo/widget.py | 14 +- examples/demo/widget_clip.py | 10 +- examples/validation/dispose.py | 122 ++ examples/vtk/cone.py | 26 +- pyproject.toml | 4 +- src/trame_vtklocal/widgets/vtklocal.py | 66 +- vue-components/package-lock.json | 1945 +++++++-------------- vue-components/package.json | 2 +- vue-components/src/components/VtkLocal.js | 591 ++++--- vue-components/src/utils.js | 69 + 10 files changed, 1228 insertions(+), 1621 deletions(-) create mode 100644 examples/validation/dispose.py create mode 100644 vue-components/src/utils.js diff --git a/examples/demo/widget.py b/examples/demo/widget.py index 2b8392e..88ae408 100644 --- a/examples/demo/widget.py +++ b/examples/demo/widget.py @@ -18,13 +18,15 @@ # /// import vtk - from trame.app import TrameApp -from trame.ui.html import DivLayout -from trame.widgets import html, client, vtklocal, trame as tw, vuetify3 as v3 -from trame.decorators import change -from trame.assets.remote import HttpFile from trame.assets.local import to_url +from trame.assets.remote import HttpFile +from trame.decorators import change +from trame.ui.html import DivLayout + +from trame.widgets import client, html, vtklocal +from trame.widgets import trame as tw +from trame.widgets import vuetify3 as v3 FULL_SCREEN = "position:absolute; left:0; top:0; width:100vw; height:100vh;" TOP_LEFT_OVERLAY = "position: absolute; top: 1rem; left: 1rem; width: 20vw; height: calc(20vw + 4rem); z-index: 1;" @@ -183,7 +185,7 @@ def _build_ui(self): self.rw, throttle_rate=20, progress_delay=500, progress_enabled=True ) as view: self.ctrl.view_update = view.update_throttle - self.widget_id = view.register_widget(self.widget) + self.widget_id = view.register_vtk_object(self.widget) view.listeners = ( "listeners", { diff --git a/examples/demo/widget_clip.py b/examples/demo/widget_clip.py index a84584c..8e732d7 100644 --- a/examples/demo/widget_clip.py +++ b/examples/demo/widget_clip.py @@ -1,11 +1,11 @@ import vtk - from trame.app import get_server +from trame.assets.remote import HttpFile +from trame.decorators import TrameApp, change from trame.ui.html import DivLayout -from trame.widgets import html, client # , vtklocal + +from trame.widgets import client, html # , vtklocal from trame_vtklocal.widgets import vtklocal # just for -e compatibility -from trame.decorators import TrameApp, change -from trame.assets.remote import HttpFile FULL_SCREEN = "position:absolute; left:0; top:0; width:100vw; height:100vh;" K_RANGE = [0.0, 15.6] @@ -138,7 +138,7 @@ def _build_ui(self): with vtklocal.LocalView(self.rw) as view: view.update_throttle.rate = 20 self.ctrl.view_update = view.update_throttle - self.widget_id = view.register_widget(self.widget) + self.widget_id = view.register_vtk_object(self.widget) view.listeners = ( "listeners", { diff --git a/examples/validation/dispose.py b/examples/validation/dispose.py new file mode 100644 index 0000000..a471bc2 --- /dev/null +++ b/examples/validation/dispose.py @@ -0,0 +1,122 @@ +# Required for vtk factory +import vtkmodules.vtkRenderingOpenGL2 # noqa +from trame.app import TrameApp +from trame.decorators import change +from trame.ui.html import DivLayout +from vtkmodules.vtkFiltersSources import vtkConeSource +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa +from vtkmodules.vtkRenderingCore import ( + vtkActor, + vtkPolyDataMapper, + vtkRenderer, + vtkRenderWindow, + vtkRenderWindowInteractor, +) + +from trame.widgets import client, html +from trame_vtklocal.widgets import vtklocal + +CLIENT_TYPE = "vue3" + +# ----------------------------------------------------------------------------- +# VTK pipeline +# ----------------------------------------------------------------------------- + + +def create_vtk_pipeline(): + renderer = vtkRenderer() + renderWindow = vtkRenderWindow() + renderWindow.AddRenderer(renderer) + + renderWindowInteractor = vtkRenderWindowInteractor() + renderWindowInteractor.SetRenderWindow(renderWindow) + renderWindowInteractor.GetInteractorStyle().SetCurrentStyleToTrackballCamera() + + cone = vtkConeSource() + + mapper = vtkPolyDataMapper() + mapper.SetInputConnection(cone.GetOutputPort()) + + actor = vtkActor() + actor.SetMapper(mapper) + + renderer.AddActor(actor) + renderer.SetBackground(0.1, 0.2, 0.4) + renderer.ResetCamera() + + return renderWindow, cone, actor + + +class DemoApp(TrameApp): + def __init__(self, server=None): + # dispose after unmount should only work with vue3 + super().__init__(server, client_type=CLIENT_TYPE) + + self.render_window, self.cone, self.actor = create_vtk_pipeline() + self._build_ui() + + def reset_camera(self): + self.ctx.view.reset_camera() + + @change("resolution") + def on_resolution_change(self, resolution, **_): + self.cone.SetResolution(int(resolution)) + self.ctx.view.update_throttle( + resolution=resolution + ) # provide custom content on update + + def _build_ui(self): + with DivLayout(self.server) as self.ui: + client.Style("body { margin: 0; }") + with html.Div( + style="position: absolute; left: 0; top: 0; width: 100vw; height: 100vh;", + v_if=("mounted", True), + ): + self.html_view = vtklocal.LocalView( + self.render_window, + ctx_name="view", + throttle_rate=20, + updated="console.log('updated', $event)", # print custom update content + ) + with html.Div( + style=""" + position: absolute; + left: 1rem; + right: 1rem; + top: 1rem; + display: flex; + padding: 10px; + background: white; + gap: 15px; + """ + ): + html.Div("Resolution") + html.Input( + type="range", + v_model=("resolution", 6), + min=3, + max=60, + step=1, + ) + html.Div("Component mounted") + html.Input( + type="checkbox", + v_model=("mounted", True), + ) + html.Button("Dispose Runtime", click=self.ctx.view.dispose_wasm_runtime) + html.Button( + "Dispose Session", click=self.ctx.view.dispose_remote_session + ) + html.Button( + "Reset Camera", + click=self.reset_camera, + ) + + +# ----------------------------------------------------------------------------- +# Main +# ----------------------------------------------------------------------------- + +if __name__ == "__main__": + app = DemoApp() + app.server.start() diff --git a/examples/vtk/cone.py b/examples/vtk/cone.py index 899d832..632ce09 100644 --- a/examples/vtk/cone.py +++ b/examples/vtk/cone.py @@ -1,10 +1,10 @@ +# Required for vtk factory +import vtkmodules.vtkRenderingOpenGL2 # noqa from trame.app import get_server -from trame.ui.html import DivLayout -from trame.widgets import html, client -from trame_vtklocal.widgets import vtklocal from trame.decorators import TrameApp, change, trigger - +from trame.ui.html import DivLayout from vtkmodules.vtkFiltersSources import vtkConeSource +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa from vtkmodules.vtkRenderingCore import ( vtkActor, vtkPolyDataMapper, @@ -13,9 +13,8 @@ vtkRenderWindowInteractor, ) -# Required for vtk factory -import vtkmodules.vtkRenderingOpenGL2 # noqa -from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa +from trame.widgets import client, html +from trame_vtklocal.widgets import vtklocal CLIENT_TYPE = "vue3" @@ -72,14 +71,18 @@ def reset_camera(self): self.html_view.reset_camera() @change("resolution") - def on_resolution_change(self, resolution, **kwargs): + def on_resolution_change(self, resolution, **_): self.cone.SetResolution(int(resolution)) - self.html_view.update_throttle() + self.html_view.update_throttle( + resolution=resolution + ) # provide custom content on update @change("opacity") - def on_opacity_change(self, opacity, **kwargs): + def on_opacity_change(self, opacity, **_): self.actor.property.opacity = float(opacity) - self.html_view.update_throttle() + self.html_view.update_throttle( + opacity=opacity + ) # provide custom content on update def _ui(self): with DivLayout(self.server) as layout: @@ -94,6 +97,7 @@ def _ui(self): emit_memory=True, memory_vtk="mem_vtk = $event", memory_arrays="mem_blob = $event", + updated="console.log('updated', $event)", # print custom update content ) html.Div( "Scene: {{ (mem_vtk / 1024).toFixed(1) }}KB - " diff --git a/pyproject.toml b/pyproject.toml index 1c5e42c..7e87a95 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ dependencies = [ "trame-common", "packaging", ] -requires-python = ">=3.9" +requires-python = ">=3.10" readme = "README.rst" license = {text = "Apache Software License"} keywords = ["Python", "Interactive", "Web", "Application", "Framework"] @@ -27,7 +27,7 @@ classifiers = [ [project.optional-dependencies] vtk = [ - "vtk>=9.4", + "vtk>=9.6.1", ] dev = [ "pre-commit", diff --git a/src/trame_vtklocal/widgets/vtklocal.py b/src/trame_vtklocal/widgets/vtklocal.py index 9599d77..3cbb5bb 100644 --- a/src/trame_vtklocal/widgets/vtklocal.py +++ b/src/trame_vtklocal/widgets/vtklocal.py @@ -2,7 +2,6 @@ import base64 import io import json -import warnings import zipfile from pathlib import Path @@ -79,10 +78,6 @@ class LocalView(HtmlElement): listeners (dict): Dynamic structure describing what to observe and how to map internal WASM state to trame state variable. - use_handler (string): - Name of a global instance of WASM handler to use. This is useful for - skipping WASM reinitialization when your vue component is going to be - mounted/unmounted often. (i.e. used inside VueRouter element) progress_enabled (bool): Allow the progress synchronization to show (or not). progress_delay (int): @@ -117,10 +112,19 @@ class LocalView(HtmlElement): _next_id = 0 - def __init__(self, render_window, throttle_rate=10, **kwargs): + def __init__( + self, + render_window, + throttle_rate=10, + use_async_component=False, + **kwargs, + ): # Register response callback if not overridden kwargs.setdefault("invoke_response", (self._on_invoke_response, "[$event]")) + kwargs.setdefault("ready", (self._on_ready, "[$event]")) + kwargs.setdefault("unmount", self._on_unmount) self._pending_invoke_result = None + self._mounted = False super().__init__( "vtk-local", @@ -155,6 +159,8 @@ def __init__(self, render_window, throttle_rate=10, **kwargs): ("auto_resize", "autoResize"), ] self._event_names += [ + "ready", + "unmount", "updated", "camera", ("memory_vtk", "memory-vtk"), @@ -167,6 +173,13 @@ def __init__(self, render_window, throttle_rate=10, **kwargs): self._update_throttle = Throttle(self.update) self._update_throttle.rate = throttle_rate + def _on_ready(self, wasm_runtime_id): + self._mounted = True + self._wasm_runtime_id = wasm_runtime_id + + def _on_unmount(self): + self._mounted = False + def _on_invoke_response(self, response): if self._pending_invoke_result is None: return @@ -195,14 +208,25 @@ def eval(self, state_mapping): """ self.server.js_call(self.__ref, "evalStateExtract", state_mapping) - def detach_handler(self): + def dispose_remote_session(self): + """ + This will clear and dispose of the remote session. + """ + if self._mounted: + self.server.js_call(self.__ref, "disposeRemoteSession") + else: + self.server.js_call( + "vtkWASM", "disposeRemoteSession", self._wasm_runtime_id + ) + + def dispose_wasm_runtime(self): """ - When using `use_handler=` property, you may reach a point where you - want to free the global WASM handler on the client side. - This method will remove the global reference so an unmount would release it, - while a new mount will re-create a new handler. + This will clear and dispose of the WASM runtime. """ - self.server.js_call(self.__ref, "detachHandler") + if self._mounted: + self.server.js_call(self.__ref, "disposeWasmRuntime") + else: + self.server.js_call("vtkWASM", "disposeWasmRuntime", self._wasm_runtime_id) @property def update_throttle(self): @@ -213,13 +237,13 @@ def update_throttle(self): """ return self._update_throttle - def update(self, push_camera=False): + def update(self, push_camera=False, **options): """Sync view by pushing updates to client""" self.api.update( push_camera=push_camera, obj_to_update=[self._render_window, *self.__registered_obj], ) - self.server.js_call(self.__ref, "update") + self.server.js_call(self.__ref, "update", options) def register_vtk_object(self, vtk_instance): """Register external element (i.e. widget) into the scene so it can be managed and return its wasm_id""" @@ -230,13 +254,6 @@ def register_vtk_object(self, vtk_instance): return self.get_wasm_id(vtk_instance) - def register_widget(self, w): - """Register external element (i.e. widget) into the scene so it can be managed and return its wasm_id""" - warnings.warn( - "register_widget() is deprecated, use register_vtk_object() instead" - ) - return self.register_vtk_object(w) - def unregister_vtk_object(self, vtk_instance): """Unregister external element (i.e. widget) from the scene so it can removed from tracking""" if vtk_instance in self.__registered_obj: @@ -251,13 +268,6 @@ def unregister_all_vtk_objects(self): self.api.unregister_widget(self._render_window, vtk_instance) self.__registered_obj.remove(vtk_instance) - def unregister_widgets(self): - """Unregister all external element (i.e. widget) from the scene""" - warnings.warn( - "unregister_widgets() is deprecated, use unregister_all_vtk_objects() instead" - ) - self.unregister_all_vtk_objects() - def export(self, format="zip", **kwargs): """Export standalone scene for WASMViewer diff --git a/vue-components/package-lock.json b/vue-components/package-lock.json index a09be7a..995a6e2 100644 --- a/vue-components/package-lock.json +++ b/vue-components/package-lock.json @@ -8,7 +8,7 @@ "name": "vue-trame_vtklocal", "version": "0.0.0", "dependencies": { - "@kitware/vtk-wasm": "^1.7.5", + "@kitware/vtk-wasm": "^2.1.3", "jszip": "3.10.1" }, "devDependencies": { @@ -27,20 +27,6 @@ "vue": "^2.7.0 || >=3.0.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@antfu/utils": { "version": "0.7.10", "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", @@ -52,13 +38,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -67,9 +53,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", - "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -77,22 +63,22 @@ } }, "node_modules/@babel/core": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", - "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.1", - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helpers": "^7.27.1", - "@babel/parser": "^7.27.1", - "@babel/template": "^7.27.1", - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -118,16 +104,16 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", - "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.1", - "@babel/types": "^7.27.1", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -148,14 +134,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -206,6 +192,16 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", @@ -221,29 +217,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", - "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -308,9 +304,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "engines": { @@ -318,9 +314,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { @@ -328,9 +324,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "engines": { @@ -338,27 +334,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", - "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", - "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -483,63 +479,191 @@ } }, "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", - "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.1", - "@babel/parser": "^7.27.1", - "@babel/template": "^7.27.1", - "@babel/types": "^7.27.1", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.3", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.3.tgz", + "integrity": "sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.4.tgz", + "integrity": "sha512-Ryk9y9T0FFVF0cUGhAknveAyUOl/A1qReTFi+qPKtOh2Z9F4AUBz3XOrYD4ZEgZirdugVzHvd/2/Wcwy5OliTg==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.7.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-css": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", + "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.1.7" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.11", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.11.tgz", + "integrity": "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.12" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.5.tgz", + "integrity": "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.3.tgz", + "integrity": "sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.7.tgz", + "integrity": "sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.42.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.7.1.tgz", + "integrity": "sha512-uMe5UO6PamJtSHrXhhHOzSX3ReWtiJrva6GnPMwSOrZtiExb5X5eExhr2OUZQVvdxPsKpY3Ro2mFbQadpPWmHA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.37.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.7.0.tgz", + "integrity": "sha512-Zbl9NyscLMZkfXPQnNAIIAFftidrA1UbcJEIMp24C0Bukc2I5T8wJS0wsXYsnDOqCFJUeJ1BITGNs5CqPDSmSg==", + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/theme-one-dark": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz", + "integrity": "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.43.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.2.tgz", + "integrity": "sha512-8kU6WNRYBKV9Sw3cxNz+uSvUvx3tt+1qgupGFPubnbLFDHOgh5qQdIGmXcD7bkA/PROK6LDKVhKMpcY7H++Amg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.7.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", @@ -966,9 +1090,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1008,34 +1132,37 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "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.6", + "@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-helpers": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", - "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1046,20 +1173,20 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "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.0", - "minimatch": "^3.1.2", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" }, "engines": { @@ -1083,19 +1210,22 @@ } }, "node_modules/@eslint/js": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", - "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", + "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": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1103,13 +1233,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", - "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.13.0", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { @@ -1183,34 +1313,31 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.0.0" + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", "engines": { @@ -1225,9 +1352,9 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -1236,37 +1363,82 @@ } }, "node_modules/@kitware/vtk-wasm": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@kitware/vtk-wasm/-/vtk-wasm-1.7.5.tgz", - "integrity": "sha512-5YOOjl+ZIsUEkozWESakSgaRQ8zs/K29DcNGxbp6g1nxWNIEw1WyMMnWCapE8mA1X4ED7HSl4QNFTosJLyFxIg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@kitware/vtk-wasm/-/vtk-wasm-2.1.3.tgz", + "integrity": "sha512-gQz3i4hMjKqZMzuD4RT8ERzv74fWeJIYa/tXQM5EnAXihaxMCTnH6vSlbBRBjnWCTjOKLdP1QSYA7Symc9D6Mw==", "license": "Apache-2.0", "dependencies": { + "@codemirror/lang-html": "^6.4.11", + "@codemirror/lang-javascript": "^6.2.4", + "@codemirror/theme-one-dark": "^6.1.3", + "codemirror": "^6.0.2", "js-untar": "^2.0.0", "jszip": "3.10.1" } }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.2.tgz", - "integrity": "sha512-H9vwztj5OAqHg9GockCQC06k1natgcxWQSRpQcPJf6i5+MWBzfKkRtxGbjQf0X2ihii0ffLZCRGbYV2f2bjNCQ==", - "dev": true, + "node_modules/@lezer/common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.2.tgz", + "integrity": "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==", + "license": "MIT" + }, + "node_modules/@lezer/css": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.3.tgz", + "integrity": "sha512-RzBo8r+/6QJeow7aPHIpGVIH59xTcJXp399820gZoMo9noQDRVpJLheIBUicYwKcsbOYoBRoLZlf2720dG/4Tg==", "license": "MIT", "dependencies": { - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.3", - "eventsource": "^3.0.2", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.23.8", - "zod-to-json-schema": "^3.24.1" - }, - "engines": { - "node": ">=18" + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" } }, + "node_modules/@lezer/html": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.13.tgz", + "integrity": "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz", + "integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.10.tgz", + "integrity": "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "license": "MIT" + }, "node_modules/@pkgr/core": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz", @@ -1311,9 +1483,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz", - "integrity": "sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", "cpu": [ "arm" ], @@ -1325,9 +1497,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz", - "integrity": "sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", "cpu": [ "arm64" ], @@ -1339,9 +1511,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz", - "integrity": "sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", "cpu": [ "arm64" ], @@ -1353,9 +1525,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz", - "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", "cpu": [ "x64" ], @@ -1367,9 +1539,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz", - "integrity": "sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", "cpu": [ "arm64" ], @@ -1381,9 +1553,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz", - "integrity": "sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", "cpu": [ "x64" ], @@ -1395,9 +1567,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz", - "integrity": "sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", "cpu": [ "arm" ], @@ -1409,9 +1581,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz", - "integrity": "sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", "cpu": [ "arm" ], @@ -1423,9 +1595,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz", - "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", "cpu": [ "arm64" ], @@ -1437,9 +1609,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz", - "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", "cpu": [ "arm64" ], @@ -1450,10 +1622,24 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz", - "integrity": "sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", "cpu": [ "loong64" ], @@ -1464,10 +1650,24 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz", - "integrity": "sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", "cpu": [ "ppc64" ], @@ -1479,9 +1679,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz", - "integrity": "sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", "cpu": [ "riscv64" ], @@ -1493,9 +1693,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz", - "integrity": "sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", "cpu": [ "riscv64" ], @@ -1507,9 +1707,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz", - "integrity": "sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", "cpu": [ "s390x" ], @@ -1521,9 +1721,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz", - "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", "cpu": [ "x64" ], @@ -1535,9 +1735,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz", - "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", "cpu": [ "x64" ], @@ -1548,10 +1748,38 @@ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz", - "integrity": "sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", "cpu": [ "arm64" ], @@ -1563,9 +1791,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz", - "integrity": "sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", "cpu": [ "ia32" ], @@ -1576,10 +1804,24 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz", - "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", "cpu": [ "x64" ], @@ -1611,9 +1853,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, @@ -1878,24 +2120,10 @@ "dev": true, "license": "MIT" }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "dev": true, "license": "MIT", "bin": { @@ -1916,9 +2144,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.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -1962,6 +2190,19 @@ "dev": true, "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.38", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", + "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/birpc": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.3.0.tgz", @@ -1972,27 +2213,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -2001,9 +2221,9 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -2012,9 +2232,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", - "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", + "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", "dev": true, "funding": [ { @@ -2032,10 +2252,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001716", - "electron-to-chromium": "^1.5.149", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.10.38", + "caniuse-lite": "^1.0.30001799", + "electron-to-chromium": "^1.5.376", + "node-releases": "^2.0.48", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -2060,47 +2281,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2112,9 +2292,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001718", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", - "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", "dev": true, "funding": [ { @@ -2149,6 +2329,21 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/codemirror": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", + "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2176,55 +2371,12 @@ "dev": true, "license": "MIT" }, - "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } + "license": "MIT" }, "node_modules/copy-anything": { "version": "3.0.5", @@ -2248,19 +2400,11 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -2365,55 +2509,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true, - "license": "MIT" - }, "node_modules/electron-to-chromium": { - "version": "1.5.152", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.152.tgz", - "integrity": "sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==", + "version": "1.5.377", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.377.tgz", + "integrity": "sha512-cH1jZgJHoezfTnKfKwnScpHywTFVnJUNITDPREFdhNjiuD502+QFpG0Qk7G8jhsV/f+CEAFlIrzP1fT+IMb92g==", "dev": true, "license": "ISC" }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -2437,39 +2539,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/esbuild": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", @@ -2521,13 +2590,6 @@ "node": ">=6" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, - "license": "MIT" - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -2542,34 +2604,32 @@ } }, "node_modules/eslint": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz", - "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==", + "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.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.13.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.26.0", - "@eslint/plugin-kit": "^0.2.8", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@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", - "@modelcontextprotocol/sdk": "^1.8.0", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", + "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2581,10 +2641,9 @@ "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", - "zod": "^3.24.2" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -2674,9 +2733,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -2691,9 +2750,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "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==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2704,15 +2763,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2774,39 +2833,6 @@ "node": ">=0.10.0" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", - "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eventsource-parser": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", - "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/execa": { "version": "9.5.3", "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.3.tgz", @@ -2834,65 +2860,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-rate-limit": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", - "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": "^4.11 || 5 || ^5.0.0-beta.1" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2950,24 +2917,6 @@ "node": ">=16.0.0" } }, - "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3000,32 +2949,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/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/fs-extra": { "version": "11.3.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", @@ -3056,16 +2985,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -3076,45 +2995,6 @@ "node": ">=6.9.0" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/get-stream": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", @@ -3158,19 +3038,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -3188,32 +3055,6 @@ "node": ">=8" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/hookable": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", @@ -3221,23 +3062,6 @@ "dev": true, "license": "MIT" }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/human-signals": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", @@ -3248,19 +3072,6 @@ "node": ">=18.18.0" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3310,16 +3121,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/is-docker": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", @@ -3391,13 +3192,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true, - "license": "MIT" - }, "node_modules/is-stream": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", @@ -3480,10 +3274,20 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -3621,9 +3425,9 @@ } }, "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", "peer": true @@ -3655,66 +3459,10 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "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": { @@ -3749,9 +3497,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.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", "dev": true, "funding": [ { @@ -3774,23 +3522,16 @@ "dev": true, "license": "MIT" }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "node_modules/node-releases": { + "version": "2.0.48", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.48.tgz", + "integrity": "sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" } }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" - }, "node_modules/npm-run-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", @@ -3834,52 +3575,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "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==", - "dev": true, - "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", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/open": { "version": "10.1.2", "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", @@ -3981,16 +3676,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4011,16 +3696,6 @@ "node": ">=8" } }, - "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -4043,9 +3718,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "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": { @@ -4055,20 +3730,10 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pkce-challenge": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", - "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -4086,7 +3751,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -4169,20 +3834,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4193,48 +3844,6 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.6.3", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -4274,13 +3883,13 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.2.tgz", - "integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@types/estree": "1.0.9" }, "bin": { "rollup": "dist/bin/rollup" @@ -4290,46 +3899,34 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.40.2", - "@rollup/rollup-android-arm64": "4.40.2", - "@rollup/rollup-darwin-arm64": "4.40.2", - "@rollup/rollup-darwin-x64": "4.40.2", - "@rollup/rollup-freebsd-arm64": "4.40.2", - "@rollup/rollup-freebsd-x64": "4.40.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.40.2", - "@rollup/rollup-linux-arm-musleabihf": "4.40.2", - "@rollup/rollup-linux-arm64-gnu": "4.40.2", - "@rollup/rollup-linux-arm64-musl": "4.40.2", - "@rollup/rollup-linux-loongarch64-gnu": "4.40.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.40.2", - "@rollup/rollup-linux-riscv64-gnu": "4.40.2", - "@rollup/rollup-linux-riscv64-musl": "4.40.2", - "@rollup/rollup-linux-s390x-gnu": "4.40.2", - "@rollup/rollup-linux-x64-gnu": "4.40.2", - "@rollup/rollup-linux-x64-musl": "4.40.2", - "@rollup/rollup-win32-arm64-msvc": "4.40.2", - "@rollup/rollup-win32-ia32-msvc": "4.40.2", - "@rollup/rollup-win32-x64-msvc": "4.40.2", + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", "fsevents": "~2.3.2" } }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -4343,34 +3940,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" - }, "node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", @@ -4384,58 +3953,12 @@ "node": ">=10" } }, - "node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - } - }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "license": "MIT" }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, - "license": "ISC" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4459,82 +3982,6 @@ "node": ">=8" } }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -4583,16 +4030,6 @@ "node": ">=0.10.0" } }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -4634,6 +4071,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "license": "MIT" + }, "node_modules/superjson": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", @@ -4709,16 +4152,6 @@ } } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -4749,21 +4182,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "dev": true, - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/unicorn-magic": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", @@ -4787,20 +4205,10 @@ "node": ">= 10.0.0" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -4844,20 +4252,10 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", "dev": true, "license": "MIT", "dependencies": { @@ -5080,6 +4478,12 @@ "eslint": "^8.57.0 || ^9.0.0" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5106,13 +4510,6 @@ "node": ">=0.10.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, "node_modules/xml-name-validator": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", @@ -5155,26 +4552,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zod": { - "version": "3.24.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", - "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.24.5", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", - "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", - "dev": true, - "license": "ISC", - "peerDependencies": { - "zod": "^3.24.1" - } } } } diff --git a/vue-components/package.json b/vue-components/package.json index d02e7dd..3f3dc13 100644 --- a/vue-components/package.json +++ b/vue-components/package.json @@ -14,7 +14,7 @@ "vue": "^2.7.0 || >=3.0.0" }, "dependencies": { - "@kitware/vtk-wasm": "^1.7.5", + "@kitware/vtk-wasm": "^2.1.3", "jszip": "3.10.1" }, "devDependencies": { diff --git a/vue-components/src/components/VtkLocal.js b/vue-components/src/components/VtkLocal.js index abf2be1..094c091 100644 --- a/vue-components/src/components/VtkLocal.js +++ b/vue-components/src/components/VtkLocal.js @@ -4,28 +4,51 @@ import { ref, reactive, unref, + onBeforeMount, onMounted, onBeforeUnmount, toRef, watchEffect, + watch, } from "vue"; import "@kitware/vtk-wasm/style.css"; -import { RemoteSession } from "@kitware/vtk-wasm/remote"; +import { loadAsync } from "@kitware/vtk-wasm"; -const WASM_HANDLERS = {}; +import { + debounce, + bindNetwork, + createExtractCallback, + generateNextCanvasId, + createFuture, +} from "../utils"; + +const WASM_RUNTIMES = {}; +const WASM_REMOTE_SESSIONS = {}; + +function disposeRemoteSession(runtimeId) { + if (WASM_REMOTE_SESSIONS[runtimeId]) { + WASM_REMOTE_SESSIONS[runtimeId].dispose(); + delete WASM_REMOTE_SESSIONS[runtimeId]; + return true; + } + return false; +} -function createExtractCallback(trame, wasmManager, extractInfo) { - return function () { - wasmManager.clearStateCache(); - for (const [name, props] of Object.entries(extractInfo)) { - const value = {}; - for (const [propName, statePath] of Object.entries(props)) { - value[propName] = wasmManager.getStateValue(statePath, true); - } - trame.state.set(name, value); - } - wasmManager.clearStateCache(); +function disposeWasmRuntime(runtimeId) { + disposeRemoteSession(runtimeId); + if (WASM_RUNTIMES[runtimeId]) { + WASM_RUNTIMES[runtimeId].dispose(); + delete WASM_RUNTIMES[runtimeId]; + return true; + } + return false; +} + +if (window.trame.refs) { + window.trame.refs.vtkWASM = { + disposeRemoteSession, + disposeWasmRuntime, }; } @@ -37,6 +60,8 @@ export default { "camera", "invoke-response", "progress", + "ready", + "unmount", ], props: { progressEnabled: { @@ -46,11 +71,9 @@ export default { type: Number, default: 500, }, - useHandler: { - type: String, - }, renderWindow: { type: Number, + default: 0, }, eagerSync: { type: Boolean, @@ -102,26 +125,24 @@ export default { autoResize: { type: Boolean, default: true, - } + }, }, setup(props, { emit }) { - // Create global WASM handler if missing - if (props.useHandler && !WASM_HANDLERS[props.useHandler]) { - WASM_HANDLERS[props.useHandler] = new RemoteSession(); - } + // Local ------------------------------------------------------------------ - const trame = inject("trame"); - const wasmURL = trame.state.get("__trame_vtklocal_wasm_url"); - const wasmBaseName = trame.state.get("__trame_vtklocal_wasm_base_name"); + let remoteSession = null; + let removeProgressCallback = null; const cameraTags = []; const listenersTags = []; + const wasmFuture = createFuture(); + + // Vue.js ----------------------------------------------------------------- + const canvasId = generateNextCanvasId(); + const wasmRuntime = ref(null); + const wasmLoading = ref(true); const container = ref(null); - const client = props.wsClient || trame?.client; + const canvas = ref(null); const listeners = toRef(props, "listeners"); - const wasmManager = props.useHandler - ? WASM_HANDLERS[props.useHandler] - : new RemoteSession(); - let subscription = null; const progress = reactive({ active: false, tsStart: 0, @@ -135,12 +156,11 @@ export default { total: 0, }, }); - const wasmLoading = ref(!wasmManager.loaded); const showLoading = computed( () => props.progressEnabled && progress.tsNow - progress.tsStart > props.progressDelay && - (wasmLoading.value || progress.active), + progress.active, ); const statePercent = computed(() => { if (!progress.state.total) { @@ -160,144 +180,206 @@ export default { Math.floor((progress.hash.current / progress.hash.total) * 100), ); }); - function updateProgress(payload) { - if (!payload) { - return; - } - progress.tsNow = Date.now(); - if (!progress.active && payload.active) { - progress.tsStart = progress.tsNow; + + // trame ------------------------------------------------------------------ + + const trame = inject("trame"); + const client = unref(props.wsClient) || trame?.client; + const url = trame.state.get("__trame_vtklocal_wasm_url"); + const wasmBaseName = trame.state.get("__trame_vtklocal_wasm_base_name"); + + // wasm ------------------------------------------------------------------- + function hasRemoteSession() { + if (!remoteSession || remoteSession.disposed) { + return false; } - progress.active = !!payload.active; - progress.state.current = payload.state?.current || 0; - progress.state.total = payload.state?.total || 0; - progress.hash.current = payload.hash?.current || 0; - progress.hash.total = payload.hash?.total || 0; - emit("progress", { - active: progress.active, - elapsed: progress.tsNow - progress.tsStart, - state: { - current: progress.state.current, - total: progress.state.total, - }, - hash: { - current: progress.hash.current, - total: progress.hash.total, - }, - }); - } - let removeProgressCallback = null; - if (wasmManager.addProgressCallback) { - removeProgressCallback = wasmManager.addProgressCallback(updateProgress); + return true; } - // network connector ------------------------------------------------------ + onBeforeMount(async () => { + try { + const runtime = await loadAsync({ + url, + wasmBaseName, + urlIsGzip: false, + ...props.config, + }); + WASM_RUNTIMES[runtime.id] = runtime; + if (!WASM_REMOTE_SESSIONS[runtime.id]) { + WASM_REMOTE_SESSIONS[runtime.id] = runtime.createRemoteSession(); + } + remoteSession = WASM_REMOTE_SESSIONS[runtime.id]; + bindNetwork(client, remoteSession); + + // Connect progress + removeProgressCallback = remoteSession.addProgressCallback( + (payload) => { + if (!payload) { + return; + } + progress.tsNow = Date.now(); + if (!progress.active && payload.active) { + progress.tsStart = progress.tsNow; + } + progress.active = !!payload.active; + progress.state.current = payload.state?.current || 0; + progress.state.total = payload.state?.total || 0; + progress.hash.current = payload.hash?.current || 0; + progress.hash.total = payload.hash?.total || 0; + emit("progress", { + active: progress.active, + elapsed: progress.tsNow - progress.tsStart, + state: { + current: progress.state.current, + total: progress.state.total, + }, + hash: { + current: progress.hash.current, + total: progress.hash.total, + }, + }); + }, + ); - async function netFetchState(vtkId) { - const session = client.getConnection().getSession(); - return await session.call("vtklocal.get.state", [vtkId]); - } + // Activate component + wasmRuntime.value = runtime.id; + wasmFuture.resolve(); + } catch (error) { + wasmFuture.reject(error); + } + }); - async function netFetchBlob(hash) { - const session = client.getConnection().getSession(); - const content = await session.call("vtklocal.get.hash", [hash]); - // handle either blob or TypedArray - const array = content.arrayBuffer - ? new Uint8Array(await content.arrayBuffer()) - : content; - return array; - } + // Eager state synchronization -------------------------------------------- - async function netFetchStatus(vtkId) { - const session = client.getConnection().getSession(); - return await session.call("vtklocal.get.status", [vtkId]); + if (props.eagerSync) { + const rpcSession = client.getConnection().getSession(); + const subscription = rpcSession.subscribe( + "vtklocal.subscriptions", + ([event]) => { + if (!hasRemoteSession()) return; + if (event.type === "state") { + remoteSession.patchState(event.content); + } + if (event.type === "blob") { + remoteSession.pushHash(event.hash, event.content); + } + }, + ); + onBeforeUnmount(async () => { + rpcSession.unsubscribe(subscription); + if (props.renderWindow > 0) { + await rpcSession.call("vtklocal.subscribe.update", [ + props.renderWindow, + -1, + ]); + } + }); + watch( + () => props.renderWindow, + async (newId, oldId) => { + if (oldId > 0) { + await rpcSession.call("vtklocal.subscribe.update", [oldId, -1]); + } + if (newId > 0) { + await rpcSession.call("vtklocal.subscribe.update", [newId, +1]); + } + }, + { immediate: true }, + ); } - // Subscription handling -------------------------------------------------- + // Logger verbosity synchronization --------------------------------------- - function handleMessage([event]) { - if (event.type === "state") { - wasmManager.patchState(event.content); + watchEffect(() => { + const settings = props.verbosity; + if (!wasmRuntime.value || !hasRemoteSession()) return; + + if ( + settings.objectManager && + remoteSession.native.setObjectManagerLogVerbosity + ) { + remoteSession.native.setObjectManagerLogVerbosity( + settings.objectManager, + ); } - if (event.type === "blob") { - wasmManager.pushHash(event.hash, event.content); + if (settings.invoker && remoteSession.native.setInvokerLogVerbosity) { + remoteSession.native.setInvokerLogVerbosity(settings.invoker); } - } - - async function subscribe() { - const session = client.getConnection().getSession(); - subscription = session.subscribe("vtklocal.subscriptions", handleMessage); - await session.call("vtklocal.subscribe.update", [props.renderWindow, +1]); - } - - async function unsubscribe() { - const session = client.getConnection().getSession(); - if (subscription) { - session.unsubscribe(subscription); - subscription = null; + if ( + settings.deserializer && + remoteSession.native.setDeserializerLogVerbosity + ) { + remoteSession.native.setDeserializerLogVerbosity(settings.deserializer); } - await session.call("vtklocal.subscribe.update", [props.renderWindow, -1]); - } + if ( + settings.serializer && + remoteSession.native.setSerializerLogVerbosity + ) { + remoteSession.native.setSerializerLogVerbosity(settings.serializer); + } + }); // Resize ----------------------------------------------------------------- - async function resize() { + const resize = debounce(async () => { + if (!hasRemoteSession()) return; const { width, height } = container.value.getBoundingClientRect(); const w = Math.floor(width * window.devicePixelRatio + 0.5); const h = Math.floor(height * window.devicePixelRatio + 0.5); - await wasmManager.setSize(props.renderWindow, w, h); - } + await remoteSession.setSizeAsync(props.renderWindow, w, h); + }, 100); + let resizeObserver = props.autoResize && new ResizeObserver(resize); // Memory ----------------------------------------------------------------- function checkMemory() { - wasmManager.freeMemory(props.cacheSize); - if (props.emitMemory) { - emit( - "memory-vtk", - wasmManager.sceneManager.getTotalVTKDataObjectMemoryUsage(), - ); - emit( - "memory-arrays", - wasmManager.sceneManager.getTotalBlobMemoryUsage(), - ); - } + if (!hasRemoteSession()) return; + + remoteSession.freeMemory(props.cacheSize); + if (!props.emitMemory) return; + emit( + "memory-vtk", + remoteSession.native.getTotalVTKDataObjectMemoryUsage(), + ); + emit("memory-arrays", remoteSession.native.getTotalBlobMemoryUsage()); } // Update ----------------------------------------------------------------- - async function update(bindCanvas = false) { - if (!wasmManager.loaded) { - return; - } + async function update(options) { + if (!hasRemoteSession()) return; - await wasmManager.update(props.renderWindow, bindCanvas); - emit("updated"); + await remoteSession.updateAsync(props.renderWindow); + emit("updated", options); checkMemory(); } - // resetCamera ------------------------------------------------------------ + // render / resetCamera --------------------------------------------------- - function resetCamera(rendererId) { - wasmManager.sceneManager.resetCamera(rendererId); - wasmManager.sceneManager.render(props.renderWindow); + function render() { + if (!hasRemoteSession()) return; + + remoteSession.native.render(props.renderWindow); } - // render ------------------------------------------------------------ + function resetCamera(rendererId) { + if (!hasRemoteSession()) return; - function render() { - wasmManager.sceneManager.render(props.renderWindow); + remoteSession.native.resetCamera(rendererId); + remoteSession.native.render(props.renderWindow); } // invoke ------------------------------------------------------------ async function invoke(objId, method, args) { - const result = await wasmManager.sceneManager.invoke(objId, method, args); + if (!hasRemoteSession()) return; + + const result = await remoteSession.native.invoke(objId, method, args); // Extract object state if object is returned if (result?.Id && result?.Success) { - result.Value = wasmManager.getState(result.Id); + result.Value = remoteSession.getState(result.Id); } emit("invoke-response", result); @@ -308,223 +390,161 @@ export default { // debug ------------------------------------------------------------ function printSceneManagerInformation() { - wasmManager.sceneManager.printSceneManagerInformation(); + if (!hasRemoteSession()) return; + + remoteSession.native.printSceneManagerInformation(); } // startWebXR ---------------------------------------------------------------- function startWebXR(mode, requiredFeatures, optionalFeatures) { - wasmManager.sceneManager.startWebXR(mode, requiredFeatures, optionalFeatures); + if (!hasRemoteSession()) return; + + remoteSession.native.startWebXR(mode, requiredFeatures, optionalFeatures); } // stopWebXR ---------------------------------------------------------------- function stopWebXR() { - wasmManager.sceneManager.stopWebXR(); + if (!hasRemoteSession()) return; + + remoteSession.native.stopWebXR(); } // Life Cycles ------------------------------------------------------------ onMounted(async () => { - // console.log("vtkLocal::mounted"); - wasmManager.bindNetwork(netFetchState, netFetchBlob, netFetchStatus); - if (!wasmManager.loaded) { - wasmLoading.value = true; - try { - await wasmManager.load(wasmURL, props.config, wasmBaseName); - } finally { - wasmLoading.value = false; - } - } - const selector = wasmManager.bindCanvasToDOM( - props.renderWindow, - unref(container), - ); - unref(container) - .querySelector(selector) - .setAttribute( - "style", - "position: absolute; left: 0; top: 0; width: 100%; height: 100%;", + // Wait for wasm to be fully loaded + await wasmFuture.promise; + + // Should never happen + if (!hasRemoteSession()) { + throw new Error( + "LocalView is mounting but the remote session is not valid.", ); - if (props.eagerSync) { - subscribe(); } + // Bind canvas to renderWindow + remoteSession.bindCanvas(props.renderWindow, unref(canvas)); + // Figure out size if (resizeObserver) { resizeObserver.observe(unref(container)); } - - // Update loggers - watchEffect(() => { - const settings = props.verbosity; - if ( - settings.objectManager && - wasmManager.sceneManager.setObjectManagerLogVerbosity - ) { - wasmManager.sceneManager.setObjectManagerLogVerbosity( - settings.objectManager, - ); - } - if ( - settings.invoker && - wasmManager.sceneManager.setInvokerLogVerbosity - ) { - wasmManager.sceneManager.setInvokerLogVerbosity(settings.invoker); - } - if ( - settings.deserializer && - wasmManager.sceneManager.setDeserializerLogVerbosity - ) { - wasmManager.sceneManager.setDeserializerLogVerbosity( - settings.deserializer, - ); - } - if ( - settings.serializer && - wasmManager.sceneManager.setSerializerLogVerbosity - ) { - wasmManager.sceneManager.setSerializerLogVerbosity( - settings.serializer, - ); - } - }); - - await update(true); - + await update({ onMounted: props.renderWindow }); + wasmLoading.value = false; // Camera listener - if (wasmManager.sceneManager.addObserver) { - // Old API - before vtk 9.5 - wasmManager.cameraIds.forEach((cid) => { - cameraTags.push([ - cid, - wasmManager.sceneManager.addObserver(cid, "ModifiedEvent", () => { - emit("camera", wasmManager.getState(cid)); - }), - ]); - }); - } else { - // New API - starting with vtk 9.5 - wasmManager.cameraIds.forEach((cid) => { - cameraTags.push([ - cid, - wasmManager.sceneManager.observe(cid, "ModifiedEvent", () => { - emit("camera", wasmManager.getState(cid)); - }), - ]); - }); - } - + remoteSession.cameraIds.forEach((cid) => { + cameraTags.push([ + cid, + remoteSession.native.observe(cid, "ModifiedEvent", () => { + emit("camera", remoteSession.getState(cid)); + }), + ]); + }); // Attach listeners watchEffect(() => { - if (wasmManager.sceneManager.removeObserver) { - // Old API - before vtk 9.5 - while (listenersTags.length) { - const [cid, tag] = listenersTags.pop(); - wasmManager.sceneManager.removeObserver(cid, tag); - } + // register tracking + const allListeners = listeners.value || {}; - for (const [cid, eventMap] of Object.entries(listeners.value || {})) { - const wasmId = Number(cid); - for (const [eventName, extractInfo] of Object.entries( - eventMap || {}, - )) { - const fn = createExtractCallback(trame, wasmManager, extractInfo); - listenersTags.push([ - wasmId, - wasmManager.sceneManager.addObserver(wasmId, eventName, fn), - ]); - - // Push update at registration - fn(); - } - } - } else { - // New API - starting with vtk 9.5 - while (listenersTags.length) { - const [cid, tag] = listenersTags.pop(); - wasmManager.sceneManager.unObserve(cid, tag); - } + // Exit on disposed session + if (!hasRemoteSession()) return; - for (const [cid, eventMap] of Object.entries(listeners.value || {})) { - const wasmId = Number(cid); - for (const [eventName, extractInfo] of Object.entries( - eventMap || {}, - )) { - const fn = createExtractCallback(trame, wasmManager, extractInfo); - listenersTags.push([ - wasmId, - wasmManager.sceneManager.observe(wasmId, eventName, fn), - ]); - - // Push update at registration - fn(); - } + while (listenersTags.length) { + const [cid, tag] = listenersTags.pop(); + remoteSession.native.unObserve(cid, tag); + } + for (const [cid, eventMap] of Object.entries(allListeners)) { + const wasmId = Number(cid); + for (const [eventName, extractInfo] of Object.entries( + eventMap || {}, + )) { + const fn = createExtractCallback(trame, remoteSession, extractInfo); + listenersTags.push([ + wasmId, + remoteSession.native.observe(wasmId, eventName, fn), + ]); + // Push update at registration + fn(); } } }); - if (!wasmManager.sceneManager.startEventLoop(props.renderWindow)) { + // Start event loop + if (!remoteSession.startEventLoop(props.renderWindow)) { console.error("Could not startEventLoop for", props.renderWindow); } // trigger an emit right away - wasmManager.cameraIds.forEach((cid) => { - emit("camera", wasmManager.getState(cid)); + remoteSession.cameraIds.forEach((cid) => { + emit("camera", remoteSession.getState(cid)); }); + + // Send ready event with WASM Runtime Id + emit("ready", wasmRuntime.value); }); - onBeforeUnmount(() => { - if (subscription) { - unsubscribe(); - } - if (removeProgressCallback) { - removeProgressCallback(); - removeProgressCallback = null; + onBeforeUnmount(async () => { + emit("unmount"); + + // Remove progress tracking + removeProgressCallback && removeProgressCallback(); + + // Remove size observer + if (resizeObserver) { + resizeObserver.disconnect(); + resizeObserver = null; } - // Old/New API - detection - const removeObserverMethodName = wasmManager.sceneManager.removeObserver - ? "removeObserver" - : "unObserve"; + // Exit if already disposed + if (!hasRemoteSession()) return; // Camera listeners while (cameraTags.length) { const [cid, tag] = cameraTags.pop(); - wasmManager.sceneManager[removeObserverMethodName](cid, tag); + remoteSession.native.unObserve(cid, tag); } while (listenersTags.length) { const [cid, tag] = listenersTags.pop(); - wasmManager.sceneManager[removeObserverMethodName](cid, tag); - } - - // console.log("vtkLocal::unmounted"); - wasmManager.sceneManager.stopEventLoop(props.renderWindow); - if (resizeObserver) { - resizeObserver.disconnect(); - resizeObserver = null; + remoteSession.native.unObserve(cid, tag); } - // unbind canvas - wasmManager.unbindCanvasToDOM(props.renderWindow); + // Cleanup our view in wasm session + const rwId = props.renderWindow; + remoteSession.stopEventLoop(rwId); + remoteSession.unbindCanvas(rwId); + await remoteSession.native.invoke(rwId, "Finalize", []); }); // Public ----------------------------------------------------------------- function evalStateExtract(definition) { - createExtractCallback(trame, wasmManager, definition)(); + createExtractCallback(trame, remoteSession, definition)(); } function getVtkObject(vtkId) { - return wasmManager.getVtkObject(vtkId); + return remoteSession.getVtkObject(vtkId); } /** - * Remove WASM handler from global map to free memory once component unmount. + * dispose WASM remoteSession + */ + function disposeRemoteSession(runtimeId) { + const rId = runtimeId || wasmRuntime.value; + if (WASM_REMOTE_SESSIONS[rId]) { + WASM_REMOTE_SESSIONS[rId].dispose(); + delete WASM_REMOTE_SESSIONS[rId]; + } + } + /** + * dispose wasm runtime */ - function detachHandler() { - if (props.useHandler && WASM_HANDLERS[props.useHandler]) { - delete WASM_HANDLERS[props.useHandler]; + function disposeWasmRuntime(runtimeId) { + const rId = runtimeId || wasmRuntime.value; + disposeRemoteSession(rId); + if (WASM_RUNTIMES[rId]) { + WASM_RUNTIMES[rId].dispose(); + delete WASM_RUNTIMES[rId]; } } @@ -536,9 +556,9 @@ export default { evalStateExtract, invoke, resize, - wasmManager, printSceneManagerInformation, - detachHandler, + disposeRemoteSession, + disposeWasmRuntime, getVtkObject, progress, showLoading, @@ -547,9 +567,12 @@ export default { wasmLoading, startWebXR, stopWebXR, + canvas, + canvasId, }; }, template: `
+ { + resolve = res; + reject = rej; + }); + return { promise, resolve, reject }; +} +export function debounce(func, delay = 100) { + let timeoutId; + + return function (...args) { + clearTimeout(timeoutId); + timeoutId = setTimeout(func, delay, ...args); + }; +} + +export function bindNetwork(client, remoteSession) { + const rpcSession = client.getConnection().getSession(); + + async function netFetchState(vtkId) { + return await rpcSession.call("vtklocal.get.state", [vtkId]); + } + + async function netFetchBlob(hash) { + const content = await rpcSession.call("vtklocal.get.hash", [hash]); + // handle either blob or TypedArray + const array = content.arrayBuffer + ? new Uint8Array(await content.arrayBuffer()) + : content; + return array; + } + + async function netFetchStatus(vtkId) { + return await rpcSession.call("vtklocal.get.status", [vtkId]); + } + + remoteSession.bindNetwork(netFetchState, netFetchBlob, netFetchStatus); +} + +export function createExtractCallback(trame, remoteSession, extractInfo) { + return function () { + remoteSession.clearStateCache(); + for (const [name, props] of Object.entries(extractInfo)) { + const value = {}; + for (const [propName, statePath] of Object.entries(props)) { + value[propName] = remoteSession.getStateValue(statePath, true); + } + trame.state.set(name, value); + } + remoteSession.clearStateCache(); + }; +} + +export function generateNextCanvasId() { + return CANVAS_ID_GENERATOR.nextId(); +} From befbdd0394705df678b9c012a54094c65ef86262 Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Tue, 23 Jun 2026 15:31:57 -0600 Subject: [PATCH 2/9] docs(examples): replace register_widget by register_vtk_object --- examples/docker/app.py | 14 ++++++++------ examples/pyvista/basic.py | 7 ++++--- examples/pyvista/bg_image.py | 7 ++++--- examples/pyvista/drap2dsurf.py | 7 ++++--- examples/pyvista/eye_dome_lighting.py | 7 ++++--- examples/pyvista/linked_view.py | 7 ++++--- examples/vtk/borderWidget.py | 19 +++++++++---------- examples/vtk/widgets_box.py | 21 ++++++++++----------- examples/vtk/widgets_camera.py | 20 ++++++++++---------- examples/vtk/widgets_plane.py | 21 ++++++++++----------- examples/vtk/widgets_plane_slice.py | 21 ++++++++++----------- 11 files changed, 77 insertions(+), 74 deletions(-) diff --git a/examples/docker/app.py b/examples/docker/app.py index 9d70561..5e569ca 100644 --- a/examples/docker/app.py +++ b/examples/docker/app.py @@ -1,11 +1,13 @@ import vtk - from trame.app import get_server -from trame.ui.html import DivLayout -from trame.widgets import html, client, vtklocal, trame as tw, vuetify3 as v3 -from trame.decorators import TrameApp, change -from trame.assets.remote import HttpFile from trame.assets.local import to_url +from trame.assets.remote import HttpFile +from trame.decorators import TrameApp, change +from trame.ui.html import DivLayout + +from trame.widgets import client, html, vtklocal +from trame.widgets import trame as tw +from trame.widgets import vuetify3 as v3 FULL_SCREEN = "position:absolute; left:0; top:0; width:100vw; height:100vh;" K_RANGE = [0.0, 15.6] @@ -174,7 +176,7 @@ def _build_ui(self): with vtklocal.LocalView(self.rw) as view: view.update_throttle.rate = 20 self.ctrl.view_update = view.update_throttle - self.widget_id = view.register_widget(self.widget) + self.widget_id = view.register_vtk_object(self.widget) view.listeners = ( "listeners", { diff --git a/examples/pyvista/basic.py b/examples/pyvista/basic.py index e76b344..e9c8df9 100644 --- a/examples/pyvista/basic.py +++ b/examples/pyvista/basic.py @@ -1,10 +1,11 @@ # import os import pyvista as pv from pyvista import examples - from trame.app import get_server from trame.ui.html import DivLayout -from trame.widgets import html, client, vtk as vtk_widgets + +from trame.widgets import client, html +from trame.widgets import vtk as vtk_widgets from trame_vtklocal.widgets import vtklocal WASM = True # "USE_WASM" in os.environ @@ -46,7 +47,7 @@ def _ui(self): if WASM: self.html_view = vtklocal.LocalView(self.render_window) for w in self.widgets: - self.html_view.register_widget(w) + self.html_view.register_vtk_object(w) else: self.html_view = vtk_widgets.VtkRemoteView( self.render_window, interactive_ratio=1 diff --git a/examples/pyvista/bg_image.py b/examples/pyvista/bg_image.py index b4ccbf5..d7ddd6a 100644 --- a/examples/pyvista/bg_image.py +++ b/examples/pyvista/bg_image.py @@ -1,10 +1,11 @@ # import os import pyvista as pv from pyvista import examples - from trame.app import get_server from trame.ui.html import DivLayout -from trame.widgets import html, client, vtk as vtk_widgets + +from trame.widgets import client, html +from trame.widgets import vtk as vtk_widgets from trame_vtklocal.widgets import vtklocal WASM = True # "USE_WASM" in os.environ @@ -42,7 +43,7 @@ def _ui(self): if WASM: self.html_view = vtklocal.LocalView(self.render_window) for w in self.widgets: - self.html_view.register_widget(w) + self.html_view.register_vtk_object(w) else: self.html_view = vtk_widgets.VtkRemoteView( self.render_window, interactive_ratio=1 diff --git a/examples/pyvista/drap2dsurf.py b/examples/pyvista/drap2dsurf.py index be40b20..d43b4f7 100644 --- a/examples/pyvista/drap2dsurf.py +++ b/examples/pyvista/drap2dsurf.py @@ -2,10 +2,11 @@ import numpy as np import pyvista as pv from pyvista import examples - from trame.app import get_server from trame.ui.html import DivLayout -from trame.widgets import html, client, vtk as vtk_widgets + +from trame.widgets import client, html +from trame.widgets import vtk as vtk_widgets from trame_vtklocal.widgets import vtklocal WASM = True # "USE_WASM" in os.environ @@ -60,7 +61,7 @@ def _ui(self): if WASM: self.html_view = vtklocal.LocalView(self.render_window) for w in self.widgets: - self.html_view.register_widget(w) + self.html_view.register_vtk_object(w) else: self.html_view = vtk_widgets.VtkRemoteView( self.render_window, interactive_ratio=1 diff --git a/examples/pyvista/eye_dome_lighting.py b/examples/pyvista/eye_dome_lighting.py index f06399b..8034005 100644 --- a/examples/pyvista/eye_dome_lighting.py +++ b/examples/pyvista/eye_dome_lighting.py @@ -1,10 +1,11 @@ # import os import pyvista as pv from pyvista import examples - from trame.app import get_server from trame.ui.html import DivLayout -from trame.widgets import html, client, vtk as vtk_widgets + +from trame.widgets import client, html +from trame.widgets import vtk as vtk_widgets from trame_vtklocal.widgets import vtklocal WASM = True # "USE_WASM" in os.environ @@ -45,7 +46,7 @@ def _ui(self): if WASM: self.html_view = vtklocal.LocalView(self.render_window) for w in self.widgets: - self.html_view.register_widget(w) + self.html_view.register_vtk_object(w) else: self.html_view = vtk_widgets.VtkRemoteView( self.render_window, interactive_ratio=1 diff --git a/examples/pyvista/linked_view.py b/examples/pyvista/linked_view.py index 0ee0170..c12bee1 100644 --- a/examples/pyvista/linked_view.py +++ b/examples/pyvista/linked_view.py @@ -1,10 +1,11 @@ # import os import pyvista as pv from pyvista import examples - from trame.app import get_server from trame.ui.html import DivLayout -from trame.widgets import html, client, vtk as vtk_widgets + +from trame.widgets import client, html +from trame.widgets import vtk as vtk_widgets from trame_vtklocal.widgets import vtklocal WASM = True # "USE_WASM" in os.environ @@ -51,7 +52,7 @@ def _ui(self): if WASM: self.html_view = vtklocal.LocalView(self.render_window) for w in self.widgets: - self.html_view.register_widget(w) + self.html_view.register_vtk_object(w) else: self.html_view = vtk_widgets.VtkRemoteView( self.render_window, interactive_ratio=1 diff --git a/examples/vtk/borderWidget.py b/examples/vtk/borderWidget.py index b296b42..50cd37d 100644 --- a/examples/vtk/borderWidget.py +++ b/examples/vtk/borderWidget.py @@ -1,22 +1,21 @@ -from trame.app import TrameApp -from trame.ui.html import DivLayout -from trame.widgets import html, client -from trame_vtklocal.widgets import vtklocal - # Required for vtk factory import vtkmodules.vtkRenderingOpenGL2 # noqa -from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa - +from trame.app import TrameApp +from trame.ui.html import DivLayout from vtkmodules.vtkFiltersSources import vtkSphereSource -from vtkmodules.vtkInteractionWidgets import vtkBorderWidget, vtkBorderRepresentation +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa +from vtkmodules.vtkInteractionWidgets import vtkBorderRepresentation, vtkBorderWidget from vtkmodules.vtkRenderingCore import ( vtkActor, vtkPolyDataMapper, + vtkRenderer, vtkRenderWindow, vtkRenderWindowInteractor, - vtkRenderer, ) +from trame.widgets import client, html +from trame_vtklocal.widgets import vtklocal + def create_vtk_pipeline(): ss = vtkSphereSource() @@ -77,7 +76,7 @@ def _build_ui(self): throttle_rate=20, ctx_name="view", ) - self.widget_id = self.ctx.view.register_widget(self.widget) + self.widget_id = self.ctx.view.register_vtk_object(self.widget) return layout diff --git a/examples/vtk/widgets_box.py b/examples/vtk/widgets_box.py index f571642..60f2a16 100644 --- a/examples/vtk/widgets_box.py +++ b/examples/vtk/widgets_box.py @@ -1,25 +1,24 @@ -from trame.app import get_server -from trame.ui.html import DivLayout -from trame.widgets import html, client -from trame_vtklocal.widgets import vtklocal -from trame.decorators import TrameApp, change - # Required for vtk factory import vtkmodules.vtkRenderingOpenGL2 # noqa -from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa - +from trame.app import get_server +from trame.decorators import TrameApp, change +from trame.ui.html import DivLayout from vtkmodules.vtkCommonColor import vtkNamedColors from vtkmodules.vtkCommonTransforms import vtkTransform from vtkmodules.vtkFiltersSources import vtkConeSource -from vtkmodules.vtkInteractionWidgets import vtkBoxWidget2, vtkBoxRepresentation +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa +from vtkmodules.vtkInteractionWidgets import vtkBoxRepresentation, vtkBoxWidget2 from vtkmodules.vtkRenderingCore import ( vtkActor, vtkPolyDataMapper, + vtkRenderer, vtkRenderWindow, vtkRenderWindowInteractor, - vtkRenderer, ) +from trame.widgets import client, html +from trame_vtklocal.widgets import vtklocal + def create_vtk_pipeline(): colors = vtkNamedColors() @@ -148,7 +147,7 @@ def _ui(self): throttle_rate=20, listeners=("wasm_listeners", {}), ) - self.widget_id = self.html_view.register_widget(self.widget) + self.widget_id = self.html_view.register_vtk_object(self.widget) return layout diff --git a/examples/vtk/widgets_camera.py b/examples/vtk/widgets_camera.py index 2fe16a6..632eccb 100644 --- a/examples/vtk/widgets_camera.py +++ b/examples/vtk/widgets_camera.py @@ -5,27 +5,27 @@ # import os from pathlib import Path -from trame.app import get_server -from trame.ui.html import DivLayout -from trame.widgets import html, client, vtk as vtk_widgets -from trame_vtklocal.widgets import vtklocal - # Required for vtk factory import vtkmodules.vtkRenderingOpenGL2 # noqa -from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa - +from trame.app import get_server +from trame.ui.html import DivLayout from vtkmodules.vtkCommonColor import vtkNamedColors -from vtkmodules.vtkIOXML import vtkXMLPolyDataReader from vtkmodules.vtkFiltersSources import vtkConeSource +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa from vtkmodules.vtkInteractionWidgets import vtkCameraOrientationWidget +from vtkmodules.vtkIOXML import vtkXMLPolyDataReader from vtkmodules.vtkRenderingCore import ( vtkActor, vtkPolyDataMapper, + vtkRenderer, vtkRenderWindow, vtkRenderWindowInteractor, - vtkRenderer, ) +from trame.widgets import client, html +from trame.widgets import vtk as vtk_widgets +from trame_vtklocal.widgets import vtklocal + WASM = True # "USE_WASM" in os.environ @@ -94,7 +94,7 @@ def _ui(self): ): if WASM: self.html_view = vtklocal.LocalView(self.render_window) - self.widget_id = self.html_view.register_widget(self.widget) + self.widget_id = self.html_view.register_vtk_object(self.widget) else: self.html_view = vtk_widgets.VtkRemoteView(self.render_window) diff --git a/examples/vtk/widgets_plane.py b/examples/vtk/widgets_plane.py index 40a4fa8..d4fa4a0 100644 --- a/examples/vtk/widgets_plane.py +++ b/examples/vtk/widgets_plane.py @@ -1,34 +1,33 @@ # import os from pathlib import Path -from trame.app import get_server -from trame.ui.html import DivLayout -from trame.widgets import html, client -from trame_vtklocal.widgets import vtklocal -from trame.decorators import TrameApp, change - # Required for vtk factory import vtkmodules.vtkRenderingOpenGL2 # noqa -from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa - +from trame.app import get_server +from trame.decorators import TrameApp, change +from trame.ui.html import DivLayout from vtkmodules.vtkCommonColor import vtkNamedColors from vtkmodules.vtkCommonDataModel import vtkPlane from vtkmodules.vtkFiltersCore import vtkClipPolyData from vtkmodules.vtkFiltersSources import vtkSphereSource -from vtkmodules.vtkIOXML import vtkXMLPolyDataReader +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa from vtkmodules.vtkInteractionWidgets import ( vtkImplicitPlaneRepresentation, vtkImplicitPlaneWidget2, ) +from vtkmodules.vtkIOXML import vtkXMLPolyDataReader from vtkmodules.vtkRenderingCore import ( vtkActor, vtkPolyDataMapper, vtkProperty, + vtkRenderer, vtkRenderWindow, vtkRenderWindowInteractor, - vtkRenderer, ) +from trame.widgets import client, html +from trame_vtklocal.widgets import vtklocal + def create_vtk_pipeline(file_to_load): colors = vtkNamedColors() @@ -186,7 +185,7 @@ def _ui(self): throttle_rate=20, listeners=("wasm_listeners", {}), ) - self.widget_id = self.html_view.register_widget(self.widget) + self.widget_id = self.html_view.register_vtk_object(self.widget) return layout diff --git a/examples/vtk/widgets_plane_slice.py b/examples/vtk/widgets_plane_slice.py index d7c193a..86b1089 100644 --- a/examples/vtk/widgets_plane_slice.py +++ b/examples/vtk/widgets_plane_slice.py @@ -1,33 +1,32 @@ # import os from pathlib import Path -from trame.app import get_server -from trame.ui.html import DivLayout -from trame.widgets import html, client -from trame_vtklocal.widgets import vtklocal -from trame.decorators import TrameApp, change - # Required for vtk factory import vtkmodules.vtkRenderingOpenGL2 # noqa -from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa - +from trame.app import get_server +from trame.decorators import TrameApp, change +from trame.ui.html import DivLayout from vtkmodules.vtkCommonColor import vtkNamedColors from vtkmodules.vtkCommonDataModel import vtkPlane from vtkmodules.vtkFiltersCore import vtkCutter from vtkmodules.vtkFiltersSources import vtkSphereSource -from vtkmodules.vtkIOXML import vtkXMLPolyDataReader +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa from vtkmodules.vtkInteractionWidgets import ( vtkImplicitPlaneRepresentation, vtkImplicitPlaneWidget2, ) +from vtkmodules.vtkIOXML import vtkXMLPolyDataReader from vtkmodules.vtkRenderingCore import ( vtkActor, vtkPolyDataMapper, + vtkRenderer, vtkRenderWindow, vtkRenderWindowInteractor, - vtkRenderer, ) +from trame.widgets import client, html +from trame_vtklocal.widgets import vtklocal + def create_vtk_pipeline(file_to_load): colors = vtkNamedColors() @@ -191,7 +190,7 @@ def _ui(self): throttle_rate=20, listeners=("wasm_listeners", {}), ) - self.widget_id = self.html_view.register_widget(self.widget) + self.widget_id = self.html_view.register_vtk_object(self.widget) return layout From 7fa2f236000757ec5858cd55243b782160325a98 Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Thu, 25 Jun 2026 14:53:46 -0600 Subject: [PATCH 3/9] feat(wasm32/64): add selection support --- examples/validation/dispose.py | 11 ++++++ src/trame_vtklocal/module/__init__.py | 6 ++-- src/trame_vtklocal/module/wasm.py | 22 ++++++------ src/trame_vtklocal/widgets/vtklocal.py | 1 + vue-components/src/components/VtkLocal.js | 41 +++++++++++++++++------ 5 files changed, 59 insertions(+), 22 deletions(-) diff --git a/examples/validation/dispose.py b/examples/validation/dispose.py index a471bc2..0d16edd 100644 --- a/examples/validation/dispose.py +++ b/examples/validation/dispose.py @@ -76,6 +76,7 @@ def _build_ui(self): self.render_window, ctx_name="view", throttle_rate=20, + config=("{ mode, exec, rendering }",), updated="console.log('updated', $event)", # print custom update content ) with html.Div( @@ -98,6 +99,16 @@ def _build_ui(self): max=60, step=1, ) + with html.Select(v_model=("mode", "wasm32")): + html.Option("wasm32") + html.Option("wasm64") + with html.Select(v_model=("exec", "sync")): + html.Option("sync") + html.Option("async") + with html.Select(v_model=("rendering", "webgl")): + html.Option("webgl") + html.Option("webgpu") + html.Div("Component mounted") html.Input( type="checkbox", diff --git a/src/trame_vtklocal/module/__init__.py b/src/trame_vtklocal/module/__init__.py index 08b4510..8e75143 100644 --- a/src/trame_vtklocal/module/__init__.py +++ b/src/trame_vtklocal/module/__init__.py @@ -1,7 +1,8 @@ from pathlib import Path + from trame_vtklocal import __version__ -from trame_vtklocal.module.wasm import register_wasm from trame_vtklocal.module.protocol import ObjectManagerHelper +from trame_vtklocal.module.wasm import register_wasm __all__ = [ "serve", @@ -34,4 +35,5 @@ def setup(trame_server, **kwargs): HELPERS_PER_SERVER[trame_server.name] = ObjectManagerHelper( trame_server, addon_serdes_registrars=kwargs.pop("addon_serdes_registrars", []) ) - trame_server.enable_module(register_wasm(serve_path, **kwargs)) + trame_server.enable_module(register_wasm(serve_path, wasm_bits="wasm64", **kwargs)) + trame_server.enable_module(register_wasm(serve_path, wasm_bits="wasm32", **kwargs)) diff --git a/src/trame_vtklocal/module/wasm.py b/src/trame_vtklocal/module/wasm.py index 8174a5d..6215c19 100644 --- a/src/trame_vtklocal/module/wasm.py +++ b/src/trame_vtklocal/module/wasm.py @@ -1,9 +1,10 @@ import asyncio -import aiohttp -from pathlib import Path import os import shutil import tarfile +from pathlib import Path + +import aiohttp from packaging.version import parse from trame_vtklocal import __version__ @@ -50,18 +51,17 @@ async def setup_wasm_directory(target_directory, wasm_url): Path(dest_file).unlink() -def get_wasm_info(): +def get_wasm_info(wasm_bits="wasm32"): from vtkmodules.vtkCommonCore import vtkVersion vtk_version = vtkVersion() - wasm_bits = "wasm32" version = vtk_version.GetVTKVersion() url = f"https://gitlab.kitware.com/api/v4/projects/13/packages/generic/vtk-{wasm_bits}-emscripten/{version}/vtk-{version}-{wasm_bits}-emscripten.tar.gz" return version, url -def register_wasm(serve_path, **kwargs): +def register_wasm(serve_path, wasm_bits="wasm32", **kwargs): """Register the VTK WebAssembly files in the given serve path. Keywords: wasm_url: The URL to the VTK WebAssembly files. It is used if wasm_dir is not provided and VTK_WASM_DIR_OVERRIDE @@ -69,10 +69,10 @@ def register_wasm(serve_path, **kwargs): wasm_base_name: The base name of the VTK WebAssembly files. (default: "vtk") wasm_dir: The directory containing the VTK WebAssembly files. """ - version, wasm_url = get_wasm_info() + version, wasm_url = get_wasm_info(wasm_bits) wasm_base_name = kwargs.get("wasm_base_name", "vtk") - BASE_URL = f"__trame_vtklocal_{__version__}/wasm/{version}" - dest_directory = Path(serve_path) / "wasm" / version + BASE_URL = f"__trame_vtklocal_{__version__}/{wasm_bits}/{version}" + dest_directory = Path(serve_path) / wasm_bits / version # get wasm directory from kwargs or environment variable wasm_dir = kwargs.get("wasm_dir", os.environ.get("VTK_WASM_DIR_OVERRIDE")) @@ -116,7 +116,9 @@ def register_wasm(serve_path, **kwargs): return dict( state={ - "__trame_vtklocal_wasm_url": BASE_URL, - "__trame_vtklocal_wasm_base_name": wasm_base_name, + f"__trame_vtklocal_{wasm_bits}": { + "url": BASE_URL, + "wasmBaseName": wasm_base_name, + } }, ) diff --git a/src/trame_vtklocal/widgets/vtklocal.py b/src/trame_vtklocal/widgets/vtklocal.py index 3cbb5bb..23123c3 100644 --- a/src/trame_vtklocal/widgets/vtklocal.py +++ b/src/trame_vtklocal/widgets/vtklocal.py @@ -227,6 +227,7 @@ def dispose_wasm_runtime(self): self.server.js_call(self.__ref, "disposeWasmRuntime") else: self.server.js_call("vtkWASM", "disposeWasmRuntime", self._wasm_runtime_id) + self._wasm_runtime_id = None @property def update_throttle(self): diff --git a/vue-components/src/components/VtkLocal.js b/vue-components/src/components/VtkLocal.js index 094c091..0288bb0 100644 --- a/vue-components/src/components/VtkLocal.js +++ b/vue-components/src/components/VtkLocal.js @@ -27,7 +27,13 @@ const WASM_RUNTIMES = {}; const WASM_REMOTE_SESSIONS = {}; function disposeRemoteSession(runtimeId) { + if (!runtimeId) { + const ids = Object.keys(WASM_REMOTE_SESSIONS); + ids.forEach(disposeRemoteSession); + return ids.length > 0; + } if (WASM_REMOTE_SESSIONS[runtimeId]) { + console.log("Removing remote session for wasm runtime", runtimeId); WASM_REMOTE_SESSIONS[runtimeId].dispose(); delete WASM_REMOTE_SESSIONS[runtimeId]; return true; @@ -36,8 +42,14 @@ function disposeRemoteSession(runtimeId) { } function disposeWasmRuntime(runtimeId) { + if (!runtimeId) { + const ids = Object.keys(WASM_RUNTIMES); + ids.forEach(disposeWasmRuntime); + return ids.length > 0; + } disposeRemoteSession(runtimeId); if (WASM_RUNTIMES[runtimeId]) { + console.log("Removing wasm runtime with ID:", runtimeId); WASM_RUNTIMES[runtimeId].dispose(); delete WASM_RUNTIMES[runtimeId]; return true; @@ -185,8 +197,8 @@ export default { const trame = inject("trame"); const client = unref(props.wsClient) || trame?.client; - const url = trame.state.get("__trame_vtklocal_wasm_url"); - const wasmBaseName = trame.state.get("__trame_vtklocal_wasm_base_name"); + const bits = props.config?.mode || "wasm32"; + const { url, wasmBaseName } = trame.state.get(`__trame_vtklocal_${bits}`); // wasm ------------------------------------------------------------------- function hasRemoteSession() { @@ -340,9 +352,12 @@ export default { if (!props.emitMemory) return; emit( "memory-vtk", - remoteSession.native.getTotalVTKDataObjectMemoryUsage(), + Number(remoteSession.native.getTotalVTKDataObjectMemoryUsage()), + ); + emit( + "memory-arrays", + Number(remoteSession.native.getTotalBlobMemoryUsage()), ); - emit("memory-arrays", remoteSession.native.getTotalBlobMemoryUsage()); } // Update ----------------------------------------------------------------- @@ -435,12 +450,16 @@ export default { wasmLoading.value = false; // Camera listener remoteSession.cameraIds.forEach((cid) => { - cameraTags.push([ - cid, - remoteSession.native.observe(cid, "ModifiedEvent", () => { - emit("camera", remoteSession.getState(cid)); - }), - ]); + try { + cameraTags.push([ + cid, + remoteSession.native.observe(cid, "ModifiedEvent", () => { + emit("camera", remoteSession.getState(cid)); + }), + ]); + } catch (err) { + console.error("wasm64 has issue with observer", err); + } }); // Attach listeners watchEffect(() => { @@ -532,6 +551,7 @@ export default { function disposeRemoteSession(runtimeId) { const rId = runtimeId || wasmRuntime.value; if (WASM_REMOTE_SESSIONS[rId]) { + console.log("Removing remote session for wasm runtime", rId); WASM_REMOTE_SESSIONS[rId].dispose(); delete WASM_REMOTE_SESSIONS[rId]; } @@ -543,6 +563,7 @@ export default { const rId = runtimeId || wasmRuntime.value; disposeRemoteSession(rId); if (WASM_RUNTIMES[rId]) { + console.log("Removing wasm runtime with ID:", rId); WASM_RUNTIMES[rId].dispose(); delete WASM_RUNTIMES[rId]; } From 750729435de7216d6c28d593bb41b5393f305fb9 Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Thu, 25 Jun 2026 15:00:36 -0600 Subject: [PATCH 4/9] fix: dispose call from python --- src/trame_vtklocal/widgets/vtklocal.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/trame_vtklocal/widgets/vtklocal.py b/src/trame_vtklocal/widgets/vtklocal.py index 23123c3..71e8949 100644 --- a/src/trame_vtklocal/widgets/vtklocal.py +++ b/src/trame_vtklocal/widgets/vtklocal.py @@ -116,7 +116,6 @@ def __init__( self, render_window, throttle_rate=10, - use_async_component=False, **kwargs, ): # Register response callback if not overridden @@ -212,7 +211,7 @@ def dispose_remote_session(self): """ This will clear and dispose of the remote session. """ - if self._mounted: + if self._mounted and self._wasm_runtime_id: self.server.js_call(self.__ref, "disposeRemoteSession") else: self.server.js_call( @@ -223,7 +222,7 @@ def dispose_wasm_runtime(self): """ This will clear and dispose of the WASM runtime. """ - if self._mounted: + if self._mounted and self._wasm_runtime_id: self.server.js_call(self.__ref, "disposeWasmRuntime") else: self.server.js_call("vtkWASM", "disposeWasmRuntime", self._wasm_runtime_id) @@ -239,7 +238,7 @@ def update_throttle(self): return self._update_throttle def update(self, push_camera=False, **options): - """Sync view by pushing updates to client""" + """Sync view by pushing updates to client. The options are going to be the content of the @updated= event.""" self.api.update( push_camera=push_camera, obj_to_update=[self._render_window, *self.__registered_obj], From 6a40936e521b0118b709c2fee1946803bb5ac0a4 Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Thu, 25 Jun 2026 15:29:15 -0600 Subject: [PATCH 5/9] docs(example): improve validation example --- examples/validation/dispose.py | 16 ++++++++++++++++ vue-components/src/components/VtkLocal.js | 1 + 2 files changed, 17 insertions(+) diff --git a/examples/validation/dispose.py b/examples/validation/dispose.py index 0d16edd..4f36a71 100644 --- a/examples/validation/dispose.py +++ b/examples/validation/dispose.py @@ -51,6 +51,22 @@ class DemoApp(TrameApp): def __init__(self, server=None): # dispose after unmount should only work with vue3 super().__init__(server, client_type=CLIENT_TYPE) + self.server.cli.add_argument( + "--mode", + default="wasm32", + ) + self.server.cli.add_argument( + "--exec", + default="sync", + ) + self.server.cli.add_argument( + "--rendering", + default="webgl", + ) + args, _ = self.server.cli.parse_known_args() + self.state.mode = args.mode + self.state.exec = args.exec + self.state.rendering = args.rendering self.render_window, self.cone, self.actor = create_vtk_pipeline() self._build_ui() diff --git a/vue-components/src/components/VtkLocal.js b/vue-components/src/components/VtkLocal.js index 0288bb0..57a9c28 100644 --- a/vue-components/src/components/VtkLocal.js +++ b/vue-components/src/components/VtkLocal.js @@ -116,6 +116,7 @@ export default { default: () => ({ rendering: "webgl", exec: "sync", + mode: "wasm32", }), }, listeners: { From 7dec54f1b0c28f67b3181ac0b64fd548a2405941 Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Thu, 25 Jun 2026 15:40:21 -0600 Subject: [PATCH 6/9] feat: expose getRemoteSession/getWasmRuntime on vue component --- vue-components/src/components/VtkLocal.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vue-components/src/components/VtkLocal.js b/vue-components/src/components/VtkLocal.js index 57a9c28..67881ea 100644 --- a/vue-components/src/components/VtkLocal.js +++ b/vue-components/src/components/VtkLocal.js @@ -579,6 +579,8 @@ export default { invoke, resize, printSceneManagerInformation, + getRemoteSession: () => remoteSession, + getWasmRuntime: () => WASM_RUNTIMES[wasmRuntime.value], disposeRemoteSession, disposeWasmRuntime, getVtkObject, From a6ce513060b53045a5e6ffb5759b9cb7da918249 Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Thu, 25 Jun 2026 15:45:51 -0600 Subject: [PATCH 7/9] docs(example): add wasm64 observer validation --- examples/validation/wasm64_observer.py | 124 +++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 examples/validation/wasm64_observer.py diff --git a/examples/validation/wasm64_observer.py b/examples/validation/wasm64_observer.py new file mode 100644 index 0000000..3dce917 --- /dev/null +++ b/examples/validation/wasm64_observer.py @@ -0,0 +1,124 @@ +# Required for vtk factory +import vtkmodules.vtkRenderingOpenGL2 # noqa +from trame.app import TrameApp +from trame.decorators import change +from trame.ui.html import DivLayout +from vtkmodules.vtkFiltersSources import vtkConeSource +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa +from vtkmodules.vtkRenderingCore import ( + vtkActor, + vtkPolyDataMapper, + vtkRenderer, + vtkRenderWindow, + vtkRenderWindowInteractor, +) + +from trame.widgets import client, html +from trame_vtklocal.widgets import vtklocal + +CLIENT_TYPE = "vue3" + +# ----------------------------------------------------------------------------- +# VTK pipeline +# ----------------------------------------------------------------------------- + + +def create_vtk_pipeline(): + renderer = vtkRenderer() + renderWindow = vtkRenderWindow() + renderWindow.AddRenderer(renderer) + + renderWindowInteractor = vtkRenderWindowInteractor() + renderWindowInteractor.SetRenderWindow(renderWindow) + renderWindowInteractor.GetInteractorStyle().SetCurrentStyleToTrackballCamera() + + cone = vtkConeSource() + + mapper = vtkPolyDataMapper() + mapper.SetInputConnection(cone.GetOutputPort()) + + actor = vtkActor() + actor.SetMapper(mapper) + + renderer.AddActor(actor) + renderer.SetBackground(0.1, 0.2, 0.4) + renderer.ResetCamera() + + return renderWindow, cone, actor + + +class DemoApp(TrameApp): + def __init__(self, server=None): + # dispose after unmount should only work with vue3 + super().__init__(server, client_type=CLIENT_TYPE) + self.render_window, self.cone, self.actor = create_vtk_pipeline() + self._build_ui() + + def reset_camera(self): + self.ctx.view.reset_camera() + + @change("resolution") + def on_resolution_change(self, resolution, **_): + self.cone.SetResolution(int(resolution)) + self.ctx.view.update_throttle( + resolution=resolution + ) # provide custom content on update + + def _build_ui(self): + with DivLayout(self.server) as self.ui: + client.Style("body { margin: 0; }") + with html.Div( + style="position: absolute; left: 0; top: 0; width: 100vw; height: 100vh;", + v_if=("mounted", True), + ): + self.html_view = vtklocal.LocalView( + self.render_window, + ctx_name="view", + throttle_rate=20, + config=("{ mode: 'wasm64' }",), + camera="console.log($event)", + updated="console.log('updated', $event)", # print custom update content + ) + with html.Div( + style=""" + position: absolute; + left: 1rem; + right: 1rem; + top: 1rem; + display: flex; + padding: 10px; + background: white; + gap: 15px; + """ + ): + html.Div("Resolution") + html.Input( + type="range", + v_model=("resolution", 6), + min=3, + max=60, + step=1, + ) + + html.Div("Component mounted") + html.Input( + type="checkbox", + v_model=("mounted", True), + ) + html.Button("Dispose Runtime", click=self.ctx.view.dispose_wasm_runtime) + html.Button( + "Dispose Session", click=self.ctx.view.dispose_remote_session + ) + html.Button( + "Reset Camera", + click=self.reset_camera, + ) + + +# ----------------------------------------------------------------------------- +# Main +# ----------------------------------------------------------------------------- + +if __name__ == "__main__": + app = DemoApp() + app.server.start() From 52422c0d7616fa28700f2f5bf550f2580e260670 Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Thu, 25 Jun 2026 15:57:08 -0600 Subject: [PATCH 8/9] docs(example): add camera jump --- examples/validation/camera_jump.py | 175 +++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 examples/validation/camera_jump.py diff --git a/examples/validation/camera_jump.py b/examples/validation/camera_jump.py new file mode 100644 index 0000000..84c44cb --- /dev/null +++ b/examples/validation/camera_jump.py @@ -0,0 +1,175 @@ +import asyncio + +# Required for vtk factory +import vtkmodules.vtkRenderingOpenGL2 # noqa +from trame.app import TrameApp, asynchronous +from trame.decorators import change +from trame.ui.html import DivLayout +from vtkmodules.vtkFiltersSources import vtkConeSource +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa +from vtkmodules.vtkRenderingCore import ( + vtkActor, + vtkPolyDataMapper, + vtkRenderer, + vtkRenderWindow, + vtkRenderWindowInteractor, +) + +from trame.widgets import client, html +from trame_vtklocal.widgets import vtklocal + +CLIENT_TYPE = "vue3" + +# ----------------------------------------------------------------------------- +# VTK pipeline +# ----------------------------------------------------------------------------- + + +def create_vtk_pipeline(): + renderer = vtkRenderer() + renderWindow = vtkRenderWindow() + renderWindow.AddRenderer(renderer) + + renderWindowInteractor = vtkRenderWindowInteractor() + renderWindowInteractor.SetRenderWindow(renderWindow) + renderWindowInteractor.GetInteractorStyle().SetCurrentStyleToTrackballCamera() + + cone = vtkConeSource() + + mapper = vtkPolyDataMapper() + mapper.SetInputConnection(cone.GetOutputPort()) + + actor = vtkActor() + actor.SetMapper(mapper) + + renderer.AddActor(actor) + renderer.SetBackground(0.1, 0.2, 0.4) + renderer.ResetCamera() + + return renderWindow, cone, actor + + +class DemoApp(TrameApp): + def __init__(self, server=None): + # dispose after unmount should only work with vue3 + super().__init__(server, client_type=CLIENT_TYPE) + self.delta = 1 + self.server.cli.add_argument( + "--mode", + default="wasm32", + ) + self.server.cli.add_argument( + "--exec", + default="sync", + ) + self.server.cli.add_argument( + "--rendering", + default="webgl", + ) + args, _ = self.server.cli.parse_known_args() + self.state.mode = args.mode + self.state.exec = args.exec + self.state.rendering = args.rendering + + self.render_window, self.cone, self.actor = create_vtk_pipeline() + self._build_ui() + + def reset_camera(self): + self.ctx.view.reset_camera() + + @change("resolution") + def on_resolution_change(self, resolution, **_): + self.cone.SetResolution(int(resolution)) + self.ctx.view.update_throttle( + resolution=resolution + ) # provide custom content on update + + @change("play") + def on_play_change(self, play, **_): + if play: + asynchronous.create_task(self._animate()) + + async def _animate(self): + while self.state.play: + await asyncio.sleep(0.01) + + resolution = self.cone.resolution + + if resolution > 60: + self.delta = -1 + if resolution < 4: + self.delta = +1 + + self.on_resolution_change(resolution + self.delta) + + def _build_ui(self): + with DivLayout(self.server) as self.ui: + client.Style("body { margin: 0; }") + with html.Div( + style="position: absolute; left: 0; top: 0; width: 100vw; height: 100vh;", + v_if=("mounted", True), + ): + self.html_view = vtklocal.LocalView( + self.render_window, + ctx_name="view", + throttle_rate=20, + config=("{ mode, rendering, exec }",), + ) + with html.Div( + style=""" + position: absolute; + left: 1rem; + right: 1rem; + top: 1rem; + display: flex; + padding: 10px; + background: white; + gap: 15px; + """ + ): + html.Div("Resolution") + html.Input( + type="range", + v_model=("resolution", 6), + min=3, + max=60, + step=1, + ) + + with html.Select(v_model=("mode", "wasm32")): + html.Option("wasm32") + html.Option("wasm64") + with html.Select(v_model=("exec", "sync")): + html.Option("sync") + html.Option("async") + with html.Select(v_model=("rendering", "webgl")): + html.Option("webgl") + html.Option("webgpu") + + html.Div("Animate") + html.Input( + type="checkbox", + v_model=("play", False), + ) + html.Div("Component mounted") + html.Input( + type="checkbox", + v_model=("mounted", True), + ) + html.Button("Dispose Runtime", click=self.ctx.view.dispose_wasm_runtime) + html.Button( + "Dispose Session", click=self.ctx.view.dispose_remote_session + ) + html.Button( + "Reset Camera", + click=self.reset_camera, + ) + + +# ----------------------------------------------------------------------------- +# Main +# ----------------------------------------------------------------------------- + +if __name__ == "__main__": + app = DemoApp() + app.server.start() From 7989ec182d0529016d1da8c2b2feefbf4de4b9bb Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Fri, 26 Jun 2026 09:37:48 -0600 Subject: [PATCH 9/9] fix(wasm-runtime): allow Async/Sync runtime to work in parallel --- vue-components/package-lock.json | 9 ++++----- vue-components/package.json | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/vue-components/package-lock.json b/vue-components/package-lock.json index 995a6e2..79ce9a3 100644 --- a/vue-components/package-lock.json +++ b/vue-components/package-lock.json @@ -8,8 +8,7 @@ "name": "vue-trame_vtklocal", "version": "0.0.0", "dependencies": { - "@kitware/vtk-wasm": "^2.1.3", - "jszip": "3.10.1" + "@kitware/vtk-wasm": "^2.1.4" }, "devDependencies": { "@eslint/js": "^9.22.0", @@ -1363,9 +1362,9 @@ } }, "node_modules/@kitware/vtk-wasm": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@kitware/vtk-wasm/-/vtk-wasm-2.1.3.tgz", - "integrity": "sha512-gQz3i4hMjKqZMzuD4RT8ERzv74fWeJIYa/tXQM5EnAXihaxMCTnH6vSlbBRBjnWCTjOKLdP1QSYA7Symc9D6Mw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@kitware/vtk-wasm/-/vtk-wasm-2.1.4.tgz", + "integrity": "sha512-yjHM3xq7f2jw43eBrz8b2MHnSi6zEL7OR93X8dpL9Wvi8q831k5p7aZd0UjoSe7VgsG00qXCGPpneilYyT4GqQ==", "license": "Apache-2.0", "dependencies": { "@codemirror/lang-html": "^6.4.11", diff --git a/vue-components/package.json b/vue-components/package.json index 3f3dc13..c37b27b 100644 --- a/vue-components/package.json +++ b/vue-components/package.json @@ -14,8 +14,7 @@ "vue": "^2.7.0 || >=3.0.0" }, "dependencies": { - "@kitware/vtk-wasm": "^2.1.3", - "jszip": "3.10.1" + "@kitware/vtk-wasm": "^2.1.4" }, "devDependencies": { "@eslint/js": "^9.22.0",